I'm trying to implement a push notification app created with Cordava 3.3 using this: https://github.com/phonegap-build/PushPlugin ; Basing me in this tutorial: www.androidhive.info/2012/10/android-push-notifications-using-google-cloud-messaging-gcm-php-and-mysql
But I have 2 basic problems the first is that the notification does not lead if the app is in background or is closed and the second is that the message reaches Undefined when the app is open in the foreground, could help, as far as I was reading may be due the format of the JSON response or parameters sent in the same.
Here is my code not take long:
https://github.com/jedidas/Push
I achieved a solution that is on file with the plugin "GCMIntentService.java" near line 80 is the next instruction
else {
extras.putBoolean("foreground", false);
// Send a notification if there is a message
if (extras.getString("message") != null && extras.getString("message").length() != 0) {
createNotification(context, extras);
}
}
discover you can change the "price" for what you want, for example change the "price" for "message" and everything was solved milagorsamente, explain:
we have this:
. 1 $ message = array ("deprive" => $ message);
and read when I read it as:
1. E.payload.message
gives us comes as undefined because payload.price.
In this sense, we have to file in the JAVA plugin
if (extras.getString ("message")! = null && extras.getString ("message"). length ()! = 0) {
createNotification (context, options);
}
if that does not run because it is coming as "price" instead of "message". everything is solved when I change the "price" of SEND_MESSAGE.PHP for "message." thus not even need to modify the JAVA.
Related
I have a great headache.
I have a running 'web-app', writed whith Rails4, in production hosted on a Google Compute Engine virtual machine with Ubuntu 14.04, where I use Rpush gem/Firebase for notification to an Android app 'my-app'.
Locally I use a similar configuration for development: an environment rvm with same Rails version.
Simultaneously, with AndroidStudio, I'm developing 'my-app' android app.
On Ubuntu 16.04.
When Rails/Rpush send a notification, I receive it on 'my-app'.
So I controls both sides of notification process (except Firebase as middle tier).
Great.
It worked fine until some days ago.
Production enviroment continues to working well.
Locally, on development, when 'web-app' send a notification (through RPush/Firebase) I don't receive any kind of message, but I receive it in production, on 'released-version' of 'my-app' !!!
Normally, working local, when 'local' 'web-app' send notification, 'local' 'my-app' receive it;
in production, when 'host' 'we-app' send notification, 'released-version' of 'my-app' receive it.
For a few days is like if, in Firebase, in middle tier, each notification is broadcasted through 'released-version' of 'my-app', also if came from 'local' debug environment !!
Same releases for both envs.
It worked well until a few days ago.
Surely I've touched somethings ... the project is in progess.
I've much debugged, I've controlled many times configurations (local, host and Firebase) read many logs without results.
Everything seems working well !!
Someone know some ways to show me how debugging/understand this mysterious (for me) behavior ?
In Rails, when a message is saved, is triggered a method to push notification as described in GitHub by RPush repository.
In Android, in class 'MyFirebaseMessagingService extends FirebaseMessagingService', on overrided method 'onMessageReceived(RemoteMessage remoteMessage)' I receive messages (notification or data) - following 'quickstart-android/messaging' example.
In Firebase I have a project where I take 'Server Key' and 'google-services.json'.
My headache is growing.
Any advice is welcome.
UPDATE 20180326
I upgrade my question with code executed when sending message, configuration and an extract of rpush log (Rails server side - both local and hosted).
Rails method triggered after save 'Message'
def notify_gcm(data)
if Rpush::Gcm::App.find_by_name(<firebase_app>).nil?
app = Rpush::Gcm::App.new
app.name = <firebase_app>
app.auth_key = <firebase-server_key>
app.connections = 1
app.save!
end
n = Rpush::Gcm::Notification.new
n.app = Rpush::Gcm::App.find_by_name(<firebase_app>)
n.delay_while_idle = true
n.registration_ids = [<device_token>, ...]
n.priority = 'high'
n.content_available = true
# notification type: DATA MESSAGE
n.data = { data: { message: data[:message]["content"] }, notificationdata: { body: ..., title: ..., icon: ... }
}
n.save!
Rpush.push
end
config/initializers/rpush
Rpush.configure do |config|
config.client = :active_record
config.push_poll = 5
config.batch_size = 100
config.pid_file = 'tmp/rpush.pid'
config.log_file = 'log/rpush.log'
config.log_level = (defined?(Rails) && Rails.logger) ? Rails.logger.level : ::Logger::Severity::ERROR
end
Rpush log
BEGIN
INSERT INTO `rpush_notifications` (`type`, `app_id`, `delay_while_idle`, `registration_ids`, `priority`, `content_available`, `data`, `created_at`, `updated_at`) VALUES (...)
COMMIT
SELECT `rpush_apps`.* FROM `rpush_apps`[<firebase_app>] Starting 1 dispatcher...
SELECT COUNT(*) FROM `rpush_notifications` WHERE (processing = 0 AND delivered = 0 AND failed = 0 AND (deliver_after IS NULL OR deliver_after < '2018-03-25 10:27:22.719515'))
BEGIN
SELECT `rpush_notifications`.* FROM `rpush_notifications` WHERE (processing = 0 AND delivered = 0 AND failed = 0 AND (deliver_after IS NULL OR deliver_after < '2018-03-25 10:27:22.720521')) ORDER BY created_at ASC LIMIT 100 FOR UPDATE
UPDATE `rpush_notifications` SET processing = 1 WHERE rpush_notifications`.`id` = 210
COMMIT
SELECT COUNT(*) FROM `rpush_notifications` WHERE (processing = 0 AND delivered = 0 AND failed = 0 AND (deliver_after IS NULL OR deliver_after < '2018-03-25 10:27:22.774452'))
SELECT `rpush_apps`.* FROM `rpush_apps` WHERE `rpush_apps`.`id` = 1 LIMIT 1
[<firebase_app>] 210 sent to ... <proper registration_ids>
Rpush is started as a daemon by commandline:
rpush start -e production
SOLVED
Gemfile
removed gem 'rails_12factor', group :production
this it was been previously removed to hosted (production) :(
I am trying to implement OneSignal Corna SDK for receiving PUSH NOTIFICATIONS,
But it is giving me a runtime error
stack traceback:
/Users/ojussave/Library/Application Support/Corona/Simulator/Plugins/plugin_OneSignal.lua:49: in function 'Init'
main.lua:52: in main chunk
This error means that there was likely a syntax error in your code. Make sure you have formatted the call to the OneSignal init method correctly, like so:
-- This function gets called when the user opens a notification or one is received when the app is open and active.
-- Change the code below to fit your apps needs.
function DidReceiveRemoteNotification(message, additionalData, isActive)
if (additionalData) then
if (additionalData.discount) then
native.showAlert( "Discount!", message, { "OK" } )
-- Take user to your app store
elseif (additionalData.actionSelected) then -- Interactive notification button pressed
native.showAlert("Button Pressed!", "ButtonID:" .. additionalData.actionSelected, { "OK"} )
end
else
native.showAlert("OneSignal Message", message, { "OK" } )
end
end
local OneSignal = require("plugin.OneSignal")
-- Uncomment SetLogLevel to debug issues.
-- OneSignal.SetLogLevel(4, 4)
OneSignal.Init("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "############", DidReceiveRemoteNotification)
Katzer Local notification plugin
I can set and use single notification.
According to the description mutiple notification can be set using
cordova.plugins.notification.local.schedule([{
id: 1,
text: "Multi Notification 1",
sound: isAndroid ? 'file://sound.mp3' : 'file://beep.caf',
data: { secret:key }
},{
id: 2,
title: "Local Notification Example",
text: "Multi Notification 2",
icon: "http://sciactive.com/pnotify/includes/github-icon.png"
}]);
But my notifications are dynamic and it's total number is also dynamic. For example say total is the variable where total number of notification is saved. total can be 1 or 10 or 30 etc.
Now how to build the array for it?? I tried like this
for(i=0;i<total;i++)
{
// ......... calculate bhhour,vmin,vsec etc. ............. //
time_for_noti=new Date(year,month-1,parseInt(i),vhour,vmin,vsec);
arr[i]=' id: app_'+i+' , title: ' +i+' - '+time_for_noti+',text: app alarm.,sound: null,at : '+time_for_noti+' ';
}
And then
cordova.plugins.notification.local.schedule(arr);
App hangs for some time say 15-20 sec, then crashes. Then I tried brackets '{}' before and after the strings.
for(i=0;i<total;i++)
{
// ......... calculate bhhour,vmin,vsec etc. ............. //
time_for_noti=new Date(year,month-1,parseInt(i),vhour,vmin,vsec);
arr[i]='{ id: app_'+i+' , title: ' +i+' - '+time_for_noti+',text: app alarm.,sound: null,at : '+time_for_noti+' }';
}
Again same result. App crashes after 10-15 sec from schedule line's execution. I also tried making a huge string manually something like
ex='[{ id:........} , {..........}]';
And then
cordova.plugins.notification.local.schedule(ex);
It crashes the app immediately after this line's execution. I know it's a dumb idea, but desperate times.
What I'm doing wrong? How to achive this multiple alarm dynamically for total 20-40 notification? What I'm missing?
I think each element in the array needs to be an object, not a string. Have you tried something like this?
arr[i]={ id: i, text: "Multi Notification " + i };
That is, replace the quote marks around your object with curly brackets.
I can't try it myself because I'm using the Meteor version which doesn't seem to work the same way.
no need to add multiple notification.
I've looped the sound of 1 notification until user clicks on it.
and to give more alarm like feature I bring the app to foreground when notification is triggered.
have a look at https://github.com/vasani-arpit/cordova-plugin-local-notifications/blob/master/README.md. it is forked from Katzer Local notification plugin so all the syntax is the same.
Here is my solution and it works well :
var notiflist = [];
for(var i = 0; i < data.length; i++) {
notiflist[i] = { id: i, title: data[i].Title, text: data[i].TextPush };
}
cordova.plugins.notification.local.schedule(notiflist);
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
I am trying to make GCM push notifications work in my app and therefore I am using this project (https://github.com/marknutter/GCM-Cordova) as an example.
When I run the example code everything works fine, but when I transfer all the required files and edit my code to let it work in my own app it does not work anymore.
I also tried the following plugin (https://github.com/phonegap-build/PushPlugin) and after installing it automatically it gives exactly the same error.
The app does not crash, but when I call the register function my callback function "onNotificationGCM" does not receive any messages back.
Register function:
window.plugins.GCM.register("my_gcm_id", "onNotificationGCM", successHandler, errorHandler );
After some debugging I figured out that the native android code is able to register the phone and does indeed get an ID message from the GCM server, but that it is unable to send this to my javascript.
Native android code:
public static void sendJavascript( JSONObject _json )
{
String _d = "javascript:"+gECB+"(" + _json.toString() + ")";
Log.v(ME + ":sendJavascript", _d);
if (gECB != null ) {
gwebView.sendJavascript( _d );
}
}
LogCat gives the following 'failed' message:
03-24 17:05:21.844: V/GCMPlugin:sendJavascript(31782): javascript:onNotificationGCM({"regid":"APA91bHX...31ASD","event":"registered"})
03-24 17:05:22.834: D/CordovaLog(31782): processMessage failed: Message: Jjavascript:onNotificationGCM({"regid":"APA91bHX...31ASD","event":"registered"})
The capital J in front of the message is strange and maybe that is what causes the problem, but it seems to be happening somewhere in the Cordova 2.5.0 code.
Does anyone have any idea how I can solve this?
Try to add
window.onNotificationGCM = onNotificationGCM;
to change the context of your function
It solve the problem for me
I had the same problem. After some debugging as I understood I had an unwanted new line character "\n" at the end of my string that I wasn't responsible for and it seems that phone gap added the character. So what I did was to .replace("\n", "") the string on the Java part of the code.
String js = "javascript:displayTextMessage('" + date.toString() + " - " + msg.replace("\n", "") + "');" ;
sendJavascript(js);
This is not an Cordova 2.5.0 Bug! If you copy and paste from the "CORDOVA_GCM_script.js" example, you will have something like this:
case 'registered':
// the definition of the e variable is json return defined in GCMReceiver.java
// In my case on registered I have EVENT and REGID defined
gApp.gcmregid = e.regid;
if ( gApp.gcmregid.length > 0 )
{
$("#app-status-ul").append('<li>REGISTERED -> REGID:' + e.regid + "</li>");
// ==============================================================================
// ==============================================================================
// ==============================================================================
//
// This is where you would code to send the REGID to your server for this device
//
// ==============================================================================
// ==============================================================================
// ==============================================================================
}
break
Make sure the "gApp" Array and the "gcmregedit" variable is declared in your script, or just don't use them in your eventhandler. Otherwise you'll get an "processMessage failed"-Message because of the "undefined"-error occuring before.
Check your code for any incorrect JSON.parse's... these "illegal access" etc. error messages seem to be thrown when JSON.parse(not_a_json_string) happens.