I am trying to integrate GCM following steps in the google developers site.
I am getting the token but I am not getting any notification from the server.
I have three services
1.MyGcmListenerService.java
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.google.android.gms.gcm.GcmListenerService;
public class MyGcmListenerService extends GcmListenerService {
private static final String TAG = "MyGcmListenerService";
/**
* Called when message is received.
*
* #param from SenderID of the sender.
* #param data Data bundle containing message data as key/value pairs.
* For Set of keys use data.keySet().
*/
// [START receive_message]
#Override
public void onMessageReceived(String from, Bundle data) {
String message = data.getString("message");
Log.d(TAG, "From: " + from);
Log.d(TAG, "Message: " + message);
// [START_EXCLUDE]
/**
* Production applications would usually process the message here.
* Eg: - Syncing with server.
* - Store message in local database.
* - Update UI.
*/
/**
* In some cases it may be useful to show a notification indicating to the user
* that a message was received.
*/
sendNotification(message);
// [END_EXCLUDE]
}
// [END receive_message]
/**
* Create and show a simple notification containing the received GCM message.
*
* #param message GCM message received.
*/
private void sendNotification(String message) {
Intent intent = new Intent(this, Home.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.uplogo)
.setContentTitle("GCM Message")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0 /* ID of notification */, notificationBuilder.build());
}
}
RegistrationIntentService.java
import android.app.IntentService;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import com.google.android.gms.gcm.GcmPubSub;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.google.android.gms.iid.InstanceID;
import java.io.IOException;
public class RegistrationIntentService extends IntentService {
private static final String TAG = "RegIntentService";
private static final String[] TOPICS = {"global"};
public RegistrationIntentService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
try {
// [START register_for_gcm]
// Initially this call goes out to the network to retrieve the token, subsequent calls
// are local.
// [START get_token]
InstanceID instanceID = InstanceID.getInstance(this);
String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
// [END get_token]
Log.i(TAG, "GCM Registration Token: " + token);
// TODO: Implement this method to send any registration to your app's servers.
sendRegistrationToServer(token);
// Subscribe to topic channels
subscribeTopics(token);
// You should store a boolean that indicates whether the generated token has been
// sent to your server. If the boolean is false, send the token to your server,
// otherwise your server should have already received the token.
sharedPreferences.edit().putBoolean(QuickstartPreferences.SENT_TOKEN_TO_SERVER, true).apply();
// [END register_for_gcm]
} catch (Exception e) {
Log.d(TAG, "Failed to complete token refresh", e);
// If an exception happens while fetching the new token or updating our registration data
// on a third-party server, this ensures that we'll attempt the update at a later time.
sharedPreferences.edit().putBoolean(QuickstartPreferences.SENT_TOKEN_TO_SERVER, false).apply();
}
// Notify UI that registration has completed, so the progress indicator can be hidden.
Intent registrationComplete = new Intent(QuickstartPreferences.REGISTRATION_COMPLETE);
LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
}
/**
* Persist registration to third-party servers.
*
* Modify this method to associate the user's GCM registration token with any server-side account
* maintained by your application.
*
* #param token The new token.
*/
private void sendRegistrationToServer(String token) {
// Add custom implementation, as needed.
}
/**
* Subscribe to any GCM topics of interest, as defined by the TOPICS constant.
*
* #param token GCM token
* #throws IOException if unable to reach the GCM PubSub service
*/
// [START subscribe_topics]
private void subscribeTopics(String token) throws IOException {
GcmPubSub pubSub = GcmPubSub.getInstance(this);
for (String topic : TOPICS) {
pubSub.subscribe(token, "/topics/" + topic, null);
}
}
// [END subscribe_topics]
}
MyInstanceIDListenerService
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
import com.google.android.gms.iid.InstanceID;
import com.google.android.gms.iid.InstanceIDListenerService;
public class MyInstanceIDListenerService extends InstanceIDListenerService {
private static final String TAG = "MyInstanceIDLS";
/**
* Called if InstanceID token is updated. This may occur if the security of
* the previous token had been compromised. This call is initiated by the
* InstanceID provider.
*/
// [START refresh_token]
#Override
public void onTokenRefresh() {
// Fetch updated Instance ID token and notify our app's server of any changes (if applicable).
Intent intent = new Intent(this, RegistrationIntentService.class);
startService(intent);
}
// [END refresh_token]
}
And I am doint this in my splash Screen
SplashScreen.java
mRegistrationBroadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
SharedPreferences sharedPreferences =
PreferenceManager.getDefaultSharedPreferences(context);
boolean sentToken = sharedPreferences
.getBoolean(QuickstartPreferences.SENT_TOKEN_TO_SERVER, false);
if (sentToken) {
Toast.makeText(getApplicationContext(),"token sent",Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(),"token not sent",Toast.LENGTH_LONG).show();
}
}
};
And I have given all the permissions in the manifest.
My Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="app.aguai.medieazy"
android:versionCode="17"
android:versionName="2.0" >
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<permission
android:name="app.aguai.medieazy.permission.MAPS_RECEIVE"
android:protectionLevel="signature" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="app.aguai.medieazy.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="app.aguai.medieazy.permission.C2D_MESSAGE" />
<uses-permission android:name="app.aguai.medieazy.permission.MAPS_RECEIVE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#drawable/uplogo"
android:label="#string/app_name"
android:theme="#style/AppTheme"
tools:replace="android:icon" >
<activity
android:name=".activities.Login"
android:label="#string/title_activity_login" >
</activity>
<activity android:name=".activities.Home" >
</activity>
<activity
android:name=".activities.AddAddress"
android:label="#string/title_activity_add_address"
android:theme="#style/AppTheme2" >
</activity>
<activity
android:name=".activities.UploadPrescription"
android:label="#string/title_activity_upload_prescription"
android:theme="#style/AppTheme2" >
</activity>
<activity
android:name=".activities.OrderMedicines"
android:label="#string/title_activity_order_medicines"
android:theme="#style/AppTheme2" >
</activity>
<activity
android:name=".activities.Pharmacies"
android:label="#string/title_activity_pharmacies" >
</activity>
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="#string/google_maps_key" />
<activity
android:name=".activities.PharmacyDetails"
android:label="#string/title_activity_pharmacy_details"
android:theme="#style/AppTheme2" >
</activity>
<activity
android:name=".activities.SplashScreen"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".activities.ReviewOrder"
android:label="#string/title_activity_review_order"
android:theme="#style/AppTheme2" >
</activity>
<activity
android:name=".activities.FetchMyOrders"
android:label="#string/title_activity_fetch_my_orders" >
</activity>
<activity
android:name=".activities.MyOrders"
android:label="#string/title_activity_my_orders" >
</activity>
<activity
android:name=".activities.FetchMyOrderDetails"
android:label="#string/title_activity_fetch_my_order_details" >
</activity>
<activity
android:name=".activities.OrderDetails"
android:label="#string/title_activity_order_details"
android:theme="#style/AppTheme2" >
</activity>
<activity
android:name=".activities.AddMeasurements"
android:label="#string/title_activity_add_measurements"
android:theme="#style/AppTheme2" >
</activity>
<activity
android:name=".activities.ViewMeasurements"
android:label="#string/title_activity_view_measurements"
android:theme="#style/AppTheme2" >
</activity>
<activity
android:name=".activities.EditProfile2"
android:label="#string/title_activity_edit_profile2"
android:theme="#style/AppTheme2" >
</activity>
<activity
android:name=".activities.CircleOfCare"
android:label="#string/title_activity_circle_of_care"
android:theme="#style/AppTheme2" >
</activity>
<activity
android:name=".activities.Adherence"
android:label="#string/title_activity_adherence"
android:theme="#style/AppTheme2" >
</activity>
<activity
android:name=".activities.Test"
android:label="#string/title_activity_test" >
</activity>
<activity
android:name=".activities.MyMedications"
android:label="#string/title_activity_my_medications"
android:theme="#style/AppTheme2" >
</activity>
<activity
android:name=".activities.AddMedicine"
android:label="#string/title_activity_add_medicine"
android:theme="#style/AppTheme2" >
</activity>
<activity
android:name=".activities.ReminderPopUp"
android:label="#string/title_activity_reminder_pop_up"
android:theme="#style/AppTheme2" >
</activity>
<service
android:name=".models.RemindService"
android:enabled="true" >
<intent-filter>
<action android:name="app.aguai.medieazy.models.START_SERVICE" />
</intent-filter>
</service>
<service
android:name=".models.SnoozeService"
android:enabled="true" >
<intent-filter>
<action android:name="app.aguai.medieazy.models.START_SERVICE" />
</intent-filter>
</service>
<activity
android:name=".activities.SnoozePopUp"
android:label="#string/title_activity_snooze_pop_up" >
</activity>
<activity
android:name=".activities.MedicineDetails"
android:label="#string/title_activity_medicine_details"
android:theme="#style/AppTheme2" >
</activity>
<activity
android:name=".activities.Signup"
android:label="#string/title_activity_signup" >
</activity>
<activity
android:name=".activities.ReorderDetails"
android:label="#string/title_activity_reorder_details"
android:theme="#style/AppTheme2">
</activity>
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
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="app.aguai.medieazy" />
</intent-filter>
</receiver>
<service
android:name="app.aguai.medieazy.GCM.MyGcmListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<!-- [END gcm_listener] -->
<!-- [START instanceId_listener] -->
<service
android:name="app.aguai.medieazy.GCM.MyInstanceIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID"/>
</intent-filter>
</service>
<!-- [END instanceId_listener] -->
<service
android:name="app.aguai.medieazy.GCM.RegistrationIntentService"
android:exported="false">
</service>
</application>
Please help.
I figured it out.
When I tried on other phones, it worked.
Actually, my phone is Jellybean and in pre-kitkat versions, we need to add this line in manifest
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
When I did, it worked.
Related
I have included Firebase Cloud Messaging Service and push notification service in my app by following official documentation. However, when I receive the message my app crash
However, I cannot receive push notification from my server. The error log says below.
Error Message:
Unable to instantiate service com.abc.myapp.MyFirebaseMessagingService: java.lang.ClassNotFoundException: Didn't find class "com.abc.myapp.MyFirebaseMessagingService" on path: DexPathList[[zip file "/data/app/com.abc.myapp-2/base.apk"],nativeLibraryDirectories=[/data/app/com.abc.myapp-2/lib/arm64, /system/lib64, /vendor/lib64]]
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.abc.myapp">
<!-- adding internet permission -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.wifi" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme"
android:usesCleartextTraffic="true">
<service
android:name=".MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<activity android:name=".QRScanner" />
<activity android:name=".ApproveLeaveActivity" />
<activity android:name=".AddLeaveActivity" />
<activity android:name=".LeaveActivity" />
<activity android:name=".CustInParking" />
<activity android:name=".SalaryActivity" />
<activity android:name=".AttendanceActivityDataHandler" />
<activity android:name=".AttendanceActivity" />
<activity
android:name=".LoginActivity"
android:label="#string/title_activity_login"
android:windowSoftInputMode="stateHidden" />
<activity android:name=".SplashActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
</activity>
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="#drawable/ic_stat_name" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="#color/colorAccent" />
<meta-data
android:name="firebase_messaging_auto_init_enabled"
android:value="ture" />
<meta-data
android:name="firebase_analytics_collection_enabled"
android:value="true" />
</application>
</manifest>
MyFirebaseMessagingService:
package com.abc.myapp;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.media.RingtoneManager;
import android.os.IBinder;
import android.util.Log;
import androidx.core.app.NotificationCompat;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.messaging.FirebaseMessaging;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
import static android.content.ContentValues.TAG;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
//showNotification(remoteMessage.getNotification().getBody());
Log.e(TAG, "From: " + remoteMessage.getFrom());
Log.e(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
#Override
public void onNewToken(String token) {
Log.d(TAG, "Refreshed token: " + token);
// If you want to send messages to this application instance or
// manage this apps subscriptions on the server side, send the
// Instance ID token to your app server.
sendRegistrationToServer(token);
}
private void sendRegistrationToServer(String token) {
Log.d("TOKEN ", token);
}
public void showNotification(String message){
PendingIntent pi = PendingIntent.getActivity(this,0, new Intent(this, MainActivity.class),0);
Notification notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_stat_name)
.setContentTitle("Suzuki Islamabad Motors")
.setContentText(message)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentIntent(pi)
.setAutoCancel(true)
.build();
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(0,notification);
}
}
Gradle Dependancies:
apply plugin: 'com.google.gms.google-services'
implementation 'com.google.firebase:firebase-analytics:17.2.2'
implementation 'com.google.firebase:firebase-messaging:20.1.0'
I have just implemented FCM push notification to my webview app, when I run my app on the emulator and send a notification from FCM console, my app will receive the notification when my app running in background. But when I build and apk file and install it on my gadget, the same notification will never receive on my gadget. How to fix this problem?
package com.example.intawebapp.activity;
import android.util.Log;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
public class FirebaseIDService extends FirebaseInstanceIdService {
private static final String TAG = "FirebaseIDService";
#Override
public void onTokenRefresh() {
// Get updated InstanceID token.
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);
// TODO: Implement this method to send any registration to your app's servers.
sendRegistrationToServer(refreshedToken);
}
private void sendRegistrationToServer(String token) {
// Add custom implementation, as needed.
}
}
and
package com.example.intawebapp.activity;
import android.util.Log;
import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = "FCM Service";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// TODO: Handle FCM messages here.
// If the application is in the foreground handle both data and notification messages here.
// Also if you intend on generating your own notifications as a result of a received FCM
// message, here is where that should be initiated.
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());
}
}
and the manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.intawebapp">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity
android:name=".activity.MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
</activity>
<activity
android:name=".activity.SplashActivity"
android:theme="#style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".activity.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service android:name=".activity.FirebaseIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
</application>
</manifest>
My gadget can receive notification now after I put SHA 1 in FCM console
I am getting following error when trying to configure Push Notification:
Failed to resolve target intent service, skipping classname enforcement
Error while delivering the message: ServiceIntent not found.
Manifest:
<manifest package="com.packageName"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> <!-- support previous 4.4 KitKat devices-->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.packageName.permission.C2D_MESSAGE" />
<application
android:name="AppName"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#android:style/Theme.Black.NoTitleBar">
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
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.packageName" />
</intent-filter>
<intent-filter> <!-- support previous 4.4 KitKat devices-->
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.packageName" />
</intent-filter>
</receiver>
<service
android:name="com.packageName.activities.RegistrationIntentService"
android:exported="false" >
</service>
<service
android:name="com.packageName.activities.GcmIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
<service
android:name="com.packageName.activities.MyGcmListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
</application>
MyGcmListenerService:
public class MyGcmListenerService extends GcmListenerService {
#Override
public void onMessageReceived(String from, Bundle data) {
String message = data.getString("message");
Log.d("From", "From: " + from);
Log.d("Msg", "Message: " + message);
}
}
RegistrationIntentService
public class RegistrationIntentService extends IntentService {
private static String SENDER_ID = "MySenderID";
public RegistrationIntentService(){
super(SENDER_ID);
}
#Override
public void onHandleIntent(Intent intent){
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
try {
InstanceID instanceID = InstanceID.getInstance(this);
String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
Log.i("TOKEN", "GCM Registration Token: " + token);
} catch (Exception e) {
Log.d("Fail token", "Failed to complete token refresh", e);
}
}
}
GcmIDListenerService
public class GcmIDListenerService extends InstanceIDListenerService {
#Override
public void onTokenRefresh() {
Intent intent = new Intent(this, RegistrationIntentService.class);
startService(intent);
}
}
I have placed google-services.json in projectName/app
I send push notification from web http://techzog.com/development/gcm-notification-test-tool-android/ and the response is success:1 but it not received in Android device.
I am implementing push notification using GCM.I m getting the token and instance id successfully, the server is also returning success on sending the notification but i m unable to reveive notification on my phone. Please help!!!
Below is my code
Android Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.appname"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- [START gcm_permission] -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- [END gcm_permission] -->
<permission android:name="com.example.appname.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.appname.permission.C2D_MESSAGE" />
<supports-screens
android:anyDensity="true"
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true" />
<application
android:allowBackup="true"
android:icon="#drawable/appicon"
android:label="#string/app_name"
android:theme="#style/Theme.AppCompat.NoActionBar">
<activity
android:name=".Outlet.Activities.SplashActivity"
android:label="#string/app_name"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="gcm_test_app_notification_click_action"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity
android:name=".Outlet.Activities.LoginActivity"
android:screenOrientation="portrait" />
<service
android:name="com.paypal.android.sdk.payments.PayPalService"
android:exported="false" />
<activity android:name="com.paypal.android.sdk.payments.PaymentActivity" />
<activity android:name="com.paypal.android.sdk.payments.LoginActivity" />
<activity android:name="com.paypal.android.sdk.payments.PaymentMethodActivity" />
<activity android:name="com.paypal.android.sdk.payments.PaymentConfirmActivity" />
<activity
android:name="io.card.payment.CardIOActivity"
android:configChanges="keyboardHidden|orientation" />
<activity android:name="io.card.payment.DataEntryActivity" />
<!-- [START gcm_receiver] -->
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
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.example.appname" />
<!--<category android:name="gcm.play.android.samples.com.gcmquickstart" />-->
</intent-filter>
</receiver>
<!-- [END gcm_receiver] -->
<!-- [START gcm_listener] -->
<service
android:name="com.example.appname.CommonFiles.Push.MyGcmListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<!-- [END gcm_listener] -->
<!-- [START instanceId_listener] -->
<service
android:name="com.example.appname.CommonFiles.Push.MyInstanceIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID"/>
</intent-filter>
</service>
<!-- [END instanceId_listener] -->
<service
android:name="com.example.appname.CommonFiles.Push.RegistrationIntentService"
android:exported="false">
</service>
</application>
</manifest>
GCMIntentservice class:-
public class MyGcmListenerService extends GcmListenerService {
private static final String TAG = "MyGcmListenerService";
public static final int MESSAGE_NOTIFICATION_ID = 435345;
/**
* Called when message is received.
*
* #param from SenderID of the sender.
* #param data Data bundle containing message data as key/value pairs.
* For Set of keys use data.keySet().
*/
// [START receive_message]
#Override
public void onMessageReceived(String from, Bundle data) {
String message = data.getString("message");
Log.d(TAG, "From: " + from);
Log.d(TAG, "Message: " + message);
if (from.startsWith("/topics/")) {
// message received from some topic.
} else {
// normal downstream message.
}
// [START_EXCLUDE]
/**
* Production applications would usually process the message here.
* Eg: - Syncing with server.
* - Store message in local database.
* - Update UI.
*/
/**
* In some cases it may be useful to show a notification indicating to the user
* that a message was received.
*/
sendNotification(message);
// [END_EXCLUDE]
}
// [END receive_message]
/**
* Create and show a simple notification containing the received GCM message.
*
* #param message GCM message received.
*/
private void sendNotification(String message) {
Intent intent = new Intent(this, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0 /* Request code */, intent,
PendingIntent.FLAG_ONE_SHOT);
Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("GCM Message")
.setContentText(message)
.setAutoCancel(true)
.setSound(defaultSoundUri)
.setContentIntent(pendingIntent);
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(MESSAGE_NOTIFICATION_ID /* ID of notification */, notificationBuilder.build());
}
}
RegisterIntentService:-
public class RegistrationIntentService extends IntentService {
private static final String TAG = "RegIntentService";
private static final String[] TOPICS = {"global"};
UserSession userSession;
public RegistrationIntentService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
userSession=new UserSession(this);
try {
// [START register_for_gcm]
// Initially this call goes out to the network to retrieve the token, subsequent calls
// are local.
// [START get_token]
InstanceID instanceID = InstanceID.getInstance(this);
// R.string.gcm_defaultSenderId (the Sender ID) is typically derived from google-services.json.
// See https://developers.google.com/cloud-messaging/android/start for details on this file.
String token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),
GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
userSession.saveGCMToken(token);
// [END get_token]
Log.i(TAG, "GCM Registration Token: " + token);
// TODO: Implement this method to send any registration to your app's servers.
sendRegistrationToServer(token);
// Subscribe to topic channels
subscribeTopics(token);
// You should store a boolean that indicates whether the generated token has been
// sent to your server. If the boolean is false, send the token to your server,
// otherwise your server should have already received the token.
sharedPreferences.edit().putBoolean(QuickstartPreferences.SENT_TOKEN_TO_SERVER, true).apply();
// [END register_for_gcm]
} catch (Exception e) {
Log.d(TAG, "Failed to complete token refresh", e);
// If an exception happens while fetching the new token or updating our registration data
// on a third-party server, this ensures that we'll attempt the update at a later time.
sharedPreferences.edit().putBoolean(QuickstartPreferences.SENT_TOKEN_TO_SERVER, false).apply();
}
// Notify UI that registration has completed, so the progress indicator can be hidden.
Intent registrationComplete = new Intent(QuickstartPreferences.REGISTRATION_COMPLETE);
LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
}
/**
* Persist registration to third-party servers.
*
* Modify this method to associate the user's GCM registration token with any server-side account
* maintained by your application.
*
* #param token The new token.
*/
private void sendRegistrationToServer(String token) {
// Add custom implementation, as needed.
GCMHelper gcmHelper = new GCMHelper(this);
gcmHelper.checkRegisterDevice();
}
/**
* Subscribe to any GCM topics of interest, as defined by the TOPICS constant.
*
* #param token GCM token
* #throws IOException if unable to reach the GCM PubSub service
*/
// [START subscribe_topics]
private void subscribeTopics(String token) throws IOException {
GcmPubSub pubSub = GcmPubSub.getInstance(this);
for (String topic : TOPICS) {
pubSub.subscribe(token, "/topics/" + topic, null);
}
}
// [END subscribe_topics]
}
Change the permission like below and check
<!-- Creates a custom permission so only this app can receive its messages. -->
<permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="YOUR_PACKAGE_NAME.permission.C2D_MESSAGE" />
<!-- This app has permission to register and receive data message. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
I have got the soluion to my problem.
Firstly,Corrected these permissions in my app although these do not create problem with new vesrions
<permission
android:name="com.example.appname.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.appname.permission.C2D_MESSAGE" />
Second,The problem was wifi privacy. When I used my company wifi, I coudn't receive message in mobile, since they were blocked GCM server port .
You can use to following links to implement GCM effectively:
https://developers.google.com/cloud-messaging/
https://github.com/codepath/android_guides/wiki/Google-Cloud-Messaging
Happy Coding :)
You have write in manifest
<permission android:name="com.example.gcm.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" />
where com.example is your package name.
But your application package name is com.example.appname
So, you have to write
<permission android:name="com.example.appname.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.appname.permission.C2D_MESSAGE" />
My GCM client is able to register on all versions but messages are received on android above 4.x versions, not on android 2.3.6. I have made many changes but I cannot figure this problem out please help me, thanks in advance.
manifest file code
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.democlientapp"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<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.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="com.democlientapp.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.democlientapp.permission.C2D_MESSAGE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version"/>
<activity android:name="com.google.android.gms.ads.AdActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"/>
<activity
android:name="com.democlientapp.RegisterActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.democlientapp.MainActivity"
android:label="#string/app_name" >
</activity>
<receiver
android:name="com.democlientapp.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.democlientapp" />
</intent-filter>
</receiver>
<service android:name="com.democlientapp.GcmIntentService" />
</application>
</manifest>
GCMBrodcastReceiver.java
package com.democlientapp;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.WakefulBroadcastReceiver;
import android.util.Log;
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("tag", "****************GcmBroadcastReceiver.java ok*************");
// Explicitly specify that GcmIntentService will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(),
GcmIntentService.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
GCMIntentService.java
package com.democlientapp;
import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import com.google.android.gms.gcm.GoogleCloudMessaging;
public class GcmIntentService extends IntentService {
public static int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
String TAG="tag";
SharedPreferences sp;
StringBuffer sb;
public GcmIntentService() {
super("GcmIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.i("tg", "intent sservice******************");
String extras1 = intent.getExtras().getString("data");
//Log.i("tag", "string extras :"+extras1.toString());
Bundle extras=intent.getExtras();
//Log.i("tag", "bundle extras :"+extras);
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
// The getMessageType() intent parameter must be the intent you received
// in your BroadcastReceiver.
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty()) { // has effect of unparcelling Bundle
Log.i("tag", "entered");
/*
* Filter messages based on message type. Since it is likely that GCM
* will be extended in the future with new message types, just ignore
* any message types you're not interested in, or that you don't
* recognize.
*/
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.i(TAG, "Working... " + (i+1)
+ "/5 # " + SystemClock.elapsedRealtime());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
Log.i(TAG, "Completed work # " + SystemClock.elapsedRealtime());
Log.i(TAG, "Received: " + extras.toString());
// Post notification of received message.
sendNotification("Received: " + extras);
}
}
//Log.i(TAG, "Received11111111111111111111");
//sendNotification("Received: registeration "+extras);
// Release the wake lock provided by the WakefulBroadcastReceiver.
//Log.i(TAG, "Received22222222222222222222222");
GcmBroadcastReceiver.completeWakefulIntent(intent);
//Log.i(TAG, "Received3333333333333333");
}
// 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) {
Log.i("tag","GcmBroadcastReceiver.java send notification");
//storing message in shared preference
StoreMsg(msg);
mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle("Spy notification")
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(msg))
.setContentText(msg);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
//mNotificationManager.no
//NOTIFICATION_ID++;
}
public void StoreMsg(String Msg)
{
String name="MyPrefs";
sp = this.getSharedPreferences(name, Context.MODE_PRIVATE);
sb=new StringBuffer();
String mg = sp.getString("MESSAGES", "false");
if (mg.equals("false")) {
//sb.append(mg);
sb.append(Msg);
}
else{
sb.append(mg+"\n****************");
sb.append("\n"+Msg);
}
Log.i("tag", "storemsg is: "+sb);
Editor editor = sp.edit();
editor.putString("MESSAGES",sb.toString());
//Log.i("tag","Gcmintentservice.java,MESSAGES storing SharedPreferences");
editor.commit();
//Log.i("tag", "registeractivity.java, onclick method client username exists in DB");
}
public String getMsg(){
String name="MyPrefs";
sp = this.getSharedPreferences(name, Context.MODE_PRIVATE);
String prefName = sp.getString("MESSAGES", "false");
Log.i("tag", "storemsg is: "+sb);
return prefName;
}
}
If you are using product flavors maybe you have the same problem than I found.
I found that when using flavors with diferent applicationId, then your package in the AndroidManifest file for the permission and the category is not correct.
And this does not matter for Android 5.x, but for Android 2.3 causes that the broadcast receiver will never be called.
The solution I found is use the gradle's placeholder support. Using ${applicationId} the issue is resolved for all the Android versions.
build.gradle:
productFlavors {
prod {
applicationId 'com.democlientapp'
}
dev {
applicationId 'com.democlientapp.dev'
}
}
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.democlientapp"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<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.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="${applicationId}.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version"/>
<activity android:name="com.google.android.gms.ads.AdActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize"/>
<activity
android:name="com.democlientapp.RegisterActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.democlientapp.MainActivity"
android:label="#string/app_name" >
</activity>
<receiver
android:name="com.democlientapp.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="${applicationId}" />
</intent-filter>
</receiver>
<service android:name="com.democlientapp.GcmIntentService" />
</application>
</manifest>
Use Latest dependency/library for GCM for sdk version 4 or heigher
compile "com.google.android.gms:play-services-gcm:10.2.0"
in build.gradle file in dependency.
and add build.gragle level file
classpath 'com.google.gms:google-services:3.0.0'
its works for hiegher versions.