亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Android Service 服務(三)—— bindService與

系統 2237 0

一、bindService簡介

bindService是綁定Service服務,執行service服務中的邏輯流程。

service通過Context.startService()方法開始,通過Context.stopService()方法停止;也可以通過Service.stopSelf()方法或者Service.stopSelfResult()方法來停止自己。只要調用一次stopService()方法便可以停止服務,無論之前它被調用了多少次的啟動服務方法。

客戶端建立一個與Service的連接,并使用此連接與Service進行通話,通過Context.bindService()方法來綁定服務,Context.unbindService()方法來關閉服務。多個客戶端可以綁定同一個服務,如果Service還未被啟動,bindService()方法可以啟動服務。

上面startService()和bindService()兩種模式是完全獨立的。你可以綁定一個已經通過startService()方法啟動的服務。例如:一個后臺播放音樂服務可以通過startService(intend)對象來播放音樂。可能用戶在播放過程中要執行一些操作比如獲取歌曲的一些信息,此時activity可以通過調用bindServices()方法與Service建立連接。這種情況下,stopServices()方法實際上不會停止服務,直到最后一次綁定關閉。


二、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在一個生命周期中只能被調用一次。 詳見: Android Service 服務(一)—— Service


三、 bindService生命周期

像一個activity那樣,一個service有些可以用來改變狀態的生命周期方法,但是比activity的方法少,service生命周期方法只有三個public

void onCreate()

void onStart(Intent intent)

void onDestroy()

通過實現這三個生命周期方法,你可以監聽service的兩個嵌套循環的生命周期:

1、整個生命周期

service的整個生命周期是在onCreate()和onDestroy()方法之間。和activity一樣,在onCreate()方法里初始化,在onDestroy()方法里釋放資源。例如,一個背景音樂播放服務可以在onCreate()方法里播放,在onDestroy()方法里停止。

2、活動的生命周期

service的活動生命周期是在onStart()之后,這個方法會處理通過startServices()方法傳遞來的Intent對象。音樂service可以通過開打intent對象來找到要播放的音樂,然后開始后臺播放。注: service停止時沒有相應的回調方法,即沒有onStop()方法,只有onDestroy()銷毀方法。

onCreate()方法和onDestroy()方法是針對所有的services,無論它們是否啟動,通過Context.startService()和Context.bindService()方法都可以訪問執行。然而, 只有通過startService()方法啟動service服務時才會調用onStart()方法

Android Service 服務(三)—— bindService與remoteService

如果一個service允許別人綁定,那么需要實現以下額外的方法:

IBinder onBind(Intent intent)

boolean onUnbind(Intent intent)

void onRebind(Intent intent)

onBind()回調方法會繼續傳遞通過bindService()傳遞來的intent對象

onUnbind()會處理傳遞給unbindService()的intent對象。如果service允許綁定,onBind()會返回客戶端與服務互相聯系的通信句柄(實例)。

如果建立了一個新的客戶端與服務的連接,onUnbind()方法可以請求調用onRebind()方法。


記住: 任何服務無論它怎樣建立,默認客戶端都可以連接,所以任何service都能夠接收onBind()和onUnbind()方法



四、bindService示例

Activity

    public class PlayBindMusic extends Activity implements OnClickListener {

	private Button playBtn;
	private Button stopBtn;
	private Button pauseBtn;
	private Button exitBtn;

	private BindMusicService musicService;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setContentView(R.layout.bind_music_service);

		playBtn = (Button) findViewById(R.id.play);
		stopBtn = (Button) findViewById(R.id.stop);
		pauseBtn = (Button) findViewById(R.id.pause);
		exitBtn = (Button) findViewById(R.id.exit);

		playBtn.setOnClickListener(this);
		stopBtn.setOnClickListener(this);
		pauseBtn.setOnClickListener(this);
		exitBtn.setOnClickListener(this);

		connection();
	}

	private void connection() {
		Intent intent = new Intent("com.homer.bind.bindService");
		bindService(intent, sc, Context.BIND_AUTO_CREATE);			// bindService
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.play:
			musicService.play();
			break;
		case R.id.stop:
			if (musicService != null) {
				musicService.stop();
			}
			break;
		case R.id.pause:
			if (musicService != null) {
				musicService.pause();
			}
			break;
		case R.id.exit:
			this.finish();
			break;
		}
	}

	private ServiceConnection sc = new ServiceConnection() {

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {		//connect Service
			musicService = ((BindMusicService.MyBinder) (service)).getService();
			if (musicService != null) {
				musicService.play();		// play music
			}
		}
		
		@Override
		public void onServiceDisconnected(ComponentName name) {					//disconnect Service
			musicService = null;
		}
	};
	
	@Override
	public void onDestroy(){
		super.onDestroy();
		
		if(sc != null){
			unbindService(sc);
		}
	}
}
  

