Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> Android--綁定服務調用服務的方法

Android--綁定服務調用服務的方法

編輯:關於android開發

Android--綁定服務調用服務的方法


Service按照其啟動的方式,可分為兩種:
1、Started
Started的Service,通過在Application裡用startService(Intent intent)方法來啟動。這種類型的Service一經啟動,會在後面無休止地運行,即使啟動它的Activity被Destroy掉。要停止此類型的Service,可在Service中調用stopSelf()或在Application中調用stopService(Intent intent),要不然就只能等Android系統在系統資源緊張的時候把它殺掉。

2、Bound

Bound的Service,通過在Application裡調用bindService()方法來啟動。該類型的Service與Application綁定在一起,一旦綁定的所有Application消失了,Android會Detroy掉該Service。也可以主動調用unbindService()方法來解綁Service。

有時候我們想在Activity中獲知Service的狀態,例如一個音樂播放器,Service負責音樂播放,Activity負責顯示當前歌曲名和播放進度。

可以用Broadcast,這個也不失為一個解決方法。

但如果可以獲取Service實例,那麼就可以調用Service中自定義的一些方法來獲取Service狀態了。

首先要明確的是,第一種類型的Service是無能為力的。因為Activity與Service之間並沒有相關聯的接口,即使這個Service是在Activity裡start的,一旦start,兩者不再有關聯。

一、本地Service調用。

如果Activity與Service在同一應用程序中,兩者間的交互就屬於本地Service調用。

可通過bindService實現,具體操作如下:

1、自定義子類MyService,繼承Service類
2、在MyService類中,自定義內部類MyBinder,繼承Binder類

在內部類中,根據需要交互的數據,創建一些方法,以便Activity可通過這些方法得到Service中的一些數據。或者干脆通過一個方法返回Service實例。

public class MyBinder extends Binder  
{  
public MyService getServiceInstance()  
{  
return MyService.this;  
}  
}  
3、在Service類中,new一個MyBinder私有成員,並在onBind()方法中return一個MyBinder實例。

之所以這樣做,是因為Service一旦綁定,就會回調onBind()方法,並返回一個Binder對象給Activity。具體看下一個步驟。


4、在Activity中覆寫ServiceConnection接口中的onServiceConnected(ComponentName name, IBinder service)方法,

其中的service參數就是MyService類中onBind()方法返回的MyBinder對象,調用MyBinder對象的自定義方法getServiceInstance()可得到Service實例。

下面是一個DEMO:
import android.os.Bundle;
import android.os.IBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.view.Menu;
import android.view.View;

public class MainActivity extends Activity {

	MusicInterface mi;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(this, MusicService.class);
        //混合調用
        //為了把服務所在進程變成服務進程
        startService(intent);
        //為了拿到中間人對象
        bindService(intent, new MusicServiceConn(), BIND_AUTO_CREATE);
    }

    class MusicServiceConn implements ServiceConnection{

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			// TODO Auto-generated method stub
			mi = (MusicInterface) service;
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub
			
		}
    	
    }

    //開始播放按鈕
    public void play(View v){
    	mi.play();
    }
    //暫停播放按鈕
    public void pause(View v){
    	mi.pause();
    }
}

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;

public class MusicService extends Service{
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return new MusicController();
	}
	
	
	//必須繼承binder,才能作為中間人對象返回
	class MusicController extends Binder implements MusicInterface{
		public void play(){
			MusicService.this.play();
		}
		public void pause(){
			MusicService.this.pause();
		}
	}
	
	public void play(){
		System.out.println("播放音樂");
	}
	
	public void pause(){
		System.out.println("暫停播放");
	}

	
}
public interface MusicInterface {

	void play();
	void pause();
}

 

二、跨進程Service調用

跨進程Service調用,即在當前應用程序中,調用另一個應用程序中的Service。

因為Android中,每個應用程序都運行於自己的進程中,擁有獨立的Dalvik虛擬機實例,因而稱為跨進程調用(Inter-Process Comunication)。

可通過AIDL服務來實現。

AIDL(Android Interface Definition Language),是Android定義的一種類似Java的語言。主要用於定義跨進程調用時,服務端跟客戶端用於數據交互的接口。

AIDL服務並不支持所有的Java數據類型。它只支持以下的幾種類型:
1、Java的簡單類型(int, char, boolean等)。無需import
2、String和CharSequence。無需import
3、List和Map。無需import(應當注意的是:List和Map的元素類型必須是AIDL支持的)
4、AIDL自動生成的接口。需要import
5、實現android.os.Parcelable接口的類。需要import

建立簡單的AIDL服務的步驟如下:
(一)服務端步驟:
1、在服務端創建AIDL文件IMyAidl.aidl
AIDL與Java代碼很相近,示例代碼如下:(注意:aidl文件後綴名為.aidl)

