Sony Smartwatch 2 and push notifications - android

Im trying to subscribe the notification+control sample to Google Cloud Messaging in order to recieve push notification directly to the watch.
i have add the permisions:
<permission android:name="com.example.myapp.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.sonymobile.smartconnect.extension.notificationsample.permission.C2D_MESSAGE" />
Added the receiver update and service:
<receiver android:name=".MyReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<!-- Receive the actual message -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.sonymobile.smartconnect.extension.notificationsample" />
</intent-filter>
<!-- Receive the registration id -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.sonymobile.smartconnect.extension.notificationsample" />
</intent-filter>
</receiver>
And implemented the MyReceiver class with methods as in this link
The onReceive method is just called the first time it register. It gives me back the tokenID but neither it recieve the notification nor is called when I activate the sample app.
I've tested the Sender Server with a normal Android app and it sends the notification succesfully
Any hint on sending push notifications to the smartwatch?
Thx!
UPDATE:Now i have move forward in my issue, I've changed the MyReceiver.java to:
public class MyReceiver extends GCMBroadcastReceiver{
#Override
protected String getGCMIntentServiceClassName(Context context)
{
return RemoteNotificationIntentService.class.getName();
}
}
And I have implemented the RemoteNotificationIntentService class:
public class RemoteNotificationIntentService extends GCMBaseIntentService {
public static enum RemoteNotificationFields{
RN_TITLE, RN_BODY, RN_TICKER, RN_SOUND, RN_SMALL_ICON, RN_LARGE_ICON, RN_LED_COLOR_ARGB
};
private static HashMap FIELD_MAP;
private static final String APPLICATION_NAME = "Appverse Bank 4 Sw2";
public RemoteNotificationIntentService(String senderId) {
super(senderId);
System.out.println("init");
// TODO Auto-generated constructor stub
}
public RemoteNotificationIntentService() {
super("PUSH_NOTIFICATION_SERVICE");
// TODO Auto-generated constructor stub
System.out.println("init");
}
private HashMap<String, String> storeIntentExtras(Context context, Intent intent) {
try{
HashMap<String, String> returnValue = new HashMap<String, String>();
HashMap<String, String> JSONSerializable = new HashMap<String, String>();
for(String sFieldName:intent.getExtras().keySet()){
if(FIELD_MAP.containsKey(sFieldName)){
String sFieldType = FIELD_MAP.get(sFieldName);
returnValue.put(sFieldType, intent.getStringExtra(sFieldName));
JSONSerializable.put(sFieldType, intent.getStringExtra(sFieldName));
}else{
JSONSerializable.put(sFieldName, intent.getStringExtra(sFieldName));
}
}
//fill mandatory fields
if(!returnValue.containsKey(RemoteNotificationFields.RN_TITLE.toString())||returnValue.get(RemoteNotificationFields.RN_TITLE.toString()).trim().equals("")){returnValue.put(RemoteNotificationFields.RN_TITLE.toString(), APPLICATION_NAME);}
if(!returnValue.containsKey(RemoteNotificationFields.RN_TICKER.toString())||returnValue.get(RemoteNotificationFields.RN_TICKER.toString()).trim().equals("")){returnValue.put(RemoteNotificationFields.RN_TICKER.toString(), returnValue.get(RemoteNotificationFields.RN_TITLE.toString()));}
if(!returnValue.containsKey(RemoteNotificationFields.RN_SMALL_ICON.toString())||returnValue.get(RemoteNotificationFields.RN_SMALL_ICON.toString()).trim().equals("")){returnValue.put(RemoteNotificationFields.RN_SMALL_ICON.toString(), "icon");}
if(!returnValue.containsKey(RemoteNotificationFields.RN_LED_COLOR_ARGB.toString())||returnValue.get(RemoteNotificationFields.RN_LED_COLOR_ARGB.toString()).trim().equals("")){returnValue.put(RemoteNotificationFields.RN_LED_COLOR_ARGB.toString(), String.valueOf(Color.BLUE));}
JSONSerializable = null;
return returnValue;
}catch(Exception ex){}
return null;
}
#Override
protected void onMessage(Context context, Intent intent) {
try{
System.out.println("message!!!");
}catch(Exception ex){/*CANNOT LOG CAUSE CALLING LOGGER WILL PROMPT NULL POINTER EXCEPTION*/}
}
#Override
protected void onRegistered(Context context, String registrationId) {
try{
System.out.println("Register K");
}catch(Exception ex){
System.out.println("onRegistered "+ex.getMessage());
}
}
#Override
protected void onUnregistered(Context context, String registrationId) {
try{
System.out.println("Unregister K");
} catch(Exception ex){
System.out.println("onUnregistered "+ex.getMessage());
}
}
#Override
protected void onError(Context context, String error) {
System.out.println("error");
}
}
but it doesnt enter in any method this method and i get this message:
V/GCMBroadcastReceiver(4052): onReceive: com.google.android.c2dm.intent.RECEIVE
V/GCMBroadcastReceiver(4052): GCM IntentService class: com.sonymobile.smartconnect.extension.notificationsample.RemoteNotificationIntentService
V/GCMBaseIntentService(1825): Acquiring wakelock
UPDATE 2
I finnally achieve to get the data in my class, I need to add the service to the manifest

