Услуги Android: START_STICKY не работает в Kitkat
Я использую службы в приложении для прослушивания того, сколько раз пользователь нажимает свою кнопку питания. Реализация отлично работала на всех устройствах. Но когда я тестировал приложение на Android Kitkat, я заметил что-то не так.
Как только я удаляю приложение из приложений recents, приложение больше не слушает кнопку питания.
Вот код, с которым я работаю:
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);
}
}
Как можно заметить, я использую уведомление, чтобы показать, что служба активна. Меня смущает то, что после прокрутки из приложения recents уведомление все еще остается, что неактивно - это BroadcastReceiver
? или это ложь.
В приложении onDestroy
я не вызывал никаких функций для регистрации или отмены регистрации, а также для остановки службы. Еще раз эта проблема наблюдается только в Android KitKat. Пожалуйста, если вы, ребята, знаете, что происходит. Помогите:)
ОБНОВЛЕНИЕ: Я также заметил с помощью Play Music
в Kitkat, когда я удаляю его из приложения recents, музыка останавливается. Это ошибка в Kitkat? Но службы sound/mediaplayer на SoundCloud
работают даже тогда, когда они удалены от приложения recents.
UPDATE:
Записан, как Проблема 63618 в трее.
Подробнее читайте в комментариях к проблеме.
Ответы
Ответ 1
Кажется, что это ошибка, присутствующая в 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
не убивает мою службу.
Ответ 2
У меня есть это решение, которое отлично работает.
@Override
public void onDestroy() {
startService(new Intent(yourcontext, YourService.class));
}
Ответ 3
Это все еще является открытой ошибкой для KK,
https://code.google.com/p/android/issues/detail?id=63793
Ответ 4
попробуйте мое решение: this
этот трюк перезапустит вашу службу каждый раз, когда пользователь закроет службу из обоих диспетчеров задач и закроет настройки, надеюсь, это тоже поможет вам.
Ответ 5
Если вы не можете перезапустить службу, обратитесь к аламу, чтобы запустить этот ресивер,
Манифест есть,
<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>
IN Основной манипулятор запуска активации таким образом,
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 называет один раз, когда приложение Android открыто и когда приложение закрыто. SO служба похожа на это,
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");
}
}