Android服务:START_STICKY不适用于Kitkat

我在应用程序中使用服务来监听用户按下电源button的次数。 所有设备的实现工作正常。 但是当我testingAndroid Kitkat上的应用程序时,我注意到了一些错误。

只要我将应用程序从最近的应用程序中移开,应用程序就不再监听电源button。

以下是我正在使用的代码:

public class Receiver extends Service { Notification notification; private static final int NOTIFICATION_ID = 0; NotificationManager manager; PendingIntent toOpen; Intent intent; private BroadcastReceiver POWER_BUTTON = new Powerbuttonrecceiver(); @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); registerReceiver(POWER_BUTTON, filter); startNotify(); return START_STICKY; } @Override public void onDestroy() { // TODO Auto-generated method stub unregisterReceiver(POWER_BUTTON); dismissNotification(); super.onDestroy(); } public void startNotify(){ manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); int icon = R.drawable.ic_launcher_drop; CharSequence tickerText = "Service activated"; CharSequence tickerContent = "Service is now on. You can press your power button and the app will listen to it. Tap to turn this feature off"; intent = new Intent(Receiver.this, Options.class); toOpen = PendingIntent.getActivity(getApplicationContext(), 0, intent, 0); notification = new NotificationCompat.Builder(getApplicationContext()) .setContentTitle(tickerText) .setContentText(tickerContent) .setSmallIcon(icon) .setOngoing(true) .setContentIntent(toOpen) .build(); manager.notify(NOTIFICATION_ID, notification); } public void dismissNotification(){ manager.cancel(NOTIFICATION_ID); } } 

正如人们可以注意到,我正在使用通知来表示服务处于活动状态。 让我感到困惑的是,在从最近的应用程序中滑动之后,通知仍然存在,那么BroadcastReceiver是不活动的? 或者是错误的。

在应用程序的onDestroy我没有调用任何函数来注册或注销以及停止服务。 再一次,这个问题只能在Android KitKat中看到。 请如果你们知道最新情况。 帮忙:)

更新 :我也注意到在Kitkat上Play Music时,当我从最近的应用程序中滑过音乐时,音乐停止。 这是Kitkat上的错误吗? 但SoundCloud的声音/ mediaplayer服务即使在从最新应用程序中移除时也能正常工作。

更新:在Android问题跟踪器上logging为问题63618 。 阅读问题评论以了解更多详情。

Solutions Collecting From Web of "Android服务:START_STICKY不适用于Kitkat"

似乎这是Android 4.4存在的一个错误,用下面的代码解决了它:

 @Override public void onTaskRemoved(Intent rootIntent) { // TODO Auto-generated method stub Intent restartService = new Intent(getApplicationContext(), this.getClass()); restartService.setPackage(getPackageName()); PendingIntent restartServicePI = PendingIntent.getService( getApplicationContext(), 1, restartService, PendingIntent.FLAG_ONE_SHOT); AlarmManager alarmService = (AlarmManager)getApplicationContext().getSystemService(Context.ALARM_SERVICE); alarmService.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() +1000, restartServicePI); } 

所以这是一个在Service类中被覆盖的方法。 我使用AlarmManager的原因是Kitkat不会杀死我的服务。

我有这个解决scheme,完美的作品。

 @Override public void onDestroy() { startService(new Intent(yourcontext, YourService.class)); } 

这对于KK来说仍然是一个开放的bug,

https://code.google.com/p/android/issues/detail?id=63793

试试我的解决scheme: 这个

这个技巧将重新启动您的服务,每次用户closures服务,从任务pipe理器和强制closures设置,我希望这也能帮助你

如果您无法重新启动服务,请拨打阿拉姆邮箱来启动接收器,

清单是,

  <service android:name=".BackgroundService" android:description="@string/app_name" android:enabled="true" android:label="Notification" /> <receiver android:name="AlarmReceiver"> <intent-filter> <action android:name="REFRESH_THIS" /> </intent-filter> </receiver> 

在主要活动启动闹铃pipe理器这样,

 String alarm = Context.ALARM_SERVICE; AlarmManager am = (AlarmManager) getSystemService(alarm); Intent intent = new Intent("REFRESH_THIS"); PendingIntent pi = PendingIntent.getBroadcast(this, 123456789, intent, 0); int type = AlarmManager.RTC_WAKEUP; long interval = 1000 * 50; am.setInexactRepeating(type, System.currentTimeMillis(), interval, pi); 

这会叫reciver和reciver是,

 public class AlarmReceiver extends BroadcastReceiver { Context context; @Override public void onReceive(Context context, Intent intent) { this.context = context; System.out.println("Alarma Reciver Called"); if (isMyServiceRunning(this.context, BackgroundService.class)) { System.out.println("alredy running no need to start again"); } else { Intent background = new Intent(context, BackgroundService.class); context.startService(background); } } public static boolean isMyServiceRunning(Context context, Class<?> serviceClass) { ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE); if (services != null) { for (int i = 0; i < services.size(); i++) { if ((serviceClass.getName()).equals(services.get(i).service.getClassName()) && services.get(i).pid != 0) { return true; } } } return false; } } 

而这个Alaram reciver在Android应用程序被打开和应用程序closures时会调用一次。这个服务就是这样,

 public class BackgroundService extends Service { private String LOG_TAG = null; @Override public void onCreate() { super.onCreate(); LOG_TAG = "app_name"; Log.i(LOG_TAG, "service created"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(LOG_TAG, "In onStartCommand"); //ur actual code return START_STICKY; } @Override public IBinder onBind(Intent intent) { // Wont be called as service is not bound Log.i(LOG_TAG, "In onBind"); return null; } @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) @Override public void onTaskRemoved(Intent rootIntent) { super.onTaskRemoved(rootIntent); Log.i(LOG_TAG, "In onTaskRemoved"); } @Override public void onDestroy() { super.onDestroy(); Log.i(LOG_TAG, "In onDestroyed"); } }