In your normal Android app are you able to receive the C2DM messages successfully? Receiving C2DM notifications should be the same whether you are creating a standard Android app or a Control extension for SW2. The only difference is that for the SW2 after you receive the C2DM notification you then add it to the Content Provider for SW2 to push the notification from your phone to the watch.

Related

Can't figure out why NotificationListenerService isn't working

public class ReadNotifications extends NotificationListenerService {
Context context;
#Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
#Override
public void onNotificationPosted(StatusBarNotification sbn) {
for (StatusBarNotification sbm : ReadNotifications.this.getActiveNotifications()) {
String title = sbm.getNotification().extras.getString("android.title");
String text = sbm.getNotification().extras.getString("android.text");
String package_name = sbm.getPackageName();
Log.v("Notification title is:", title);
Log.v("Notification text is:", text);
Log.v("Package Name is:", package_name);
}
}
}
<service android:name=".ReadNotifications"
android:label="#string/app_name"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
Previously I was able to get NotificationListenerService to work, but now I can't figure out why it isn't working. I've tried running it as it is, trying to start the service from the main activity, creating notifications from the same app, sending notifications from another app, changing emulators, but no logs are being sent.
You should grant the special permission in the android settings, you can open them like this (requires API level 22):
if (!NotificationManagerCompat.getEnabledListenerPackages(this).contains(getPackageName())) {
startActivity(new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));
}

How can I get the MobileFirst Foundation SDK to ignore Push Notifications sent by sources other than MobileFirst?

The MobileFirst Foundation SDK push notification receiver doesn't appear to be able to differentiate between notifications coming from MobileFirst and those from other sources.
We are trying to implement push notification in our app such that it can receive notifications from multiple sources. But what we've observed is that, while other cloud push providers' SDKs on process push notifications sources from that provider, the MobileFirst SDK processes all push notifications received by the device. This causes notifications sent from the cloud providers to be displayed twice on the device.
Some additional details:
This seems true regardless of the 3rd party cloud provider. We've tried 5 and all ignore MobileFirst notifications, however MobileFirst processes notifications from all of them.
GCM sender ID is the same for MobileFirst as for the other providers.
We are building native Android and iOS applications.
MobileFirst does not support this functionality out of the box, however because the other push services don't use the MobileFirst adapter used to send notifications via MobileFirst, the key is to add a property to the notification payload that can tell the device whether or not to show the notification.
So for instance, one solution would be to add a custom property in the adapter with the value "mfp" to the payload like this:
notification = WL.Server.createDefaultNotification(notificationText,
badgeDigit, {custom:"mfpush"});
Then in MyListener.java in the Android native code, add an "if" statement in the onReceive() function. This will handle the case when the application is running in the foreground:
public void onReceive(String props, String payload) {
JSONObject jsonObject;
JSONObject payloadJSON;
String notification = "";
String payloadNotif = "";
try {
// get payload from MFP adapter: custom property
payloadJSON = new JSONObject(payload);
payloadNotif = payloadJSON.getString("custom");
// if the payload "custom" property is "mfp", show the alert,
// if not, don't show the alert
if (payloadNotif.contains("mfp")) {
jsonObject = new JSONObject(props);
notification = jsonObject.getString("alert");
}else{
return;
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
MainActivity.alertMsg("Notification", notification);
}
In the case where the application is running in the background, a new class needs to be created that extends com.worklight.wlclient.push.WLBroadcastReceiver and overrides the receive method. Create a CustomBroadcastReceiver class that extends WLBroadCastReceiver and overrides the onReceive method to call CustomGCMIntentService
public class CustomBroadcastReceiver extends WLBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
intent.setClassName(context,
CustomGCMIntentService.class.getName());
WakefulIntentService.sendWakefulWork(context, intent); } }
Then in CustomGCMIntentService, extend the MFP GCMIntentService class and override the two notify methods to check of the push came from MFP:
package com.sample.eventsourcenotificationsandroid.custom;
import android.content.Context;
import android.content.Intent;
import com.worklight.wlclient.push.GCMIntentService;
import org.json.JSONObject;
public class CustomGCMIntentService extends GCMIntentService {
#Override
public void notify(Context context, String tickerText) {
super.notify(context, tickerText);
}
#Override
public void notify(Context context, String alert, int badge, String
sound, Intent intent) {
if(isMobileFirstNotification(intent)) {
super.notify(context, alert, badge, sound, intent);
} }
#Override
public void notify(Context context, Message message, Intent intent) {
if(isMobileFirstNotification(intent)) {
super.notify(context, message, intent);
} }
private boolean isMobileFirstNotification(Intent intent) {
Message message = intent.getParcelableExtra("message");
JSONObject payload = message.getPayload();
return payload.optBoolean("mfpush", false);
} }
The way you're checking for notifications from MFP is by checking that the mfppush key as a value of true in the notification payload.
data: {
badge: "",
alert: "YourMessageContent",
sound: "your sound",
payload:{
mfpush: true
} }
Lastly, the manifest needs to be updated to use the new class instead of com.worklight.wlclient.push.WLBroadcastReceiver as follows:
<service android:name="com.worklight.wlclient.push.GCMIntentService" />
<receiver android:name="com.worklight.wlclient.push.WLBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<!-- removed intent-filter for com.google.android.c2dm.intent.RECEIVE
-->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.sample.eventsourcenotificationsandroid" />
</intent-filter>
</receiver>
<!-- start custom service and receiver -->
<service android:name="com.sample.eventsourcenotificationsandroid.custom.
CustomGCMIntentService" />
<receiver android:name="com.sample.eventsourcenotificationsandroid.custom.CustomB roadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.sample.eventsourcenotificationsandroid" />
</intent-filter>
</receiver>
<!-- end custom service and receiver -->

