當前位置:首頁 » 安卓系統 » androidibinder

androidibinder

發布時間: 2022-11-03 14:20:10

㈠ android,,service求助, public IBinder onBind(Intent intent) { ///////此處的IBinder是什麼作用啊

在Android中Service的啟動方式有兩種,第一種是startService,第二種是bindService. 你這里問的是第二種方法,生命周期是這樣的:
bindSerivce->onCreate->onBind->running->onUnbind->onDestroy.
由字面意思可以看出來onBind方法就是當試圖綁定服務時做的事,作用一般情況下主要是返回IBinder對象,為後面服務成功綁定時的操作做准備,也可以做一些服務初始化之類的事。
如果用過bindService就會知道這個方法里的第二個參數是一個ServiceConnection的對象,在使用這個對象的時候你需要重寫兩個方法onServiceConnected(ComponentName name, IBinder service)和onServiceDisconnected(ComponentName name). 其中onServiceConnected方法參數中的service就是你上面所說的返回的IBinder的對象,只有你在onBind方法裡面返回一個IBinder對象的時候onServiceConnected才會被調用,說明服務成功綁定,而在這個方法裡面你可以對服務中的一些數據進行初始化控制等操作,實現Activity與Service之間簡單的交互。
說的應該挺明白了吧,建議自己可以參照網上資料把Service的兩種啟動方式所涉及到的知識點梳理一遍,然後再編程調試,可以加深對這一部分知識的理解。

㈡ Android源碼解析RPC系列(一)---Binder原理

看了幾天的Binder,決定有必要寫一篇博客,記錄一下學習成果,Binder是Android中比較綜合的一塊知識了,目前的理解只限於java層。首先Binder是幹嘛用的?不用說,跨進程通信全靠它,操作系統的不同進程之間,數據不共享,對於每個進程來說,它都天真地以為自己獨享了整個系統,完全不知道其他進程的存在,進程之間需要通信需要某種系統機制才能完成,在Android整個系統架構中,採用了大量的C/S架構的思想,所以Binder的作用就顯得非常重要了,但是這種機制為什麼是Binder呢?在linux中的RPC方式有管道,消息隊列,共享內存等,消息隊列和管道採用存儲-轉發方式,即數據先從發送方緩存區拷貝到內核開辟的緩存區中,然後再從內核緩存區拷貝到接收方緩存區,這樣就有兩次拷貝過程。共享內存不需要拷貝,但控制復雜,難以使用。Binder是個折中的方案,只需要拷貝一次就行了。其次Binder的安全性比較好,好在哪裡,在下還不是很清楚,基於安全性和傳輸的效率考慮,選擇了Binder。Binder的英文意思是粘結劑,Binder對象是一個可以跨進程引用的對象,它的實體位於一個進程中,這個進程一般是Server端,該對象提供了一套方法用以實現對服務的請求,而它的引用卻遍布於系統的各個進程(Client端)之中,這樣Client通過Binder的引用訪問Server,所以說,Binder就像膠水一樣,把系統各個進程粘結在一起了,廢話確實有點多。

為了從而保障了系統的安全和穩定,整個系統被劃分成內核空間和用戶空間
內核空間:獨立於普通的應用程序,可以訪問受保護的內存空間,有訪問底層硬體設備的所有許可權。
用戶空間:相對與內核空間,上層運用程序所運行的空間就是用戶空間,用戶空間訪問內核空間的唯一方式就是系統調用。一個4G的虛擬地址空間,其中3G是用戶空間,剩餘的1G是內核空間。如果一個用戶空間想與另外一個用戶空間進行通信,就需要內核模塊支持,這個運行在內核空間的,負責各個用戶進程通過Binder通信的內核模塊叫做Binder驅動,雖然叫做Binder驅動,但是和硬體並沒有什麼關系,只是實現方式和設備驅動程序是一樣的,提供了一些標准文件操作。

在寫AIDL的時候,一般情況下,我們有兩個進程,一個作為Server端提供某種服務,然後另外一個進程作為Client端,連接Server端之後,就 可以使用Server裡面定義的服務。這種思想是一種典型的C/S的思想。值得注意的是Android系統中的Binder自身也是C/S的架構,也有Server端與Client端。一個大的C/S架構中,也有一個小的C/S架構。

先籠統的說一下,在整個Binder框架中,由系列組件組成,分別是Client、Server、ServiceManager和Binder驅動程序,其中Client、Server和ServiceManager運行在用戶空間,Binder驅動程序運行內核空間。運行在用戶空間中的Client、Server和ServiceManager,是在三個不同進程中的,Server進程中中定義了服務提供給Client進程使用,並且Server中有一個Binder實體,但是Server中定義的服務並不能直接被Client使用,它需要向ServiceManager注冊,然後Client要用服務的時候,直接向ServiceManager要,ServiceManager返回一個Binder的替身(引用)給Client,這樣Client就可以調用Server中的服務了。

場景 :進程A要調用進程B裡面的一個draw方法處理圖片。

分析 :在這種場景下,進程A作為Client端,進程B做為Server端,但是A/B不在同一個進程中,怎麼來調用B進程的draw方法呢,首先進程B作為Server端創建了Binder實體,為其取一個字元形式,可讀易記的名字,並將這個Binder連同名字以數據包的形式通過Binder驅動發送給ServiceManager,也就是向ServiceManager注冊的過程,告訴ServiceManager,我是進程B,擁有圖像處理的功能,ServiceManager從數據包中取出名字和引用以一個注冊表的形式保留了Server進程的注冊信息。為什麼是以數據包的形式呢,因為這是兩個進程,直接傳遞對象是不行滴,只能是一些描述信息。現在Client端進程A聯系ServiceManager,說現在我需要進程B中圖像處理的功能,ServiceManager從注冊表中查到了這個Binder實體,但是呢,它並不是直接把這個Binder實體直接給Client,而是給了一個Binder實體的代理,或者說是引用,Client通過Binder的引用訪問Server。分析到現在,有個關鍵的問題需要說一下,ServiceManager是一個進程,Server是另一個進程,Server向ServiceManager注冊Binder必然會涉及進程間通信。當前實現的是進程間通信卻又要用到進程間通信,這就好象蛋可以孵出雞前提卻是要找只雞來孵蛋,確實是這樣的,ServiceManager中預先有了一個自己的Binder對象(實體),就是那隻雞,然後Server有個Binder對象的引用,就是那個蛋,Server需要通過這個Binder的引用來實現Binder的注冊。雞就一隻,蛋有很多,ServiceManager進程的Binder對象(實體)僅有一個,其他進程所擁有的全部都是它的代理。同樣一個Server端Binder實體也應該只有一個,對應所有Client端全部都是它的代理。

我們再次理解一下Binder是什麼?在Binder通信模型的四個角色裡面;他們的代表都是「Binder」,一個Binder對象就代表了所有,包括了Server,Client,ServiceManager,這樣,對於Binder通信的使用者而言,不用關心實現的細節。對Server來說,Binder指的是Binder實體,或者說是本地對象,對於Client來說,Binder指的是Binder代理對象,也就是Binder的引用。對於Binder驅動而言,在Binder對象進行跨進程傳遞的時候,Binder驅動會自動完成這兩種類型的轉換。

簡單的總結一下,通過上面一大段的分析,一個Server在使用的時候需要經歷三個階段

1、定義一個AIDL文件
Game.aidl

GameManager .aidl

2、定義遠端服務Service
在遠程服務中的onBind方法,實現AIDL介面的具體方法,並且返回Binder對象

3、本地創建連接對象

以上就是一個遠端服務的一般套路,如果是在兩個進程中,就可以進程通信了,現在我們分析一下,這個通信的流程。重點是GameManager這個編譯生成的類。

從類的關系來看,首先介面GameManager 繼承 IInterface ,IInterface是一個介面,在GameManager內部有一個內部類Stub,Stub繼承了Binder,(Binder實現了IBinder),並且實現了GameManager介面,在Stub中還有一個內部類Proxy,Proxy也實現了GameManager介面,一個整體的結構是這樣的

現在的問題是,Stub是什麼?Proxy又是什麼?在上面說了在Binder通信模型的四個角色裡面;他們的代表都是「Binder」,一個Binder對象就代表了所有,包括了Server,Clinet,ServiceManager,為了兩個進程的通信,系統給予的內核支持是Binder,在抽象一點的說,Binder是系統開辟的一塊內存空間,兩個進程往這塊空間裡面讀寫數據就行了,Stub從Binder中讀數據,Proxy向Binder中寫數據,達到進程間通信的目的。首先我們分析Stub。

Stub 類繼承了Binder ,說明了Stub有了跨進程傳輸的能力,實現了GameManager介面,說明它有了根據游戲ID查詢一個游戲的能力。我們在bind一個Service之後,在onServiceConnecttion的回調裡面,就是通過asInterface方法拿到一個遠程的service的。

asInterface調用queryLocalInterface。

mDescriptor,mOwner其實是Binder的成員變數,Stub繼承了Binder,在構造函數的時候,對著兩個變數賦的值。

如果客戶端和服務端是在一個進程中,那麼其實queryLocalInterface獲取的就是Stub對象,如果不在一個進程queryLocalInterface查詢的對象肯定為null,因為不同進程有不同虛擬機,肯定查不到mOwner對象的,所以這時候其實是返回的Proxy對象了。拿到Stub對象後,通常在onServiceConnected中,就把這個對象轉換成我們多定義AIDL介面。

比如我們這里會轉換成GameManager,有了GameManager對象,就可以調用後querryGameById方法了。如果是一個進程,那直接調用的是自己的querryGameById方法,如果不是一個進程,那調用了就是代理的querryGameById方法了。

看到其中關鍵的一行是

mRemote就是一個IBinder對象,相對於Stub,Proxy 是組合關系(HAS-A),內部有一個IBinder對象mRemote,Stub是繼承關系(IS-A),直接實現了IBinder介面。

transact是個native方法,最終還會回掉JAVA層的onTransact方法。

onTransact根據調用號(每個AIDL函數都有一個編號,在跨進程的時候,不會傳遞函數,而是傳遞編號指明調用哪個函數)調用相關函數;在這個例子裡面,調用了Binder本地對象的querryGameById方法;這個方法將結果返回給驅動,驅動喚醒掛起的Client進程裡面的線程並將結果返回。於是一次跨進程調用就完成了。

***Please accept mybest wishes for your happiness and success ! ***

㈢ 如何在Android下使用Binder

1概述
Binder是基於OpenBinder,在Android系統上使用的進程間通信機制。
Binder基於Client-Server通信模式,本質上可以理解為它實現了Client對Server對象的遠程調用。比如,有某個binder對象A位於Server中,該對象提供了一套函數用以實現對服務的請求,而在一個或多個Client中包含對象A的引用,Client通過該引用可以調用遠端Server中對象A的介面函數,這種遠端調用對Client而言,與調用本地對象並無區別。

2 通信模型
Binder機制定義了四個組件,分別是Client,Server,ServiceManager和binder驅動,其中Client,Server,ServiceManager運行於用戶空間,binder驅動運行於內核空間。

binder驅動
binder驅動是內核中的一個字元設備驅動/dev/binder,它是整個Binder通信機制的核心。Client,Server,ServiceManager通過open()和ioctl()文件操作函數與binder驅動進行通信,從而實現了Client向Server發送請求,Server處理請求並返回結果到Client。具體來說,它負責進程之間Binder通信的建立,Binder在進程之間的傳遞,Binder引用計數管理,數據包在進程之間的傳遞和交互等一系列底層支持。

ServiceManager
ServiceManager是一個守護進程,負責管理服務,即所有的Server需要向ServiceManager注冊服務。同時,ServiceManager向Client提供查詢和獲取Server的介面。

3 binder通信實例

實現一個binder通信實例,需要經過以下步驟:
(1)獲得ServiceManager的對象引用
(2)向ServiceManager注冊新的Service
(3)在Client中通過ServiceManager獲得Service對象引用
(3)在Client中發送請求,由Service返回結果。

下面看具體的代碼如何實現。

3.1 libmyservice代碼實現

(1)新建目錄frameworks/base/myservice/libservice,進入該目錄

view plain
$ cd frameworks/base
$ mkdir myservice
$ cd myservice
$ mkdir libmyservice
$ cd libmyservice

(2)編寫libmyservice/myservic.h文件

view plain
#include <utils/threads.h>

#include <utils/RefBase.h>

#include <binder/IInterface.h>

#include <binder/BpBinder.h>

#include <binder/Parcel.h>

namespace android {

class MyService : public BBinder

{

mutable Mutex mLock;

int32_t mNextConnId;

public:

static int instantiate();

MyService();

virtual ~MyService();

virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t);

};

}; //namespace

