Firebase Custom Messages iOS - ios

I'm referring to the interpreting messages portion in https://firebase.google.com/docs/cloud-messaging/ios/receive .
Where in my code can I change the text for notifications in Firebase?

In order to send a push notification to a device, You need to have a script (or a piece of code) ideally hosted on a server that would send a push notification on your behalf.
There you can customize the message and even play an audio upon receiving a notification.
Here is a code snippet in java that can be used to send a push notification to a device (or a group of devices).
private Map sendPush(String to, String from, String title, String message,
String sound) throws IOException {
sound = (sound != null) ? sound : "default"; // set default audio file name
// Creating the URL and connection
URL url = new URL(FCM_URL); // your firebase URL
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Authorization", "key=" + FCM_KEY); // the firebase project key
conn.setDoOutput(true);
// set the notification body
Map<String, String> notificationBody = new HashMap();
notificationBody.put("title", title); // notification title
notificationBody.put("body", message); // notification message
notificationBody.put("sound", sound);
notificationBody.put("badge", "1");
Map<String, String> dataBody = new HashMap();
dataBody.put("sender", from); // sender id
Map<String, Object> pushBody = new HashMap();
pushBody.put("notification", notificationBody);
pushBody.put("data", dataBody);
pushBody.put("to", to); // receiver(s) id
pushBody.put("priority", "high");
// convert your dictionary to json string using Google Gson library (similar to JsonSerialization class in swift)
String input = new Gson().toJson(pushBody);
// write input bytes in request body
try (OutputStream os = conn.getOutputStream()) {
os.write(input.getBytes());
os.flush();
}
StringBuilder responseString;
Reader reader = new InputStreamReader(conn.getInputStream()); // send request and receive response
// parse response
try (BufferedReader in = new BufferedReader(reader)) {
String inputLine;
responseString = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
responseString.append(inputLine);
}
}
// using Google Gson to convert json string into Map (similar to JsonSerialization class in swift)
Map<String, Object> responseObject = new Gson().fromJson(responseString.toString(),
Map.class);
return responseObject;
}
Since this is a java code, so i have hosted it in a java application deployed on Apache Tomcat Server.
You can find several similar implementations in various languages like php or node.js etc.
Hope this helps

first create p.12 certificate and upload in firebase ->project settings ->cloud messaging tab ->select your iOS app ->add APNS certificate.
A. Create a (.certSigningRequest) CSR file
Open Keychain Access from Utilities
From Keychain Access toolbar select Keychain Access -> Preference
In the pop up window select Certificates tab
Set both “Online Certificate Status Protocol” and “Certificate Revocation List” to “Off"
Close this window
Now from toolbar, open Keychain Access > Certificate Assistant > Request a Certificate From a Certificate Authority
Enter email address and common name that you used to register in the iOS Developer Program
Keep CA Email blank and select “Saved to disk” and “Let me specify key pair information”
Click Continue
Choose a filename & destination on your hard drive
Click Save
In the next window, set “Key Size” value to “2048 bits”
Set “Algorithm” to “RSA”
Click Continue
This will create and save your certSigningRequest file (CSR) to your hard drive. A public and private key will also be created in Keychain Access with the Common Name entered.
B. Create ".cer" file in iOS developer account
Login to apple developer account Click “Certificates, Identifiers & Profiles”
Click “Provisioning Profiles”
In the “Certificates” section click “Production”
Click the “Add” (+) button at the top-right of the main panel
Now, choose “App Store and Ad Hoc”
Click Continue
Click “Choose File” & find CSR file you’ve made from your hard drive
Click Generate
Click Download to get the file
C. Install .cer and generate .p12 certificate
Find .cer file you’ve downloaded and double-click
Set Login drop-down to “login" and Click Add
Open up KeyChain Access and you'll find profile created in Step A
You can expand “private key” profile (shows certificate you added)
Select only these two items (not the public key)
Right click and click “Export 2 items…” from popup
Now make sure file format is “.p12” and choose filename and destination on your hard drive
Click Save. Now, you’ll be prompted to set a password but keep these both blank
Click OK. Now, you have a .p12 file on your hard drive
and open your Xcode project and select target->capabilities->pusnotification->on
next do this stuff https://firebase.google.com/docs/cloud-messaging/ios/receive
next push message from firebase cloud messaging console with message and title and select your app target->user segment->your app.
then your app will able