Include GCM Push Notification into my app

I want to send a notification to the user when a task is assigned (i.e on a button click). When a task is assigned to the user I change some values in my server(i.e i'm performing a post method) I would like to know how to achieve this.
I have reached till registering the user when he logs in to my app & i'm storing users token id into my server I have also gone through google developers guide and have registered my app and obtained senderid and serverapikey. I will post the code till where I have reached please help me on how to proceed further.
LoginActivity
private void checkUserRegistrationToken() {
String url = URLMap.getGcmtokenUrl("gcmtoken_url");
employeeId = LoggedInUserStore.getLoggedInEmployeeId(getApplicationContext());
companyId = LoggedInUserStore.getLoggedInCompanyId(getApplicationContext());
url = url.replace("{eid}", employeeId).replace("{cid}", companyId);
final StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jObj = new JSONObject(response);
tokenId = jObj.getString("TokenId");
if (tokenId.equals("null")) {
registerInBackground();
}
} catch (JSONException e) {
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println("Error===" + error.toString());
}
});
request.setRetryPolicy(new VolleyRetryPolicy().getRetryPolicy());
RequestQueue queue = ((VolleyRequestQueue) getApplication()).getRequestQueue();
queue.add(request);
}
private void registerInBackground() {
new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
String msg = "";
try {
if (gcmObj == null) {
gcmObj = GoogleCloudMessaging.getInstance(LoginActivity.this);
}
tokenId = gcmObj.register(String.valueOf(R.string.gcm_defaultSenderId));
msg = "Registration ID:" + tokenId;
if (new ServiceManager(getApplicationContext()).isNetworkAvailable() && checkPlayServices()) {
String storeUrl = URLMap.getGcmtokenPostUrl();
employeeId = LoggedInUserStore.getLoggedInEmployeeId(getApplicationContext());
companyId = LoggedInUserStore.getLoggedInCompanyId(getApplicationContext());
HashMap<String, String> map = new HashMap<String, String>();
map.put("EmployeeId", employeeId);
map.put("CompanyId", companyId);
map.put("TokenId", tokenId);
JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, storeUrl, new JSONObject(map), new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.i(TAG, "Token has been posted in server!");
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.i(TAG, "Error posting token into server!!");
}
});
request.setRetryPolicy(new VolleyRetryPolicy().getRetryPolicy());
RequestQueue queue = ((VolleyRequestQueue) getApplication()).getRequestQueue();
queue.add(request);
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Token Mesage=" + msg);
return msg;
}
#Override
protected void onPostExecute(String s) {
}
}.execute();
}
As you can see that I'm storing token id of user into my server.
Now I have also created a GcmBroadcastReceiver class
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
ComponentName comp = new ComponentName(context.getPackageName(),
NotificationService.class.getName());
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
and I have also created a NotificationService class which has on MessageReceived method
public class NotificationService extends GcmListenerService {
public static final int notifyID = 9001;
public static final String appname = "FM Ninja";
NotificationCompat.Builder builder;
public NotificationService() {
// super("GcmIntentService");
}
#Override
public void onMessageReceived(String from, Bundle data) {
Intent resultIntent = null;
PendingIntent resultPendingIntent;
resultIntent = new Intent(this, HomeActivity.class);
resultPendingIntent = PendingIntent.getActivity(this, 0,
resultIntent, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Builder mNotifyBuilder;
NotificationManager mNotificationManager;
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotifyBuilder = new NotificationCompat.Builder(this)
.setContentTitle("title")
.setTicker("New Message !")
.setContentText("first message please")
.setSmallIcon(R.mipmap.cms_launch_icon);
// Set pending intent
mNotifyBuilder.setContentIntent(resultPendingIntent);
// Set Vibrate, Sound and Light
int defaults = 0;
defaults = defaults | Notification.DEFAULT_LIGHTS;
defaults = defaults | Notification.DEFAULT_VIBRATE;
defaults = defaults | Notification.DEFAULT_SOUND;
mNotifyBuilder.setDefaults(defaults);
mNotifyBuilder.setAutoCancel(true);
// Post a notification
mNotificationManager.notify(notifyID, mNotifyBuilder.build());
}
}
The problem is even after adding permission in Manifeast when a call is made from server onMessageReceived is never getting executed Please help me.
I will also post manifeast file
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!--GCM Permissions-->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="com.google.android.c2dm.permission.SEND"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<permission android:name="com.six30labs.cms.permission.C2D_MESSAGE"
android:protectionLevel="signature"/>
<uses-permission android:name="com.six30labs.cms.permission.C2D_MESSAGE" />
<application
android:name="com.six30labs.cms.general.VolleyRequestQueue"
android:allowBackup="true"
android:icon="#mipmap/cms_launch_icon"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".SplashScreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity android:name=".LoginActivity" />
<activity android:name=".ForgotPassword" />
<activity android:name=".NoInternet" />
<activity android:name=".HomeActivity"/>
<activity android:name=".ComplaintDetailsSupervisor" />
<activity android:name=".ComplaintDetailsEmployee" />
<activity android:name=".NavBarProfile" />
<activity android:name=".ComplaintDetailsWorker" />
<activity android:name=".AssignedDetailSupervisor" />
<activity android:name=".AcceptedComplaintDetailsWorker" />
<activity android:name=".VerifyDetailSupervisor"/>
<activity android:name=".ManagerComplaintListActivity"/>
<!--<service android:name="com.six30labs.cms.storage.RegistrationIntentService"
android:exported="false"/>-->
<receiver
android:name="com.six30labs.cms.general.GcmBroadcastReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.six30labs.cms"/>
</intent-filter>
</receiver>
<!-- Register Service -->
<service android:name="com.six30labs.cms.general.NotificationService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
</application>
Server side script
public class GCMNotification
{
private CMSEntities db = new CMSEntities();
static string gcmid = "AIzaSyB7HSIF1RIvkyCnpP6KtYiy6wQ-s6YBscY";
public void AssignEmpNotification(string employeeid)
{
long id = Convert.ToInt64(employeeid);
PushBroker pushBroker = new PushBroker();
pushBroker.RegisterGcmService(new GcmPushChannelSettings(gcmid));
pushBroker.QueueNotification(new GcmNotification().ForDeviceRegistrationId("APA91bGElkVodLyubuMM90TEnfUMab0Fs6JudsjXcgIUrTrT8Zk3GezKYWc9w2gGs6pzLLq_nPSZCXU30M5iYKdRJcKZnkafWuwhnihZQ88vcwUrKhiQn6eWSqGrLCeHFblVT09IR7jy")
.WithJson(#"{""message"":""Hi Hello" + "wsfdasd" + #""",""title"":""title" + "vendorBids" + #""",""Bidsid"":""" + "1" + #""",""Eventdate"":""" + "2/2/2016" + #""",""vendorname"":""" + "name" + #"""}"));
pushBroker.StopAllServices();
}
}
The server needs to send http post request
to "https://android.googleapis.com/gcm/send" along with list of
registration ids and message as body data.
The body data is a combination of :
a. registration ids (which is a list of array)
b. message
The header is a combination of :
a. Content-Type
b. Authorization (key:project id)
List regIds = new ArrayList();
//add regIds to this list : regIds.add("value");
JSONObject data = new JSONObject ();
data.put("registration_ids", regIds);
data.put("Message", "Hello");
ApiKey is the value we received during project created in google store.
Map headers = new HashMap();
headers.put("Content-Type", "application/json");
header.put("Authorization","key=ApiKey");
After sending http post request. The google gcm server will send
the message to all users whose registration id is mentioned in http
request.
The android mobile will receive a notification from gcm server as response
which will be handled by GCMBroadcastReceiver.
Now NotificationService class will be invoked which will extent
IntentService.
In this class ,
#Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty() &&
GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
showNotification(intent.getStringExtra("Message"));
}
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
This method is calling "showNotification" method which has a string
parameter.
Use this message and show in notification using NotificationManager.
Hope this helps :)
Start logging the response that the server is getting after sending the notification payload to google servers. If there is a problem with the device token, you will get a detailed error like "Not Registered".
If the there is no problem in token, google server will respond you with success and message id.
Once you are assured that there is no problem with the device token, then we can think about the issues in the device code.
Other probable issue I can think of is that the SHA hash that you have added in the google developer console is not matching with the SHA hash of the keystore that you have signed the app with.
Add the SHA hash of debug.keystore as well as the production signing keystore.

Android GCMIntentService onMessage issue

I am new to Android. I am trying to send message (GCM) from my server (Java) to android phone. On debugging the server code, I found that the messages are successfully sent to android phones. But I was not able to receive any messages in phone. I tried to have a break-point in onMessage(), but there was no use.
Once after the every message from server, my phone is only getting an alert box something like: "PROJECT is not responding. Would you like to close it?" It has 2 buttons in the alert box: wait and OK.
Can anyone please help me on this. Even though, my server sent messages successfully, Why I was not receiving any messages in phone. My client and server code are as follows:
Server:
public void sendPushNotification(String theRegistrationId, String thePushMsg)
{
//Used to transmit messages to the Google Cloud Messaging service.
Sender aGcmSender = new Sender(API_KEY);
//Constructing message which need to be transmitted to android device.
Message aMessage = new Message.Builder().addData("message", thePushMsg).build();
try
{
Result result = aGcmSender.send(aMessage, theRegistrationId, 1);
}
catch (Exception theException)
{
}
}
Client:
AndroidManifest.xml:
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="15" />
<permission android:name="com.test.app.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.test.app.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<!-- App receives GCM messages. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- GCM requires a Google account. -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.READ_OWNER_DATA" />
<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- Permission to vibrate -->
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.SET_DEBUG_APP"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<application
android:icon="#drawable/icon"
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:name="MyApplication">
<uses-library android:name="com.google.android.maps" />
<activity
android:name=".view.welcome.WelcomeView"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="com.google.android.gcm.GCMBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.test.app" />
</intent-filter>
</receiver>
<service android:name="com.test.app.GCMIntentService" />
</application>
GCMIntentService:
package com.test.app;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import com.google.android.gcm.GCMBaseIntentService;
public class GCMIntentService extends GCMBaseIntentService
{
private static final String TAG = "===GCMIntentService===";
private static String GCM_SENDER_ID = "697532398835"; //Project id in Google API Console
public GCMIntentService()
{
super(GCM_SENDER_ID);
Log.d(TAG, "GCMIntentService init");
}
#Override
protected void onRegistered(Context theContext, String theRegistrationId)
{
Log.i(TAG, "Device registered: regId = " + theRegistrationId);
}
#Override
protected void onUnregistered(Context theContext, String theArg)
{
Log.i(TAG, "unregistered = "+theArg);
}
#Override
protected void onMessage(Context theContext, Intent theIntent)
{
Log.i(TAG, "new message= ");
String aMessage = theIntent.getStringExtra("message");
sendGCMIntent(theContext, aMessage);
}
private void sendGCMIntent(Context theContext, String theMessage)
{
Intent aBroadcastIntent = new Intent();
aBroadcastIntent.setAction("GCM_RECEIVED_ACTION");
aBroadcastIntent.putExtra("gcm", theMessage);
theContext.sendBroadcast(aBroadcastIntent);
}
#Override
protected void onError(Context theContext, String theErrorId)
{
Log.i(TAG, "Received error: " + theErrorId);
}
#Override
protected boolean onRecoverableError(Context theContext, String theErrorId)
{
return super.onRecoverableError(theContext, theErrorId);
}
}
My activity:
package com.test.app.view.welcome;
import java.net.MalformedURLException;
import java.net.URL;
import com.google.android.gcm.GCMRegistrar;
public class LoginView extends Activity implements Runnable {
Typeface itsTypeFace;
IntentFilter gcmFilter;
String broadcastMessage = "No broadcast message";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.login);
gcmFilter = new IntentFilter();
gcmFilter.addAction("GCM_RECEIVED_ACTION");
}
private BroadcastReceiver gcmReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
broadcastMessage = intent.getExtras().getString("gcm");
if (broadcastMessage != null)
{
System.out.println(broadcastMessage);
}
}
};
/**
* Method to avoid back key press for a higher api level 2.0 and above
*/
#Override
public void onBackPressed() {}
/** If the user changes the orientation of his phone, the current activity
is destroyed, and then re-created. This means that our broadcast message
will get wiped out during re-orientation.
So, we save the broad cast message during an onSaveInstanceState()
event, which is called prior to the destruction of the activity.
*/
#Override
public void onSaveInstanceState(Bundle savedInstanceState)
{
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putString("BroadcastMessage", broadcastMessage);
}
/** When an activity is re-created, the os generates an onRestoreInstanceState()
event, passing it a bundle that contains any values that you may have put
in during onSaveInstanceState()
We can use this mechanism to re-display our last broadcast message.
*/
#Override
public void onRestoreInstanceState(Bundle savedInstanceState)
{
super.onRestoreInstanceState(savedInstanceState);
broadcastMessage = savedInstanceState.getString("BroadcastMessage");
}
/** If our activity is paused, it is important to UN-register any
broadcast receivers.
*/
#Override
protected void onPause()
{
unregisterReceiver(gcmReceiver);
super.onPause();
}
/** When an activity is resumed, be sure to register any
broadcast receivers with the appropriate intent
*/
#Override
protected void onResume()
{
super.onResume();
registerReceiver(gcmReceiver, gcmFilter);
}
/**
* The call to GCMRegistrar.onDestroy()
*/
#Override
public void onDestroy()
{
GCMRegistrar.onDestroy(this);
super.onDestroy();
}
}
Can anyone please help me on this issue. Even though, my server sent messages successfully, Why I was not receiving any messages in phone.
I found a solution for this problem. On deploying my application (server side), I found there was some problem with json-simple.jar.
I have upgraded the jar to json-simple-1.1.1.jar and it worked!
And also as NickT suggested, I have updated my canonicalid as follows:
Sender aGcmSender = new Sender(API_KEY);
//Constructing message which need to be transmitted to android device.
Message aMessage = new Message.Builder().addData("message", thePushMsg).build();
Result result = aGcmSender.send(aMessage, REG_ID, 1); //Transmitting message to android device
if(result != null)
{
if(result.getMessageId() != null)
{
String aCanonicalRegistrationId = result.getCanonicalRegistrationId();
if(aCanonicalRegistrationId != null)
{
//Updated my database with aCanonicalRegistrationId (replaced REG_ID)
}
}
else
{
String error = result.getErrorCodeName();
if (error.equals(Constants.ERROR_NOT_REGISTERED)) {
// application has been removed from device - unregister database
}
}
}
}
Thank You.

