多くのコンポーネントで構成されるアプリに取り組んでいます。
アプリはAlarmManager
、サーバーからのポーリングを行うために使用しています。データを表示する通常のアクティビティもあります ( と に保存されますSqlite
) SharedPreferences
。
デバイスが boot( BOOT_COMPLETED
) を終了しSharedPreferences
たContext
ときにポーリングを開始する機能を追加しようとするまで、すべてがうまくonReceive(Context context, Intent intent)
機能していましたBroadcastReceiver
。
もう 1 つのことは、Singleton を使用してすべての機能を処理していることSharedPreferences
ですDB
。この Singleton は、アプリContext
の最初のランチ アクティビティ( LoginActivity
) を保持します。アプリ全体と Polling で使用しますBroadcastReciver
。
だから私は理解しています(信じています...)デバイスがブートを終了すると、私は別 Context
のものになり(私が取得していたLoginActivity
コンテキストではありません)、これが問題の原因です(それは???)
このすべての前文の後、私が本当に必要としているのは、そのようなタスクのベストプラクティスアプローチです-アプリ上SharedPreferences
およびDB
アプリ全体でデータを保存および取得する方法:
- ユーザーがそれを実行するとき
- 経由でバックグラウンドタスクを実行するとき
AlarmManager
BOOT_COMPLETED
ブロードキャスト経由で自動起動するとき
Context
この問題に苦しむことなく。例は素晴らしいでしょう。
編集: ここに私のコードスニペットがあります:
ConnectionManager.java
- このクラスは REST リクエストの実装を保持し、SharedPreferences にデータを保存します:
public class ConnectionManager {
//There are many more variables here - irrelevant for the example
private CookieStore _cookieStore;
private static ConnectionManager _instance;
private SharedPreferences _sharedPref;
private Context _context;
private DataPollingBroadcastReceiver _dataPoller;
private ConnectionManager(Context caller) {
_context = caller;
_sharedPref = PreferenceManager.getDefaultSharedPreferences(_context);
}
public static ConnectionManager getInstance(Context caller) {
if (_instance == null) {
_instance = new ConnectionManager(caller);
}
return _instance;
}
public void setPollingActive(boolean active) {
if (active) {
SharedPreferences.Editor editor = _sharedPref.edit();
editor.putString("myapp.polling", "true");
editor.commit();
startRepeatingTimer();
} else {
SharedPreferences.Editor editor = _sharedPref.edit();
editor.putString("myapp.polling", "false");
editor.commit();
cancelRepeatingTimer();
}
}
private void startRepeatingTimer() {
if (_dataPoller!= null) {
_dataPoller.SetAlarm(_context);
} else {
Toast.makeText(_context, "_dataPoller object is null",
Toast.LENGTH_SHORT).show();
}
}
private void cancelRepeatingTimer() {
if (_dataPoller!= null) {
_dataPoller.CancelAlarm(_context);
} else {
Toast.makeText(_context, "_dataPoller object is null",
Toast.LENGTH_SHORT).show();
}
}
//There are many more methods here - irrelevant for the example
}
MainBootListener.java
: このクラスは、ポーリング メカニズムをアクティブにすることを想定しています - ConnectionManager に例外があるため、機能していません。
public class MainBootListener extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Activated by boot event",
Toast.LENGTH_LONG).show();
ConnectionManager cm = ConnectionManager.getInstance(context);
cm.setPollingActive(true);
}
}
DataPollingBroadcastReceiver.java
: サーバーからデータをポーリングするこのクラス
public class DataPollingBroadcastReceiver extends BroadcastReceiver {
private ConnectionManager _mngr;
@Override
public void onReceive(Context context, Intent intent) {
if (_mngr == null) {
_mngr = ConnectionManager.getInstance(context);
}
PowerManager pm = (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, TAG);
// Acquire the lock
wl.acquire();
// You can do the processing here update the widget/remote views.
Bundle extras = intent.getExtras();
StringBuilder msgStr = new StringBuilder();
Format formatter = new SimpleDateFormat("hh:mm:ss");
msgStr.append(formatter.format(new Date()));
// /////
_mngr.updateDataFromServer();
msgStr.append(" [Updated AccessControlTable]");
Log.i(TAG, msgStr.toString());
Toast.makeText(context, msgStr, Toast.LENGTH_SHORT).show();
// ////
// Release the lock
wl.release();
}
public void SetAlarm(Context context) {
if (_mngr == null) {
_mngr = ConnectionManager.getInstance(context);
}
AlarmManager am = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, DataPollingBroadcastReceiver.class);
intent.putExtra(ONE_TIME, Boolean.TRUE);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
1000 * _mngr.getPollingIntervalInSeconds(), pi);
}
public void CancelAlarm(Context context) {
if (_mngr == null) {
_mngr = ConnectionManager.getInstance(context);
}
Intent intent = new Intent(context, DataPollingBroadcastReceiver.class);
PendingIntent sender = PendingIntent
.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
}
}
もちろん、もっと多くのクラスがあります-私は必要最小限のものを持ってくるようにしています.
編集私が受け取った例外2:アプリケーションからポーリングメカニズムがアクティブであり(シングルトーンがLoginActivityをコンテキストとして保持している)、タスクマネージャーからアプリケーションを閉じると、ポーリングが停止し、この例外が表示されました:
12-29 14:02:03.061: E/AndroidRuntime(9402): FATAL EXCEPTION: main
12-29 14:02:03.061: E/AndroidRuntime(9402): java.lang.RuntimeException: Unable to start receiver my.app.DataPollingBroadcastReceiver : java.lang.NullPointerException
12-29 14:02:03.061: E/AndroidRuntime(9402): at android.app.ActivityThread.handleReceiver(ActivityThread.java:2277)
12-29 14:02:03.061: E/AndroidRuntime(9402): at android.app.ActivityThread.access$1500(ActivityThread.java:140)
12-29 14:02:03.061: E/AndroidRuntime(9402): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
12-29 14:02:03.061: E/AndroidRuntime(9402): at android.os.Handler.dispatchMessage(Handler.java:99)
12-29 14:02:03.061: E/AndroidRuntime(9402): at android.os.Looper.loop(Looper.java:137)
12-29 14:02:03.061: E/AndroidRuntime(9402): at android.app.ActivityThread.main(ActivityThread.java:4898)
12-29 14:02:03.061: E/AndroidRuntime(9402): at java.lang.reflect.Method.invokeNative(Native Method)
12-29 14:02:03.061: E/AndroidRuntime(9402): at java.lang.reflect.Method.invoke(Method.java:511)
12-29 14:02:03.061: E/AndroidRuntime(9402): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
12-29 14:02:03.061: E/AndroidRuntime(9402): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
12-29 14:02:03.061: E/AndroidRuntime(9402): at dalvik.system.NativeStart.main(Native Method)
12-29 14:02:03.061: E/AndroidRuntime(9402): Caused by: java.lang.NullPointerException
12-29 14:02:03.061: E/AndroidRuntime(9402): at my.app.ConnectionManager.<init>(ConnectionManager.java:172)
12-29 14:02:03.061: E/AndroidRuntime(9402): at my.app.ConnectionManager.getInstance(ConnectionManager.java:196)
12-29 14:02:03.061: E/AndroidRuntime(9402): at my.app.DataPollingBroadcastReceiver .onReceive(DataPollingBroadcastReceiver .java:27)
12-29 14:02:03.061: E/AndroidRuntime(9402): at android.app.ActivityThread.handleReceiver(ActivityThread.java:2270)
12-29 14:02:03.061: E/AndroidRuntime(9402): ... 10 more
アプリが実行されていないときに2番目の例外が発生し、シングルトーンが初期化しようとしたよりも、adbからBOOT_COMPLETEDを送信しました。BroadcastReciver コンテキストを使用します。これは例外でした:
12-26 11:54:58.556: E/AndroidRuntime(12373): FATAL EXCEPTION: main
12-26 11:54:58.556: E/AndroidRuntime(12373): java.lang.RuntimeException: Unable to start receiver my.app.MainBootListener : java.lang.NullPointerException
12-26 11:54:58.556: E/AndroidRuntime(12373): at android.app.ActivityThread.handleReceiver(ActivityThread.java:2277)
12-26 11:54:58.556: E/AndroidRuntime(12373): at android.app.ActivityThread.access$1500(ActivityThread.java:140)
12-26 11:54:58.556: E/AndroidRuntime(12373): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
12-26 11:54:58.556: E/AndroidRuntime(12373): at android.os.Handler.dispatchMessage(Handler.java:99)
12-26 11:54:58.556: E/AndroidRuntime(12373): at android.os.Looper.loop(Looper.java:137)
12-26 11:54:58.556: E/AndroidRuntime(12373): at android.app.ActivityThread.main(ActivityThread.java:4898)
12-26 11:54:58.556: E/AndroidRuntime(12373): at java.lang.reflect.Method.invokeNative(Native Method)
12-26 11:54:58.556: E/AndroidRuntime(12373): at java.lang.reflect.Method.invoke(Method.java:511)
12-26 11:54:58.556: E/AndroidRuntime(12373): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
12-26 11:54:58.556: E/AndroidRuntime(12373): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
12-26 11:54:58.556: E/AndroidRuntime(12373): at dalvik.system.NativeStart.main(Native Method)
12-26 11:54:58.556: E/AndroidRuntime(12373): Caused by: java.lang.NullPointerException
12-26 11:54:58.556: E/AndroidRuntime(12373): at my.app.ConnectionManager.<init>(ConnectionManager.java:172)
12-26 11:54:58.556: E/AndroidRuntime(12373): at my.app.ConnectionManager.getInstance(ConnectionManager.java:196)
12-26 11:54:58.556: E/AndroidRuntime(12373): at my.app.MainBootListener .onReceive(MainBootListener .java:14)
12-26 11:54:58.556: E/AndroidRuntime(12373): at android.app.ActivityThread.handleReceiver(ActivityThread.java:2270)
12-26 11:54:58.556: E/AndroidRuntime(12373): ... 10 more