【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】怎么在Android中利用Service實(shí)現(xiàn)IPC通信_(tái)第1頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】怎么在Android中利用Service實(shí)現(xiàn)IPC通信_(tái)第2頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】怎么在Android中利用Service實(shí)現(xiàn)IPC通信_(tái)第3頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】怎么在Android中利用Service實(shí)現(xiàn)IPC通信_(tái)第4頁(yè)
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】怎么在Android中利用Service實(shí)現(xiàn)IPC通信_(tái)第5頁(yè)
已閱讀5頁(yè),還剩9頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】怎么在Android中利用Service實(shí)現(xiàn)IPC通信

本篇文章給大家分享的是有關(guān)怎么在Android中利用Service實(shí)現(xiàn)IPC通信,在下覺(jué)得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著在下一起來(lái)看看吧。Android是一種基于Linux內(nèi)核的自由及開(kāi)放源代碼的操作系統(tǒng),主要使用于移動(dòng)設(shè)備,如智能手機(jī)和平板電腦,由美國(guó)Google公司和開(kāi)放手機(jī)聯(lián)盟領(lǐng)導(dǎo)及開(kāi)發(fā)。借助AIDL實(shí)現(xiàn)IPC通信AIDL:AndroidInterfaceDefinitionLanguage,即Android接口定義語(yǔ)言。Service跨進(jìn)程傳遞數(shù)據(jù)需要借助aidl,主要步驟是這樣的:編寫(xiě)aidl文件,AS自動(dòng)生成的java類(lèi)實(shí)現(xiàn)IPC通信的代理繼承自己的aidl類(lèi),實(shí)現(xiàn)里面的方法在onBind()中返回我們的實(shí)現(xiàn)類(lèi),暴露給外界需要跟Service通信的對(duì)象通過(guò)bindService與Service綁定,并在ServiceConnection接收數(shù)據(jù)。我們通過(guò)代碼來(lái)實(shí)現(xiàn)一下:1、首先我們需要新建一個(gè)Servicepublic

class

MyRemoteService

extends

Service

{

@Nullable

@Override

public

IBinder

onBind(Intent

intent)

{

Log.e("MyRemoteService",

"MyRemoteService

thread

id

=

"

+

Thread.currentThread().getId());

return

null;

}

}2、在manifest文件中聲明我們的Service同時(shí)指定運(yùn)行的進(jìn)程名,這里并是不只能寫(xiě)remote進(jìn)程名,你想要進(jìn)程名都可以<service

android:name=".service.MyRemoteService"

android:process=":remote"

/>3、新建一個(gè)aidl文件用戶進(jìn)程間傳遞數(shù)據(jù)。AIDL支持的類(lèi)型:八大基本數(shù)據(jù)類(lèi)型、String類(lèi)型、CharSequence、List、Map、自定義類(lèi)型。List、Map、自定義類(lèi)型放到下文講解。里面會(huì)有一個(gè)默認(rèn)的實(shí)現(xiàn)方法,刪除即可,這里我們新建的文件如下:package

xxxx;//aidl所在的包名

//interface之前不能有修飾符

interface

IProcessInfo

{

//你想要的通信用的方法都可以在這里添加

int

getProcessId();

}4、實(shí)現(xiàn)我們的aidl類(lèi)public

class

IProcessInfoImpl

extends

IProcessInfo.Stub

{

@Override

public

int

getProcessId()

throws

RemoteException

{

return

android.os.Process.myPid();

}

}5、在Service的onBind()中返回public

class

MyRemoteService

extends

Service

{

IProcessInfoImpl

mProcessInfo

=

new

IProcessInfoImpl();

@Nullable

@Override

public

IBinder

onBind(Intent

intent)

{

Log.e("MyRemoteService",

"MyRemoteService

thread

id

=

"

+

Thread.currentThread().getId());

return

mProcessInfo;

}

}6、綁定Service

mTvRemoteBind.setOnClickListener(new

View.OnClickListener()

{

@Override

public

void

onClick(View

v)

{

Intent

intent

=

new

Intent(MainActivity.this,

MyRemoteService.class);

bindService(intent,

mRemoteServiceConnection,

BIND_AUTO_CREATE);

}

});

mRemoteServiceConnection

=

new

ServiceConnection()

