2013-12-19 15 views
18

アプリケーションでサービスを使用して、ユーザーが電源ボタンを何回押したかを聞いています。実装はすべてのデバイスで正常に動作していました。しかし、私がAndroid Kitkatでアプリをテストしたとき、私は間違ったことに気づいた。Androidサービス:START_STICKYが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); 
    } 

} 

1は、私はサービスがアクティブであることを意味する通知を使用していお気づきのように。私を混乱させることは、recentsアプリからスワイプしても通知が残っていることですが、何が非アクティブなのはBroadcastReceiverですか?またはそれは偽である。

アプリのonDestroyでは、登録や登録解除、サービス停止の機能を呼び出すことはありません。もう一度、この問題はAndroid KitKatでのみ見られます。もしあなたが何が起こっているのか知っていればどうか。ヘルプ:)

UPDATEを行います。また、私は離れ更新ムービーから、それをスワイプアプリ際に音楽が停止し、キットカットのPlay Musicに気づきました。これはKitkatのバグですか?しかし、SoundCloudのサウンド/メディアプレイヤーサービスは、recentsアプリからスワイプされても機能します。

更新: ログインしてください。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で十分ではないかもしれません。失敗した場合は長い遅延を試してください。例えば2000ms – AVEbrahimi

+2

onTaskRemovedはスワイプ後の再起動にのみ有効ですが、システムがバックグラウンドでアプリを停止し、 "onTaskRemoved"が呼び出されないことがあります。 – AVEbrahimi

+0

あなたは本当に私を救った! – powder366

0

これは、私は完璧に動作します。このソリューションを持って、まだ

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

+0

他のアプリはどのようにこれを回避していますか? –

+0

これは開発者によって異なります。私はあなたも良い考えをしていると思いますが、数秒後に再開しようとすると、パフォーマンスが向上します。 –

1

KKのためのオープンバグです。私は、これはあなたがしている場合は、あまりにも

0

私の解決策を試してみてくださいマニフェストは、

ある

、このようなreciverを開始するためにアラムマネージャを呼び出してサービスを再起動することはできませんメインActivty、IN

これはreciverとreciverを呼び出します、このように

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); 

をアラームマネージャを起動するには、

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; 
    } 
} 

であるとAndroidアプリを開いたとき、アプリケーションされている場合、このAlaramのreciverは一度呼び出し、あなたのサービスは次のようなものです。

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"); 
    } 
} 
0

を助けることを願って、this

このトリックは、両方のタスクマネージャからあなたのサービス毎回の利用者に近いサービスを再起動し、設定から強制終了されます:

@Override 
public void onDestroy() { 
    startService(new Intent(yourcontext, YourService.class)); 
} 
関連する問題