Service

    public class BindMusicService extends Service {

	private MediaPlayer mediaPlayer;

	private final IBinder binder = new MyBinder();

	public class MyBinder extends Binder {
		BindMusicService getService() {
			return BindMusicService.this;
		}
	}

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

	@Override
	public void onCreate() {
		super.onCreate();
		
		Toast.makeText(this, "show media player", Toast.LENGTH_SHORT).show();
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		
		Toast.makeText(this, "stop media player", Toast.LENGTH_SHORT);
		if(mediaPlayer != null){
			mediaPlayer.stop();
			mediaPlayer.release();
		}
	}

	
	public void play() {
		if (mediaPlayer == null) {
			mediaPlayer = MediaPlayer.create(this, R.raw.tmp);
			mediaPlayer.setLooping(false);
		}
		if (!mediaPlayer.isPlaying()) {
			mediaPlayer.start();
		}
	}

	public void pause() {
		if (mediaPlayer != null && mediaPlayer.isPlaying()) {
			mediaPlayer.pause();
		}
	}

	public void stop() {
		if (mediaPlayer != null) {
			mediaPlayer.stop();
			try {
				mediaPlayer.prepare();		// 在調用stop后如果需要再次通過start進行播放,需要之前調用prepare函數
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
	}
}
  

AndroidManifest.xml

            <service
            android:name=".bind.BindMusicService"
            android:enabled="true" >
            <intent-filter>
                <action android:name="com.homer.bind.bindService" />
            </intent-filter>
        </service>
  


五、代碼解析

1、 Activity中,Intent intent = new Intent("com.homer.bind.bindService"); 構建一個service的action,然后bindService(intent, sc, Context.BIND_AUTO_CREATE); 綁定服務

2、 Activity中,通過private ServiceConnection sc = new ServiceConnection() 建立一個Service連接,onServiceConnected()獲取Service實例,onServiceDisconnected()釋放連接

3、 Service中,重載onBind(Intent intent)方法,返回Service實例(即BindMusicService)給Activity,然后執行onCreate()函數( 注: bindService不執行onStart()函數)

4、 Activity中,通過返回的Service實例musicService,執行音樂播放的操作(play、pause、stop等)



六、Remote Service拓展

通常每個應用程序都在它自己的進程內運行,但有時需要在進程之間傳遞對象(IPC通信),你可以通過應用程序UI的方式寫個運行在一個不同的進程中的service。在android平臺中,一個進程通常不能訪問其它進程中的內存區域。所以,他們需要把對象拆分成操作系統能理解的簡單形式,以便偽裝成對象跨越邊界訪問。編寫這種偽裝代碼相當的枯燥乏味,好在android為我們提供了AIDL工具可以來做這件事。

AIDL (android接口描述語言)是一個IDL語言,它可以生成一段代碼,可以使 在一個android設備上運行的兩個進程使用內部通信進程進行交互 。如果你需要在一個進程中(例如在一個Activity中)訪問另一個進程中(例如一個Service)某個對象的方法,你就可以使用AIDL來生成這樣的代碼來偽裝傳遞各種參數。

要使用AIDL,Service需要以aidl文件的方式提供服務接口,AIDL工具將生成一個相應的java接口,并且在生成的服務接口中包含一個功能調用的stub服務樁類。Service的實現類需要去繼承這個stub服務樁類。Service的onBind方法會返回實現類的對象,之后你就可以使用它了,參見下例:

IMusicControlService.aidl

    package com.homer.remote;

interface IMusicControlService{
        void play(); 
        void stop(); 
        void pause();
}
  

使用eclipse的Android插件,會根據這個aidl文件生成一個Java接口類,生成的接口類中會有一個內部類Stub類,Service來繼承該Stub類:
Service
      public class RemoteMusicService extends Service {

	private MediaPlayer mediaPlayer;

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

	private final IMusicControlService.Stub binder = new IMusicControlService.Stub() {

		@Override
		public void play() throws RemoteException {
			if (mediaPlayer == null) {
				mediaPlayer = MediaPlayer.create(RemoteMusicService.this, R.raw.tmp);
				mediaPlayer.setLooping(false);
			}
			if (!mediaPlayer.isPlaying()) {
				mediaPlayer.start();
			}
		}

		@Override
		public void pause() throws RemoteException {
			if (mediaPlayer != null && mediaPlayer.isPlaying()) {
				mediaPlayer.pause();
			}			
		}

		@Override
		public void stop() throws RemoteException {
			if (mediaPlayer != null) {
				mediaPlayer.stop();
				try {
					mediaPlayer.prepare();		// 在調用stop后如果需要再次通過start進行播放,需要之前調用prepare函數
				} catch (IOException ex) {
					ex.printStackTrace();
				}
			}
		}
	};
	
	@Override
	public void onDestroy() {
		super.onDestroy();
		
		if(mediaPlayer != null){
			mediaPlayer.stop();
			mediaPlayer.release();
		}
	}
}
    

客戶端(Activity)應用連接到這個Service時,onServiceConnected方法將被調用,客戶端就可以獲得IBinder對象。參看下面的客戶端onServiceConnected方法:

Activity

    public class PlayRemoteMusic extends Activity implements OnClickListener {

	private Button playBtn;
	private Button stopBtn;
	private Button pauseBtn;
	private Button exitBtn;

	private IMusicControlService musicService;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.remote_music_service);

		playBtn = (Button) findViewById(R.id.play);
		stopBtn = (Button) findViewById(R.id.stop);
		pauseBtn = (Button) findViewById(R.id.pause);
		exitBtn = (Button) findViewById(R.id.exit);

		playBtn.setOnClickListener(this);
		stopBtn.setOnClickListener(this);
		pauseBtn.setOnClickListener(this);
		exitBtn.setOnClickListener(this);

		connection();
	}

	private void connection() {
		Intent intent = new Intent("com.homer.remote.remoteMusicReceiver");
		bindService(intent, sc, Context.BIND_AUTO_CREATE);				// bindService
	}

	@Override
	public void onClick(View v) {

		try {
			switch (v.getId()) {
			case R.id.play:
				musicService.play();
				break;
			case R.id.stop:
				if (musicService != null) {
					musicService.stop();
				}
				break;
			case R.id.pause:
				if (musicService != null) {
					musicService.pause();
				}
				break;
			case R.id.exit:
				this.finish();
				break;
			}
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}

	private ServiceConnection sc = new ServiceConnection() {
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {		//connect Service
			musicService = IMusicControlService.Stub.asInterface(service);
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {					//disconnect Service
			musicService = null;
		}

	};
	
	@Override
	public void onDestroy(){
		super.onDestroy();
		
		if(sc != null){
			unbindService(sc);				// unBindService
		}
	}
}
  

Remote Service流程總結:

1、 Activity(客戶端)中,Intent intent = new Intent("com.homer.remote.remoteMusicReceiver");構建intent,然后bindService(intent, sc, Context.BIND_AUTO_CREATE);綁定服務

2、 Activity(客戶端)中,通過ServiceConnection()重載onServiceConnected()建立連接,獲取Service.Stub實例;onServiceDisconnected()釋放連接(與bindService類似)

3、 Service中,通過重載onBind(Intent intent) 返回Service.Stub實例,但Service.Stub類是由aidl文件生成的接口類中的一個內部類Stub類,Service來繼承該Stub類

4、 Activity中,通過操作Service實例(musicService),執行音樂播放操作(play、pause、stop等)


源碼下載



參考推薦:

Service (android developer)

Android Service 服務(一)—— Service

Android Service 服務(二)—— BroadcastReceiver

android中service和aidl詳細整理

Android Service AIDL

android筆記--Service與AIDL


Android Service 服務(三)—— bindService與remoteService


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: www亚洲视频 | 色综合亚洲天天综合网站 | 免费人成年短视频在线观看网站 | 久久中文字幕免费视频 | 日韩免费片 | 欧美亚洲中日韩中文字幕在线 | 成人a毛片在线看免费全部播放 | 性做久久久久久久久25的美女 | 亚洲成人毛片 | 在线播放heyzo北条麻妃 | 久热精品在线 | 91在线免费观看网站 | 国产一级特黄特色aa毛片 | 欧美视频在线不卡 | 亚洲国产精品久久久久久网站 | 国产精品久久久久久 | 毛片18| 亚洲成 人a影院青久在线观看 | 国产高清精品一区 | 亚洲午夜久久久精品影院视色 | 免费骚视频| 亚洲精品毛片久久久久久久 | 日本免费一区二区三区毛片 | 成人最新午夜免费视频 | 欧美一级美片在线观看免费 | 亚洲狠狠 | 久久这里有精品视频 | 免费国产黄线在线观看视频 | 夜夜操夜夜骑 | 亚洲一区二区欧美日韩 | 欧洲免费无线码二区5 | 久久香蕉国产线看观看式 | 青草社区在线观看 | 色婷婷色婷婷 | 91久久亚洲精品国产一区二区 | 神马影院我不卡手机 | 久久伊人一区二区三区四区 | 天天舔天天射天天操 | 国产亚洲精品激情一区二区三区 | 欧美成年黄网站色高清视频 | 好吊色妞|