(2)編寫libservice/myservice.cpp文件

view plain
#include "myservice.h"

#include <binder/IServiceManager.h>

#include <binder/IPCThreadState.h>

namespace android {

static struct sigaction oldact;

static pthread_key_t sigbuskey;

int MyService::instantiate()

{

LOGE("MyService instantiate");

// defaultServiceManager ()獲得ServiceManager的對象引用,addService()可向ServiceManager注冊新的服務

int r = defaultServiceManager()->addService(String16("android.myservice"), new MyService());

LOGE("MyService r = %d/n", r);

return r;

}

MyService::MyService()

{

LOGV("MyService created");

mNextConnId = 1;

pthread_key_create(&sigbuskey, NULL);

}

MyService::~MyService()

{

pthread_key_delete(sigbuskey);

LOGV("MyService destroyed");

}

// 每個系統服務都繼承自BBinder類,都應重寫BBinder的onTransact虛函數。當用戶發送請求到達Service時,系統框架會調用Service的onTransact函數,該函數分析接收到的數據包,調用相應的介面函數處理請求

status_t MyService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

{

switch(code)

{

case 0: {

pid_t pid = data.readInt32();

int num = data.readInt32();

num = num + 100;

reply->writeInt32(num);

return NO_ERROR;

}

break;

default:

return BBinder::onTransact(code, data, reply, flags);

}

}

}; //namespace

