




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐ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),主要使用于移動設(shè)備,如智能手機(jī)和平板電腦,由美國Google公司和開放手機(jī)聯(lián)盟領(lǐng)導(dǎo)及開發(fā)。借助AIDL實(shí)現(xiàn)IPC通信AIDL:AndroidInterfaceDefinitionLanguage,即Android接口定義語言。Service跨進(jìn)程傳遞數(shù)據(jù)需要借助aidl,主要步驟是這樣的:編寫aidl文件,AS自動生成的java類實(shí)現(xiàn)IPC通信的代理繼承自己的aidl類,實(shí)現(xiàn)里面的方法在onBind()中返回我們的實(shí)現(xiàn)類,暴露給外界需要跟Service通信的對象通過bindService與Service綁定,并在ServiceConnection接收數(shù)據(jù)。我們通過代碼來實(shí)現(xiàn)一下:1、首先我們需要新建一個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同時指定運(yùn)行的進(jìn)程名,這里并是不只能寫remote進(jìn)程名,你想要進(jìn)程名都可以<service
android:name=".service.MyRemoteService"
android:process=":remote"
/>3、新建一個aidl文件用戶進(jìn)程間傳遞數(shù)據(jù)。AIDL支持的類型:八大基本數(shù)據(jù)類型、String類型、CharSequence、List、Map、自定義類型。List、Map、自定義類型放到下文講解。里面會有一個默認(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定義時定義action我們在定義的線程的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、我們在需要bindService的AppB中需要做這些處理首先要將A中定義的aidl文件復(fù)制到B中,比如我們在上面定義的IProcessInfo.aidl這個文件,包括路徑在內(nèi)需要原封不動的復(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中自定義對象的傳遞主要步驟如下:定義自定對象,需要實(shí)現(xiàn)Parcelable接口新建自定義對象的aidl文件在傳遞數(shù)據(jù)的aidl文件中引用自定義對象將自定義對象以及aidl文件拷貝到需要bindService的app中,主要路徑也要原封不動我們來看一下具體的代碼:1、定義自定義對象,并實(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修飾時需要自己添加這個方法
public
void
readFromParcel(Parcel
dest)
{
mPackageName
=
dest.readString();
}
}2、新建自定義對象的aidl文件package
com.jxx.server.aidl;
//注意parcelable
是小寫的
parcelable
ServerInfo;3、引用自定義對象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ù)端的修改不會通知到客戶端-out:服務(wù)端修改同步到客戶端,但是服務(wù)端獲取到的對象可能為空-inout:修改都收同步的當(dāng)使用out和inout時,除了要實(shí)現(xiàn)Parcelable外還要手動添加readFromParcel(Parceldest)4、拷貝自定義對象以及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中引用的對象也應(yīng)該是符合上面要求的自定義對象,或者其他的幾種數(shù)據(jù)類型。使用Messenger實(shí)現(xiàn)IPC通信步驟是這樣的:在Server端新建一個Messenger對象,用于響應(yīng)Client端的注冊操作,并在onBind()中傳遞出去在Client端的ServiceConnection中,將Server端傳遞過來的Messenger對象進(jìn)行保存同時Client端也新建一個Messenger對象,通過Server傳遞過來的Messenger注冊到Server端,保持通信用。不管是否進(jìn)行unbindService()操作,只要Client保有Server端的Messenger對象,仍然能和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;
//這個是給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端想對應(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對象,
//我們就能繼續(xù)與Server通信
unbindService(mServerServiceConnection);
}
});
mTvSend.setOnClickListener(new
View.OnClickListener()
{
@Override
public
void
onClick(View
v)
{
if
(mServerMessenger
!=
null)
{
try
{
//測試一下能否設(shè)置數(shù)據(jù)
Message
test
=
Message.obtain(null,
MSG_SET_VALUE,
new
Random().nextInt(100),
0);
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025至2030年中國高壓噴霧車市場分析及競爭策略研究報(bào)告
- 2025至2030年中國透氣帽市場分析及競爭策略研究報(bào)告
- 2025至2030年中國聚氨酯發(fā)泡保溫巖棉制品市場分析及競爭策略研究報(bào)告
- 2025至2030年中國立式單層儲液罐市場分析及競爭策略研究報(bào)告
- 2025至2030年中國焊接銷套市場分析及競爭策略研究報(bào)告
- 2025至2030年中國橋梁組合鋼模板市場分析及競爭策略研究報(bào)告
- 2025至2030年中國方便車市場分析及競爭策略研究報(bào)告
- 2025至2030年中國微機(jī)遠(yuǎn)動力學(xué)終端單元市場分析及競爭策略研究報(bào)告
- 2025至2030年中國參鹿強(qiáng)身膠囊市場分析及競爭策略研究報(bào)告
- 2025至2030年中國人棉粒粒布市場分析及競爭策略研究報(bào)告
- YY/T 1851-2022用于增材制造的醫(yī)用純鉭粉末
- GB/Z 13800-2021手動輪椅車
- GB/T 6109.17-2008漆包圓繞組線第17部分:180級自粘性直焊聚酯亞胺漆包銅圓線
- GB/T 5163-2006燒結(jié)金屬材料(不包括硬質(zhì)合金)可滲性燒結(jié)金屬材料密度、含油率和開孔率的測定
- 英語學(xué)科核心素養(yǎng)教案設(shè)計(jì)
- 小學(xué)二年級數(shù)學(xué)下冊找規(guī)律復(fù)習(xí)題
- GPS與慣導(dǎo)系統(tǒng)的組合導(dǎo)航技術(shù)課件
- 2020-2021年度廣東省湛江市赤坎區(qū)教師縣鄉(xiāng)選調(diào)招聘考試《教育基礎(chǔ)知識》試卷及答案【解析】
- DB15T 489-2019 石油化學(xué)工業(yè)建設(shè)工程技術(shù)資料管理規(guī)范
- (新版)無人機(jī)駕駛員資格理論考試題庫及答案
- HALCON編程基礎(chǔ)與工程應(yīng)用全書ppt課件匯總(完整版)
評論
0/150
提交評論