Related

Docusign iOS SDK directly sending envelope without opening anything also not asking to do the signature

I have created a template in docusign web and using its template id, i am calling the function from iOS SDK.
TemplatesManager.sharedInstance.displayTemplateForSignature(templateId: templateId, controller: self, tabData: tabData, recipientData: recipientData, customFields:customFields, onlineSign: onlineSign, attachmentUrl: attachmentUrl) { (controller, errMsg) in
print(errMsg)
}
The recipient data i am sending is
let recipientDatum = DSMRecipientDefault()
// Use recipient roleName (other option to use recipient-id) to find unique recipient in the template
recipientDatum.recipientRoleName = "Client"
recipientDatum.recipientSelectorType = .recipientRoleName
recipientDatum.recipientType = .inPersonSigner
// In-person-signer name
recipientDatum.inPersonSignerName = "Akshay Somkuwar"
// Host name (must match the name on the account) and email
recipientDatum.recipientName = "Akshay Somkuwar"
recipientDatum.recipientEmail = "akshay.s.somkuwar#gmail.com"
let recipientData: Array = [recipientDatum]
Same recipient is added for template in docusign website
Also i have added observers for DSMSigningCompleted and DSMSigningCancelled to get envelopeId.
Now when i am calling this function displayTemplateForSignature no screen is opening to show the PDF or To sign the PDF, without asking for signature, the envelope is directly sent to the recipient. and i am getting this response in console with notification.
name = DSMSigningCompletedNotification, object = Optional(<Public_Adjuster.AgreementSignViewController: 0x110bb8060>), userInfo = Optional([AnyHashable("templateId"): 506346f5-7adb-4132-b15f-d288aa268398, AnyHashable("signingMode"): online, AnyHashable("envelopeId"): 2eeeeda8-5b74-4930-904e-94b2ce6451ac])
I want to open the pdf for the passed templateId but its not opening the pdf nor its asking for signature, and its directly sent to the recipient.
Any help will be appreciated, Thank you.
This behaviour, sending the envelope directly, is triggered when DocuSign SDK can not find any signers in the template/envelope that matches the logged-in user. Given that you are using the recipientDefaults, ensure that your signer information on the template (preset signer on the DocuSign web) matches the Account information exactly with the recipientDefaults object.
You may compare it with .
One issue I noticed is the signer type is set to need to sign which corresponds to a remoteSigner on the DocuSign web. And on the recipientDefaults object it's set as inPersonSigner. It should be .signer corresponding to DSMRecipientTypeSigner.
recipientDatum.recipientType = .signer.
Or you may change the need to sign to in person signer on the DocuSign web.
Another suggestion is to remove the name & email from the template screenshot shared and keep that empty as the client app is passing name & email with the recipientDefaults object to the SDK.
More details: How to set recipient defaults

Xamarin.iOS KeyChain Identity not persisting

I have created a self-signed .pfx file that when I drag onto the emulator, the import screen appears, I can click through and then using select * from cert; on the emulators Keychain, I can see the imported certificate.
When I load this certificate in code and attempt to add it, I am getting a Success back from the save operation but on subsequent attempts to access the identity, it is returning ItemNotFound, further to that, when I inspect the KeyChain after the import there is no cert in the table either.
await certStream.CopyToAsync(ms);
var options = NSDictionary.FromObjectsAndKeys(new[]
{
NSObject.FromObject("CertPassword")
}, new[]
{
SecImportExport.Passphrase
});
var result = SecImportExport.ImportPkcs12(ms.ToArray(), options, out
NSDictionary[] imports);
if (result != SecStatusCode.Success)
throw new Exception("Failed importing certificate identity");
var identity = imports[0][SecImportExport.Identity];
certRecord.SetValueRef(new SecIdentity(identity.Handle));
var identityImportResult = SecKeyChain.Add(certRecord);
var savedIdentity = SecKeyChain.QueryAsRecord(new
SecRecord(SecKind.Identity)
{
Label = "ApplicationIdentityCertificate"
}, out SecStatusCode savedResult);
Reading round, I have ensured that there is a Entitlements associated with the emulator and that also, it has the keychain sharing entitlement as there appears to be anecdotal evidence that this can sometimes also impact the ability to save to the Keychain.
So I finally managed to get this working. It turns out I was missing a pretty simple method that is available on the SecKeyChain class.
var identity = imports[0][SecImportExport.Identity];
SecKeyChain.AddIdentity(new SecIdentity(identity.Handle));
The above snippet is the change I needed to make and now the identity is being stored in the Keychain with the correct bundle ID and our application can load the certificate and the private key, for whatever reason, adding it via the SecKeyChain.Add() method was not working for identities.