(3)編寫libservice/Android.mk文件

view plain
# File: Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := myservice.cpp
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
LOCAL_SHARED_LIBRARIES := libutils libbinder
LOCAL_MODULE_TAGS := optional
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := libmyservice

include $(BUILD_SHARED_LIBRARY)

(4)編譯libmyservice.so動態庫

在android源碼主目錄下
view plain
$ source build/envsetup.sh

including device/htc/passion/vendorsetup.sh

including device/samsung/crespo4g/vendorsetup.sh

including device/samsung/crespo/vendorsetup.sh

$ mmm frameworks/base/myservice/libmyservice/

編譯成功後生成文件:out/target/proct/generic/system/lib/libmyservice.so

3.2 myserver代碼實現

(1)新建目錄myservice/myserver,並進入該目錄

(2)編寫myserver/myserver.cpp文件

view plain
#include <sys/types.h>

#include <unistd.h>

#include <grp.h>

#include <binder/IPCThreadState.h>

#include <binder/ProcessState.h>

#include <binder/IServiceManager.h>

#include <utils/Log.h>

#include <private/android_filesystem_config.h>

#include "../libmyservice/myservice.h"

using namespace android;

int main(int argc, char** argv)

{

sp<ProcessState> proc(ProcessState::self());

sp<IServiceManager> sm = defaultServiceManager();//獲得ServiceManager介面

LOGI("ServiceManager: %p", sm.get());

MyService::instantiate();
//執行addService()函數,注冊服務
ProcessState::self()->startThreadPool();

IPCThreadState::self()->joinThreadPool();
//進入循環,等待客戶端的請求
return 0;

}