{

@Override

public

void

onServiceConnected(ComponentName

name,

IBinder

service)

{

Log.e("MainActivity",

"MyRemoteService

onServiceConnected");

//

通過(guò)aidl取出數(shù)據(jù)

IProcessInfo

processInfo

=

IProcessInfo.Stub.asInterface(service);

try

{

Log.e("MainActivity",

"MyRemoteService

process

id

=

"

+

processInfo.getProcessId());

}

catch

(RemoteException

e)

{

e.printStackTrace();

}

}

@Override

public

void

onServiceDisconnected(ComponentName

name)

{

Log.e("MainActivity",

"MyRemoteService

onServiceDisconnected");

}

};只要綁定成功就能在有l(wèi)og打印成MyRemoteService所在進(jìn)程的進(jìn)程id。這樣我們就完成了跟不同進(jìn)程的Service通信的過(guò)程。二、代碼實(shí)操調(diào)用其他app的Service跟調(diào)同app下不同進(jìn)程下的Service相比,調(diào)用其他的app定義的Service有一些細(xì)微的差別1、由于需要其他app訪問(wèn),所以之前的bindService()使用的隱式調(diào)用不在合適,需要在Service定義時(shí)定義action我們?cè)诙x的線程的AppA中定義如下Service:<service

android:name=".service.ServerService">

<intent-filter>

//這里的action自定義

<action

android:name="com.jxx.server.service.bind"

/>

<category

android:name="ent.category.DEFAULT"

/>

</intent-filter>

</service>2、我們?cè)谛枰猙indService的AppB中需要做這些處理首先要將A中定義的aidl文件復(fù)制到B中,比如我們?cè)谏厦娑x的IProcessInfo.aidl這個(gè)文件,包括路徑在內(nèi)需要原封不動(dòng)的復(fù)制過(guò)來(lái)。在B中調(diào)用Service通過(guò)顯式調(diào)用mTvServerBind.setOnClickListener(new

View.OnClickListener()

{

@Override

public

void

onClick(View

v)

{

Intent

intent

=

new

Intent();

intent.setAction("com.jxx.server.service.bind");//Service的action

intent.setPackage("com.jxx.server");//App

A的包名

bindService(intent,

mServerServiceConnection,

BIND_AUTO_CREATE);

}

});aidl中自定義對(duì)象的傳遞主要步驟如下:定義自定對(duì)象,需要實(shí)現(xiàn)Parcelable接口新建自定義對(duì)象的aidl文件在傳遞數(shù)據(jù)的aidl文件中引用自定義對(duì)象將自定義對(duì)象以及aidl文件拷貝到需要bindService的app中,主要路徑也要原封不動(dòng)我們來(lái)看一下具體的代碼:1、定義自定義對(duì)象,并實(shí)現(xiàn)Parcelable接口public

class

ServerInfo

implements

Parcelable

{

public

ServerInfo()

{

}

String

mPackageName;

public

String

getPackageName()

{

return

mPackageName;

}

public

void

setPackageName(String

packageName)

{

mPackageName

=

packageName;

}

protected

ServerInfo(Parcel

in)

{

mPackageName

=

in.readString();

}

public

static

final

Creator<ServerInfo>

CREATOR

=

new

Creator<ServerInfo>()

{

@Override

public

ServerInfo

createFromParcel(Parcel

in)

{

return

new

ServerInfo(in);

}

@Override

public

ServerInfo[]

newArray(int

size)

{

return

new

ServerInfo[size];

}

};

@Override

public

int

describeContents()

{

return

0;

}

@Override

public

void

writeToParcel(Parcel

dest,

int

flags)

{

dest.writeString(mPackageName);

}

//使用out或者inout修飾時(shí)需要自己添加這個(gè)方法

public

void

readFromParcel(Parcel

dest)

{

mPackageName

=

dest.readString();

}

}2、新建自定義對(duì)象的aidl文件package

com.jxx.server.aidl;

//注意parcelable

是小寫(xiě)的

parcelable

ServerInfo;3、引用自定義對(duì)象package

com.jxx.server.aidl;

//就算在同一包下,這里也要導(dǎo)包

import

com.jxx.server.aidl.ServerInfo;

interface

IServerServiceInfo

{

ServerInfo

getServerInfo();

void

setServerInfo(inout

ServerInfo

serverinfo);

}注意這里的set方法,這里用了inout,一共有3種修飾符-in:客戶端寫(xiě)入,服務(wù)端的修改不會(huì)通知到客戶端-out:服務(wù)端修改同步到客戶端,但是服務(wù)端獲取到的對(duì)象可能為空-inout:修改都收同步的當(dāng)使用out和inout時(shí),除了要實(shí)現(xiàn)Parcelable外還要手動(dòng)添加readFromParcel(Parceldest)4、拷貝自定義對(duì)象以及aidl文件到在要引用的App中即可。5、引用mServerServiceConnection

=

new

ServiceConnection()