Slack deep link into client: how to link into im if im not open

I made a platform-independent contactlist-style standalone client for Slack in Qt/C++.
It uses Slack's Deep Linking scheme to navigate through the official Slack-Client when clicking Items in my ContactList.
The problem is, when clicking a user item in my list (which gets the user id and creates the link), the slack client will only enter the im dialog, if it was open before (if i have a im history with that user).
Otherwise it will just show the team directory context for that user, where i manually have to click "message" to actually enter the chat dialog.
Is there really no way to do it right just with slack:// deep links?
The only solution that i can think of right now is to open a new im, if not exist, using api call from my application before opening the link. or maybe open im's for all users at app launch.
But that's kind of a dirty workaround, that i don't like.
Is there a more elegant way to go directly to a new IM than this?
EDIT: quick Workaround without error handling is working this way:
void Window::contactListDoubleClicked(QTableWidgetItem *item)
{
QString id = listWidget->item(item->row(),1)->text();
int type = listWidget->item(item->row(),3)->text().toInt();
if (type == 1) { // if item is a user, we have to ensure that im exists by requesting im.open
QEventLoop eventLoop;
QNetworkAccessManager mgr;
QObject::connect(&mgr, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));
QNetworkRequest req(QUrl(QString("https://slack.com/api/im.open?token=").append(m_token).append("&user=").append(id)));
QNetworkReply *reply = mgr.get(req);
// block stack until reply is ready
eventLoop.exec();
qDebug() << reply->readAll();
QDesktopServices::openUrl(QUrl(QString("slack://user?team=XXXXXXXX&id=").append(id),QUrl::TolerantMode));
} else {
QDesktopServices::openUrl(QUrl(QString("slack://channel?team=XXXXXXX&id=").append(id),QUrl::TolerantMode));
}
}

Save email address to accounts app iOS

I have two apps (eg: App1 and App2) which requires login with an account. What I need to achieve is when an user log-in successfully into the App1, the email address should get saved to the default Accounts app of the device. Then when the user opens up the App2, the email address saved from App1 should show up as a recommendation for the user if he need to use the same account to sign in to App2 as well. Just like some apps do if you click on sign in with Google or Facebook.
Since I am new to iOS, I need to ask if this is possible to achieve in iOS and if yes what procedure should I follow.
EDIT
I tried implementing KeyChain for this. Something like below :-
void StoreKeysInKeychain (string key, string value) {
var s = new SecRecord (SecKind.GenericPassword) {
ValueData = NSData.FromString (value),
Generic = NSData.FromString (key)
};
var err = SecKeyChain.Add (s);
}
void GetRecordsFromKeychain (string key)
{
SecStatusCode res;
var rec = new SecRecord (SecKind.GenericPassword) {
Generic = NSData.FromString (key)
};
var match = SecKeyChain.QueryAsRecord (rec, out res);
if (match != null) {
// nsdata object : match.ValueData;
}
}
This way when I login to the App1 with an email address it gets saved and when I open the App2 I get that email address. This works fine. But now the issue is that if I logout from App1 and login with another email address. That account is not visible in App2. How can I get a list of all the email address?
Any help is appreciated.
you need to use app Group to share information among app, Enable app Group from build settings in both app and certificate , assign same group to them , and put information for each other on a suite of NSuserdefault .
Xamarin documentation for app group is here : https://developer.xamarin.com/guides/ios/watch/working-with/app-groups/
I believe you can set up a ParseServer that user account management for both apps

Notification Hub Devices disappearing after Push (APNS)