(3)編寫myserver/Android.mk文件

view plain
# File: Android.mk

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \

myserver.cpp

LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)

LOCAL_SHARED_LIBRARIES := \

libutils libbinder libmyservice

LOCAL_MODULE_TAGS := optional

LOCAL_PRELINK_MODULE := false

LOCAL_MODULE := myserver

include $(BUILD_EXECUTABLE)

(4)編譯myserver可執行程序
在android源碼主目錄下執行:
view plain
$mmm frameworks/base/myservice/myserver/

編譯成功後生成文件:out/target/proct/generic/symbols/system/bin/myserver

3.3 MyClient客戶端代碼實現
(1)新建目錄myservice/myclient,進入該目錄

(2)編寫myclient/myclient.h文件

view plain
namespace android

{

class MyClient {

public:

void add100(int n);

private:

static const void getMyService();
//通過ServiceManager獲取服務介面
};

}; //namespace

(3)編寫myclient/myclient.cpp文件

view plain
#include <binder/IServiceManager.h>

#include <binder/IPCThreadState.h>

#include "myclient.h"

namespace android

{

sp<IBinder> binder;

void MyClient::add100(int n)

{

getMyService();

Parcel data, reply;

int answer;

data.writeInt32(getpid());

data.writeInt32(n);

LOGE("BpMyService::create remote()->transact()/n");

binder->transact(0, data, &reply);

answer = reply.readInt32();

printf("answner=%d/n", answer);

return;

}

const void MyClient::getMyService()

{

sp<IServiceManager> sm = defaultServiceManager();

binder = sm->getService(String16("android.myservice"));

LOGE("MyClient::getMyService %p/n",sm.get());

if (binder == 0) {

LOGW("MyService not published, waiting...");

return;

}

}

}; //namespace

using namespace android;

int main(int argc, char** argv)

{

MyClient* p = new MyClient();

p->add100(1);

return 0;

}

(4)編寫myclient/Android.mk文件

view plain
LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \

myclient.cpp

LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)

LOCAL_SHARED_LIBRARIES := \

libutils libbinder libmyservice

LOCAL_MODULE_TAGS := optional

LOCAL_PRELINK_MODULE := false

LOCAL_MODULE := myclient

include $(BUILD_EXECUTABLE)

(5)編譯myclient可執行程序

在android源碼主目錄下,執行:
view plain
$ mmm frameworks/base/myservice/myclient/

編譯成功後生成可執行文件:out/target/proct/generic/symbols/system/bin/myclient

3.4在模擬器上運行
(1)啟動模擬器

view plain
$ cd ~/software/android/android-sdk-linux/tools
$ ./emulator -avd gbread -partition-size 512

(2)拷貝libmyservice.so到模擬器的/system/lib目錄

view plain
$cd out/target/proct/generic/obj/lib
$adb remount
$ adb push libmyservice.so /system/lib

159 KB/s (10084 bytes in 0.061s)

(3)拷貝myserver到模擬器的/system/bin目錄

view plain
$cd out/target/proct/generic/symbols/system/bin
$ adb push myserver /system/bin

668 KB/s (27508 bytes in 0.040s)

(4)拷貝myclient到/system/bin目錄

view plain
$ adb push myclient /system/bin

1549 KB/s (46840 bytes in 0.029s)

(5)在模擬器上啟動服務,並執行客戶端程序。

view plain
# adb shell
# cd system/bin
# ls my*

myclient

myserver

# ./myserver
# ./myclient
answner=101/n#

由客戶端程序的執行結果可知,由服務端返回的執行結果是正確的。

㈣ android 如何讓兩個apk相互通信

