web-dev-qa-db-ja.com

Androidアプリケーションを閉じた後、アラームはキャンセルされます

AlarmManagerに問題があります。繰り返しアラームをスケジュールするためのコードを設定し、アプリケーションを実行した後、アラームは正常に実行されます。ホームボタンをクリックしても(そしてアプリケーションが一時停止していても)、アラームはその間隔で実行されます。

問題は、タスクマネージャーを開いてアプリケーションを強制的に閉じると、アラームの実行が停止することです。

これは正常な動作ですか?これを回避し、アプリケーションを閉じた後もアラームを実行し続ける方法はありますか?

コードは次のとおりです。メソッドはApplicationContextクラスonCreate()によって呼び出されます。

 private void scheduleAlarm() {
  if (alarmScheduled == true) { return; } // we only need to schedule once.

  int alarmInterval = Def.pref(getApplicationContext()).getInt("alarmInterval", 30);

  final Intent intent = new Intent(getApplicationContext(), CollectorAlarmReceiver.class);
  final PendingIntent pending = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, 0);

  AlarmManager alarmMgr = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);

  alarmMgr.cancel(pending); // cancel others.

  alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+1000,
    alarmInterval*1000, pending);

  Def.log(TAG,"scheduleAlarm(): alarm scheduled, interval: "+alarmInterval+" seconds");
  alarmScheduled = true;
 }

受信者コード:

public void onReceive(Context context, Intent intent) {
    Log.i(TAG, "CollectorAlarmReceiver invoked, starting CollectorService in background");

    context.startService(new Intent(context, CollectorService.class));

    Intent collectorService = new Intent(context,CollectorService.class);
    collectorService.putExtra("action", CollectorService.ACTION_BACKGROUND_REQUEST_MESSAGES);

    context.sendBroadcast(collectorService);
}

ありがとう!

25
Allan Denot

これは正常な動作です。ユーザーが自発的にアプリケーションを強制的に停止する場合は、アプリケーションを停止する必要があります。それ以外の場合は、アプリケーションのようなウイルスを作成しています。

本当に必要な場合は、他のサービスが実行されているかどうかを監視し、実行されていない場合はサービスを実行する別のサービスを作成できます。しかし、これは別のアプリケーションになり、(あなたが望む)ユーザーはタスクマネージャーを使用してこのアプリを強制終了しません。

個人的には心配しません。ユーザーがそれを止めた場合、彼らはそれを止めたかったのです。ユーザーを悩ませないでください。

11
GSree

@GSreeは間違っていると思います。これを実現する簡単な方法があります。カスタムアクションを使用するだけです。方法は次のとおりです。

まず、次のようなカスタムアクション名を定義します。

public static final String MY_ACTION = "com.sample.myaction"

次に、BroadcastReceiverを作成します。

public class MyAlarmReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(MY_ACTION)) {
            // Do something here
        }
    }    
}

AndroidManifest.xmlにレシーバーを登録します。

<receiver Android:name="com.sample.MyAlarmReceiver">
    <intent-filter>
        <action Android:name="com.sample.myaction"/>
    </intent-filter>
</receiver>

次に、アラームを設定するには、次のPendingIntentを使用します。

Intent i = new Intent(MY_ACTION);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), 0, i, 0);

他の方法もあるかもしれませんが、このソリューションを試したところ、シェルからアプリを強制終了しても、BroadcastReceiverが呼び出されました。

このソリューションでは、サービスを作成する必要がないことに注意してください。

8
fatline

これは正常な動作です。アプリがonDestroy()に移行すると、アラームは機能しなくなります。

2
utkarsh dubey

私はこれを数回行いましたが、なぜyaがrequestCode0を割り当てるのか疑問に思います。アラームに一意の番号を付けると大いに役立つと思います。

2

追加

<receiver Android:name=".AlarmReceiver" Android:process=":remote" />

マニフェストファイル内。アプリが強制終了されても、アラームは機能します。

0

アプリケーションを強制的に閉じることは、アプリを閉じる正しい方法ではなく、誤った動作をする可能性があります。

この 質問 も役立つかもしれません。

0
ninjasense

私はあなたが必要なことを正確に行うことができました。アプリケーションマネージャツールの[実行中]タブからアプリケーションを停止しても、サービスは自動的に再起動します。それを強制終了する唯一の方法は、アプリケーションマネージャのアンインストールオプションの横にある強制停止ボタンを使用することです。基本的には、サービスを直接呼び出します。これが私のコードです:

public class TestService extends Service {

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(this, "Ejecutando Servicio ...", Toast.LENGTH_SHORT).show();
    return Service.START_NOT_STICKY;    
    }

@Override
    public void onCreate() {
      super.onCreate();
      Toast.makeText(this, "Iniciando Servicio ...", Toast.LENGTH_SHORT).show();
}

    @Override
    public void onDestroy() {
      super.onDestroy();
      Toast.makeText(this, "Deteniendo Servicio ...", Toast.LENGTH_SHORT).show();
}   

クライアントアクティビティで、次のコードを記述します。

            Calendar cal = Calendar.getInstance();
        Intent intent = new Intent(this,TestService.class);
        PendingIntent pIntent = PendingIntent.getService(this.getApplicationContext(), 0, intent, 0);
        alarm=  (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        alarm.setRepeating(AlarmManager.RTC_WAKEUP,cal.getTimeInMillis(), 3*1000, pIntent);

そして、マニフェストでサービスを宣言します。

        <service
      Android:name="TestService"
      Android:icon="@drawable/ic_launcher"
      Android:label="TestService"
      >
    </service>         
0
Igor Zelaya