7

Androidウィジェット、特にAndroidサービスについて質問があります。これが私がやりたいことです:電話で、ユーザーは私のウィジェットを彼のホームスクリーンに追加できるはずです。ウィジェットはネットワークからデータを取得します。これについていくつかのチュートリアルを読んだ後、最善のアプローチは、ネットワーク(TCPソケット)からデータを取得し、ウィジェットを絶えず更新するサービスを作成することであることがわかりました。これは、Runnableを特定の間隔で実行するScheduledExecutorServiceを使用して行われます。Runnableはサーバーに接続し、データを取得してウィジェットを更新する必要があります)。

私の問題は、画面がオフのときにウィジェットを更新する必要がないため、バッテリーの消耗のためにサービスを実行できないことです。私の質問は:それを最善の方法で行う方法は?

私は多かれ少なかれ私が望むことをする2つのアプローチを見つけました:

  1. ウィジェットの最初のインスタンスがホーム画面に追加されると、AndroidOSからACTION_SCREEN_ONおよびACTION_SCREEN_OFFインテントアクションを受信するブロードキャストレシーバーが登録されます。ACTION_SCREEN_ONが起動されると、アップデータサービスが開始されます。それ以外の場合は、停止されます。しかし、放送受信機の寿命のため、それが良いアプローチであるかどうかは本当にわかりません。

  2. ScheduledExecutorServiceによって定期的に実行され、実際にネットワーク処理を実行するアップデータサービスのRunnableで、画面がオンになっているかどうかをPowerManager.isScreenOn()で確認します。はいの場合、ネットワークコードを実行し、そうでない場合は実行しません。しかし、デバイスがスタンバイ状態になるとどうなりますか?このコードは実行されますか?ここでのバッテリーの消耗はどうですか?

私がやりたいことに対する「ベストプラクティス」のアプローチはありますか?私はAlarmManagerについてたくさん読みましたが、それは非常に強力なツールです。ディスプレイがオンのときにのみ実行されるように、これを使用してタスクをスケジュールできますか?

ご協力いただきありがとうございます。

よろしくNiThDi

4

2 に答える 2

3

この問題に対する最初の解決策(ウィジェット処理画面のオンとオフのブロードキャスト)は、進むべき道です。アプリケーションサーバーへのバックグラウンド通信用に新しいIntentServiceを開始します。完了したら、カスタムの「完了」ブロードキャストを結果とともに送信し、ウィジェットで処理します。

追加の利点として、ウィジェットの複数のインスタンスが1つの「ソース」から機能できるようになり、ユーザーがウィジェットを追加しなかった場合にリソースを消費しなくなります。

更新ウィジェットで画面のオン/オフブロードキャストを使用することは不可能なので、おそらくこれELAPSED_REALTIME( (ではない)アラーム付きのAlarmManager ELAPSED_REALTIME_WAKEUP)を使用して(意図的な)サービスの実行をスケジュールします。このように、画面がオフのときはサービスがスケジュールされませんが、オンのときは定期的に実行されます。また、画面のオンとオフの間の遅延が期間よりも長い場合は、画面がオンに戻ったときにすぐに実行されます。

ブロードキャストレシーバーの存続期間に関する質問については、前述のように、長時間実行されるタスクにIntentServiceを使用してから、結果をブロードキャストします。通話がブロックされないサービスを開始すると、放送受信機はタイムリーに終了します。

UPDATE 2この画面によると、 OFFはデバイスがスリープしていることを意味するものではありません。PowerManager.isScreenOn()を使用すると、この問題の解決策がすでにあります。

于 2013-01-18T15:48:00.800 に答える
0

ELAPSED_REALTIMEアプローチはうまくいくと思いますが、私が作成した小さなテストアプリ用ではありません。基本的に、テストアプリはウィジェットとIntentServiceです。ウィジェットは現在の時刻のみを表示しますが、インテントサービスは現在の時刻を取得し、ウィジェットがonReceive()メソッドで消費して自身を更新するブロードキャストを送信します。ウィジェットはもちろん、カスタムブロードキャストアクションの登録済みレシーバーです。ウィジェットのonEnabled()メソッドで、AlarmManagerのアラームを初期化します。今いくつかのコード:

ウィジェットonEnabled():

@Override
public void onEnabled(Context c) {
    super.onEnabled(c);

    Intent intent = new Intent(c.getApplicationContext(), SimpleIntentService.class);

    PendingIntent intentExecuted = PendingIntent.getService(c.getApplicationContext(), 45451894, intent,
            PendingIntent.FLAG_UPDATE_CURRENT);

    AlarmManager alarmManager = (AlarmManager) c.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
    alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, 0, 3000, intentExecuted);
}

ウィジェットonReceive():

@Override
public void onReceive(Context context, Intent intent) {
    super.onReceive(context, intent);
    if (intent.getAction().equals(ACTION_RESP)) {
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);

        ComponentName thisWidget = new ComponentName(context.getApplicationContext(), Widget.class);
        int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);

        for (int appWidgetId : allWidgetIds) {
            RemoteViews remoteViews = new RemoteViews(context.getApplicationContext().getPackageName(), R.layout.widget);

            String s = "";

            if (intent.hasExtra("msg")) s = intent.getStringExtra("msg");

            // Set the text
            remoteViews.setTextViewText(R.id.textView1, s);

            appWidgetManager.updateAppWidget(allWidgetIds, remoteViews);
        }
    }
}

SimpleIntentService onHandleIntent():

@Override
protected void onHandleIntent(Intent intent) {
    Log.w("TestService", "SimpleIntentService onHandleIntent called.");
    String msg = new Date().toGMTString();

    Intent broadcastIntent = new Intent();
    broadcastIntent.setAction(Widget.ACTION_RESP);
    broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
    broadcastIntent.putExtra("msg", msg);
    sendBroadcast(broadcastIntent);
}

そこで、Android4.2.1を実行しているNexus4とAndroid4.0.4を搭載したエミュレーターでこれをテストしました。どちらの場合も、手動で表示をオフにしても、SimpleIntentServiceが作成され、onHandleIntent()が3秒ごとに呼び出されます。なぜAlarmManagerがまだアラームをスケジュールしているのか、まったくわかりません。

ありがとうございました!

于 2013-01-20T18:36:57.480 に答える