A.apk,B.apk都是我寫的.現在我想在B.apk里實現獲得A.apk的某控制項ID,並向其發送一個按鍵事件.如何實現,謝謝!也就是用B控制A.

這兩個apk 是在兩個進程里的,(或許可以配置成一個進程。不過如何直接操作這個沒有試過。)

所以一般的有兩種方法:
1、RPC
2、通過 BroadcastRecever 或 Service

第二種方法比較簡單一些。
比如B 控制 A的話,
A定義Service ,比如com.my.ServerA .自定義actionFilter 「com.my.serverA.action"
B中調用Intent it = newIntent("com.my.serverA.action");
it.putExtra(....);// 傳遞你的自定義控制指令。
B.startService(it);
在A中ServerA的 onStartService(Intent it) 。解析這個控制指令,做相應操作就可以了。

用BroadcastRecever 的道理一樣。

Aidl,android平台的IPC方式之一,基於系統的Ibinder機制。
網上大多數例子都是在一個apk下來測試調用service,現在我在兩個project下面來調用。
一個是server project,一個是client project
首先我們建立的是server project,這裡面要實現aidl文件和一個service,activity只是用來啟動service的,當然,你也可以通過發廣播的形式來啟動service。
首先看IAidlService.aidl文件:

Java代碼
package com.ds.server;
interface IAidlService {
int getType();
}

這樣在eclipse裡面自動編譯的時候會在gen下面生成IAidlService.java文件(燈下我們的client project要用)。
然後新建一個service,這個service裡面has a IAidlService的stub對象,service具體代碼如下:

Java代碼
package com.ds.server;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class AidlService extends Service {

private IAidlService.Stub mBinder = new IAidlService.Stub() {

@Override
public int getType() throws RemoteException {
// TODO Auto-generated method stub
return 5;
}
};

private void Log(String str) {
Log.d("AidlService", "------ " + str + "------");
}

@Override
public void onCreate() {
Log("service create");
}

@Override
public void onStart(Intent intent, int startId) {
Log("service start id=" + startId);
}

@Override
public IBinder onBind(Intent t) {
Log("service on bind");
return mBinder;
}

@Override
public void onDestroy() {
Log("service on destroy");
super.onDestroy();
}

@Override
public boolean onUnbind(Intent intent) {
Log("service on unbind");
return super.onUnbind(intent);
}

public void onRebind(Intent intent) {
Log("service on rebind");
super.onRebind(intent);
}

}

這里一定要實現onBind方法,並返回一個IAidlService.Stub對象。
再去AndroidManifest.xml注冊這個service:

Xml代碼
<service
android:name=".AidlService"
android:enabled="true"
android:process=":remote" >
<intent-filter>
<action android:name="com.ds.server.IAidlService" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>

android:enabled="true"
android:process=":remote"這兩個標簽可有可無。
只要注冊了這個service就行。
好了,到此,服務端已經完成。

-------------------華麗的分割線-----------------------------------------

下面我們開始client project。
client project比較簡單,需要注意的地方是,首先需要把server project中gen文件夾中aidl生成的那個IAidlService.java類以及包都拷貝到我們的client project中。
(注意:client project的包名為com.ds.client;另外一個包名com.ds.server以及這個server包下面的IAidlService.java類都是從server project的gen文件夾拷貝過來的,至於gen文件夾的其他文件就不需要拷貝過來。)。
好了,這樣的話,client project只要從activity去遠程調用service就好了,實現代碼如下:

Java代碼
package com.ds.client;

import com.ds.server.IAidlService;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class AidlClientActivity extends Activity {

IAidlService iservice;

private ServiceConnection connection = new ServiceConnection() {

public void onServiceConnected(ComponentName name, IBinder service) {
// TODO Auto-generated method stub
// 從遠程service中獲得AIDL實例化對象
iservice = IAidlService.Stub.asInterface(service);
Log.i("Client","Bind Success:" + iservice);
}

public void onServiceDisconnected(ComponentName name) {
// TODO Auto-generated method stub
iservice = null;
Log.i("Client","onServiceDisconnected");
}
};

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final TextView tv = (TextView) findViewById(R.id.tv);
Button bt = (Button) findViewById(R.id.bt);
bt.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent service = new Intent(IAidlService.class.getName());
bindService(service, connection, BIND_AUTO_CREATE);
if (iservice != null) {
try {
tv.setText("" + iservice.getType());
} catch (RemoteException e) {
e.printStackTrace();
}
}

}

});

}
}

注意幾點:
1,import com.ds.server.IAidlService;使用的是我們拷貝過來的IAidlService.java類
2,需要一個ServiceConnection對象
3,通過Intent service = new Intent(IAidlService.class.getName());
bindService(service, connection, BIND_AUTO_CREATE);來bind service。這樣就可以調用aidl中定義的介面來獲取service中的值了。

