I'm developing an app using Quickblox to create a chat with users. I've managed to get push services within the app, even when its in background but, once the app is force closed no push is received.
My android devices are registering on GMC QB services, the token appears and it registers with no problem.
Moreover I've even tried using the Push Admin on Quickblox but Push are not working either.
sourcecode:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<permission
android:name="com.myapp.app.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.myapp.app.permission.C2D_MESSAGE" />
<receiver
android:name="com.quickblox.chat.push.QBGcmBroadcastReceiver"
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.myapp.app" />
</intent-filter>
</receiver>
<service android:name="com.quickblox.chat.push.QBGcmIntentServiceNewVersion"/>
<!-- CUSTOM -->
<service
android:name="com.myapp.app.push.CPInstanceIDListenerService"
android:exported="false">
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
<service
android:name="com.myapp.app.push.CPRegistrationIntentService"
android:exported="false" />
And my BroadcastReceiver:
public class QBGcmBroadcastReceiver extends WakefulBroadcastReceiver {
public static int QBNotificationID = 4444;
#Override
public void onReceive(Context context, Intent intentReceived) {
Log.e(CPApplication.TAG, "QBGcmBroadcastReceiver -> Push RECIBIDA");
Log.e(CPApplication.TAG, "APP is ON ?() -> " + CPApplication.appIsON);
// Explicitly specify that GcmIntentService will handle the intent.
ComponentName comp = new ComponentName(context.getPackageName(), QBGcmIntentServiceNewVersion.class.getName());
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, (intentReceived.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
// App is not running
if (!CPApplication.appIsON) {
// Is New Message Push enabled ?
boolean isPushNewMessage = CPApplication.getSharedPrefs().getBoolean(CPConstants.SP_PUSH_NEW_MESSAGE, true);
// Is the user registered
boolean rememberPassword = CPApplication.getSharedPrefs().getBoolean(CPConstants.SP_REMEMBER_PASSWORD, false);
if (rememberPassword && isPushNewMessage) {
// Notification
NotificationCompat.Builder builder = new NotificationCompat.Builder(CPApplication.getInstance());
builder.setSmallIcon(R.drawable.push_icon)
.setTicker("Nuevo mensaje")
.setAutoCancel(true)
.setContentTitle(CPApplication.getInstance().getString(R.string.app_name))
.setContentText("Tiene un mensaje nuevo");
// Is New Message Sound enabled ?
boolean isSoundNewMessage = CPApplication.getSharedPrefs().getBoolean(CPConstants.SP_SOUND_NEW_MESSAGE, true);
if (isSoundNewMessage) {
builder.setDefaults(Notification.DEFAULT_SOUND);
}
// Intent
Intent intent = new Intent(CPApplication.getInstance(), SplashActivity.class);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(CPApplication.getInstance(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
// Notification
Notification note = builder.build();
// Will show lights and make the notification disappear when the presses it
note.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_SHOW_LIGHTS;
NotificationManager manager = (NotificationManager) CPApplication.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(QBNotificationID, note);
}
}
}
}
I've also created an intent service class:
public class QBGcmIntentServiceNewVersion extends IntentService {
public static int QBNotificationID = 4444;
public QBGcmIntentServiceNewVersion() {
super(QBPushConstants.GCM_INTENT_SERVICE);
}
#Override
protected void onHandleIntent(Intent intentReceived) {
Log.i(CPApplication.TAG, "QBGcmIntentServiceNewVersion :: onHandleIntent");
// App is not running
// if (!CPApplication.appIsON) {
// Is New Message Push enabled ?
boolean isPushNewMessage = CPApplication.getSharedPrefs().getBoolean(CPConstants.SP_PUSH_NEW_MESSAGE, true);
// Is the user registered
boolean rememberPassword = CPApplication.getSharedPrefs().getBoolean(CPConstants.SP_REMEMBER_PASSWORD, false);
if (rememberPassword && isPushNewMessage) {
// Notification
NotificationCompat.Builder builder = new NotificationCompat.Builder(CPApplication.getInstance());
builder.setSmallIcon(R.drawable.push_icon)
.setTicker("Nuevo mensaje")
.setAutoCancel(true)
.setContentTitle(CPApplication.getInstance().getString(R.string.app_name))
.setContentText("Tiene un mensaje nuevo");
// Is New Message Sound enabled ?
boolean isSoundNewMessage = CPApplication.getSharedPrefs().getBoolean(CPConstants.SP_SOUND_NEW_MESSAGE, true);
if (isSoundNewMessage) {
builder.setDefaults(Notification.DEFAULT_SOUND);
}
// Intent
Intent intent = new Intent(CPApplication.getInstance(), SplashActivity.class);
intent.setAction(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(CPApplication.getInstance(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
// Notification
Notification note = builder.build();
// Will show lights and make the notification disappear when the presses it
note.flags = Notification.FLAG_AUTO_CANCEL | Notification.FLAG_SHOW_LIGHTS;
NotificationManager manager = (NotificationManager) CPApplication.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(QBNotificationID, note);
}
// }
}
}
Thank you
Sorry, but I was putting the token instead of the deviceID, so it appears as a new registered device on QB admin, but with the wrong info, and that was the problem. I was using the new method from QB
new SendPushTokenToQBTask(token, deviceId).execute();
instead of
new SendPushTokenToQBTask(deviceId, token).execute()
Thank you anyways
Posting your permissions might also help but you didn't change the name in the receiver to your package name:
android:name="com.quickblox.chat.push.QBGcmBroadcastReceiver"
try changing it to:
android:name="com.myapp.app.QBGcmBroadcastReceiver"
if it doesn't work edit your question an add your permissions. Hope it helps.
Related
I want to ring alarm on exact time but below code is not working on Android 10.
If app is in stack alarm ring successfully but when its not in recent app stack it never run on any os version.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
manager.setAlarmClock(
new AlarmManager.AlarmClockInfo(
timeMillis,
PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0)
),
getIntent(context)
);
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
manager.setExact(AlarmManager.RTC_WAKEUP, timeMillis, getIntent(context));
else
manager.set(AlarmManager.RTC_WAKEUP, timeMillis, getIntent(context));
Intent intent = new Intent("android.intent.action.ALARM_CHANGED");
intent.putExtra("alarmSet", true);
context.sendBroadcast(intent);
}
I have added below permission
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.SET_ALARM" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="com.learntodroid.simplealarmclock.permission.ALARM" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
What can i do to ring alarm on Android 10?
To schedule an alarm at a specific time try this:
First Schedule an alarm at your desired time using Alarm Manager
void scheduleAlarm(Context context) {
// scheduling an alarm at 05:00 PM
//getting instance of a calendar
Calendar calendar = Calendar.getInstance();
//setting exact date and time of alarm
// in my case it is 17/11/2020 at 05.00 PM
calendar.set(Calendar.MONTH,10); // month count starts from 0; here 10 denotes November
calendar.set(Calendar.YEAR,2020); // year
calendar.set(Calendar.DAY_OF_MONTH,17); // day
calendar.set(Calendar.HOUR_OF_DAY,17); // hour
calendar.set(Calendar.MINUTE,0); // min
Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,12345678,intent,PendingIntent.FLAG_CANCEL_CURRENT);
android.app.AlarmManager alarmManager = (android.app.AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(),5000,pendingIntent);
}
}
Then receive the alarm at the Broadcast Receiver
class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// this will trigger at the alarm time
// show notification or vibration here
}
}
Don't forget to add the receiver in your Manifest file:
<receiver
android:name=".AlarmReceiver" // need to specify the path of your receiver
android:enabled="true"
android:exported="true">
// this filter is optional, needed if you want to trigger the receiver even after a restart
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
This should work for all android versions.
Android 10 won't start Activity from background task (alarm) if it won't have Intent.FLAG_ACTIVITY_NEW_TASK. try to replace new Intent(context, MainActivity.class) with intent object, which sould be declared as follows:
Intent intent = new Intent(context, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
(optionally you may add also Intent.FLAG_ACTIVITY_CLEAR_TOP)
My GCM Service is not working. I have declared a few things in my manifest file which looks something like:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<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.GET_ACCOUNTS" />
<permission android:name="com.xxxx.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.xxxx.xxxxxx.permission.C2D_MESSAGE" />
<receiver android:name=".core.push.receiver.GCMBroadcastReceiver" 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.SEND" />
<category android:name="com.xxxx.xxxxxx" />
</intent-filter>
</receiver>
<service android:name=".core.push.service.GCMIntentService" />
My Broadcast receiver code looks like:
public class GCMBroadcastReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
ComponentName messageProcessingService = new ComponentName(context.getPackageName(), GCMIntentService.class.getName());
context.startService(intent.setComponent(messageProcessingService));
setResultCode(Activity.RESULT_OK);
}
}
My Intent Service:
public class GCMIntentService extends IntentService
{
private static final int NOTIFICATION_NEW_MESSAGE = 0;
public GCMIntentService()
{
super(GCMIntentService.class.getSimpleName());
}
#Override
protected void onHandleIntent(Intent intent)
{
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
if (!extras.isEmpty())
{
if (!GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType))
{
return;
}
// TODO Make more efficient. Load message stream here, not in two places later!
int newUnreadCount = MessagingController.getInstance().getUnreadCount() + 1;
MessagingController.getInstance().prepareStream();
MessagingController.getInstance().setUnreadCount(newUnreadCount);
final boolean isUserAuthenticated = !TextUtils.isEmpty(AuthenticationController.getInstance().getAuthToken());
if (isUserAuthenticated)
{
new Handler(Looper.getMainLooper()).post(new Runnable()
{
#Override
public void run()
{
App.from(GCMIntentService.this).fire(MessagingEvent.NEW_MESSAGE);
}
});
}
else
{
displayNotification(newUnreadCount + " New Message" + (newUnreadCount > 1 ? "s" : ""), newUnreadCount);
}
}
}
private void displayNotification(CharSequence message, int eventCount)
{
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
boolean shouldDisplayMessages = preferences.getBoolean("notifications_new_message", true);
if (!shouldDisplayMessages)
{
return;
}
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent openMessagingScreen = new Intent(this, LandingActivity.class);
openMessagingScreen.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
openMessagingScreen.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
preferences.edit().putBoolean(MessagingFragment.PREF_MESSAGE_WAITING, true).apply();
PendingIntent notificationAction = PendingIntent.getActivity(this, 0, openMessagingScreen, PendingIntent.FLAG_CANCEL_CURRENT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(getString(R.string.app_name))
.setStyle(new NotificationCompat.BigTextStyle().bigText(message))
.setContentText(message)
.setAutoCancel(true)
.setContentIntent(notificationAction)
.setNumber(eventCount);
Notification notification = notificationBuilder.build();
notification.defaults |= Notification.DEFAULT_ALL;
try
{
notificationManager.notify(NOTIFICATION_NEW_MESSAGE, notification);
}
catch (SecurityException ex)
{
// This is required due to a bug in android
// http://stackoverflow.com/questions/13602190/java-lang-securityexception-requires-vibrate-permission-on-jelly-bean-4-2
Log.e("PPDirect", ex.getLocalizedMessage());
}
}
}
I had several questions regarding push notifications:
which call back function actually checks for arrived message and is called once push notification arrives?
Is it possible that since google have updated GCM to FCM I need to make updates to the key or migrate GCM to FCM?
Can there be some other reason?
Any help in the matter would be much appreciated.
1. which call back function actually checks for arrived message and is called once push notification arrives?
For Android, it's commonly received in onMessageReceived in the GcmListenerService. However, it may also depend whether or not the app is in background or foreground.
2. Is it possible that since google have updated GCM to FCM I need to make updates to the key or migrate GCM to FCM?
As per the note here:
Starting from Sept. 2016 new server key can only be created in the Firebase Console using the Cloud Messaging tab of the Settings panel. Existing projects that need to create a new server key can be imported in the Firebase console without affecting their existing configuration.
New users of GCM is in need of creating a Firebase projext, regardless if you are going to use FCM or not, in order to have a Server Key. For the migration steps, you can see my answer here.
3. Can there be some other reason?
This is too broad to answer. Maybe it's because of your payload structure or the implementation of your onMessageReceived(), etc.
I migrated to Firebase Cloud Messaging for push notifications. Every thing works great , I get notifications whenever the app is open or running in background , but when the app is closed and a message is sent from the server then you don't receive it in the device ( obviously ). Now when I reopen the app , I should get the pending notification ( the notification sent while the app was closed ) but I don't get the notification.
This is my FireBaseMessagingService class
public class MyFirebaseMessagingService extends FirebaseMessagingService {
public static String TAG="Firebase";
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
Log.d(TAG, "Notification Message Body: " + remoteMessage.getData().get("message"));
notification(remoteMessage.getData().get("message"));
}
void notification(String s)
{
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this);
mBuilder.setSmallIcon(R.mipmap.logo);
mBuilder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
mBuilder.setContentTitle("App");
mBuilder.setContentText(s);
mBuilder.setAutoCancel(true);
Intent resultIntent = new Intent(this, MainActivity.class);
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addParentStack(MainActivity.class);
stackBuilder.addNextIntent(resultIntent);
PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(101,mBuilder.build());
}
}
This is my FirebaseInstance class
public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
public static String TAG="Firebase";
#Override
public void onTokenRefresh() {
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);
}
}
AndroidManifest.xml -
<service
android:name=".Helpers.MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service
android:name=".Helpers.MyFirebaseInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
Is it possible to get the Pending Notification when the app is relaunched ?
i think it is possible since you're using a service, but android won't let you receive it until you add some sort of permission. Research for what permission will make this condition possible, and please update us.
add the following permission, then u should be good.
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
I'm using the new GoogleCloudMessaging API (from Play Services library, because old Google cloud messaging for android was deprecated) in my project and I have some bugs. When I send messages from my server to all registered devices, my nexus 4 (android 4.4) receives the notification messages, but my Samsung Galaxy Ace doesn't receive them, That's strange, because there are no exceptions or crashes of my project.
Any ideas?
Thanks.
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest package="ru.test"
android:installLocation="preferExternal"
android:versionCode="1"
android:versionName="1.0" xmlns:android="http://schemas.android.com/apk/res/android">
<uses-sdk
android:minSdkVersion="7"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<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="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="com.example.gcm.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/MyTheme" >
<service android:name=".GcmIntentService" />
<receiver
android:name=".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.example.gcm" />
</intent-filter>
</receiver>
<activity
android:name="ru.test.MainActivity"
android:label="#string/app_name"
android:configChanges="orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
GcmBroadcastReceiver.java
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String regId = intent.getExtras().getString("registration_id");
if(regId != null && !regId.equals("")) {
/* Do what ever you want with the regId eg. send it to your server */
Log.d(MainActivity.tag, "onReceive " + regId);
}
// 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
public class GcmIntentService extends IntentService {
public static int NOTIFICATION_ID = 1;
private NotificationManager mNotificationManager;
NotificationCompat.Builder builder;
static final String TAG = "myLogs";
String title = "";
String message = "";
String subtext = "";
public GcmIntentService() {
super("GcmIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
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
title = extras.getString("title");
message = extras.getString("message");
subtext = extras.getString("subtext");
/*
* 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)) {
message = "Send error";
sendNotification(title, message, subtext);
} else if (GoogleCloudMessaging.
MESSAGE_TYPE_DELETED.equals(messageType)) {
message = "Deleted messages on server";
sendNotification(title, message, subtext);
// If it's a regular GCM message, do some work.
} else if (GoogleCloudMessaging.
MESSAGE_TYPE_MESSAGE.equals(messageType)) {
// Post notification of received message.
sendNotification(title, message, subtext);
Log.d(TAG, "Received: " + extras.toString());
}
}
// 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 title, String message, String subtext) {
mNotificationManager = (NotificationManager)
this.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, SplashScreen.class), 0);
NotificationCompat.BigTextStyle bigxtstyle =
new NotificationCompat.BigTextStyle();
bigxtstyle.bigText(message);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_small)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_large))
.setTicker(message)
.setContentTitle(title)
.setDefaults(Notification.DEFAULT_ALL | Notification.FLAG_AUTO_CANCEL)
//.setContentInfo("Content info")
.setAutoCancel(true)
.setSubText(subtext)
.setWhen(System.currentTimeMillis())
.setStyle(new NotificationCompat.BigTextStyle().bigText(message))
.setContentText(message);
mBuilder.setContentIntent(contentIntent);
mNotificationManager.notify(++NOTIFICATION_ID, mBuilder.build());
}
}
Your main package name is ru.test, but in the GCM permissions you specified com.example.gcm as the package name. That's why it doesn't work in 2.x Android version (for some reason this mismatch doesn't affect 4.x versions).
The following changes will solve your problem:
<permission android:name="ru.test.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="ru.test.permission.C2D_MESSAGE" />
<receiver
android:name=".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="ru.test" />
</intent-filter>
</receiver>
I also suggest that you change your minSdkVersion from 7 to 8, since GCM is not supported in API level 7.
Your Google Play application is updated in Galaxy Ace? Probably this is the problem.
Another hypothesis would not be logged into any google account on the device. to receive notifications in versions prior to 4.0.4 is mandatory to be logged in at least one regard.
I'm trying to implement GCM to my app in Android. The server and client side setup seems to be right, because the onMessage method is called when I "push" a string from the server side. I can read the extras from the intent, however, using a notification or a Toast message doesn't work. The phone doesn't show anything, even with the app running, so I guess something isn't right with the context object I use from the callback.
Here's the revelvant part of the manifest.xml, where PACKAGE is the base package.
<receiver
android:name="PACKAGE.gcm.GCMReceiver"
android:enabled="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="PACKAGE" />
</intent-filter>
</receiver>
<service
android:name="PACKAGE.gcm.GCMIntentService"
android:enabled="true" />
</application>
<permission
android:name="PACKAGE.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="PACKAGE.C2D_MESSAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- 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" />
<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
</manifest>
Now the onMessage Method:
#Override
protected void onMessage(Context context, Intent intent)
{
if (DEBUG)
{
System.out.println("[GCMIntentService] Message Received! " + intent.getStringExtra("message"));
}
Toast.makeText(context, intent.getStringExtra("message"), Toast.LENGTH_SHORT).show();
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
// int icon = R.drawable.notification_icon;
CharSequence tickerText = intent.getStringExtra("message");
long when = System.currentTimeMillis();
Notification notification = new Notification(0, tickerText, when);
CharSequence contentTitle = "Some Notification";
CharSequence contentText = tickerText + " some more text";
notification.setLatestEventInfo(context, contentTitle, contentText, null);
final int HELLO_ID = 1;
mNotificationManager.notify(HELLO_ID, notification);
}
The Toast and the Notification aren't working. I call the service and registration routines in the onCreate of the first Activity, wich is used as Splash and closed after a few seconds. Might that have something to do with it?
This isn't a Context issue.
GCM reciever runs in an intent service which in its self runs on a separate thread.
To show a toast just call from inside a UIThread. Which you can do like so:
Handler h = new Handler(Looper.getMainLooper());
h.post(new Runnable(){
Toast.makeText(context, intent.getStringExtra("message"), Toast.LENGTH_SHORT).show();
});
This will now post on your UI thread and you will then see the toast!
(You will need to make your local variable's final for them to be executed by the anonymous class)
Cheers!