2

私はAndroidサービスを持っており、そのサービスのメンバー変数にデータを収集しますが、時折(常にとはほど遠い)nullになります。このサービスがAndroidデバイスの配列でどれだけ長く実行されていても、私自身はこれを生成できませんでした。したがって、誰かがフォローに間違いを見つけたのではないかと思います(これは問題を説明するための簡略化された例であることに注意してください)。

public class CollectionService extends Service {
    private final CollectionServiceBinder binder = new CollectionServiceBinder();
    private PowerManager.WakeLock wakeLock;
    private UserData userData; // this is the object that sometimes becomes null

    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        wakeLock = ((PowerManager) getSystemService(POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AppId");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        if (wakeLock != null && wakeLock.isHeld()) {
            wakeLock.release();
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_STICKY;
    }

    public void startCollecting() {
        userData = new UserData();
        Notification notification = new Notification();
        // initializing notification variable

        startForeground(0xABCD, notification);

        // trigger logic that collects relevant data here, just imagine some Runnable that's triggered on a certain interval and adds data to the UserData value object.
    }

    public UserData finishCollecting() {
        try {
            userData.setFinishDate(new Date()); // throws NullPointerException every now and then.       return userData;
        } finally {
            if (wakeLock.isHeld()) {
                wakeLock.release();
            }
            stopForeground(true);
            userData = null;
        }
    }

    public boolean isCollecting() {
        return userData != null;
    }

    public class CollectionServiceBinder extends Binder {
        public CollectionService getService() {
            return CollectionService.this;
        }
    }
}

サービスは、...を使用するアクティビティで開始されます。

Intent i = new Intent(this, CollectionService.class);
getApplicationContext().startService(i);
getApplicationContext().bindService(i, serviceConnection, BIND_AUTO_CREATE); // just so the activity has a handle and can call startCollecting()/finishCollecting()

...そして...を使用してonDestroy()でバインド解除されます。

getApplicationContext.unbindService(serviceConnection);

ServiceConnectionクラスは次のようになります。

public class MyServiceConnection implements ServiceConnection {
    private CollectionService service;

    @Override
    public void onServiceConnected(ComponentName componentName, IBinder binder) {
        service = ((CollectionService.CollectionServiceBinder) binder).getService();
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        service = null;
    }

    public CollectionService getCollectionService() {
        return service;
    }
}

また、startCollectingは、次のようにOnClickListenerでトリガーされ、2回の開始を防ぎます。

if (!serviceConnection.getCollectionService().isCollecting()) {
    serviceConnection.getCollectionService().startCollecting();
}    

これはすべて問題ないと思いますが、userData(コード例でコメントされている)がnullになる場合があります。繰り返しになりますが、これは非常にまれです(Google Playにインストールされた50.000以上のアクティブなデバイスのうち、1年間で50件のレポートを受け取ったばかりですが、それでも、誰もがアプリを楽しめるようにしたいと思います)。

何か案は?

4

1 に答える 1

1

startCollectingあなたが呼び出す場所はあなたが初期化している場所であるため、関連する場所はわかりませんuserDataが、おそらく何が起こっているかは、何らかの理由でサービスが強制終了されてから再起動されていることです。必要に応じてデータを永続化/リロードするか、少なくとも遅延ロードして、データがuserData新たに開始されるようにする必要があります。

ここにすべてのコードがあるわけではありませんが、onCreate でウェイク ロックを取得するだけで、 で解放することに注意してくださいfinishCollecting。、 を呼び出す可能性がある場合はstartCollecting、同じで再度実行すると、ウェイクロックが保持されずにfinishCollecting実行されることになります。startCollectingServiceService

于 2013-02-21T00:30:54.977 に答える