唉,由於在使用中沒有注意拷貝server project中gen文件夾下面的包和IAidlService.java,老是出現Unable to start service Intent這樣的錯誤。搞了好久。
附件是源碼。注意使用的時候,先要運行server project,啟動服務,然後再運行client project。

㈤ android intentservice和bindservice的區別

Service的生命周期方法比Activity少一些,只有onCreate,onStart,onDestroy我們有兩種方式啟動一個Service,他們對Service生命周期的影響是不一樣的。1通過startServiceService會經歷onCreate-->onStartstopService的時候直接onDestroy如果是調用者直接退出而沒有調用stopService的話,Service會一直在後台運行。下次調用者再起來仍然可以stopService。2通過bindServiceService只會運行onCreate,這個時候調用者和Service綁定在一起調用者退出了,Srevice就會調用onUnbind-->onDestroyed所謂綁定在一起就共存亡了。注意:Service的onCreate的方法只會被調用一次,就是你無論多少次的startService又bindService,Service只被創建一次。如果先是bind了,那麼start的時候就直接運行Service的onStart方法,如果先是start,那麼bind的時候就直接運行onBind方法。如果你先bind上了,就stop不掉了,只能先UnbindService,再StopService,所以是先start還是先bind行為是有區別的。Android中的服務和windows中的服務是類似的東西,服務一般沒有用戶操作界面,它運行於系統中不容易被用戶發覺,可以使用它開發如監控之類的程序。服務不能自己運行,需要通過調用Context.startService()或Context.bindService()方法啟動服務。這兩個方法都可以啟動Service,但是它們的使用場合有所不同。使用startService()方法啟用服務,調用者與服務之間沒有關連,即使調用者退出了,服務仍然運行。使用bindService()方法啟用服務,調用者與服務綁定在了一起,調用者一旦退出,服務也就終止,大有「不求同時生,必須同時死」的特點。如果打算採用Context.startService()方法啟動服務,在服務未被創建時,系統會先調用服務的onCreate()方法,接著調用onStart()方法。如果調用startService()方法前服務已經被創建,多次調用startService()方法並不會導致多次創建服務,但會導致多次調用onStart()方法。採用startService()方法啟動的服務,只能調用Context.stopService()方法結束服務,服務結束時會調用onDestroy()方法。如果打算採用Context.bindService()方法啟動服務,在服務未被創建時,系統會先調用服務的onCreate()方法,接著調用onBind()方法。這個時候調用者和服務綁定在一起,調用者退出了,系統就會先調用服務的onUnbind()方法,接著調用onDestroy()方法。如果調用bindService()方法前服務已經被綁定,多次調用bindService()方法並不會導致多次創建服務及綁定(也就是說onCreate()和onBind()方法並不會被多次調用)。如果調用者希望與正在綁定的服務解除綁定,可以調用unbindService()方法,調用該方法也會導致系統調用服務的onUnbind()-->onDestroy()方法.onBind將返回給客戶端一個IBind介面實例,IBind允許客戶端回調服務的方法,比如得到Service運行的狀態或其他操作。這個時候調用者會和Service綁定在一起,但onBind只能一次,不可多次綁定。在Service每一次的開啟關閉過程中,只有onStart可被多次調用(通過多次startService調用),其他onCreate,onBind,onUnbind,onDestory在一個生命周期中只能被調用一次。由於Android中的Service使用了onBind的方法去綁定服務,返回一個Ibinder對象進行操作,而我們要獲取具體的Service方法的內容的時候,我們需要Ibinder對象返回具體的Service對象才能操作,所以說具體的Service對象必須首先實現Binder對象,這個樣子的話我們才能利用bindService的方法對Service進行綁定,獲取Binder對象之後獲取具體的Service對象,然後才獲取Service中的方法等等。與採用Context.startService()方法啟動服務有關的生命周期方法onCreate()--onStart()--onDestroy()onCreate()該方法在服務被創建時調用,該方法只會被調用一次,無論調用多少次startService()或bindService()方法,服務也只被創建一次。onStart()只有採用Context.startService()方法啟動服務時才會回調該方法。該方法在服務開始運行時被調用。多次調用startService()方法盡管不會多次創建服務,但onStart()方法會被多次調用。onDestroy()該方法在服務被終止時調用。與採用Context.bindService()方法啟動服務有關的生命周期方法onCreate()--onBind()--onUnbind()--onDestroy()onBind()只有採用Context.bindService()方法啟動服務時才會回調該方法。該方法在調用者與服務綁定時被調用,當調用者與服務已經綁定,多次調用Context.bindService()方法並不會導致該方法被多次調用。轉載

㈥ 什麼是IBinder

