14

背景情報:

アプリが閉じられている場合でも、約 1 時間ごとに Web からいくつかのデータを更新する必要があります。データ自体の更新には40秒~1分程度かかります。その後、Serializable としてファイルに保存されます。このファイルは、アプリの起動時に読み取られます。

これは私が今のところ取ったアプローチです(サービスを使用していません)

次のように AlarmManager と BroadcastReceiver を使用します。

private void set_REFRESH_DATA_Alarm(){
    mContext = Main.this;
    alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
    broadcast_intent = new Intent(mContext, 
            RepeatingAlarmReceiver_REFRESH_DATA.class);
    pendingIntent = PendingIntent.getBroadcast(mContext, 0,  broadcast_intent, 0);
    // do a REFRESH every hour, starting for the first time in 30 minutes from now ...
    Calendar now = Calendar.getInstance();
    long triggerAtTime = now.getTimeInMillis()+ (1 * 30 * 60 * 1000); // starts in 30 minutes
    long repeat_alarm_every = (1 * 60 * 60 * 1000); // repeat every 60 minutes
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtTime, 
            repeat_alarm_every, pendingIntent);
}

私のRepeatingAlarmReceiver_REFRESH_DATA.classは、Web からのデータの更新を処理します。

public class RepeatingAlarmReceiver_REFRESH_DATA extends BroadcastReceiver {

    public static Context mContext;
    ConnectivityManager mConnectivity;

    @Override
    public void onReceive(Context context, Intent intent) {
        mContext = context;
        // if Network connection is OK (Wifi or Mobile) then Load data ...
        mConnectivity = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        Log.i("Hub",
                "mConnectivity.getNetworkInfo(0)="
                        + mConnectivity.getNetworkInfo(0));
        Log.i("Hub",
                "mConnectivity.getNetworkInfo(1)="
                        + mConnectivity.getNetworkInfo(1));
        if ((mConnectivity.getNetworkInfo(0).getState() == NetworkInfo.State.CONNECTED)
                || (mConnectivity.getNetworkInfo(1).getState() == NetworkInfo.State.CONNECTED)) {
            Log.i("Hub", "Connectivity OK ...");
            Refresh_HIST_DATA();
        } else {
            // else Show Dialog "No network connection" ...
            Log.i("Hub",
                    "No network connection for the moment... will try again later!");
        }
    }

    // =========================================================================
    private void Refresh_HIST_DATA() {
        Log.i("Hub", "Refresh_HIST_DATA()... Starting ...");
        // etc...
    }
}

私が持っているマニフェストで:

<receiver android:name="com.cousinHub.myapp.RepeatingAlarmReceiver_REFRESH_DATA" android:process=":remote" />

問題 :

アラームは時間通りに起動され、更新が開始されますが、約 10 秒後に停止します (タイムアウト):

06-25 11:55:05.278: WARN/ActivityManager(76): ブロードキャスト BroadcastRecord{44bb4348 null} のタイムアウト - receiver=android.os.BinderProxy@44bcc670

06-25 11:55:05.278: WARN/ActivityManager(76): タイムアウト中の受信者: ResolveInfo{44bb42c0 com.cousinHub.myapp.RepeatingAlarmReceiver_REFRESH_DATA p=0 o=0 m=0x0}

06-25 11:55:05.278: 情報/プロセス (76): 信号を送信しています。PID: 819 SIG: 9

06-25 11:55:05.298: INFO/ActivityManager(76): プロセス com.cousinHub.myapp:remote (pid 819) が停止しました。

ps: 奇妙なことに、この「タイムアウト」は、HTC Hero (まだ Android 1.5 - API レベル 4) では約 10 秒後に発生しませんが、Nexus One (2.1-update1) では問題ありません。

質問:

  1. なぜこのタイムアウト?これを回避する簡単な方法はありますか?
  2. マニフェストで BroadcastReceiver を正しく設定しましたか? (このタイムアウトを回避するために) 何かを追加する必要がありますか?
  3. この種の「Web から更新」機能のサービスを絶対に利用する必要がありますか? (この記事を考慮: http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/ ) YES の場合 (サービスに切り替える必要があります): 適切なコード スニペット/これのチュートリアル...

いつものように、あなたの助けに感謝します.

H.

4

3 に答える 3

18

なぜこのタイムアウト?

メイン アプリケーション スレッドで実行しています。メイン アプリケーション スレッドで数秒以上実行することはできません。また、これを行っている間、ゲームやビデオでフレームレートの損失を引き起こすなど、デバイスのパフォーマンスを損なっています (フォアグラウンド優先で実行しているため)。

これを回避する簡単な方法はありますか?

メイン アプリケーション スレッドで重要な作業 (>100ms) を実行しないでください。BroadcastReceiverデリゲートをIntentService、おそらくに持ってくださいWakefulIntentService

マニフェストで BroadcastReceiver を正しく設定しましたか?

どうぞどうぞどうぞお手にとってくださいandroid:process=:remote。あなたはそれを必要としません、それはあなたを助けません、そしてそれはデバイスのパフォーマンスをさらに低下させます.

この種の「Web から更新」機能のサービスを絶対に利用する必要がありますか? (この記事を考慮: http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/ ) YES の場合 (サービスに切り替える必要があります): 適切なコード スニペット/これのチュートリアル ...

私見、はい。それからまた、私はそのブログ記事を書きました。例については、WakefulIntentServiceプロジェクトを参照してください。

于 2010-06-25T11:37:09.903 に答える
1

詳細については、新しいスレッドで試してみましたが、Wifi で動作します (電話がスリープ状態のときにデータを更新するのに約 1'30" かかりますが、「強制終了」されません!

//let's try with a new separate thread ?
        new Thread(new Runnable() {
            public void run() {
                Refresh_HIST_DATA();
            }
          }).start();

ただし、約 10 秒後に終了するため、モバイル (GPRS) ではそうではありません!

それは今のところ半分の解決策であり、CommonsWare の解決策をよりクリーンで持続可能なアプローチとして試してみます...

新しいスレッド ソリューションが常に正常に機能するのか、それとも単に運が良かったのかを見てみましょう (数時間しかテストしていません) ...

他の誰かが別の提案を持っている場合は、投稿してください。

于 2010-06-25T13:49:20.283 に答える
0

スレッドの代わりに。ブロードキャストレシーバーのonRecive()メソッドからAsyncTaskを開始できます。これにより、UIスレッドがブロックされることはありません。私自身も同じ性質のプロジェクトで同じことをしました。つまり、1時間ごとにデータを投稿する必要があります。

public void onReceive(Context context, Intent intent) {
        // start your Asynctask from here. which will post data in doInBackground() method
}
于 2012-08-28T06:56:20.817 に答える