1

アラームを使用してトリガーしたいかなり標準的なサービスがあります。サービスの開始セクションは次のとおりです。

class MyService extends Service {
    private Context context;
    private AlarmManager  alarmManager = null;

    private final String startReason = "com.stuff.myreason";
    private final int REASON_NO_INTENT = 0;
    private final int REASON_ALARM     = 1;
    private final int REASON_X         = 2; // and so on.

    @Override
    void onCreate() {
        super.onCreate();
        context = getApplicationContext();
        alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
        // do onCreate stuff
    }

    @Override
    int onStartCommand (Intent intent, int flags, int startId) {
        int reason = REASON_NO_INTENT;
        if (intent != null) {
            reason = intent.getExtra(startReason, REASON_NO_INTENT);
        }

        switch(reason) {
            // handle the different reasons we may have been "started"
        }

        return START_STICKY;
    }
}

アクティビティからcontext.startServiceを使用してトリガーすると、完全に正常に起動します。特に、すでに実行されている場合は、最初から(再)開始するのではなく、を介して既存のインスタンス化に入るだけonStartCommand()です。これは予想される動作です。ただし、AlarmManagerを使用してトリガーすると、次のようになります。

Intent intent = new Intent(context, MyService.class);
intent.putExtra(purposeOfStartCode, REASON_ALARM);

PendingIntent pi = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

alarmManager.set(AlarmManager.RTC_WAKEUP, /* A time in the future */, pi);

アラームの期限が来ると、サービスを最初から再開するように見えます。すでに実行中のインスタンス化を呼び出すだけonCreate()onStartCommand()なく、新しいインスタンス化を開始して呼び出します。onStartCommand()

私はすでにPendingIntentフラグをに変更して、改善なしFLAG_ONE_SHOTで置き換えることを試みました。contextMyService.this

私はこれにかなり戸惑っています-誰かがこの動作を説明し、期待どおりに動作させる方法を提案できますか?

編集-解決策をもたらしたアクションのコレクションは、以下の私の答えにあります。

4

3 に答える 3

4

いくつかの調査と作業の後、私は多くのことを発見しました。それらをすべて実行すると、この問題は解消されたように見えます。

  1. サービスで onStart と onStartCommand をオーバーライドして (古いデバイスを許可するために)、後者に super.onStartCommand を配置すると、onStart が呼び出されます。つまり、すべてのインテントが 2 回受信されます。

  2. 他の回答 (およびそれに関するコメント) の 1 つによると、AlarmManager は、他のタイプではなくブロードキャスト インテントを配信するように設計および指定されています。ただし、実際には、うるさいわけではなく、他の形式を尊重しているようです。これが問題解決のカギの一つだったと思います。

  3. サービスが他のアクティビティなどと同じプロセスにある場合、サービスが「再起動された」ように見えることがあります。これが、この質問に記載されている問題の実際の原因である可能性があります。onDestroyを呼び出さずに Android サービス onCreate が複数回呼び出されることを確認してください

  4. メッセンジャーをバインドして使用したり、メソッドをバインドしてアクセスしたりするのではなく、インテントのみを使用してサービスと通信する場合、物事はより安定しているようです。これらは両方とも正しいですが、管理が非常に複雑です (ただし、このアプローチを使用することもできます:サービス スレッドから Android アクティビティを呼び出すための推奨される方法とAndroidアプリケーション クラスを使用してデータを永続化する)。アンドロイドのドキュメントが私に同意しないことを十分に理解していますが、私の観察では、ブロードキャストの意図のみに移行することが重要であるように思われました. 別のプロセスアプローチを採用する場合は、とにかくこれを行う必要があります。

  5. クラスの宣言方法とアドレス指定方法に一貫性を持たせることには価値があります。少し面倒ですが、短い名前 (「CleverService」または「.CleverService」) ではなくフルネーム (「com.company.superapp.CleverService」) を使用する方が料金がかかる場合があるためです。したがって、常にフルネームを使用する方がよいでしょう。

  6. コンテキストに関する一般的な経験則 (「getApplicationContext を使用する」) は、実際には正しい方法ではありません。アクティビティ コンテキストまたはアプリケーション コンテキストをいつ呼び出すかを参照してください。; より広いコンテキストを使用し、変数を適切に管理する必要がない限り、本質的にこれを使用してください。

  7. 不要になったアクティビティ、サービス、スレッド、AsyncTask などで作成されたものである場合、ガベージ コレクターはまだ使用されているものをクリアすることができます。アプリケーションがサービスに基づいている場合は、入ってくるクラスのコピーを作成して、後で片付けられないようにするのが賢明かもしれません。

  8. よく提案されるよりもサービスを開始するためのより適切な方法は、アクションとしてサービスのフル ネームを持つインテント フィルターをサービスに与えることです。次に、クラス名だけを文字列として開始するインテントを作成できます。これは、コンテキストを気にする必要がないことを意味します。サービスの呼び出しに関する問題 を参照してください。

于 2013-03-28T20:00:07.733 に答える
1

さて、私はそれがあなたServiceをまったく動かしていることに実際に驚いています!あなたPendingIntentが渡すものAlarmManagerは放送である必要がありますIntent。したがって、コードを少し再設計する必要があります。はAlarmManagerをトリガーしBroadcastReceiverBroadcastRecieverはを呼び出すことができますstartService()

の説明を参照してくださいAlarmManager.set()

于 2013-03-15T14:44:45.550 に答える
0

次のコードを使用して、これを機能させました。

AlarmManager almgr = (AlarmManager)MyContext.getSystemService(Context.ALARM_SERVICE);
Intent timerIntent = new Intent(MyUniqueLabel);
timerIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
PendingIntent pendingOffLoadIntent = PendingIntent.getBroadcast(MyContext, 1, timerIntent, 0);

それが機能するためには、これらのことをしなければなりません。
1.) addFlags とインテントを呼び出し、それを FLAG_RECEIVER_FORGROUND に渡します
2.) PendingIntent.getBroadcast でゼロ以外のリクエスト コードを使用します

これらの手順のいずれかを除外すると、機能しません。

于 2013-11-26T01:30:26.720 に答える