版權(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 醫(yī)療廢物處理招投標(biāo)科研申請(qǐng)表
- 2024雙方同意離婚協(xié)議之市場(chǎng)營(yíng)銷(xiāo)合同
- 2024年企業(yè)環(huán)境污染第三方治理合同
- 耐潮濕木地板安裝協(xié)議
- 公共衛(wèi)生驗(yàn)收管理辦法
- 煙草產(chǎn)品留樣程序
- 二手車(chē)交易合同樣本認(rèn)證
- 體育場(chǎng)彩鋼瓦翻新合同
- 建筑隔音甲方與施工方合同范本
- 住宅小區(qū)道路翻新合同
- 互聯(lián)網(wǎng)護(hù)理的居家溝通唐瑩教授護(hù)患溝通護(hù)患關(guān)系護(hù)士培訓(xùn)
- 2024年全國(guó)《勞動(dòng)教育》基礎(chǔ)知識(shí)考試題庫(kù)與答案
- 國(guó)家開(kāi)放大學(xué)本科(非英語(yǔ)專業(yè))學(xué)士學(xué)位英語(yǔ)統(tǒng)一考試樣題
- 2024人教版道德與法治五年級(jí)上冊(cè)第四單元:驕人祖先燦爛文化大單元整體教學(xué)設(shè)計(jì)
- 幼兒園中班社會(huì)《節(jié)約用紙》課件
- 時(shí)代樂(lè)章第三課自然之美 課件 2024-2025學(xué)年人教版(2024)初中美術(shù)上冊(cè)
- 住宅區(qū)和住宅建筑通信配套工程技術(shù)標(biāo)準(zhǔn) DG-TJ08-606-2022
- 2024年新蘇教版一年級(jí)上冊(cè)數(shù)學(xué)全冊(cè)課件(新版教材)
- GB/T 44144-2024有聲讀物
- 《無(wú)人機(jī)測(cè)繪技能訓(xùn)練模塊》課件-模塊7:無(wú)人機(jī)航測(cè)影像獲取
- 上海市中考英語(yǔ)試卷及答案
評(píng)論
0/150
提交評(píng)論