제가 아는 것은 없지만 아는 것을 적어보겠습니다. 100%신용은 금물입니다요;
우선 3.1 버전 이전은 앱이 완전히 종료되도 C2DM or GCM을 받을수 있었습니다.
하지만 3.1이후부터 바뀌게 되었습니다.
Android 3.1 버전부터 system의 package manager가 app의 stoped 상태를 유지 관리한다고 합니다.
app이 종료 되어 있을때 Broadcast의 Intent Flag에 따라 stoped된 어플도 Broadcast를 받을지 안받을지 정해주는 걸로 알고 있습니다.
-> http://aroundck.tistory.com/684
위를 읽어보면 시스템이 Broadcast intent에 대해서는 기본값으로 FLAG_EXCLUDE_STOPPED_PACAGES를 준다고 합니다. 이를 토대로 생각해보면
GCM도 Broadcast를 이용하고, systme에서 intentFlag에 FLAG_EXCLUDE_STOPPED_PACAGES 로 Broadcast를 하기 때문에 이미 완전히 종료된 app은 GCM을 받을 수 없는 것으로 생각됩니다.
아래는 GCMBroadcastReceiver.java 입니다.
public class GCMBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "GCMBroadcastReceiver";
private static boolean mReceiverSet = false;
@Override
public final void onReceive(Context context, Intent intent) {
Log.v(TAG, "onReceive: " + intent.getAction());
// do a one-time check if app is using a custom GCMBroadcastReceiver
if (!mReceiverSet) {
mReceiverSet = true;
GCMRegistrar.setRetryReceiverClassName(getClass().getName());
}
String className = getGCMIntentServiceClassName(context);
Log.v(TAG, "GCM IntentService class: " + className);
// Delegates to the application-specific intent service.
GCMBaseIntentService.runIntentInService(context, intent, className);
setResult(Activity.RESULT_OK, null /* data */, null /* extra */);
}
/**
* Gets the class name of the intent service that will handle GCM messages.
*/
protected String getGCMIntentServiceClassName(Context context) {
return getDefaultIntentServiceClassName(context);
}
/**
* Gets the default class name of the intent service that will handle GCM
* messages.
*/
static final String getDefaultIntentServiceClassName(Context context) {
String className = context.getPackageName() +
DEFAULT_INTENT_SERVICE_CLASS_NAME;
return className;
}
}
위 소스를 보면 onReceive에서 자신의 앱의 패키지 + DEFAULT_INTENT_SERVICE_CLASS_NAME( == .GCMIntentService)로 설정하여 runIntentInService()에서 그 서비스를 실행하고 이후 나머지 로직을
실행하게 됩니다.
테스트를 하여 본 결과, 앱을 강제종료하고 GCM을 보내면, onReceive()의
Log.v(TAG, "onReceive: " + intent.getAction()); 가 실행이 안되는 것을 알 수 있습니다.
이는 GCMBroadcastReceiver.java 에서 처음에 적은 이유와 같이 'com.google.android.c2dm.intent.RECEIVE' Broadcast를 받지 못하는 것으로 생각할 수 있습니다.
이러한 이유로 강제 종료시에는 GCM을 받을수 없다고 알고 있습니다.
아쉽지만 제가 아는 범위에서는 3.1 버전이후 강제로 앱이 종료 되면 GCM을 받을 수 없는 것은 정상입니다. (루팅 된 폰은 예외 일것임)
수고하셔요..