Push notification targeting specific devices

I am trying to send a push notification to a specific Android device. I set up the Backendless and Google Developer consoles as described here: http://backendless.com/documentation/messaging/android/messaging_push_notification_setup_androi.htm

and followed the documentation to register the device and create the push messages.
However, the push messages are not received.
I downloaded the Sample Chat code and it works perfectly. However, I don’t understand its logic very well so that I could implement it in my project.
This is an excerpt from my manifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 package="com.victor.test" >



 &lt;uses-permission android:name=&quot;android.permission.WRITE_EXTERNAL_STORAGE&quot; /&gt;
 &lt;uses-permission android:name=&quot;android.permission.INTERNET&quot; /&gt;
 &lt;uses-permission android:name=&quot;android.permission.ACCESS_NETWORK_STATE&quot; /&gt;
 &lt;uses-permission android:name=&quot;android.permission.GET_ACCOUNTS&quot; /&gt;
 &lt;uses-permission android:name=&quot;android.permission.WAKE_LOCK&quot; /&gt;
 &lt;uses-permission android:name=&quot;com.google.android.c2dm.permission.RECEIVE&quot; /&gt;
 &lt;uses-permission android:name=&quot;com.victor.test.permission.C2D_MESSAGE&quot; /&gt;



 <permission
 android:name="com.victor.sexytalk.sexytalk.permission.C2D_MESSAGE"
 android:protectionLevel="signature" />






 <application
 android:name=".Test"
 android:allowBackup="true"
 android:icon="@drawable/ic_launcher"
 android:label="@string/app_name"
 android:theme="@style/AppTheme" >



 <activity
 android:name=".Main"
 android:label="@string/app_name" >
 &lt;intent-filter&gt;
 <action android:name="android.intent.action.MAIN" />



 &lt;category android:name=&quot;android.intent.category.LAUNCHER&quot; /&gt;
 &lt;/intent-filter&gt;
 </activity>
 
 <receiver
 android:name=".PushReceiver"
 android:permission="com.google.android.c2dm.permission.SEND" >
 &lt;intent-filter&gt;
 <action android:name="com.google.android.c2dm.intent.RECEIVE" />
 <action android:name="com.google.android.c2dm.intent.REGISTRATION" />



 &lt;category android:name=&quot;com.victor.test&quot; /&gt;
 &lt;/intent-filter&gt;
 &lt;/receiver&gt;












 &lt;service android:name=&quot;com.backendless.AndroidService&quot; /&gt;



 </application>



&lt;/manifest&gt;

This is my custom push receiver:

public class PushReceiver extends BackendlessBroadcastReceiver
{
 @Override
 public boolean onMessage( Context context, Intent intent )
 {
 CharSequence tickerText = intent.getStringExtra( PublishOptions.ANDROID_TICKER_TEXT_TAG );
 CharSequence contentTitle = intent.getStringExtra( PublishOptions.ANDROID_CONTENT_TITLE_TAG );
 CharSequence contentText = intent.getStringExtra( PublishOptions.ANDROID_CONTENT_TEXT_TAG );
 String subtopic = intent.getStringExtra( "message" );



 if( tickerText != null && tickerText.length() > 0 )
 {
 int appIcon = context.getApplicationInfo().icon;
 if( appIcon == 0 )
 appIcon = android.R.drawable.sym_def_app_icon;



 //Intent notificationIntent = new Intent( context, AcceptChatActivity.class );
 //notificationIntent.putExtra( "subtopic", subtopic );
 //PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);



 NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder( context );
 notificationBuilder.setSmallIcon( appIcon );
 notificationBuilder.setTicker( tickerText );
 notificationBuilder.setWhen( System.currentTimeMillis() );
 notificationBuilder.setContentTitle( contentTitle );
 notificationBuilder.setContentText( contentText );
 notificationBuilder.setAutoCancel( true );
 //notificationBuilder.setContentIntent( contentIntent );



 Notification notification = notificationBuilder.build();



 NotificationManager notificationManager = (NotificationManager) context.getSystemService( Context.NOTIFICATION_SERVICE );
 notificationManager.notify( 0, notification );
 }



 return false;
 }
}
 

This is how I register the device:




 Backendless.Messaging.registerDevice(GCMSenderID, channel, new AsyncCallback&lt;Void&gt;() {
 @Override
 public void handleResponse(Void aVoid) {
 Log.d("Test", "device registered for messaging");
 }



 @Override
 public void handleFault(BackendlessFault backendlessFault) {
 Log.d("Test", "device not registered " + backendlessFault.getMessage());
 }
 });

