LaPlayer(1)------Service淺析

  Service是一個長期運行在後臺,並不提供界面的應用組件。其餘組件能夠啓動一個服務,而且即便用戶切換到其餘的應用,該服務仍可在後臺繼續運行。另外,組件能夠把某個服務邦定到本身,來與其交互通訊,甚至包括執行進程間通訊(IPC)。所以在播放器的開發中,爲了讓播放音樂不依賴於具體的Activity,將播放音樂的控制放於Service中。html

  Service和Activity同樣,須要在AndroidMainfest.xml中進行配置,配置以下:android

1         <service  
2             android:name="com.porco.service.PlayService"   android:exported="false">
3             <intent-filter>
4                 <action android:name="PlayService" />
5             </intent-filter>
6         </service>        

    在此處設置了android:exported這個屬性。這是用於指示該服務是否可以被其餘應用程序組件調用或跟它交互:若是設置爲true,則可以被調用或交互,不然不能。設置爲false時,只有同一個應用程序的組件或帶有相同用戶ID的應用程序才能啓動或綁定該服務。
 它的默認值依賴與該服務所包含的過濾器。沒有過濾器則意味着該服務只能經過指定明確的類名來調用,這樣就是說該服務只能在應用程序的內部使用(由於其餘外部使用者不會知道該服務的類名),所以這種狀況下,這個屬性的默認值是false。另外一方面,若是至少包含了一個過濾器,則意味着該服務能夠給外部的其餘應用提供服務,所以默認值是true,此種狀況下在Eclipse中會有警告信息:Exported service does not require permission。ide

  Service的使用方式有兩種:context.s在tartService() 和 context.bindService()。其生命週期分別是:post

 

  context.startService() 啓動流程:學習

  context.startService()  -> onCreate()  -> onStartCommand()  -> Service running  -> context.stopService()  -> onDestroy()  -> Service stop 測試

  若是Service尚未運行,則android先調用onCreate(),而後調用onStartCommand();ui

  若是Service已經運行,則只調用onStartCommand(),因此一個Service的onStartCommand方法可能會重複調用屢次。 this

  若是stopService的時候會直接onDestroy,若是是調用者本身直接退出而沒有調用stopService的話,Service會一直在後臺運行,該Service的調用者再啓動起來後能夠經過stopService關閉Service。url

  因此調用startService的生命週期爲:onCreate --> onStart (可屢次調用) --> onDestroyspa

 

  context.bindService()啓動流程:

  context.bindService()  -> onCreate()  -> onBind()  -> Service running  -> onUnbind()  -> onDestroy()  -> Service stop

  onBind()將返回給客戶端一個IBind接口實例,IBind容許客戶端回調服務的方法,好比獲得Service的實例、運行狀態或其餘操做。這個時候把調用者(Context,例如Activity)會和Service綁定在一塊兒,Context退出了,Srevice就會調用onUnbind->onDestroy相應退出。 

  因此調用bindService的生命週期爲:onCreate --> onBind(只一次,不可屢次綁定) --> onUnbind --> onDestory。

  在Service每一次的開啓關閉過程當中,只有onStart可被屢次調用(經過屢次startService調用),其餘onCreate,onBind,onUnbind,onDestory在一個生命週期中只能被調用一次。

 

  在具體使用時,可分爲如下三種狀況:

  1.startService啓動服務。

  2.bindService啓動服務。

  3.startService & bindService 啓動服務。

 

  爲了測試不一樣狀況下的service的調用及生命週期,編寫測試demo代碼以下:

Activity部分·:

public class PlayActivity extends Activity {

    private Intent intent=new Intent("tService");
    private Button mButtonBind;
    private Button mButtonUnbind;
    private Button mButtonplay; 
    private Button mButtonStart;
    private Button mButtonStop;
    TestService tService;
    
    ServiceConnection conn=new ServiceConnection() {
        
        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
            Log.d("activity1","service service disconnected");
        }
        
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // TODO Auto-generated method stub
            //System.out.println("bind ok");
            Log.d("activity1","service connnected");
            tService=((TestService.MBinder) service ).getService();
        }
    };
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.player);
        //bindService(intent, conn, BIND_AUTO_CREATE);
        
        mButtonBind=(Button)findViewById(R.id.buttonbind);
        mButtonUnbind=(Button)findViewById(R.id.buttonunbind);
        mButtonplay=(Button)findViewById(R.id.buttonserviceplay);
        mButtonStart=(Button)findViewById(R.id.buttonstart);
        mButtonStop=(Button)findViewById(R.id.buttonstop);
        
        mButtonBind.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub                
                bindService(intent, conn, BIND_AUTO_CREATE);
                Log.d("activity1","activity after bindservice");
            }
        });


        mButtonUnbind.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub                
                unbindService(conn);
                Log.d("activity1","activity after unbindservice");
            }
        });
        
        mButtonplay.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                tService.play();
            }
        });
        
        mButtonStart.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub                
                startService(intent);
                Log.d("activity1","start service");
            }
        });
        
        mButtonStop.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub                
                stopService(intent);
                Log.d("activity1","stop service");
            }
        });
        
    }
}

 

Service部分:

public class TestService extends Service {

    private Thread mThread;
    
    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        Log.d("service","onbind");
        return new MBinder();
    }
    
    class MBinder extends Binder{
        public TestService getService(){
            return TestService.this;
        }
    }

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub
        super.onCreate();
        Log.d("service","service create");                
    }
    
    

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        
        super.onDestroy();
        Log.d("service","service destory");
        
    }



    @Override
    public boolean onUnbind(Intent intent) {
        // TODO Auto-generated method stub
        Log.d("service","service unbind");
        return super.onUnbind(intent);
        
    }



    @Override
    public void onRebind(Intent intent) {
        // TODO Auto-generated method stub        
        super.onRebind(intent);
        Log.d("service","service rebind");
    }



    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        Log.d("service","service start");
        return super.onStartCommand(intent, flags, startId);
    }
    
    public void play(){
        Log.d("service","service play");
        
    }
        
}

 

  1.startService啓動服務:用於啓動一個服務執行後臺任務,不進行通訊,中止服務使用stopService。點擊按鈕調用startService()方法,輸出結果以下:

  2.bindService啓動服務:該方法啓動的服務要進行通訊,中止服務使用unbindService。點擊按鈕調用bindService()方法,輸出結果以下:

  3.startService & bindService 啓動服務:Service將會一直在後臺運行,同時調用stopService和unbindService才能中止服務。輸出結果(一種)以下:

 

綜合以上,能夠得出:

  1.在Service未啓動時,不管是調用startService 仍是 bindService 方法,都會先調用service的onCreate()方法建立一個service服務。

  2.在Service建立後銷燬前,若是調用startService方法,每調用一次都會觸發一次service的onStartCommand()方法;若是調用bindService方法,若是已綁定,則不會再觸發service的onBind方法。

  3.若是要銷燬service,則須要調用對應的方法:startService--stopService ,bindService--unbindService,startService & bindService--stopService &unbindService,纔會觸發service的onDestory方法。

 

  

  此外,有一點須要注意的是,在執行bindService方法後,下一個語句的執行先於service的建立,所以,須要注意對於binder返回的對象的使用,防止出錯。具體service和activity在同一進程中的運行關係及狀況須要後續學習。

 

參考文檔:

Android Service 服務(一)—— Service

Android 中的 Service 全面總結

相關文章
相關標籤/搜索