interface IMyAidl
{
void print();
}
創建完aidl文件後,ADT會自動調用aidl命令生成相應的Java文件。可查看gen文件夾下是否有一個名為IMyAidl.java的文件。如果沒有,說明.aidl文件有誤。

2、繼承Service類,在子類中,將AIDL接口暴露出來。
這一步類似於本地Service調用,則通過onBind(Intent intent)方法返回一個IBinder對象。
示例代碼如下:

 

public class MyService extends Service
{
private AidlBinder mBinder;
//Stub類是上一步驟中,aidl命令生成的Java代碼中的一個類
//該類實現了IBinder接口和IMyAidl接口
//可以通過繼承該類,然後在onBind()方法中返回AidlBinder對象
//如此一來,即可通過AidlBinder對象對AIDL文件中定義的方法進行調用
public class AidlBinder extends Stub
{
@Override
public void print()
{
System.out.println("Hello world!")//實現AIDL文件中的接口函數
}
}
@Override
public void onCreate()
{
mBinder = new AidlBinder();//啟動服務時即創建Binder對象
}

@Override
public IBinder onBind(Intent intent)
{
return mBinder;//返回Binder對象,讓客戶端獲得Binder對象
}
}
3、配置AndroidManifest.xml文件

 

 

<!--{cke_protected}{C}%3C!%2D%2D%20%E8%87%AA%E5%AE%9A%E4%B9%89%E8%AE%BF%E9%97%AEService%E6%89%80%E9%9C%80%E7%9A%84%E6%9D%83%E9%99%90%20%2D%2D%3E-->
<permission android:protectlevel="normal" android:name="thomas.permission.AIDL_SERVICE">

<service android:name="com.thomas.aidlserver.MyService" android:exported="true" android:permission="thomas.permission.AIDL_SERVICE">
<!--{cke_protected}{C}%3C!%2D%2D%20IntentFilter%E5%B1%9E%E6%80%A7%E6%98%AF%E5%BF%85%E4%B8%8D%E5%8F%AF%E5%B0%91%E7%9A%84%20%2D%2D%3E-->
<!--{cke_protected}{C}%3C!%2D%2D%20%E5%A6%82%E6%AD%A4%E4%B8%80%E6%9D%A5%EF%BC%8C%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%89%8D%E8%83%BD%E9%80%9A%E8%BF%87%E8%AF%A5action%E8%BF%9C%E7%A8%8B%E8%B0%83%E7%94%A8%E6%9C%8D%E5%8A%A1%E7%AB%AF%E7%9A%84Service%20%2D%2D%3E-->
<intent-filter>
<action android:name="com.thomas.aidlserver.action.AIDL_SERVICE">
</action></intent-filter>
</service></permission>
(二)客戶端步驟:
1、創建AIDL文件
客戶端也要創建AIDL文件,而且是跟服務端完全一樣的AIDL文件。
復制服務端AIDL文件即可。應當注意的是:AIDL文件的包名一定要跟服務端的一致。
如果客戶端沒有該包,應創建一個包,並將AIDL文件放到包下。

2、跨進程調用Service
客戶端跨進程調用Service的方法與本地調用Service的方法差不多,也是通過bindService()。
應當注意的是,調用成功後,通過ServiceConnection接口中的onServiceConnected(ComponentName name, IBinder service)方法得到服務端onBind()方法傳遞過來的Binder對象。將該對象類型轉化為AIDL文件中聲明的接口類型,即可調用該接口中定義的方法。
示例代碼如下:
private IMyAidl mAidl;
mServiceCon = new ServiceConnection()
{
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
//將IBinder類型轉化為IMyAidl類型。
mAidl = IMyAidl.Stub.asInterface(service);
}
@Override
public void onServiceDisonnected(ComponentName name){}
}
//遠程Service綁定,其中Intent的action參數是服務端在
//AndroidManifest.xml文件中標簽下的指定的字符串
bindService(new Intent("com.thomas.aidlserver.action.AIDL_SERVICE"),
mServiceCon, Service.BIND_AUTO_CREATE);
mAidl.print();//調用AIDL文件中聲明的方法

3、配置AndroidManifest.xml文件
<!--{cke_protected}{C}%3C!%2D%2D%20%E8%AF%B7%E6%B1%82%E8%AE%BF%E9%97%AE%E8%BF%9C%E7%A8%8BService%E6%89%80%E9%9C%80%E7%9A%84%E6%9D%83%E9%99%90%EF%BC%8C%E8%AF%A5%E6%9D%83%E9%99%90%E5%AE%9A%E4%B9%89%E4%BA%8E%E6%9C%8D%E5%8A%A1%E7%AB%AF%E7%9A%84AndroidManifest.xml%E6%96%87%E4%BB%B6%E4%B8%AD%20%2D%2D%3E-->
<uses-permission android:name="thomas.permission.AIDL_SERVICE"></uses-permission>

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved