83

次のように、メインの Android アクティビティからサービスを開始しています。

final Context context = base.getApplicationContext();
final Intent intent = new Intent(context, MyService.class);
startService(intent);

最近のアプリの一覧からスワイプしてアクティビティ ページを閉じると、サービスが実行を停止し、しばらくしてから再起動します。アプリの要件により、通知付きの永続的なサービスを使用できません。サービスを再起動またはシャットダウンせずに、アプリの終了時に実行し続けるにはどうすればよいですか?

4

14 に答える 14

48

私は同じ状況にありますが、これまでのところ、アプリが閉じられたときにサービスが閉じられることを学びました。これは、それらが1つのスレッドにあるためでもあるため、サービスが閉じられないようにするために、サービスは別のスレッドにある必要があります。それを調べてくださいそして、サービスが通知に表示されないように、例http://www.vogella.com/articles/AndroidServices/article.htmlのアラーム マネージャーを使用してサービスを維持することを検討してください。

最後に、私が行ったすべての調査の結果、長期実行サービスの最良の選択はstartForeground().

于 2013-06-22T23:07:26.017 に答える
5

主な問題は、アプリを閉じたときにサービスを開始できないことです。Android OS (一部の OS では) はリソース最適化のためにサービスを強制終了します。サービスを再起動できない場合は、アラーム マネージャーを呼び出して、このように受信機を開始します。これがコード全体です。このコードはサービスを維持します。

マニフェストは、

         <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アプリが開かれたときとアプリが閉じられたときに1回呼び出されます.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");
    }
}
于 2017-01-17T07:10:00.440 に答える
1

サービスとアクティビティに同じプロセスを使用し、サービスで START_STICKY または START_REDELIVER_INTENT を使用することが、アプリケーションの再起動時にサービスを再起動できる唯一の方法です。これは、ユーザーがアプリケーションを閉じたときなどに発生しますが、システムが決定したときにも発生します。最適化の理由でそれを閉じます。中断することなく永続的に実行されるサービスを持つことはできません。これは設計によるものであり、スマートフォンは長時間連続してプロセスを実行するようには作られていません。これは、バッテリーの寿命が最優先事項であるためです。任意の時点での停止を処理できるように、サービスを設計する必要があります。

于 2017-08-06T09:57:51.487 に答える
0

IntentService を使用しないのはなぜですか?

IntentService は、メイン スレッドとは別に新しいスレッドを開き、そこで動作します。そのため、アプリを閉じても影響はありません

IntentService は onHandleIntent() を実行し、完了したらサービスを閉じることに注意してください。ニーズに合っているかどうかを確認してください。 http://developer.android.com/reference/android/app/IntentService.html

于 2015-05-31T09:02:36.797 に答える
0

最善の解決策は、Android で同期アダプターを使用してサービスを開始することです。同期アダプターを作成し、開始サービスを呼び出します.. onPerformSync メソッド内で。同期アカウントを作成するには、このリンクを参照してくださいhttps://developer.android.com/training/sync-adapters/index.html

SyncAdapter を使用する理由 回答: 以前は、アプリ コンテキストを使用してサービスを開始していたためです。そのため、アプリのプロセスが強制終了されるたびに (タスク マネージャーから削除するか、リソース不足のために OS を強制終了すると)、その時点でサービスも削除されます。SyncAdapter はアプリケーション スレッドでは機能しません。したがって、その内部で呼び出すと、サービスは削除されなくなります。削除するコードを記述しない限り。

于 2017-07-06T08:01:37.467 に答える