首先要明白,Android的遠程調用(就是跨進程調用)就是通過IBinder實現的,下面是對android開發文檔的翻譯。
IBinder是遠程對象的基本介面,是為高性能而設計的輕量級遠程調用機制的核心部分。但它不僅用於遠程調用,也用於進程內調用。這個介面定義了與遠程對象交互的協議。不要直接實現這個介面,而應該從Binder派生。
IBinder的主要API是transact(),與它對應另一方法是Binder.onTransact()。第一個方法使你可以向遠端的IBinder對象發送發出調用,第二個方法使你自己的遠程對象能夠響應接收到的調用。IBinder的API都是同步執行的,比如transact()直到對方的Binder.onTransact()方法調用完成後才返回。調用發生在進程內時無疑是這樣的,而在進程間時,在IPC的幫助下,也是同樣的效果。
通過transact()發送的數據是Parcel,Parcel是一種一般的緩沖區,除了有數據外還帶有一些描述它內容的元數據。元數據用於管理IBinder對象的引用,這樣就能在緩沖區從一個進程移動到另一個進程時保存這些引用。這樣就保證了當一個IBinder被寫入到Parcel並發送到另一個進程中,如果另一個進程把同一個IBinder的引用回發到原來的進程,那麼這個原來的進程就能接收到發出的那個IBinder的引用。這種機制使IBinder和Binder像唯一標志符那樣在進程間管理。
系統為每個進程維護一個存放交互線程的線程池。這些交互線程用於派送所有從另外進程發來的IPC調用。例如:當一個IPC從進程A發到進程B,A中那個發出調用的線程(這個應該不在線程池中)就阻塞在transact()中了。進程B中的交互線程池中的一個線程接收了這個調用,它調用Binder.onTransact(),完成後用一個Parcel來做為結果返回。然後進程A中的那個等待的線程在收到返回的Parcel後得以繼續執行。實際上,另一個進程看起來就像是當前進程的一個線程,但不是當前進程創建的。
Binder機制還支持進程間的遞歸調用。例如,進程A執行自己的IBinder的transact()調用進程B的Binder,而進程B在其Binder.onTransact()中又用transact()向進程A發起調用,那麼進程A在等待它發出的調用返回的同時,還會用Binder.onTransact()響應進程B的transact()。總之Binder造成的結果就是讓我們感覺到跨進程的調用與進程內的調用沒什麼區別。
當操作遠程對象時,你經常需要查看它們是否有效,有三種方法可以使用:
1 transact()方法將在IBinder所在的進程不存在時拋出RemoteException異常。
2 如果目標進程不存在,那麼調用pingBinder()時返回false。
3 可以用linkToDeath()方法向IBinder注冊一個IBinder.DeathRecipient,在IBinder代表的進程退出時被調用。
要實現IBinder來支持遠程調用,應從Binder類派生一個類。Binder實現了IBinder介面。但是一般不需要直接實現此類,而是跟據你的需要由開發包中的工具生成,這個工具叫AIDL。你通過AIDL語言定義遠程對象的方法,然後用AIDL工具生成Binder的派生類,然後就可使用之。然而,可是,但是,當然,你也可以直接從Binder類派生以實現自定義的RPC調用,或只是實例化一個原始的Binder對象直接作為進程間共享的令牌來使用。

㈦ Android 之 Service(一)啟動,綁定服務

Service(服務)一個運行在後台執行長時間運行的操作組件,它不提供任何用戶界面,作為與Activity同級的組件,它依舊是運行在主線程中。
其它組件可以啟動一個Service,當這個Service啟動之後便會在後台執行,這里需要注意,由於是在主線程中,所以我們需要另外開啟一個線程來執行我們的耗時操作。
此外,一個組件還可以與一個Service進行綁定來實現組件之間的交互,甚至可以執行IPC(Inter-Process Communication)進程間通信。
Service可以在後台執行很多任務,比如處理網路事務,播放音樂,文件讀寫或者與一個內容提供者交互,等等。

本地服務(Local)
該服務依附在主進程上而不是獨立的進程,這樣在一定程度上節約了資源,另外本地服務因為是在同一進程因此不需要IPC,也不需要AIDL。相應bindService會方便很多,當主進程被Kill後,服務便會終止。一般使用在音樂播放器播放等不需要常駐的服務。

遠程服務(Remote Service)
該服務是獨立的進程,對應進程名格式為所在包名加上你指定的android:process字元串。一般定義方式 android:process=":service" 由於是獨立的進程,因此在Activity所在進程被Kill的時候,該服務依然在運行,不受其他進程影響,有利於為多個進程提供服務具有較高的靈活性。由於是獨立的進程,會佔用一定資源,並且使用AIDL進行IPC比較麻煩。一般用於系統的Service,這種Service是常駐的。

startService啟動的服務
用於啟動一個服務執行後台任務,不與組件進行通信,停止服務使用stopService。 當一個應用組件比如activity通過調用startService()來啟動一個服務的時候,服務便處於啟動狀態。一旦啟動,服務可以在後台無限期地運行下去,即使當啟動它的組件已經銷毀。通常情況下,一個啟動的service執行一個單一的操作並且不會返回任何結果給調用者。

