2011-09-16 2 views
0

AsyncTask에 몇 가지 코드를 실행하는 고정 서비스 (START_STICKY을 반환)가 있는데, 어떻게 시작해야하는지, 시작, 바인딩, 중지, 바인딩 해제와 관련된 문제가 있습니다. 나는 부모 활동이 살아있는 동안 서비스 만 원한다. 나는 앱이 닫혀있을 때 배경에 매달 리고 싶지 않다. 그러나 오리엔테이션 변화에서 생존하기 위해서는 서비스가 필요하다. 현재 활성 상태의 전체 기간 동안 활성 상태 인 서비스가 필요하지 않으므로 주 작업이 AsyncTaskService에 완료된 후 stopSelf()를 호출 한 다음 필요시 다시 Service을 시작하십시오. 때로는 서비스가 수행중인 작업을 중단하고 AsyncTask을 취소하고 다른 데이터로 다시 시작해야합니다. 문제는 내가하는 일과 상관없이 가능한 모든 다른 시나리오에서 견고 해 보이지 않는다는 것입니다. 누구든지 훑어보고 내가 뭘 잘못하고 있는지 말해 줄 수 있습니까?고정 서비스 관리

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(); 
    } 
} 

현재
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(); 
     } 
    } 
} 

내 사용자 정의 View이 생성 될 때 시작되는 Service

+0

빠른 질문, 왜 바인딩하고 명시 적으로 서비스를 시작하고 있습니까? 서비스에 바인딩하거나 명시 적으로 연결하는 것으로 생각했습니다. getContext(). startService (serviceIntent);가 필요한지 잘 모르겠습니다. – WindsurferOak

+0

** 잘못된 삭제 된 주석 대체 ** bind에서 BIND_AUTO_CREATE를 사용하지 않기 때문에 서비스를 명시 적으로 시작해야한다고 생각합니다. – Martyn

답변

0

IntentService가 더 적합한 옵션이 될 수 있습니다. 작업이 완료되면 (startServiceWork()), 서비스를 시작하면 AsyncTask가 시작됩니다. 작업이 완료되면 서비스가 완료됩니다.

이제 오리엔테이션 변경과 관련하여 인 텐트 필터가 "android.intent.action.CONFIGURATION_CHANGED"인 방송 수신기를 구현해야합니다. (나는 오리엔테이션이 바뀔 때 서비스를하기를 원한다고 가정한다.) 브로드 캐스트 리시버를 당신의 활동/주 UI 스레드 안에 놓는다. 사실상 브로드 캐스트 수신기의 호스팅 프로세스가 브로드 캐스트 수신기 내에서 서비스를 시작하는 것이 더 안전하게 만드는 주요 응용 프로그램 프로세스가됩니다.