为什么实例 ID 服务会自动启动,我该如何防止这种情况发生?
Why does the InstanceID service automatically start and how do I preven this?
我有一个使用 GCM 的 android 应用程序。我正在按照教程使用 InstanceIDListenerService
class,我试图在用户输入一些信息的 "subscription" 页面之后将其作为 IntentService
触发。在此订阅页面之前,还有一些初步代码会在幕后的初始屏幕上触发。在我到达 SubscriptionActivity 之前,在 SplashScreen activity 中调用 InstanceIDListenerService
构造函数(随后调用 onHandleIntent)。为什么要这样做?意图服务是否可以自行启动?
我确实在 AndroidManifest.xml
文件中注册了该服务,当我注释掉以下行时,它不会触发实例自动创建,应用程序按预期工作(直到我需要当然使用实例...)
<service
android:name=".service.receiver.InstanceIDListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
SplashScreen.java
public class SplashScreen extends Activity {
private BroadcastReceiver dbInsertReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if(bundle != null) {
// Handle results and move to next activity, should
// be the subscribe activity where I want the instance
// id listener to start.
}
}
};
private BroadcastReceiver providerXMLReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if(bundle != null) {
// Handle results and start the next service
}
}
}
};
/** Called when the activity is first created */
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_splash_screen);
// Kick off the service download to update the provider data
Intent intent = new Intent(this, ProviderDataService.class);
startService(intent);
}
@Override
protected void onStart() {
super.onStart();
registerReceiver(providerXMLReceiver, new IntentFilter(ProviderDataService.CHANNEL));
registerReceiver(dbInsertReceiver, new IntentFilter(InternalDBService.NOTIFICATION));
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(providerXMLReceiver, new IntentFilter(ProviderDataService.CHANNEL));
registerReceiver(dbInsertReceiver, new IntentFilter(InternalDBService.NOTIFICATION));
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(providerXMLReceiver);
unregisterReceiver(dbInsertReceiver);
}
private void moveToNextActivity(int subscriptionStatus) {
if(subscriptionStatus == DBSchemaHelper.IS_SUBSCRIBED_NOT_RESPONDED) {
Intent subscribeIntent = new Intent(SplashScreen.this, SubscribeActivity.class);
startActivity(subscribeIntent);
} else {
// Create an Intent that will start the Menu-Activity.
Intent mainIntent = new Intent(SplashScreen.this, MainActivity.class);
startActivity(mainIntent);
}
this.finish();
}
SubscribeActivity.java
public class SubscribeActivity extends CustomActionBarActivity {
public static final int NO_SUBSCRIPTION_STATUS = -99;
private DBMetaDataSource metaDao;
private int subscribeResult;
public SubscribeActivity() {
metaDao = new DBMetaDataSource(this);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_subscribe);
}
@Override
protected void onStart() {
super.onStart();
registerReceiver(tokenResponseReceiver, new IntentFilter(InstanceIDListenerService.TAG));
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(tokenResponseReceiver, new IntentFilter(InstanceIDListenerService.TAG));
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(tokenResponseReceiver);
}
public void subscribeUser(View v) {
EditText emailTextView = (EditText) findViewById(R.id.subscriptionUserEmail);
String email = emailTextView.getText().toString();
// This is the only place I am manually starting this service.
// I have set a breakpoint here, but I never hit it and the service
// starts on its own and I hit the breakpoints in the service's
// onHandleIntent method.
Intent i = new Intent(this, InstanceIDListenerService.class);
i.putExtra("email", email);
startService(i);
}
public void goToNextActivity(View v) {
// They pressed the button to NOT subscribe, so we are calling this from the
// view rather than the intent receiver, meaning the view will not be null.
if(v != null) {
markUnsubscribed();
}
/* Create an Intent that will start the Menu-Activity. */
Intent mainIntent = new Intent(SubscribeActivity.this, MainActivity.class);
mainIntent.putExtra(MainActivity.SUBSCRIBE_STATUS_KEY, subscribeResult);
startActivity(mainIntent);
}
private void markUnsubscribed() {
metaDao.open(this);
DBMeta metaData = metaDao.get();
metaDao.update(Long.valueOf(metaData.getVersion()), metaData.getLastRunInMillis(), DBSchemaHelper.IS_SUBSCRIBED_RESPONDED_NO, null);
metaDao.close();
}
private BroadcastReceiver tokenResponseReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
subscribeResult = intent.getIntExtra(InstanceIDListenerService.RESPONSE_KEY, NO_SUBSCRIPTION_STATUS);
goToNextActivity(null);
}
};
}
您不应该自己启动 InstanceIDListenerService
- 这是为了让系统在您需要通过回调刷新您的实例 ID 令牌时调用 您 onTokenRefresh() - 如果您还没有创建任何实例 ID 令牌,那么您将在第一次调用时无事可做。
如果您有其他工作要做,您应该使用自己的服务。
我有一个使用 GCM 的 android 应用程序。我正在按照教程使用 InstanceIDListenerService
class,我试图在用户输入一些信息的 "subscription" 页面之后将其作为 IntentService
触发。在此订阅页面之前,还有一些初步代码会在幕后的初始屏幕上触发。在我到达 SubscriptionActivity 之前,在 SplashScreen activity 中调用 InstanceIDListenerService
构造函数(随后调用 onHandleIntent)。为什么要这样做?意图服务是否可以自行启动?
我确实在 AndroidManifest.xml
文件中注册了该服务,当我注释掉以下行时,它不会触发实例自动创建,应用程序按预期工作(直到我需要当然使用实例...)
<service
android:name=".service.receiver.InstanceIDListenerService"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.gms.iid.InstanceID" />
</intent-filter>
</service>
SplashScreen.java
public class SplashScreen extends Activity {
private BroadcastReceiver dbInsertReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if(bundle != null) {
// Handle results and move to next activity, should
// be the subscribe activity where I want the instance
// id listener to start.
}
}
};
private BroadcastReceiver providerXMLReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
if(bundle != null) {
// Handle results and start the next service
}
}
}
};
/** Called when the activity is first created */
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_splash_screen);
// Kick off the service download to update the provider data
Intent intent = new Intent(this, ProviderDataService.class);
startService(intent);
}
@Override
protected void onStart() {
super.onStart();
registerReceiver(providerXMLReceiver, new IntentFilter(ProviderDataService.CHANNEL));
registerReceiver(dbInsertReceiver, new IntentFilter(InternalDBService.NOTIFICATION));
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(providerXMLReceiver, new IntentFilter(ProviderDataService.CHANNEL));
registerReceiver(dbInsertReceiver, new IntentFilter(InternalDBService.NOTIFICATION));
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(providerXMLReceiver);
unregisterReceiver(dbInsertReceiver);
}
private void moveToNextActivity(int subscriptionStatus) {
if(subscriptionStatus == DBSchemaHelper.IS_SUBSCRIBED_NOT_RESPONDED) {
Intent subscribeIntent = new Intent(SplashScreen.this, SubscribeActivity.class);
startActivity(subscribeIntent);
} else {
// Create an Intent that will start the Menu-Activity.
Intent mainIntent = new Intent(SplashScreen.this, MainActivity.class);
startActivity(mainIntent);
}
this.finish();
}
SubscribeActivity.java
public class SubscribeActivity extends CustomActionBarActivity {
public static final int NO_SUBSCRIPTION_STATUS = -99;
private DBMetaDataSource metaDao;
private int subscribeResult;
public SubscribeActivity() {
metaDao = new DBMetaDataSource(this);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_subscribe);
}
@Override
protected void onStart() {
super.onStart();
registerReceiver(tokenResponseReceiver, new IntentFilter(InstanceIDListenerService.TAG));
}
@Override
protected void onResume() {
super.onResume();
registerReceiver(tokenResponseReceiver, new IntentFilter(InstanceIDListenerService.TAG));
}
@Override
protected void onPause() {
super.onPause();
unregisterReceiver(tokenResponseReceiver);
}
public void subscribeUser(View v) {
EditText emailTextView = (EditText) findViewById(R.id.subscriptionUserEmail);
String email = emailTextView.getText().toString();
// This is the only place I am manually starting this service.
// I have set a breakpoint here, but I never hit it and the service
// starts on its own and I hit the breakpoints in the service's
// onHandleIntent method.
Intent i = new Intent(this, InstanceIDListenerService.class);
i.putExtra("email", email);
startService(i);
}
public void goToNextActivity(View v) {
// They pressed the button to NOT subscribe, so we are calling this from the
// view rather than the intent receiver, meaning the view will not be null.
if(v != null) {
markUnsubscribed();
}
/* Create an Intent that will start the Menu-Activity. */
Intent mainIntent = new Intent(SubscribeActivity.this, MainActivity.class);
mainIntent.putExtra(MainActivity.SUBSCRIBE_STATUS_KEY, subscribeResult);
startActivity(mainIntent);
}
private void markUnsubscribed() {
metaDao.open(this);
DBMeta metaData = metaDao.get();
metaDao.update(Long.valueOf(metaData.getVersion()), metaData.getLastRunInMillis(), DBSchemaHelper.IS_SUBSCRIBED_RESPONDED_NO, null);
metaDao.close();
}
private BroadcastReceiver tokenResponseReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
subscribeResult = intent.getIntExtra(InstanceIDListenerService.RESPONSE_KEY, NO_SUBSCRIPTION_STATUS);
goToNextActivity(null);
}
};
}
您不应该自己启动 InstanceIDListenerService
- 这是为了让系统在您需要通过回调刷新您的实例 ID 令牌时调用 您 onTokenRefresh() - 如果您还没有创建任何实例 ID 令牌,那么您将在第一次调用时无事可做。
如果您有其他工作要做,您应该使用自己的服务。