2013-12-19 108 views
18

我在應用程序中使用服務來監聽用戶按下電源按鈕的次數。實施在所有設備上都工作正常。但是當我在Android Kitkat上測試應用程序時,我發現有些問題。Android服務:START_STICKY不適用於Kitkat

只要我將應用程序從最近的應用程序中滑開,應用程序就不再監聽電源按鈕。

這裏是我一起工作的代碼:

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中看到。請如果你們知道發生了什麼事。做幫助:)

UPDATE:我也注意到在Kitkat上的Play Music,當我從最近的應用程序中滑過它時,音樂停止。這是Kitkat上的錯誤嗎?但SoundCloud上的聲音/媒體播放器服務即使在從最新應用程序中移除時也能正常工作。

更新: 在Android問題跟蹤器上記錄爲Issue 63618。 閱讀問題評論瞭解更多詳情。

+0

當你滑過應用程序,你有效地銷燬服務...是不是它呢? –

+0

我沒有專門調用任何函數來銷燬服務。正如我之前所說的應用程序工作正常以前的Android API的除了Kitkat @MadhurAhuja –

+0

重複的:http://stackoverflow.com/questions/20636330/start-sticky-does-not-work-on-android-kitkat – Muzikant

回答

7

看來,這是一個存在於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不會中止我的服務。

+1

SystemClock.elapsedRealtime()+1000可能不夠,在失敗的情況下嘗試更長的延遲,例如2000毫秒 – AVEbrahimi

+2

似乎onTaskRemoved僅適用於刷卡後重新啓動,但有時系統會在後臺停止應用程序,然後不會調用「onTaskRemoved」! – AVEbrahimi

+0

哇,你真的救了我! – powder366

0

這仍然是一個開放的bug的KK,

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

+0

其他應用程序如何解決這個問題? –

+0

這取決於開發者對開發者。我認爲你的想法也很好,但如果你在幾秒鐘之後嘗試恢復,你的表現會更好。 –

1

我有這樣的解決方案,它完美的作品。

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

試試我的解決方案:this

這一招將來自兩個任務管理器重新啓動服務每次用戶貼心的服務和強制從設置密切,我希望這將幫助你太

0

如果你是無法重新啓動該服務,然後調用阿拉姆馬槽開始這樣的reciver,

貨單,

  <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主Activty以這種方式啓動報警馬槽,

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應用程序被打開,當應用程序是關閉.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"); 
    } 
} 
相關問題