{

@Override

public

void

onServiceConnected(ComponentName

name,

IBinder

service)

{

IServerServiceInfo

serverServiceInfo

=

IServerServiceInfo.Stub.asInterface(service);

try

{

ServerInfo

serviceInfo

=

serverServiceInfo.getServerInfo();

Log.e("MainActivity",

"ServerService

packageName

=

"

+

serviceInfo.getPackageName());

}

catch

(RemoteException

e)

{

e.printStackTrace();

}

}

@Override

public

void

onServiceDisconnected(ComponentName

name)

{

Log.e("MainActivity",

"ServerService

onServiceDisconnected");

}

};List、Map中引用的對(duì)象也應(yīng)該是符合上面要求的自定義對(duì)象,或者其他的幾種數(shù)據(jù)類(lèi)型。使用Messenger實(shí)現(xiàn)IPC通信步驟是這樣的:在Server端新建一個(gè)Messenger對(duì)象,用于響應(yīng)Client端的注冊(cè)操作,并在onBind()中傳遞出去在Client端的ServiceConnection中,將Server端傳遞過(guò)來(lái)的Messenger對(duì)象進(jìn)行保存同時(shí)Client端也新建一個(gè)Messenger對(duì)象,通過(guò)Server傳遞過(guò)來(lái)的Messenger注冊(cè)到Server端,保持通信用。不管是否進(jìn)行unbindService()操作,只要Client保有Server端的Messenger對(duì)象,仍然能和Server端進(jìn)行通信。一、Server端代碼public

class

MessengerService

extends

Service

{

static

final

int

MSG_REGISTER_CLIENT

=

1;

static

final

int

MSG_UNREGISTER_CLIENT

=

2;

static

final

int

MSG_SET_VALUE

=

3;

//這個(gè)是給client端接收參數(shù)用的

static

final

int

MSG_CLIENT_SET_VALUE

=

4;

static

class

ServiceHandler

extends

Handler

{

private

final

List<Messenger>

mMessengerList

=

new

ArrayList<>();

@Override

public

void

handleMessage(Message

msg)

{

switch

(msg.what)

{

case

MSG_REGISTER_CLIENT:

mMessengerList.add(msg.replyTo);

break;

case

MSG_UNREGISTER_CLIENT:

mMessengerList.remove(msg.replyTo);

break;

case

MSG_SET_VALUE:

int

value

=

msg.arg1;

for

(Messenger

messenger

:

mMessengerList)

{

try

{

messenger.send(Message.obtain(null,

MSG_CLIENT_SET_VALUE,

value,

0));

}

catch

(RemoteException

e)

{

e.printStackTrace();

}

}

break;

default:

super.handleMessage(msg);

}

}

}

private

Messenger

mMessenger

=

new

Messenger(new

ServiceHandler());

@Nullable

@Override

public

IBinder

onBind(Intent

intent)

{

return

mMessenger.getBinder();

}

}二、Client端代碼public

class

MessengerClientActivity

extends

AppCompatActivity

{

//這些類(lèi)型要和Server端想對(duì)應(yīng)

static

final

int

MSG_REGISTER_CLIENT

=

1;

static

final

int

MSG_UNREGISTER_CLIENT

=

2;

static

final

int

MSG_SET_VALUE

=

3;

static

final

int

MSG_CLIENT_SET_VALUE

=

4;

class

ClientHandler

extends

Handler

{

@Override

public

void

handleMessage(Message

msg)

{

if

(msg.what

==

MSG_CLIENT_SET_VALUE)

{

mTvValue.setText(msg.arg1

+

"");

}

else

{

super.handleMessage(msg);

}

}

}

TextView

mTvServerBind;

TextView

mTvServerUnbind;

TextView

mTvValue;

TextView

mTvSend;

ServiceConnection

mServerServiceConnection;

Messenger

mServerMessenger;

@Override

protected

void

onCreate(@Nullable

Bundle

savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_messenger);

mTvServerBind

=

findViewById(R.id.tv_server_bind);

mTvServerUnbind

=

findViewById(R.id.tv_server_unbind);

mTvValue

=

findViewById(R.id.tv_value);

mTvSend

=

findViewById(R.id.tv_send);

mTvServerBind.setOnClickListener(new

View.OnClickListener()

{

@Override

public

void

onClick(View

v)

{

Intent

intent

=

new

Intent();

intent.setAction(".server.service.messenger");

intent.setPackage(".server");

bindService(intent,

mServerServiceConnection,

BIND_AUTO_CREATE);

}

});

mTvServerUnbind.setOnClickListener(new

View.OnClickListener()

{

@Override

public

void

onClick(View

v)

{

//就算這里我們unbindService,只要我們還保留有mServerMessenger對(duì)象,

//我們就能繼續(xù)與Server通信

unbindService(mServerServiceConnection);

}

});

mTvSend.setOnClickListener(new

View.OnClickListener()

{

@Override

public

void

onClick(View

v)

{

if

(mServerMessenger

!=

null)

{

try

{

//測(cè)試一下能否設(shè)置數(shù)據(jù)

Message

test

=

Message.obtain(null,

MSG_SET_VALUE,

new

Random().nextInt(100),

0);

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論