web-dev-qa-db-ja.com

ユーザーが強制的に閉じた場合でも、サービスを自動的に再起動する方法は?

アプリケーションで常にサービスを実行したい。したがって、ユーザーによって強制的に閉じられた場合でも、再起動します。 Facebookのようなアプリがそれをやっているので、それを行う方法は間違いなくあります(プッシュ通知を使用して行われず、インターネットがオフの場合でもFacebookはサービスを再起動します)。

任意の助けをいただければ幸いです。ありがとう!

38
Vipul J

まず第一に、それは本当に非常に悪いパターンサービスを強制的に実行することですユーザーの意思に反して

とにかく、サービスのonDestroy()から送信されたブロードキャストを処理するBroadcastReceiverを使用して再起動できます。

StickyService.Java

public class StickyService extends Service
{
    private static final String TAG = "StickyService";


    @Override
    public IBinder onBind(Intent arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand");
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        sendBroadcast(new Intent("YouWillNeverKillMe"));
    }

}

RestartServiceReceiver.Java

public class RestartServiceReceiver extends BroadcastReceiver
{

    private static final String TAG = "RestartServiceReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.e(TAG, "onReceive");
    context.startService(new Intent(context.getApplicationContext(), StickyService.class));

    }

}

マニフェストのコンポーネントファイルを宣言します:

    <service Android:name=".StickyService" >
    </service>

    <receiver Android:name=".RestartServiceReceiver" >
        <intent-filter>
            <action Android:name="YouWillNeverKillMe" >
            </action>
        </intent-filter>
    </receiver>

コンポーネントでStickyServiceを開始します(つまり、ApplicationActivityFragment):

startService(new Intent(this, StickyService.class));

OR

sendBroadcast(new Intent("YouWillNeverKillMe"));
65
Mehul Joisar

onTaskRemovedメソッドをオーバーライドしてsticky serviceを作成する必要があります。この場合、コードを再度トリガーするようにアラームサービスを設定できます。

public class BackgroundService extends Service {

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        //create an intent that you want to start again.
        Intent intent = new Intent(getApplicationContext(), BackgroundService.class);
        PendingIntent pendingIntent = PendingIntent.getService(this, 1, intent, PendingIntent.FLAG_ONE_SHOT);
        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        alarmManager.set(AlarmManager.RTC_WAKEUP, SystemClock.elapsedRealtime() + 5000, pendingIntent);
        super.onTaskRemoved(rootIntent);
    }
}

また、Xiaomi、Huwaeiなどの一部のデバイスでは、最近のアプリから削除されると、アプリは強制的に閉じられます。これは、メーカーがRAM /バッテリーのパフォーマンスを向上させるタスクマネージャー機能を備えているためです。

詳細については、このリンクを確認できます。 https://stackoverflow.com/a/41360159/2798289

11
Govind

サービスが強制終了されるたびに、そのonDestroyメソッドが常に呼び出されます。 BroadcastReceiverを使用して、サービスが停止したときにサービスを開始することをお勧めします。

以下に、その実装を示すサンプルコードを示します。

@Override
public void onDestroy() {
Intent in = new Intent();
in.setAction("StartkilledService");
sendBroadcast(in);
Log.d("debug", "Service Killed");
}

次に、AndroidManifest.xml:にレシーバーを登録します

<receiver Android:name=".app.ServiceDestroyReceiver" >
    <intent-filter>
        <action Android:name="StartKilledService" >
        </action>
    </intent-filter>
</receiver>

最後に、BroadcastReceiverを作成し、onReceiveメソッドでサービスを開始します:-

@Override
public void onReceive(Context context, Intent intent) {
Log.d("debug", "ServeiceDestroy onReceive...");
Log.d("debug", "action:" + intent.getAction());
Log.d("debug", "Starting Service");
ServiceManager.startService();
}

お役に立てれば。

4
Atish Agrawal

Android document

Starting from Android 3.1, the system's package manager keeps track of applications 
that are in a stopped state and provides a means of controlling their launch from 
background processes and other applications.

