版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
【移動(dòng)應(yīng)用開發(fā)技術(shù)】怎么在Android中利用Service實(shí)現(xiàn)IPC通信
本篇文章給大家分享的是有關(guān)怎么在Android中利用Service實(shí)現(xiàn)IPC通信,在下覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著在下一起來看看吧。Android是一種基于Linux內(nèi)核的自由及開放源代碼的操作系統(tǒng),主要使用于移動(dòng)設(shè)備,如智能手機(jī)和平板電腦,由美國(guó)Google公司和開放手機(jī)聯(lián)盟領(lǐng)導(dǎo)及開發(fā)。借助AIDL實(shí)現(xiàn)IPC通信AIDL:AndroidInterfaceDefinitionLanguage,即Android接口定義語(yǔ)言。Service跨進(jìn)程傳遞數(shù)據(jù)需要借助aidl,主要步驟是這樣的:編寫aidl文件,AS自動(dòng)生成的java類實(shí)現(xiàn)IPC通信的代理繼承自己的aidl類,實(shí)現(xiàn)里面的方法在onBind()中返回我們的實(shí)現(xiàn)類,暴露給外界需要跟Service通信的對(duì)象通過bindService與Service綁定,并在ServiceConnection接收數(shù)據(jù)。我們通過代碼來實(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)程名,這里并是不只能寫remote進(jìn)程名,你想要進(jìn)程名都可以<service
android:name=".service.MyRemoteService"
android:process=":remote"
/>3、新建一個(gè)aidl文件用戶進(jìn)程間傳遞數(shù)據(jù)。AIDL支持的類型:八大基本數(shù)據(jù)類型、String類型、CharSequence、List、Map、自定義類型。List、Map、自定義類型放到下文講解。里面會(huì)有一個(gè)默認(rèn)的實(shí)現(xiàn)方法,刪除即可,這里我們新建的文件如下:package
xxxx;//aidl所在的包名
//interface之前不能有修飾符
interface
IProcessInfo
{
//你想要的通信用的方法都可以在這里添加
int
getProcessId();
}4、實(shí)現(xiàn)我們的aidl類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");
//
通過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通信的過程。二、代碼實(shí)操調(diào)用其他app的Service跟調(diào)同app下不同進(jìn)程下的Service相比,調(diào)用其他的app定義的Service有一些細(xì)微的差別1、由于需要其他app訪問,所以之前的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ù)制過來。在B中調(diào)用Service通過顯式調(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)我們來看一下具體的代碼: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
是小寫的
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:客戶端寫入,服務(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ù)類型。使用Messenger實(shí)現(xiàn)IPC通信步驟是這樣的:在Server端新建一個(gè)Messenger對(duì)象,用于響應(yīng)Client端的注冊(cè)操作,并在onBind()中傳遞出去在Client端的ServiceConnection中,將Server端傳遞過來的Messenger對(duì)象進(jìn)行保存同時(shí)Client端也新建一個(gè)Messenger對(duì)象,通過Server傳遞過來的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
{
//這些類型要和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. 本站所有資源如無特殊說明,都需要本地電腦安裝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ù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度汽車租賃公司與個(gè)人短期自駕游服務(wù)協(xié)議3篇
- 二零二五年度養(yǎng)殖場(chǎng)勞務(wù)合同(養(yǎng)殖場(chǎng)環(huán)保設(shè)施建設(shè))3篇
- 2025年度跨境電商業(yè)務(wù)承包合同3篇
- 2025年度旅游套餐分期付款購(gòu)買合同3篇
- 2025年度農(nóng)產(chǎn)品出口業(yè)務(wù)委托收購(gòu)及代理協(xié)議3篇
- 2025年度停車場(chǎng)車位資源優(yōu)化配置合同3篇
- 2025年度體育俱樂部兼職教練員聘用合同書3篇
- 二零二五年度籃球球員轉(zhuǎn)會(huì)合同變更通知3篇
- 二零二五年度公司銷售業(yè)務(wù)員協(xié)議書:環(huán)保建筑材料銷售服務(wù)合同3篇
- 二零二五年度酒店前臺(tái)禮儀與客戶滿意度勞動(dòng)合同3篇
- 2024-2025學(xué)年年八年級(jí)數(shù)學(xué)人教版下冊(cè)專題整合復(fù)習(xí)卷第11章 全等三角形單元試卷(含答案)
- 蜜雪冰城合作加盟合同
- 青海省西寧市2021-2022學(xué)年八年級(jí)上學(xué)期期末歷史試題(解析版)
- 浙江省杭州市2023-2024學(xué)年高二上學(xué)期期末學(xué)業(yè)水平測(cè)試政治試題 含解析
- 人力資源規(guī)劃
- 夜泊牛渚懷古
- 初一英語(yǔ)單詞辨音專項(xiàng)練習(xí)(共4頁(yè))
- 河北省建設(shè)工程竣工驗(yàn)收?qǐng)?bào)告
- 付款申請(qǐng)單打印版模板
- 畢業(yè)設(shè)計(jì)范本
- 26化學(xué)物的致突變、致癌變及致畸作用
評(píng)論
0/150
提交評(píng)論