bindService啟動的服務
用於啟動的服務需要進行通信。停止服務使用unbindService。 當一個應用組件通過調用bindService()來與一個服務綁定時,服務便處於綁定狀態。一個綁定的服務提供了一個客戶端-伺服器端介面來允許組件與服務進行交互,發送請求,得到結果甚至通過IPC進程間通信來完成操作。只有當其它組件與服務進行綁定時,服務才會處於綁定狀態。多個組件可以同時與服務綁定,但是當他們全部都解除綁定時,服務就會銷毀。

2.BindService:
如果一個Service在某個Activity中被調用bindService方法啟動,不論bindService被調用幾次,Service的 onCreate 方法只會執行一次,同時 onStartCommand 方法始終不會調用。當建立連接後,Service會一直運行,除非調用unbindService來接觸綁定、斷開連接或調用該Service的Context不存在了(如Activity被Finish——即通過bindService啟動的Service的生命周期依附於啟動它的Context),系統在這時會自動停止該Service。

3.StartService AND BindService:
當一個Service在被啟動(startService 的同時又被綁定(bindService ),該Service將會一直在後台運行,並且不管調用幾次, onCreate 方法始終只會調用一次, onStartCommand 的調用次數與startService 調用的次數一致(使用bindService 方法不會調用 onStartCommand )。同時,調用unBindService 將不會停止Service,必須調用stopService 或Service自身的stopSelf 來停止服務。

4.停止Service:
當一個服務被終止(stopService 、stopSelf 、unbindService )時, onDestory 方法將會被調用——所以我們需要在該方法中清除一些工作(依附該Service生命周期上的,比如:停止在Service中創建並運行的線程)。

1.創建服務

如果你才用的是 startService的方式那麼 onBind方法可以忽略
2.注冊服務

3.開啟服務
start:

bind

綁定服務,一般涉及到組件或進程之間的通信,既然需要通信,那麼我們肯定需要一個連接,這里ServiceConnection就是我們所需要的連接,通過Ibinder的傳遞,我們可以獲取到Service的Ibinder對象,從而進行相關操作。

關於粘性服務,這里需要提到 Service的onStartCommand返回值

andorid:name

adroid:exported

android:enabled

android:label

android:process

android:icon

android:permission

關於服務,當我們在應用開發中,如果需要長時間的在後台運行,獨立完成某一些事情的情況下,請使用Service!

此文綜合: http://www.jianshu.com/p/1e49e93c3ec8 以及自己的一些問題看法,用作學習,回顧之用。

Service 前台服務
請參看 紫豪 http://www.jianshu.com/p/5505390503fa

㈧ java android 中的IBinder和myBinder是同一種數據類型嗎,是引用數據類型的

Binder是一個具體類,具有其自己的功能,繼承Binder可以使用Binder原有功能,只對你需要的方法做修改;IBinder是個介面,可以讓你的類當作Binder來用,但是所有的具體功能都需要你自己編寫邏輯。

㈨ android中Boundservice和 IBinder 還有Binder這三者有什麼聯系和區別

是bindservice吧!activity先開啟服務接著綁定服務就是這個bindservice,這個方法接受三個參數,bindservice(intent,connection , bind_auto_create ),服務裡面有個方法onBind方法是返回ibinder,在activity裡面創建connection的時候有個方法將ibinder傳過來,然後activity可以通過ibinder對服務下達一些命令,讓你幹嘛幹嘛。前提是你在服務裡面已經創建好了一某個類繼承binder,然後在這個類裡面寫一下方法,這些方法就是activity讓服務去干什麼?然後就返回這類的對象,建議理解一下介面回調。

㈩ Android:實現Activity與Service的綁定,IBinder的transact()方法為什麼重要

可以,但是這個是封裝後的,適用於多個進程之間通信,如果你沒有Service源碼,不是自己定義的,那你怎麼把它cast成Service?如果使用別人的Service你也不能這么用,所以提供這種跨進程的溝通方式

熱點內容
酒店的路由器如何配置 發布:2024-05-19 15:10:44 瀏覽:499
rpgmaker腳本 發布:2024-05-19 14:48:58 瀏覽:406
hds存儲虛擬化 發布:2024-05-19 14:47:09 瀏覽:20
mysql資料庫分片 發布:2024-05-19 14:42:30 瀏覽:341
2021款魏派vv6買哪個配置 發布:2024-05-19 14:31:11 瀏覽:632
前端如何打開第二個伺服器地址 發布:2024-05-19 14:30:55 瀏覽:569
新建文件夾2百度盤 發布:2024-05-19 14:24:07 瀏覽:607
waslinux安裝部署 發布:2024-05-19 14:23:11 瀏覽:786
安卓系統怎麼注冊不了ins 發布:2024-05-19 14:01:00 瀏覽:961
買伺服器後怎麼搭建功能 發布:2024-05-19 14:00:03 瀏覽:208