Android 綁定Service 實現android控制service的生命週期

 

很多情況下,一些與用戶很少需要產生交互的應用程序,我們一般讓它們在後臺運行就行了,而且在它們運行期間我們仍然能運行其他的應用。

爲了處理這種後臺進程,Android引入了Service的概念。Service在Android中是一種長生命週期的組件,它不實現任何用戶界面。最 常見的例子如:媒體播放器程序,它可以在轉到後臺運行的時候仍然能保持播放歌曲;或者如文件下載程序,它可以在後臺執行文件的下載。

讓我們來看下如何創建Service:
創建一個Service 
Android中已經定義了一個 ‘Service’類,所有其他的Service都繼承於該類。Service類中定義了一系列的生命週期相關的方法,如: onCreate(), onStart(), onDestroy()。參見下例:

 

package com.wissen.testApp.service;

public class MyService extends Service {
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Toast.makeText(this, “Service created…”, Toast.LENGTH_LONG).show();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Toast.makeText(this, “Service destroyed…”, Toast.LENGTH_LONG).show();
    }
}

 

上例中的這個Service主要做了這些事:當服務創建和銷燬時通過界面消息提示用戶。
如Android中的其它部件一樣, Service也會和一系列Intent關聯。Service的運行入口需要在AndroidManifest.xml中進行配置,如下:

 

<service class=”.service.MyService”>
    <intent-filter>
        <action android:value=”com.wissen.testApp.service.MY_SERVICE” />
    </intent-filter>
</service>

 

 

之後我們的Service就可以被其他代碼所使用了。

使用Service: 
應用程序可以通過調用 Context.startService方法來啓動Service。如果當前沒有指定的Service實例被創建,則該方法會調用 Service的onCreate方法來創建一個實例;否則調用Service的onStart方法。參見下列代碼:

 

 

..
Intent serviceIntent = new Intent();
serviceIntent.setAction(”com.wissen.testApp.service.MY_SERVICE”);
startService(serviceIntent);
..

 

以上代碼調用了startService方法,Service會持續運行,直到調用stopService()或stopSelf()方法。
還有另一種綁定Service的方式:

 


ServiceConnection conn = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.i(”INFO”, “Service bound “);
    }

    @Override
    public void onServiceDisconnected(ComponentName arg0) {
         Log.i(”INFO”, “Service Unbound “);
    }
};

bindService(new Intent(”com.wissen.testApp.service.MY_SERVICE”), conn, Context.BIND_AUTO_CREATE);

 

當應用程序綁定一個Service後,該應用程序和Service之間就能進行互相通信,通常,這種通信的完成依靠於我們定義的一些接口,請看下例:

 

package com.wissen.testApp;

public interface IMyService {
    public int getStatusCode();
}

這裏定義了一個方法來獲取Service的狀態,但是Service是如何來使它起作用的呢?之前我們看到Service中有個返回IBinder對象的 onBind方法,這個方法會在Service被綁定到其他程序上時被調用,而這個IBinder對象和之前看到的onServiceConnected 方法中傳入的那個IBinder是同一個東西。應用和Service間就依靠這個IBinder對象進行通信:
public class MyService extends Service {
    private int statusCode;
    private MyServiceBinder myServiceBinder = new MyServiceBinder();
   
    @Override
    public IBinder onBind(Intent intent) {
        return myServiceBinder;
    }
    public class MyServiceBinder extends Binder implements IMyService {
        public int getStatusCode() {
             return statusCode;
       }
    }
   
    …
}
 下列代碼是說明getStatusCode是如何被調用的:  
ServiceConnection conn = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        IMyService myService = (IMyService) service;
        statusCode = myService.getStatusCode();
        Log.i(”INFO”, “Service bound “);
    }
   
    …
};

或者,你也可以通過使用ServiceListener接口來達成相同的目的。

與遠程Service通信(進程間Service通信): 
如何兩個進程間的Service需要進行通信,則需要把對象序列化後進行互相發送。
Android提供了一個 AIDL (Android接口定義語言)工具來處理序列化和通信。這種情況下Service需要以aidl文件的方式提供服務接口,AIDL工具將生成一個相應的java接口,並且在生成的服務接口中包含一個功能調用的stub服務樁類。Service的實現類需要去繼承這個 stub服務樁類。Service的onBind方法會返回實現類的對象,之後你就可以使用它了,參見下例:
先創建一個IMyRemoteService.aidl文件,內容如下:

 

package com.wissen.testApp;

interface IMyRemoteService {
    int getStatusCode();
}

 

如果你正在使用eclipse的 Android插件,則它會根據這個aidl文件生成一個Java接口類。生成的接口類中會有一個內部類Stub類,你要做的事就是去繼承該Stub類:

 

package com.wissen.testApp;

class RemoteService implements Service {
    int statusCode;
   
    @Override
    public IBinder onBind(Intent arg0) {
        return myRemoteServiceStub;
    }

    private IMyRemoteService.Stub myRemoteServiceStub = new IMyRemoteService.Stub() {
        public int getStatusCode() throws RemoteException {
            return 0;
        }
    };
   
    …
}

 

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

 


ServiceConnection conn = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        IMyRemoteService myRemoteService = IMyRemoteService.Stub.asInterface(service);
        try {
            statusCode = myRemoteService.getStatusCode();
       } catch(RemoteException e) {
           // handle exception
       }
        Log.i(”INFO”, “Service bound “);
    }
   
    …
};

 

權限: 
我們可以在AndroidManifest.xml文件中使用<service>標籤來指定Service訪問的權限:

 

<service class=”.service.MyService” android:permission=”com.wissen.permission.MY_SERVICE_PERMISSION”>
    <intent-filter>
        <action android:value=”com.wissen.testApp.service.MY_SERVICE” />
    </intent-filter>
</service>

 

之後應用程序要訪問該Service的話就需要使用<user-permission>標籤來指定相應的權限:

<uses-permission android:name=”com.wissen.permission.MY_SERVICE_PERMISSION”>
</uses-permission>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章