2011-09-16 11 views
0

AsyncTaskのコードを実行するスティッキーサービス(START_STICKYを返します)がありますが、開始方法、開始、バインド、停止、バインド解除に問題があります。私は親の活動が生きている間だけサービスをしたい、私はそれがバックグラウンドでアプリが閉じられているときにぶらぶらしたくありませんが、私はオリエンテーションの変更を生き残るためにサービスが必要です。私は現在、アクティブなアクティビティの期間中、サービスをアクティブにする必要はないので、メイン作業が完了した後にstopSelf()を呼び出し、ServiceAsyncTaskでコールし、必要に応じてServiceを再度開始します。場合によっては、サービスが中断し、AsyncTaskを取り消し、別のデータから再開する必要があります。問題は、私が何をしていても、可能性のあるすべてのシナリオで確固たるものを得ることができないということです。誰かが見て、私が間違っていることを教えてもらえますか?スティッキーサービスの管理

マイServiceがある:私のカスタムViewが作成されたときに

public class ChordCalculatorService extends Service { 

    private final IBinder mBinder = new LocalBinder(); 
    private AsyncTask<SearchData, SearchStatusData, List<Item>> currentTask; 

    @Override 
    public void onCreate() {} 

    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     // We want this service to continue running until it is explicitly 
     // stopped, so return sticky. 
     return START_STICKY; 
    } 

    /** 
    * Class for clients to access. Because we know this service always runs in 
    * the same process as its clients, we don't need to deal with IPC. 
    */ 
    public class LocalBinder extends Binder { 
     public ChordCalculatorService getService() { 
      return ChordCalculatorService.this; 
     } 
    } 

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

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

    public SearchData getSearchData() { 
     return searchData; 
    }   

    public void startWork() { 
     if (currentTask != null && currentTask.getStatus() == Status.RUNNING) { 
      currentTask.cancel(true); 
     } 
     if(searchData != null) { 
      Worker task = new Worker(); 
      currentTask = task.execute(new SearchData[] { searchData }); 
     } else { 
      Message msg = handler.obtainMessage(ERROR, "No search data set"); 
      handler.sendMessage(msg); 
     } 
    } 


    class Worker extends AsyncTask<SearchData, SearchStatusData, List<Item>> { 
     // ... code ... 

     @Override 
     protected void onPostExecute(List<Item> result) { 
      Message msg = handler.obtainMessage(COMPLETE, new StatusData(Status.STATUS_FINISHED, result)); 
      handler.sendMessage(msg); 
      stopSelf(); 
     } 
    } 
} 

は現在、私はServiceが開始されています:

public class MyCustomView extends BasicFretBoardView { 

    private ServiceConnection conn; 
    private MyService myService; 
    private boolean isServiceStarted; 
    private boolean isServiceBound; 

    public MyCustomView(Context context, AttributeSet attr) { 
     super(context, attr); 
     startService(); 
    } 

    public void startService() { 
     Intent serviceIntent = new Intent(getContext(), MyService.class); 
     conn = new ServiceConnection() { 
      @Override 
      public void onServiceConnected(ComponentName name, IBinder service) { 
       myService = ((LocalBinder) service).getService(); 
       myService.registerHandler(serviceHandler); 
      } 

      @Override 
      public void onServiceDisconnected(ComponentName name) { 
       myService = null; 
      } 
     }; 

     // Explicitly start the service. Don't use BIND_AUTO_CREATE, since it 
     // causes an implicit service stop when the last binder is removed. 

     getContext().startService(serviceIntent); 
     getContext().bindService(serviceIntent, conn, 0); 
     isServiceStarted = true; 
     isServiceBound = true; 
    } 

    public void stopService() { 
     if (isServiceStarted) { 
      Intent serviceIntent = new Intent(getContext(), MyService.class); 
      getContext().stopService(serviceIntent); 
      isServiceStarted = false; 
     } 
     unBindService(); 
    } 


    public void unBindService() { 
     if(isServiceBound) { 
      getContext().unbindService(conn); 
      isServiceBound = false; 
     } 
    } 

    // gets called based on some user interaction 
    private void startServiceWork() { 
     if(!isServiceStarted) { 
      startService(); 
     } else { 
      myService.cancelCalcalation(); 
     } 
     myService.setData(data); 
     myService.startWork(); 
    } 
} 

およびサービスを停止するにはActivityに処理されます

public class CustomChordActivity extends Activity { 

    // ... code ... 

    @Override 
    public void onBackPressed() { 
     super.onBackPressed(); 
    } 

    @Override 
    protected void onPause() { 
     if(isFinishing()) { 
      chordsView.stopService(); 
     } 
     super.onPause(); 
    } 

    @Override 
    protected void onStop() { 
     super.onStop(); 
    } 

    @Override 
    protected void onDestroy() { 
     chordsView.unBindService(); 
     super.onDestroy(); 
    } 

    @Override 
    protected void finalize() throws Throwable { 
     super.finalize(); 
    } 
} 
+0

簡単な質問、なぜあなたはバインディングして、明示的にサービスを開始していますか?私はあなたがサービスにバインドするか、明示的に接続すると思っていました。 getContext()。startService(serviceIntent);が必要かどうかわからない。 – WindsurferOak

+0

**間違った削除されたコメントの置き換え**私はバインドでBIND_AUTO_CREATEを使用していないので、私は明示的にサービスを開始する必要があると思います – Martyn

答えて

0

あなたの仕事はオンデマンドで実行したいと思うかもしれません。IntentServiceがもっと適切なオプションになるかもしれません。作業が必要な場合(startServiceWork())、サービスを開始するだけでAsyncTaskが起動します。タスクが終了すると、サービスは終了します。

方向変更に関して、インテントフィルタが "android.intent.action.CONFIGURATION_CHANGED"である放送受信機を実装する必要があります。 (私は、オリエンテーションが変わったときにサービスが仕事をしたいと思っています)あなたの活動/メインUIスレッド内に放送受信機を置きます。これにより、実質的にブロードキャストレシーバのホスティングプロセスが主要なアプリケーションプロセスになり、ブロードキャストレシーバ内からサービスを開始するのがより安全になります。