I am trying to get push notifications working from a sample app. Whenever I send a message from App Center, I get 0/0 messages sent and I don't see anything happening in my app.
I followed the instructions at http://learn.microsoft.com/en-us/appcenter/push/xamarin-android. At the same time I implemented App Center Analytics. That seems to work since I can send TrackEvent messages and see them in App Center. I am building my app on VS Mac.
I set up the Firebase Cloud Messaging and got the Android API Key
I added the Nuget packages.
I didn't need to update the AndroidManifest.xml file.
I didn't do anything about ProGuard since I don't use it (or know what it is)
I didn't do anything about the OnNewIntent stuff - it's not clear how to tell if that's needed or how/where to do it.
In MainActivity.c I have the AppCenter.Start(..., typeof(Push), typeof(Anayltics), typeof(Crash));
In my App.xaml.cs I have
public App()
{
InitializeComponent();
if (!AppCenter.Configured)
{
Push.PushNotificationReceived += (Sender, e) =>
{
string summary = "Title=" + e.Title + " Msg=" + e.Message;
Console.WriteLine(summary);
};
}
AppCenter.Start("androidkey" + "ios=ioskey;", typeof(Push), typeof(Analytics), typeof(Crashes));
MainPage = new NavigationPage(new MyPage());
}
In my MyPage.xaml.cs I have
protected override async void OnAppearing()
{
base.OnAppearing();
Push.PushNotificationReceived += (Sender, e) =>
{
string summary = "Title=" + e.Title + " Msg=" + e.Message;
Console.WriteLine(summary);
};
I have put the google-servicesjson file in the main folder of the Android app and set its build action to GoogleServicesJson. I had to do that by manually editing the csproj file.
I put breakpoints at both console.write... statements and then never get triggered. Like I say, I send off a message from App Center and it never arrives.
Any thoughts or suggestions would be appreciated.
Thanks
Les
Related
I just learned about notifications in the expo, now I have successfully sent notifications and I have also managed to get data from the notifications I sent, the problem is, if the application is in background or foreground, addNotificationResponseReceivedListener is working properly (redirect to another page), but if I close the application, and I receive a notification, then I press the notification, the application opens but the addNotificationResponseReceivedListener function is not running, I try this in a standalone application
what i’m using:
“expo”: “~40.0.0”,
“expo-notifications”: “^0.9.0”,
here’s my example code in Home.js:
componentDidMount() {
//another code..
Notifications.addNotificationResponseReceivedListener(
this._handleNotificationResponse
);
}
_handleNotificationResponse = (response) => {
console.log(
"CONSOLE FROM NOTIF: " +
JSON.stringify(response.notification.request.content.data.from)
);
if (response.notification.request.content.data.from== "GEMASS") {
this.props.navigation.navigate("goToPage", {
//another code...
});
} else {
}
};
here’s my file tree:
App.js
Components
- Home.js
and here’s my terminal looks like when i run on expo client:
clickme
can you guys help me? it means a lot :)
I am writing my own message provider to send out push notifications on both iOS and Android. I have the provider working well for iOS. My problem is Android. With the app not running, The phone gets the message and notifies the user a message came in. I only see the icon in the message. The message body is not displayed. If the app is running, the app gets the message event and I can see in the JSON, the message body and message title. So it would appear that the information is coming through. I've tried this on an Android running JellyBean and Marshmallow and get the same results. I also tried using Googles test notification from their web site for FCM. I get the same results with their web notification send. Any ideas?
Here is the code I am using in Delphi:
HttpClient.Request.URL := 'https://fcm.googleapis.com/fcm/send';
HttpClient.Request.ContentType := 'application/json';
HttpClient.Request.CustomHeaders.Add('Authorization: key = ***'); // Server Key from Google
HttpClient.Request.CharSet := 'utf-8';
JSONMsg := TJSONObject.Create;
JSONMsg.AddPair('to', devicetoken);
JSONInfo := TJSONObject.Create;
JSONInfo.AddPair('body', edtMessage.Text);
JSONInfo.AddPair('title', 'CODY Mobility');
JSONInfo.AddPair('priority', 'high');
JSONTrue := TJsonTrue.Create;
JSONFalse := TJsonFalse.Create;
JSONInfo.AddPair('content_available', JSONTrue);
JSONInfo.AddPair('dry_run', JSONFalse);
JSONToSend := TStringStream.Create(JSONMsg.ToString, TEncoding.UTF8);
StatusMemo.Lines.Add('Sending Android message to device: ' + deviceToken);
try
HttpClient.Post('https://fcm.googleapis.com/fcm/send', JSONToSend);
except
on E:Exception do begin
StatusMemo.Lines.Add('Message send failed: ' + E.Message);
end;
end;
StatusMemo.Lines.Add('Android message response: ' + HttpClient.ResponseText);
FreeAndNil(JSONTrue);
FreeAndNil(JSONFalse);
I have found my problem! It appears to be a bug with Delphi. My original message sent was:
{"to":<MyDeviceID>","notification":{"body":"It finally works!!!!!","title":"CODY Mobility Title","priority":"high","content_available":false,"dry_run":false}}
If I change my message to the following, it now works:
{"to":"<MyDeviceID>","data":{"message":"It finally works!!!!!","title":"CODY Mobility Title","priority":"high","content_available":false,"dry_run":false}}
I had to change from "notification" to "Data" and I had to change the "body" element to a "message" element. With those changes in place, the phone gets and displays the message when the app is closed. Of course, this no longer matches Google's specs for sending a notification with Firebase Cloud Messaging. I dug into the Delphi code and I found a Delphi java script called NotificationPublisher.Java. In there, there is code which specifically looks for a message element.
if (jsonVal != null) {
if (jsonVal.has("message"))
{ msg = jsonVal.optString("message"); }
else if (jsonVal.has("msg"))
{ msg = jsonVal.optString("msg"); }
else if (jsonVal.has("alert"))
{ msg = jsonVal.optString("alert"); }
if (jsonVal.has("title"))
{ title = jsonVal.optString("title"); }
}
} else {
// Look for msg or message in bundle
if (key.equals("message"))
{ msg = valstr; } else if (key.equals("msg")) { msg = valstr; }
if (key.equals("title"))
{ title = valstr; }
}
I am not sure where Delphi checks for Notification elements versus Data elements. But I believe this is part of the problem. I created a support ticket so Embarcadero can look into this further. If anyone else has this problem... Just change your message and it'll work.
I am a newbie on parse server and have been using it with my android app. But I am having trouble with implementing push notifications. I do not know how to get logs so any guidance will be much appreciated! The installation class does not contain any "GCMSenderId" or "deviceToken".
Here is how I set up parse server to implement push notifications.
Parse Sever : 2.2.7
1) Developer Console
a) I create a new project using the new console and clicked on the overflow menu --> Project Info and got my project number.
b) Then I went to the "Credentials" page and clicked on Create Credentials --> Api Key --> Server Key and left everything default and clicked create.
c) I got the key for my project. Let it be "MY_API_KEY".
2) Now I setup my parse server app to use this api key and project number as you can see from the image.
enter image description here
3) Now I setup my android app manifest accordingly as you can see from the picture below.
enter image description here
I also added ParseInstallation.getCurrentInstallation.saveInBackground();in my app's Application class.
I am trying to send notifications using the parse dashboard
Please provide any help if possible, thanks!
to send push notification from parse server you have to implement cloud code
in Javascript or another programming language.
below is some code in JS to send push notification to a user
function(objectids,msg) {
var pushQuery = new Parse.Query(Parse.Installation);
msg.default="default";
pushQuery.exists("deviceToken");
pushQuery.containedIn('userObjectId',objectids);
try
{
Parse.Push.send({
where: pushQuery,
data: {
alert:msg.msgInfo,
str:msg,
sound:msg.default
}
}).then(function() {
console.log("push successfully sent");
}, function(error) {
console.log("error while send pn:"+error.code+":"+error.message);
throw "Push Error " + error.code + " : " + error.message;
});
}catch(error)
{
console.log("error while send pn:"+error.code+":"+error.message);
}
}
For a while now, I have been trying to figure out how to send push notifications. The app I have made is for Android right now, but I want to extend it to other devices once I figure this out. I've looked into various services, such as Amazon SNS, but they all neglect to include how to get the device token. They all assume you know how to do that.
So what I am asking is: how do I get a device token/registration ID for a device?
I tried using this code:
var tokenID = "";
document.addEventListener("deviceready", function(){
//Unregister the previous token because it might have become invalid. Unregister everytime app is started.
window.plugins.pushNotification.unregister(successHandler, errorHandler);
if(intel.xdk.device.platform == "Android")
{
//register the user and get token
window.plugins.pushNotification.register(
successHandler,
errorHandler,
{
//senderID is the project ID
"senderID":"",
//callback function that is executed when phone recieves a notification for this app
"ecb":"onNotification"
});
}
else if(intel.xdk.device.platform == "iOS")
{
//register the user and get token
window.plugins.pushNotification.register(
tokenHandler,
errorHandler,
{
//allow application to change badge number
"badge":"true",
//allow application to play notification sound
"sound":"true",
//register callback
"alert":"true",
//callback function name
"ecb":"onNotificationAPN"
});
}
}, false);
//app given permission to receive and display push messages in Android.
function successHandler (result) {
alert('result = ' + result);
}
//app denied permission to receive and display push messages in Android.
function errorHandler (error) {
alert('error = ' + error);
}
//App given permission to receive and display push messages in iOS
function tokenHandler (result) {
// Your iOS push server needs to know the token before it can push to this device
// here is where you might want to send the token to your server along with user credentials.
alert('device token = ' + result);
tokenID = result;
}
//fired when token is generated, message is received or an error occured.
function onNotification(e)
{
switch( e.event )
{
//app is registered to receive notification
case 'registered':
if(e.regid.length > 0)
{
// Your Android push server needs to know the token before it can push to this device
// here is where you might want to send the token to your server along with user credentials.
alert('registration id = '+e.regid);
tokenID = e.regid;
}
break;
case 'message':
//Do something with the push message. This function is fired when push message is received or if user clicks on the tile.
alert('message = '+e.message+' msgcnt = '+e.msgcnt);
break;
case 'error':
alert('GCM error = '+e.msg);
break;
default:
alert('An unknown GCM event has occurred');
break;
}
}
//callback fired when notification received in iOS
function onNotificationAPN (event)
{
if ( event.alert )
{
//do something with the push message. This function is fired when push message is received or if user clicks on the tile.
alert(event.alert);
}
if ( event.sound )
{
//play notification sound. Ignore when app is in foreground.
var snd = new Media(event.sound);
snd.play();
}
if ( event.badge )
{
//change app icon badge number. If app is in foreground ignore it.
window.plugins.pushNotification.setApplicationIconBadgeNumber(successHandler, errorHandler, event.badge);
}
}
All I get is an alert that says "result = ok". The alerts later on in the code don't happen. I've tried making sense of the code but I'm not getting anywhere. Any suggestions? Is there a tutorial for this I'm not finding?
Those legacy intel.xdk functions are being retired (the will continue to live in an 01.org, see the notice on this page: https://software.intel.com/en-us/node/492826).
I recommend you investigate one of the many push notification Cordova plugins that are available. Use your favorite web search tool to search for something like "cordova phonegap push notification plugin" to find some. The good ones will have examples of how to use.
Note:-
Unregister - Its not strictly necessary to call it.....
Ensure that you have a sender ID for Android (no idea about iOS).
Result OK means that the plugin is installed correctly and has run properly.
Problems could be due to:
Incorrect sender ID
Testing in emulator without adequate setup
Important - Push notifications are intended for real devices. They are not tested for WP8 Emulator. The registration process will fail on the iOS simulator. Notifications can be made to work on the Android Emulator, however doing so requires installation of some helper libraries, as outlined here, under the section titled "Installing helper libraries and setting up the Emulator".
onNotification must be available as a global object. So try attaching it to the window. Refer to this question
Examples of properly initializing PushPlugin in:
Ionic (my answer)
Me and my friend are working on an app., and we wish to use Parse.com as our data base from which we can retrieve info.
We can't decide what is the best way to access the data on Parse. For the sake of the example, our app. (i.e. client side) needs something stored on the Parse data base (say some number) - should it directly run the query using the Parse API, or should it make a request to a server side, let it retrieve that number from Parse, and send it back to the client?
We know there's no definite answer, but we couldn't find answer regarding this specific situation. We read this post: When to use client-side or server-side?,
but this not exactly the same case.
I claim that we should try to seperate as much as possible from client side and data bases, and leave these queries run by someone who's in charge (server), where my friend claims this adds unnecessary complication, since it's very natural to use the tools supplied by Parse to access the data base from the client side, without the need for a protocol etc.
We'd appriciate any advice,
Thank you.
In general, go right ahead and make a normal call.
I'd encourage you to do that first in any case, to get everything working on both ends.
Then if necessary go to Cloud Code.
If you are going to do more than one platform (ie iOS and Android), cloud code can be a huge timesaver.
BUT don't forget that for simple calls, cloud code is a waste of time. "Normal" Parse calls are amazingly, incredibly, amazingly, fast and quick to work with.
There is absolutely nothing "wrong" with using normal Parse calls - so do that.
Regarding the question, when do you literally have to use a cloud code call -- you'll know, because you won't be able to do it with a normal call :)
Don't forget very often you can simply use "afterSave" or "beforeSave" in cloud code, to do a huge amount of work. You often don't literally need to go to a "custom call" in cloud code.
Here's a fantastic
Rule of thumb for Parse cloud code --------->
If you have to do "more than one thing" ... in that case you will likely have to make it a cloud code function. If you have to do "three or more things" then DEFINITELY make it a cloud code function.
That's a good rule of thumb.
(Again, as I say, often just an "afterSave" or similar works brilliantly...rather than literally writing a full custom call.)
Here's a typical example of a cloud call that saves 18 billion lines of code in all the platforms covered by the dotcom. First the cloud code...
Parse.Cloud.define("clientRequestHandleInvite", function(request, response)
{
// called from the client, to accept an invite from invitorPerson
var thisUserObj = request.user;
var invitorPersonId = request.params.invitorPersonId;
var theMode = request.params.theMode;
// theMode is likely "accept" or "ignore"
console.log( "clientRequestAcceptInvite called.... invitorPersonId " + invitorPersonId + " By user: " + thisUserObj.id );
console.log( "clientRequestAcceptInvite called.... theMode is " + theMode );
if ( invitorPersonId == undefined || invitorPersonId == "" )
{
response.error("Problem in clientRequestAcceptInvite, 'invitorPersonId' missing or blank?");
return;
}
var query = new Parse.Query(Parse.User);
query.get(
invitorPersonId,
{
success: function(theInvitorPersonObject)
{
console.log("clientRequestFriendRemove ... internal I got the userObj ...('no response' mode)");
if ( theMode == "accept" )
{
createOneNewHaf( thisUserObj, theInvitorPersonObject );
createOneNewHaf( theInvitorPersonObject, thisUserObj );
}
// in both cases "accept" or "ignore", delete the invite in question:
// and on top of that you have to do it both ways
deleteFromInvites( theInvitorPersonObject, thisUserObj );
deleteFromInvites( thisUserObj, theInvitorPersonObject );
// (those further functions exist in the cloud code)
// for now we'll just go with the trick of LETTING THOSE RUN
// so DO NOT this ........... response.success( "removal attempt underway" );
// it's a huge problem with Parse that (so far, 2014) is poorly handled:
// READ THIS:
// parse.com/questions/can-i-use-a-cloud-code-function-within-another-cloud-code-function
},
error: function(object,error)
{
console.log("clientRequestAcceptInvite ... internal unusual failure: " + error.code + " " + error.message);
response.error("Problem, internal problem?");
return;
}
}
);
}
);
If you are new to Parse it's incredibly hard to figure out how to call these from Android or iOS! Here's that one being called from Android ...
this will save you a day of messing about with HashMaps :)
private static void handleInvite( ParseUser invitor, final boolean accepted )
{
String invitorId = invitor.getObjectId();
// you must SEND IDs, NOT PARSEUSER OBJECTS to cloud code. Sucks!
String cloudKode;
cloudKode = (accepted? "accept" : "ignore");
HashMap<String, Object> dict = new HashMap<String, Object>();
dict.put( "invitorPersonId", invitorId );
dict.put( "theMode", cloudKode );
Toast.makeText(State.mainContext, "contacting...", Toast.LENGTH_SHORT).show();
ParseCloud.callFunctionInBackground(
"clientRequestHandleInvite",
dict,
new FunctionCallback<Object>()
{
#Override
public void done(Object s, ParseException e)
{
Toast.makeText(State.mainContext, "blah", Toast.LENGTH_SHORT).show();
// be careful with handling the exception on return...
}
});
}
And here's the same cloud call from iOS ... well for now, until you have to do it in SWIFT
-(void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
int thisRow = indexPath.row;
PFUser *delFriend = [self.theFriends objectAtIndex:thisRow];
NSLog(#"you wish to delete .. %#", [delFriend fullName] );
// note, this cloud call is happily is set and forget
// there's no return either way. life's like that sometimes
[PFCloud callFunctionInBackground:#"clientRequestFriendRemove"
withParameters:#{
#"removeThisFriendId":delFriend.objectId
}
block:^(NSString *serverResult, NSError *error)
{
if (!error)
{
NSLog(#"ok, Return (string) %#", serverResult);
}
}];
[self back]; // that simple
}
Note For the iOS/Swift experience, click to: How to make this Parse.com cloud code call? which includes comments from the Parse.com team. Hope it saves someone some typing, cheers