I want to create an android service which always runs in background even when we haven't opened the app like gmail service or whatsapp service so we can get notifications when app is closed (but not forced close). I want to get gcm notification even when app is closed like we swapped out app from recent apps.
Right now when I close app by long press on home button and swapped it all components of app close ao I couldn't get gcm notifications.
I know we can't get gcm notifications when app is forced close.
I have stuck on this problem for long time. Can somebody know how to handle this issue
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ComponentName comp = new ComponentName(context.getPackageName(),
GCMNotificationIntentService.class.getName());
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
Manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="xxxx"
android:installLocation="internalOnly">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATUS_AND_IDENTITY" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<permission
android:name="xxxx.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="xxxx.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:name=".MyApplication"
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=".MainActivity"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
//it overrides WakefulBroadcastReceiver
<receiver
android:name=".gcm.GcmBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="xxxx" />
</intent-filter>
</receiver>
//it overrides IntentService
<service android:name=".gcm.GCMNotificationIntentService" />
</application>
</manifest>
public class GCMNotificationIntentService extends IntentService {
// Sets an ID for the notification, so it can be updated
public static final int notifyID = 9001;
private static final String TAG = GCMNotificationIntentService.class.getSimpleName();
NotificationCompat.Builder builder;
public GCMNotificationIntentService() {
super("GcmIntentService");
}
@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_SEND_ERROR
.equals(messageType)) {
sendNotification("Send error: " + extras.toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
.equals(messageType)) {
sendNotification("Deleted messages on server: "
+ extras.toString());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
.equals(messageType)) {
String incomingMessage = extras.get(ApplicationConstants.MSG_KEY)+"";
String type = identifyHeaders(incomingMessage);
String processedString = removeHeaders(incomingMessage, type);
if(type.equals(NOTIFICATION_MESSAGE)) {
sendNotification(processedString);
}else if(type.equals(NOTIFICATION_PHONE_CHANGE)){
}
}
}
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
//this methos is for sending notification to notification bar
private void sendNotification(String msg) {
}
}
Updated GCM Service code
public class GCMNotificationIntentService extends Service {
// Sets an ID for the notification, so it can be updated
public static final int notifyID = 9001;
private static final String TAG = GCMNotificationIntentService.class.getSimpleName();
public GCMNotificationIntentService() {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "Service started");
processIntent(intent);
return START_STICKY;
}
void processIntent(Intent intent){
Log.d(TAG, "notification received");
Bundle extras = intent.getExtras();
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());
} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
.equals(messageType)) {
String incomingMessage = extras.get(ApplicationConstants.MSG_KEY)+"";
String type = identifyHeaders(incomingMessage);
String processedString = removeHeaders(incomingMessage, type);
if(type.equals(NOTIFICATION_MESSAGE)) {
sendNotification(processedString);
}else if(type.equals(NOTIFICATION_PHONE_CHANGE)){
updatePhoneNumber(processedString);
}
}
}
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
private void sendNotification(String msg) {
Intent resultIntent = new Intent(this, WelcomeScreen.class);
resultIntent.putExtra("msg", msg);
resultIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP| Intent.FLAG_ACTIVITY_NEW_TASK| Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0,
resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mNotifyBuilder;
NotificationManager mNotificationManager;
mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotifyBuilder = new NotificationCompat.Builder(this)
.setContentTitle("GOODSERVICE")
.setContentText("NEW LEAD FROM GOODSERVICE")
.setSmallIcon(R.drawable.ic_launcher);
mNotifyBuilder.setContentIntent(resultPendingIntent);
// Set Vibrate, Sound and Light
int defaults = 0;
defaults = defaults | Notification.DEFAULT_LIGHTS;
defaults = defaults | Notification.DEFAULT_VIBRATE;
mNotifyBuilder.setDefaults(defaults);
// Set the content for Notification
mNotifyBuilder.setContentText("NEW LEAD FROM GOODSERVICE");
// Set autocancel
mNotifyBuilder.setAutoCancel(true);
Uri soundTest = Settings.System.DEFAULT_RINGTONE_URI;
mNotifyBuilder.setSound(soundTest);
// Post a notification
mNotificationManager.notify(notifyID, mNotifyBuilder.build());
Intent intentone = new Intent(this, HomeActivity.class);
intentone.putExtra("msg", msg);
intentone.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP| Intent.FLAG_ACTIVITY_NEW_TASK| Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
this.startActivity(intentone);
}
}
This is how I am calling this service
ComponentName comp = new ComponentName(context.getPackageName(),
GCMNotificationIntentService.class.getName());
startWakefulService(context, (intent.setComponent(comp)));
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);