Note that an application's stopped state is not the same as an Activity's stopped
state. The system manages those two stopped states separately.
FLAG_INCLUDE_STOPPED_PACKAGES — Include intent filters of stopped applications in the
list of potential targets to resolve against.

FLAG_EXCLUDE_STOPPED_PACKAGES — Exclude intent filters of stopped applications from the
list of potential targets.

When neither or both of these flags is defined in an intent, the default behavior is to
include filters of stopped applications in the list of potential targets. 

Note that the system adds FLAG_EXCLUDE_STOPPED_PACKAGES to all broadcast intents.
It does this to prevent broadcasts from background services from inadvertently or
unnecessarily launching components of stopped applications. A background service 
or application can override this behavior by adding the FLAG_INCLUDE_STOPPED_PACKAGES
flag to broadcast intents that should be allowed to activate stopped applications.

アプリの強制停止では、AndroidプロセスIDを強制終了します。警告はありません。サービス/アクティビティにコールバックが与えられます。Androidドキュメント、アプリが終了すると、onPause()が呼び出される可能性があります。

私のアプリで試したとき、onPause()さえ呼び出されませんでした。唯一の方法はFLAG_INCLUDE_STOPPED_PACKAGESインテントフラグと別のアプリからの送信

4
Zohra Khan

サービスのstartCommandメソッドでSTART_STICKYを返します。一般的に、OSが停止したときにサービスを開始するように指示します。

3
Bijesh

私が正しく理解している場合、実際にはこれは不可能です、Androidアプリケーションを強制終了する機能は、ユーザーが不要なアプリケーションを削除できるように設計されたため、ユーザーが再び起動するまで、それからのアクティビティを許可しませんそのアクティビティのいずれか。

アプリが強制停止されてもサービスを再起動し、アプリを閉じた後でもバックグラウンドでサービスを実行し続けますか?

2
marcinj

状況によって「ルート」の使用が許可されている場合、通常、ハンプティダンプティパラダイムを実装できます。

アプリケーション(1番目)は別のアプリケーションをインストールし(2番目、アセットからAPKを取得)、2番目のアプリケーションのサービスを実行します。 2番目のアプリのサービスは1番目のアプリサービスにバインドされ、切断されると再バインドされます。最初のアプリも同じことをします。

確かに、すべてのアプリが一部の無料のRAMまたは同様のアプリケーションによって強制終了された場合は役に立ちませんが、Androidがこれら2つのいずれかを強制終了すると、他のアプリケーションはカウンターパート。

2
OGP

サービスを維持するための唯一の実際のソリューションは、提供された通知でService.startForeground(...)を呼び出すことです。これが唯一の有効なソリューションであり、他のすべてのソリューションは、Googleがシステムの動作をどのように変更するかに大きく依存します。 APIが更新されるたびに、Googleは他のすべてのハッキングを防ぐことができました。

また、これにより、ユーザーの意識が維持されます。アプリがアプリを維持するバックグラウンドタスクを実行しているため、ユーザーはこれを停止する必要があります。ただし、ユーザーにそれを停止する機能を提供する場合は、アプリケーションの一部です。

ドキュメントを参照してください:

void startForeground (int id, Notification notification)

このサービスをフォアグラウンドで実行し、この状態のときにユーザーに表示される継続的な通知を提供します。デフォルトでは、サービスはバックグラウンドです。つまり、システムがより多くのメモリを再利用するためにそれらを強制終了する必要がある場合(Webブラウザーで大きなページを表示する場合など)、あまり害を与えずに強制終了できます。サービスがバックグラウンドミュージックの再生を実行している場合など、サービスの強制終了がユーザーに混乱をもたらす場合、このフラグを設定して、ユーザーが音楽の再生を停止したかどうかを確認できます。

1
da_berni

強制的に停止しても、サービスを実行し続けるための非常にハッキングなソリューションがあります。ユーザーの意欲に反するため、お勧めしません。アクションXでインテントを受信するブロードキャストレシーバーを定義できます。サービスのonStartCommandハンドラー、ブロードキャストX(サービスがまだ開始されていない場合)。 Xの受信時にブロードキャストレシーバーで、最初にサービスを開始し、次に数分間スリープし、最後にXを再ブロードキャストします。

0
Nami