5

GPS/ネットワークの場所を読み取るサービスをバックグラウンドで実行しており、次のことを行う必要があります。

  • アプリの再起動時に中断することなくバックグラウンドで実行し、殺されることなく可能な限り存続させます (これは、以下のマーリンのコメントの助けを借りて解決されます)

  • 受信した新しい場所で、Web サービスを呼び出して、読み取った場所を送信します

  • 60 秒ごとに反復タスクを実行し、最後の位置情報を Web サービスに再送信します。これは、ユーザーが同じ位置に留まっている場合に役立ちます。

私が考えたことがいくつかありますが、正しく理解できたかどうかはわかりません。サービスはメイン アプリと同じスレッドで実行されるため、UI スレッドと同じスレッドでサーバーに場所を送信すると、UI がフリーズする可能性があり、これは適切ではありません。また、GPS/ネットワーク リスナーが独自のスレッドを持っているか、アプリと同じスレッドを使用しているかどうかもわかりません。

わかりやすくするために、サービスの短縮コードを次に示します。

public class GPSLoggerService extends Service {
@Override
public void onCreate() {
    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 50, locationListenerNetwork);
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 50, locationListenerGps);

    scheduleTaskExecutor = Executors.newScheduledThreadPool(5);
    scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
        @Override
        public void run() {
                updateLocation(lastLocation);
        }, 60, 60, TimeUnit.SECONDS);

    return START_STICKY;
}

LocationListener locationListenerGps = new LocationListener() {
    @Override
    public void onLocationChanged(Location location) {
        updateLocation(location);
    }
...
}    

LocationListener locationListenerNetwork = new LocationListener() {
    @Override
    public void onLocationChanged(Location location) {
        updateLocation(location);
    }
...
}

private void updateLocation(Location readLocation) {
    //web service call
    String response = WebServiceCalls.updateLocation(readLocation);

    //log data in a local Sqlite database
    saveLocation(readLocation) 
}

私の主な関心事は、 updateLocation 呼び出しを処理し、それをメイン アプリ スレッドとは別のスレッドにする方法です。scheduleTaskExecutor 私はそれが行くべき道ではないと信じています。場合によっては、stopService() を呼び出した後でも、TaskExecutor にシャットダウンするように指示しても、サービスが存続することがあります。サービスが停止していない別の説明が見つかりません。要約すると、リスナーが新しい場所を受信するたびに場所を送信し、60 秒ごとに再送信する必要があります。また、アクティブなスレッドをキャンセルして、サービスをすばやく停止できるようにする必要もあります。

私のケースをどのように処理することをお勧めしますか?

4

4 に答える 4

4

私は IntentService を使用し、AlarmManager を使用してインテントを起動します。

これの主な利点は、バックグラウンドで作業を行うため、心配するスレッド コードがないことです。

アップデート

別の興味深いアプローチは、https://stackoverflow.com/a/7709140/808940にあります。

于 2012-07-09T20:50:03.990 に答える
2
  • サービスは、スレッドではなく、メイン アプリと同じプロセスを実行します。また、別のプロセスでサービスを実行する場合は、 android:processタグを使用できます。

  • 60 秒では短すぎるため、60 秒ごとに WebService を呼び出す理由がわかりません。また、ネットワーク通信が必要でコストのかかる操作であるため、場所が変更されていない場合は WebService の呼び出しをスキップする必要があります。

  • Executor を使用する必要はありません。スレッドの数はできるだけ少なくする必要があります。特定の間隔でタスクを実行するには、AlarmManager を使用して特定の時間にインテントを配信します。アラームを設定するにはsetRepeating()メソッドを確認してください。

  • もう 1 つは、Listener でタスクを実行しないようにすることです。受信者/リスナーがブロックされ、候補が強制終了されると見なす前に、システムが許可する 10 秒のタイムアウトがあるためです。ハンドラーを使用して、バックグラウンド スレッドでタスクを実行する必要があります (つまり、リスナーから更新を受け取るたびにメッセージをハンドラー キューに追加すると、ハンドラー スレッドが解放されたときにメッセージが選択されます)。

于 2012-07-12T16:16:33.967 に答える
1

サービスが破壊されるのを防ぐために、フォアグラウンドサービスとしてサービスを開始できます。

また、onLocationChanged()メソッドから場所を取得した後、非同期タスクを使用して場所をWebサービスに送信し、UIがブロックされないようにすることができます。

編集

  1. requestLocationUpdatesメソッドで、最小時間と最小移動距離を設定できます。したがって、サーバーに場所を送信するためにスケジューラタスクを使用する必要はないと思います。最小時間と最小距離に関する議論によると、ロケーションマネージャーはロケーションをチェックします。場所が変更された場合は、新しいLocationでonLocationChanged()メソッドを呼び出します。これで、ユーザーに関するソリューションは同じ位置にとどまります。2つの連続するロケーションlocation1とlocation2の間に1時間の差がある場合、ユーザーがlocation1に1時間滞在したことを意味するように、ロジックをサーバー側に変更できます。

  2. 単一のLocationListenerクラスを使用して、GPSおよびNETWORKの場所をリッスンできます。

  3. onLocationChanged()メソッドで場所を取得すると、非同期タスクを使用してその場所を送信できます。
  4. 場所を取得したら、その場所を設定またはデータベースに保存して、GPSとネットワークプロバイダーが同じ場所を送信している天気を確認できるため、追跡する場合は、webAPI呼び出しを保存して、バッテリーの一部を節約できます。
于 2012-07-10T04:45:51.607 に答える
-1

AsynchTask を使用する必要があります。

public class RefreshTask extends AsyncTask<Integer, Void, Integer> {



    /**
     * The system calls this to perform work in a worker thread and delivers
     * it the parameters given to AsyncTask.execute()
     */

    public RefreshTask() {

    }

    protected Integer doInBackground(Integer... millis) {
        try{
            int waitTime = 0;
            while(waitTime<60000){
                Thread.sleep(100);
                waitTime += 100;
            }

            //update location here

        }catch(InterruptedException e){

        }



        return 1;
    }

    /**
     * The system calls this to perform work in the UI thread and delivers
     * the result from doInBackground()
     */
    protected void onPostExecute(Integer result) {
        new RefreshTask.execute();
    }


}
于 2012-07-15T23:30:42.713 に答える