This is how I send the push message:




 PublishOptions publishOptions = new PublishOptions();
 publishOptions.putHeader( PublishOptions.ANDROID_TICKER_TEXT_TAG, "Backendless" );
 publishOptions.putHeader(PublishOptions.ANDROID_CONTENT_TITLE_TAG, getResources().getString(R.string.app_name));
 publishOptions.putHeader(PublishOptions.ANDROID_CONTENT_TEXT_TAG, "Hi");
 
 DeliveryOptions deliveryOptions = new DeliveryOptions();
deliveryOptions.setPushPolicy(PushPolicyEnum.ONLY);



deliveryOptions.addPushSinglecast( (String) mRecepient.getProperty("deviceId") );



Backendless.Messaging.publish( "this is a private message!", publishOptions, deliveryOptions, new AsyncCallback&lt;MessageStatus&gt;() {
 @Override
 public void handleResponse(MessageStatus messageStatus) {



 }



 @Override
 public void handleFault(BackendlessFault backendlessFault) {
 String error = backendlessFault.getMessage();
 }
 } );

The problem is that the custom receiver is never called. I think the issue has something to do with the device registration as I cannot see the device in the Backendless console under the relevant channel name (There is a channel for each user).
Any help is greatly appreciated!

Hi, Victor,
I see you’re registering the device to some specific channel under the variable named “channel”. But I don’t see you publishing the message to this channel: seems you simply don’t specify the channel and the message goes to “Default” one.
Try using the following signature for message publishing:

public void Backendless.Messaging.publish( String channelName, 
                                          Object message, 
                                          PublishOptions publishOptions, 
                                          DeliveryOptions deliveryOptions, 
                                         AsyncCallback&lt;MessageStatus&gt; responder ) 

Hi Sergey,

Thank you for the reply.

I tried that but it does not work. I don’t think that the device is registered at all as I am not seeing it in the Backendless console in the channel name under “Devices”.

If I execute this code, I can see the device in the console:

 Backendless.Messaging.getRegistrations(new AsyncCallback&lt;DeviceRegistration&gt;() {
 @Override
 public void handleResponse(DeviceRegistration deviceRegistration) {
 String token = deviceRegistration.getDeviceToken();
 List&lt;String&gt; channels = new ArrayList&lt;String&gt;();
 channels.add(channel);
 Calendar c = Calendar.getInstance();
 c.add(Calendar.YEAR, 10);
 Date expiration = c.getTime();
 Backendless.Messaging.registerDeviceOnServer(token,channels,expiration.getTime(),new AsyncCallback&lt;String&gt;() {
 @Override
 public void handleResponse(String s) {
 String st = s;
 Toast.makeText(Main.this,"finally registered",Toast.LENGTH_LONG).show();
 
 }

 @Override
 public void handleFault(BackendlessFault backendlessFault) {

 }
 });
 
 }

 @Override
 public void handleFault(BackendlessFault backendlessFault) {

 }
 });

However, I still do not receive any pushes. no matter whether I send them via the console or the app. The problem is that the PushReceiver class is never called.

Thanks for the help!

I got it working but I still have to run this code to register the device:

Backendless.Messaging.getRegistrations(new AsyncCallback&lt;DeviceRegistration&gt;() {
@Override
public void handleResponse(DeviceRegistration deviceRegistration) {
String token = deviceRegistration.getDeviceToken();
List&lt;String&gt; channels = new ArrayList&lt;String&gt;();
channels.add(channel);
Calendar c = Calendar.getInstance();
c.add(Calendar.YEAR, 10);
Date expiration = c.getTime();
Backendless.Messaging.registerDeviceOnServer(token,channels,expiration.getTime(),new AsyncCallback&lt;String&gt;() {
@Override
public void handleResponse(String s) {
String st = s;
Toast.makeText(Main.this,"finally registered",Toast.LENGTH_LONG).show();
}
@Override
public void handleFault(BackendlessFault backendlessFault) {
}
});
}
@Override
public void handleFault(BackendlessFault backendlessFault) {
}
});

Any idea why this is the case? This is not recommended by the documentation and it basically requires two extra queries that slow down my app.

In addition to that, what is the best way to get the deviceId of a Backendless user? Is it saved as a property automatically after registration of the device?

Thanks
Victor

Hi, Victor,

Are you receiving push notifications now, using your last approach?
Are you sure you was using proper GCMSenderID in your registerDevice() method? It is the project number of your project on Google Developers Console. Also make sure that you’ve set the API key for server applications from the same Google Developers Console in Backendless Console. And make sure you’ve turned on Google Cloud Messaging on Google Developers Console.