We have an Azure Notification Hub set up, with APNS Configured in Production Mode, using our Production APNS Certificate.
We register our test devices (using TestFlight / Production build, and certificate) to APNS, and then to ANH with a tag dealer-1. We can send notifications using our production certificate and registered Device ID with success when using APNS directly, however, when we use 'Test Send' we get a 'Successful send' to 1 device (or however many we have registered). The notification is not received. If we then run 'Test Send' again, the are 0 devices to send to.
In the logs, we see 'APNS Errors' per device, per test send. I cannot see any way to view what the errors actually are though so this is an absolutely useless metric.
I have ran through all the troubleshooting steps and confirmed many times that everything is setup in 'Production'.
Having reviewed other questions, the answers have been along the lines of:
.. registering a sandbox certificate and then changing it to production. Unfortunately we created this hub from scratch as Production in an attempt to work around that potential issue.
.. registering sandbox devices (and thus tokens) against the production certificate. Unfortunately I have controlled this closely and ensured that we are only registering TestFlight builds (thus Production) against the ANH.
.. uploading the wrong certificate. I have confirmed with the Push Notification Tester, as above, that the certificate is correct (thumbprint confirmed, re-uploaded, etc) and works to send to the devices via Production APNS endpoint.
The resource name is: eight-technology/react-push-notification-hub
In-app registration process is as follows:
Device registers for push notifications
Registration event is handled in iOS Project (AppDelegate event)..
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
//base.RegisteredForRemoteNotifications(application, deviceToken);
App.ConfigurePushNotifications(deviceToken.ToString());
}
ConfigurePushNotifications is in the XF Shared Project..
public static void ConfigurePushNotifications(string deviceToken)
{
var azureComm = DependencyService.Get<Interop.IAzureCommunication>();
azureComm.RegisterForPushTags(
"sb://eight-technology.servicebus.windows.net/",
".. token ..",
"react-push-notification-hub",
deviceToken,
StateManager.SelectedNodes.Select(m => "dealer-" + m).ToArray());
}
The implementation is pretty much as per the sample code provided (contained in iOS project)
public class AzureCommunication : DealerwebReact.Interop.IAzureCommunication
{
public void RegisterForPushTags(string url, string key, string hubName, string deviceToken, string[] tags)
{
var cs = SBConnectionString.CreateListenAccess(new NSUrl(url), key);
var hub = new SBNotificationHub(cs, hubName);
hub.RegisterNativeAsync(deviceToken, new NSSet(tags), err =>
{
if (err != null)
Console.WriteLine("Error: " + err.Description);
else
Console.WriteLine("Success");
});
}
}
After a frustrating few days, and thanks to the help of Nikita G. and hvaughan3 I finally got to the root cause of my issue. As anticipated it wasn't any of the issues actually outlined, but was to do with the way we handled the cross-plat aspect of the registrations with Xamarin Forms.
That is, we stored our token in a class as a string. The NSData that is received as part of the iOS Device registration in RegisteredForRemoteNotifications has a ToString() method that is incompatible with sending to ANH. Furthermore, RegisterNativeAsync method from the Azure library requires an NSData which I assume Xamarin can morph a string into without warning or error, hence it was unknown that the two were somewhat incompatible.
Basically, to maintain cross platform functionality, we are now simply passing the token around as an object and performing the translation back to the original type in the platform-specific implementation of our push configuration method.
Our registration method now looks like this, note the explicit use of the NSData type so that it remains untouched whilst passing through the Xamarin Forms layer:
public void RegisterForPushTags(string url, string key, string hubName, object deviceToken, string[] tags)
{
var cs = SBConnectionString.CreateListenAccess(new NSUrl(url), key);
var hub = new SBNotificationHub(cs, hubName);
hub.RegisterNativeAsync((NSData)deviceToken, new NSSet(tags), err =>
{
if (err != null)
Console.WriteLine("Error: " + err.Description);
else
Console.WriteLine("Success");
});
}
Is this the guide you used for troubleshooting?
Is there a chance you somehow do any string (or any other type of) processing on the APN handle before you register your device? The 'APNS errors' you're seeing seem to be 'invalid token size'. Since I don't know what's going on in your code, it's hard to suggest what exactly might it be, but maybe would help you.
A similar thing happened to me when the device would register correctly but as soon as a notification was sent, the devices would disappear from the list. It always turned out to be an issue with the APNS certificate that was configured within the Notification Hub was not connected properly to the App ID and/or the app was not being signed with the correct provisioning profile.

Resources