Android GCM basic implementation

UPDATE: I fixed the problems in the code below so this makes a nice basic working example of how to use GCM
So, I'm trying to implement Android GCM into my app. Here are the relevant parts I've added to the manifest:
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="20" />
<permission
android:name=".permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name=".permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
...
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.badbob.app.gmctestapp" />
</intent-filter>
</receiver>
<service android:name=".GCMIntentService" />
I've added the following code to the onCreate of my main activity:
GCMRegistrar.checkDevice( this );
GCMRegistrar.checkManifest( this );
final String regId = GCMRegistrar.getRegistrationId( this );
if( regId.equals( "" ) ) {
GCMRegistrar.register( this, GCM_SENDER_ID );
}
else {
Log.v( LOG_TAG, "Already registered" );
}
I've also created the GCMIntenetService class like so:
public class GCMIntentService extends GCMBaseIntentService {
private static final String LOG_TAG = "GetAClue::GCMIntentService";
public GCMIntentService() {
super( GCM_SENDER_ID );
// TODO Auto-generated constructor stub
Log.i( LOG_TAG, "GCMIntentService constructor called" );
}
#Override
protected void onError( Context arg0, String errorId ) {
// TODO Auto-generated method stub
Log.i( LOG_TAG, "GCMIntentService onError called: " + errorId );
}
#Override
protected void onMessage( Context arg0, Intent intent ) {
// TODO Auto-generated method stub
Log.i( LOG_TAG, "GCMIntentService onMessage called" );
Log.i( LOG_TAG, "Message is: " + intent.getStringExtra( "message" ) );
}
#Override
protected void onRegistered( Context arg0, String registrationId ) {
// TODO Auto-generated method stub
Log.i( LOG_TAG, "GCMIntentService onRegistered called" );
Log.i( LOG_TAG, "Registration id is: " + registrationId );
}
#Override
protected void onUnregistered( Context arg0, String registrationId ) {
// TODO Auto-generated method stub
Log.i( LOG_TAG, "GCMIntentService onUnregistered called" );
Log.i( LOG_TAG, "Registration id is: " + registrationId );
}
}
When I run this I get this in LogCat:
07-11 11:28:46.340: V/GCMRegistrar(27435): Registering receiver
07-11 11:28:46.370: D/GCMRegistrar(27435): resetting backoff for com.badbob.app.getacluebeta
07-11 11:28:46.380: V/GCMRegistrar(27435): Registering app com.badbob.app.getacluebeta of senders 128205395388
From what I've gleaned from other posts I should get a registration ID in LogCat but I"m not. Also onRegistered() in GCMIntentService never gets called. So what am I doing wrong?
this is incorrect
protected GCMIntentService( String senderId ) {
super(senderId);}
As it states in the documentation. you must declare a PUBLIC, NO ARGUMENT constructor for GCMIntentService. Otherwise the GCMIntentService can't be instantiated properly by background intent services.
public GCMIntentService(){
super(senderID);}
the senderID can be a hard coded constant string because it will no longer change with the new GCM.
It's also very important you use the correct senderID. 24 hours is long enough for yours to be active so if my above solution doesn't work you are using the incorrect senderID. Everything else looks great.
The senderID is in the URL of your web browser when you are browsing the Google API access page. Click on GCM and a 12 digit number will be present in the browser URL. That is the correct key to use. NOT your API key. That is used on the App server side.
I also had this ANNOYing bug, til now. The Problem was, that i declared the intentservice inside another package... even if i declared the name in the android manifest and no classnotfound exception had been place... no error at all could be found... so i made sure the intentservice is in the root package.
I think you have some issues in the code.
You should do the registration of your own broadcast receiver in the manifest file and that receiver will trigger the <service android:name=".GCMIntentService" />.
Therefore you must do something like I write below.
The receiver must be declared like:
<receiver
android:name="your.package.name.YourBroadCastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
</intent-filter>
Your broadcast receiver that will start the service.
public class YourBroadCastReceiver extends BroadcastReceiver {
#Override
public final void onReceive(Context context, Intent intent) {
GCMIntentService .runIntentInService(context, intent);
setResult(Activity.RESULT_OK, null, null);
}
}
I advice you to take a look at the official GCM documentation where you can find a good example.
And... don't forget to enable the Google Cloud Messaging service in the main Google APIs Console page.
Let me know if it helps!
See below tutorial for GCM:-
http://www.androidhive.info/2012/10/android-push-notifications-using-google-cloud-messaging-gcm-php-and-mysql/
Here I have written few steps for How to Get RegID and Notification starting from scratch
Create/Register App on Google Cloud
Setup Cloud SDK with Development
Configure project for GCM
Get Device Registration ID
Send Push Notifications
Receive Push Notifications
You can find complete tutorial in below URL link
Getting Started with Android Push Notification : Latest Google Cloud
Messaging (GCM) - step by step complete tutorial
Code snip to get Registration ID (Device Token for Push Notification).
Configure project for GCM
Update AndroidManifest file
For enable GCM in our project we need to add few permission in our manifest file
Go to AndroidManifest.xml and add below code
Add Permission
<uses-permission android:name="android.permission.INTERNET”/>
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name=“.permission.RECEIVE" />
<uses-permission android:name=“<your_package_name_here>.permission.C2D_MESSAGE" />
<permission android:name=“<your_package_name_here>.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
Add GCM Broadcast Receiver declaration
add GCM Broadcast Receiver declaration in your application tag
<application
<receiver
android:name=".GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" ]]>
<intent-filter]]>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="" />
</intent-filter]]>
</receiver]]>
<application/>
Add GCM Servie declaration
<application
<service android:name=".GcmIntentService" />
<application/>
Get Registration ID (Device Token for Push Notification)
Now Go to your Launch/Splash Activity
Add Constants and Class Variables
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
public static final String EXTRA_MESSAGE = "message";
public static final String PROPERTY_REG_ID = "registration_id";
private static final String PROPERTY_APP_VERSION = "appVersion";
private final static String TAG = "LaunchActivity";
protected String SENDER_ID = "Your_sender_id";
private GoogleCloudMessaging gcm =null;
private String regid = null;
private Context context= null;
Update OnCreate and OnResume methods
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_launch);
context = getApplicationContext();
if (checkPlayServices())
{
gcm = GoogleCloudMessaging.getInstance(this);
regid = getRegistrationId(context);
if (regid.isEmpty())
{
registerInBackground();
}
else
{
Log.d(TAG, "No valid Google Play Services APK found.");
}
}
}
#Override protected void onResume()
{
super.onResume(); checkPlayServices();
}
# Implement GCM Required methods (Add below methods in LaunchActivity)
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
Log.d(TAG, "This device is not supported - Google Play Services.");
finish();
}
return false;
}
return true;
}
private String getRegistrationId(Context context)
{
final SharedPreferences prefs = getGCMPreferences(context);
String registrationId = prefs.getString(PROPERTY_REG_ID, "");
if (registrationId.isEmpty()) {
Log.d(TAG, "Registration ID not found.");
return "";
}
int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
int currentVersion = getAppVersion(context);
if (registeredVersion != currentVersion) {
Log.d(TAG, "App version changed.");
return "";
}
return registrationId;
}
private SharedPreferences getGCMPreferences(Context context)
{
return getSharedPreferences(LaunchActivity.class.getSimpleName(),
Context.MODE_PRIVATE);
}
private static int getAppVersion(Context context)
{
try
{
PackageInfo packageInfo = context.getPackageManager()
.getPackageInfo(context.getPackageName(), 0);
return packageInfo.versionCode;
}
catch (NameNotFoundException e)
{
throw new RuntimeException("Could not get package name: " + e);
}
}
private void registerInBackground()
{ new AsyncTask() {
Override
protected Object doInBackground(Object... params)
{
String msg = "";
try
{
if (gcm == null)
{
gcm = GoogleCloudMessaging.getInstance(context);
}
regid = gcm.register(SENDER_ID); Log.d(TAG, "########################################");
Log.d(TAG, "Current Device's Registration ID is: "+msg);
}
catch (IOException ex)
{
msg = "Error :" + ex.getMessage();
}
return null;
} protected void onPostExecute(Object result)
{ //to do here };
}.execute(null, null, null);
}
Note : please store REGISTRATION_KEY, it is important for sending PN Message to GCM
also keep in mine this will be unique for all device, by using this only GCM will send Push Notification.
Receive Push Notifications
Add GCM Broadcast Receiver Class
As we have already declared “GcmBroadcastReceiver.java” in our Manifest file, So lets create this class
update receiver class code this way
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{ ComponentName comp = new ComponentName(context.getPackageName(),
GcmIntentService.class.getName()); startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
Toast.makeText(context, “wow!! received new push notification", Toast.LENGTH_LONG).show();
}
}
Add GCM Service Class
As we have already declared “GcmBroadcastReceiver.java” in our Manifest file, So lets create this class
update receiver class code this way
public class GcmIntentService extends IntentService
{ public static final int NOTIFICATION_ID = 1; private NotificationManager mNotificationManager; private final static String TAG = "GcmIntentService"; public GcmIntentService() {
super("GcmIntentService");
} #Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
Log.d(TAG, "Notification Data Json :" + extras.getString("message"));
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent); if (!extras.isEmpty()) { if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR
.equals(messageType)) {
sendNotification("Send error: " + extras.toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
.equals(messageType)) {
sendNotification("Deleted messages on server: "
+ extras.toString()); // If it's a regular GCM message, do some work.
} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
.equals(messageType)) {
// This loop represents the service doing some work.
for (int i = 0; i < 5; i++) {
Log.d(TAG," Working... " + (i + 1) + "/5 # "
+ SystemClock.elapsedRealtime()); try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
}
Log.i(TAG, "Completed work # " + SystemClock.elapsedRealtime());
sendNotification(extras.getString("message"));
}
} // Release the wake lock provided by the WakefulBroadcastReceiver.
GcmBroadcastReceiver.completeWakefulIntent(intent);
} // Put the message into a notification and post it.
// This is just one simple example of what you might choose to do with
// a GCM message.
private void sendNotification(String msg) { mNotificationManager = (NotificationManager) this
.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, LaunchActivity.class), 0);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder( this)
.setSmallIcon(R.drawable.icon)
.setContentTitle("Ocutag Snap")
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
.setContentText(msg)
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE);
mBuilder.setContentIntent(contentIntent); mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
}
}
Not sure if this is related to your specific problem, however, I was experiencing the same issue. Everything was setup correctly, as far as I could tell, but the onRegistered() handler was never called.
I had the standard onCreate(), onStart() and onDestroy() service methods as part of my GCMIntentService class. Once I removed them, the handler was called, as expected.
My assumption is that by overriding these methods, I was by-passing needed code initialization.
After reading ClouDeveloper's post I removed onCreate(), onDestroy(), and the other onXXX() callback methods. Also, my GCMIntentService.onRegistered(Context, regId) is called with the regId.
Thank you ClouDeveloper!
You also need to register with your application server in the GCMBaseIntentService.onRegistered() callback. Otherwise you will not be able to send your app messages.
You should really checkout Google's GCM demo client as it provides a working sample with all of the correct code. We also have a working sample up on github: airbop-client. It provides a slightly more complete example given that it has working interactions with an application server, which is necessary for a GCM enabled app. It works with the AirBop servers (which I helped create) which are free up to 1000 devices.
If you are not getting response from the registration, one of the main reason is your manifest file is not configured correctly - especially give the "package_name" (your app package name like com.xxx.yyy) in the <permission> and <intent filter> correctly.

Categories

Resources