1

サービスを開始および停止するためのボタンが1つある小さなデータ収集アプリがあります。

次に、サービスは新しいスレッドを開始します。放送があるたびに電圧変化に関するデータを収集します。

データは一時的にArrayListに格納され、10秒ごとにarrayListに格納されているすべてのデータがデータベースにダンプされます。

アプリは10〜20分間正常に実行されていますが、20分後にアプリは自動的に停止します。サービスがまだ実行されている場合もあれば、サービスが強制終了されている場合もあります。

ここで何が問題になるのか教えていただけますか。この問題に関連すると思われることは次のとおりです。

1.>データベースを10秒ごとに開いたり閉じたりしています。アプリ全体が終了したときにのみデータベースを閉じるように設計を変更する必要があります。

2.>私もウェイクロックを取りましたが、それは何の違いもありませんでした。私のサービスにもウェイクロックを取る必要がありますか?

3.>そして最後に、アプリが停止したためにエラーを知るにはどうすればよいですか(USBに接続して、バッテリーを消耗モードにしたいことを知ることができません)

更新

logcatエラーは次のとおりです。

E/AndroidRuntime( 9770): FATAL EXCEPTION: Timer-0
E/AndroidRuntime( 9770): java.util.ConcurrentModificationException
E/AndroidRuntime( 9770):    at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:569)
E/AndroidRuntime( 9770):    at com.amazon.hsyal.services.LoggerThread$2.run(LoggerThread.java:78)
E/AndroidRuntime( 9770):    at java.util.Timer$TimerImpl.run(Timer.java:284)
W/ActivityManager(  236):   Force finishing activity com.amazon.hsyal/.ui.VoltageSODLoggerActivity
I/ActivityManager(  236): No longer want com.amazon.dcp:OTAService (pid 12299): hidden #16
I/WindowManager(  236): WIN DEATH: Window{417dcd20 com.amazon.hsyal/com.amazon.hsyal.ui.VoltageSODLoggerActivity paused=true}
I/UsageStats(  236): No package stats for pkg:com.amazon.kindle.otter
I/ActivityManager(  236): Process com.amazon.hsyal (pid 9770) has died.
W/ActivityManager(  236): Scheduling restart of crashed service com.amazon.hsyal/.services.LoggerService in 5000ms
I/ActivityManager(  236): Start proc com.amazon.kindle for broadcast com.amazon.kindle/.PrimeAppReceiver: pid=13075 uid=32022 gids={3003, 1015}
W/ActivityManager(  236): Activity pause timeout for ActivityRecord{4173eb10 com.amazon.kindle.otter/.Launcher}
I/ActivityManager(  236): Start proc com.android.settings for broadcast com.android.settings/.TopWindowChangereceiver: pid=13111 uid=1000 gids={1015, 3002, 3001, 3003}
I/ActivityManager(  236): Start proc com.amazon.hsyal for service com.amazon.hsyal/.services.LoggerService: pid=13138 uid=10051 gids={}
W/ActivityManager(  236): Activity destroy timeout for ActivityRecord{41750838 com.amazon.hsyal/.ui.VoltageSODLoggerActivity}

対応するスレッドコードは次のとおりです。

public void run() {
    // TODO Auto-generated method stub
    dbInstance = new DbClass(ctx);
    Log.d("Debuglogger","Came inside thread");
    ctx.registerReceiver(this.voltageReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));

    Timer timer = new Timer();
    timer.schedule(new TimerTask() {
        @Override
        public void run() {
            // TODO Auto-generated method stub
            if(threadStatus == false){
                return;
            }
            if(!DataClass.dataList.isEmpty()){
                dbInstance.open();
                Iterator<DataClass> itr = DataClass.dataList.iterator();
                DataClass a_temp;
                while(itr.hasNext()){
                    a_temp = itr.next();
                    dbInstance.createEntry(a_temp.getVoltage(), a_temp.getCurrent(), a_temp.getBattery_level(),
                            a_temp.getTime(), a_temp.getRtime());
                }
                dbInstance.close();
                DataClass.dataList.clear();
                Log.d("db-error", "Data written to database and list cleared !");
            }
        }}, 0, UPDATE_INTERVAL);
}
4

1 に答える 1

1

スタックトレースからわかるように、エラーは複数のスレッドからjava.util.ConcurrentModificationExceptionにアクセスしているためと思われます。イテレータを使用するときにConcurrentModificationExceptionを回避ArrayListする方法を確認できます。その関連部分は次のとおりです。

マルチスレッド環境でConcurrentModificationExceptionを回避するには:

  1. リストを配列に変換してから、配列を反復処理できます。このアプローチは、小規模または中規模のリストには適していますが、リストが大きい場合は、パフォーマンスに大きく影響します。

  2. 同期ブロックにリストを配置することにより、反復中にリストをロックできます。このアプローチは、マルチスレッドの利点を失うため、お勧めしません。

  3. JDK1.5以降を使用している場合は、ConcurrentHashMapクラスとCopyOnWriteArrayListクラスを使用できます。これが推奨されるアプローチです。


1.>データベースを10秒ごとに開いたり閉じたりしています。アプリ全体が終了したときにのみデータベースを閉じるように設計を変更する必要があります。

10秒ごとにデータベースを開いたり閉じたりするためのオーバーヘッドはそれほど多くありません。これは、パフォーマンスに問題がある場合にのみ考えてください。

2.>私もウェイクロックを取りましたが、それは何の違いもありませんでした。私のサービスにもウェイクロックを取る必要がありますか?

特定の問題に関連していないようです。

3.>そして最後に、アプリが停止したためにエラーを知るにはどうすればよいですか(USBに接続して、バッテリーを消耗モードにしたいことを知ることができません)

これがどのように行われるかをすでに理解していることを願っています。繰り返しになりますが、アプリケーションが停止した後でも、DDMSまたはadbコマンドを使用してlogcat出力を取得できます。adb logcat -d > log.txt

于 2012-07-02T06:29:36.790 に答える