每個應用程序都運行在自己的獨立進程中,並且可以啓動另一個應用程序的服務。在不同的進程間傳遞數據對象
一個進程不能直接訪問另一個進程的內存空間,如果想對話,則需要將對象分解成操作系統可以理解的基本單元,並且有序的通過進程邊界
首先做一個簡單的練習:不傳遞參數,啓動另一個應用程序的服務
第一步:寫服務端。
Service(服務端):
aidl:
interface StudentAIDL {
void AIDL_Student(String data);
String reutrnString();
}
Service:
public class MyService extends Service {
StudentAIDL.Stub mBinder=new StudentAIDL.Stub() {
@Override
public void AIDL_Student() throws RemoteException {
Log.e("TAG", "AIDL_Student");
}
};
@Override
public void onCreate() {
Log.e("TAG", "onCreate");
super.onCreate();
}
@Override
public void onDestroy() {
Log.e("TAG", "onDestroy");
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
Log.e("TAG", "onBind");
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.e("TAG", "onUnbind");
return super.onUnbind(intent);
}
}
配置文件:
<service
android:name=".MyService"
android:enabled="true"
android:exported="true" 設置可被其他進程調用
android:process=":remote"> //將本地服務設置成遠程服務
<intent-filter>
<action android:name="asd"></action>
</intent-filter>
</service>
第二步,寫客戶端,將服務斷的aidl文件夾整個複製到客戶端main包下。(也可以自己寫吧,就是寫一個一模一樣的)
Client(客戶端):
private StudentAIDL studentAIDL;
private ServiceConnection comn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//綁定
public void bindService(View view){
if(comn==null) {
//這裏寫的是服務端的action
Intent intent=new Intent("asd");
//這裏的路徑是服務端aidl文件的路徑
intent.setPackage("com.example.serviceaidl");
comn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e("TAG", "onServiceConnected");
studentAIDL = StudentAIDL.Stub.asInterface(service);
try {
//通過該對象調用在MyAIDLService.aidl文件中定義的接口方法,從而實現跨進程通信
studentAIDL.AIDL_Student();
String s = studentAIDL.reutrnString();
Log.e("TAG", "studentAIDL");
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e("TAG", "onServiceDisconnected");
}
};
bindService(intent, comn, BIND_AUTO_CREATE);
Log.e("TAG", "bindService");
}else{
Log.e("TAG", "Service is bound");
}
}
//解除綁定
public void unbindService(View view){
if(comn!=null) {
unbindService(comn);
//如果不設置null,即使解除了綁定,activity也綁定不了服務
comn=null;
Toast.makeText(this, "unbindservice", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "未bind service", Toast.LENGTH_SHORT).show();
}
}
public void startService(View view){
}
@Override
protected void onDestroy() {
super.onDestroy();
if(comn!=null){
unbindService(comn);
comn=null;
}
}
Service:
public class ClientService extends Service {
@Override
public IBinder onBind(Intent intent) {
Log.e("TAG", "onBind");
return new Binder();
}
}
傳遞複雜參數:
服務端返回一個bean類給客戶端:
要注意的點:
在客戶端和服務端都需要有一模一樣的bean類(也可以不一樣,比如單方只有打包和解包。)
首先,先上bean類,bean類要實現Parcelable接口,如下:
public class Student implements Parcelable {
private int id;
private String name;
public Student(int id, String name) {
this.id = id;
this.name = name;
}
public Student(Parcel in) {
id = in.readInt();
name = in.readString();
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
//將當前對象的屬性數據打成包:寫到包中
//打包
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeString(name);
}
@Override
public int describeContents() {
return 0;
}
//添加一個靜態成員,名爲Creator,該對象實現了Parcelable.Creator接口
public static final Creator<Student> CREATOR = new Creator<Student>() {
//解包:讀取包中的數據,並封裝成對象
@Override
public Student createFromParcel(Parcel in) {
return new Student(in);
}
//返回一個指定大小的對象容器
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
}
然後就是aidl接口:
package com.example.serviceaidl;
import com.example.serviceaidl.Student;
// Declare any non-default types here with import statements
interface StudentAIDL {
void AIDL_Student(String data);
String reutrnString();
Student getStudent();
}
aidl文件,需要創建一個和Bean類同意樣名字的aidl:
內容如下:
parcelable Student;
上面三個文件是客戶端和服務端共有的。
服務端:
Service:
public class MyService extends Service {
StudentAIDL.Stub mBinder=new StudentAIDL.Stub() {
@Override
public void AIDL_Student(String data) throws RemoteException {
Log.e("TAG", data);
}
@Override
public String reutrnString() throws RemoteException {
return "Hello,Client";
}
@Override
public Student getStudent() throws RemoteException {
return new Student(12,"Tom");
}
};
@Override
public void onCreate() {
Log.e("TAG", "onCreate");
super.onCreate();
}
@Override
public void onDestroy() {
Log.e("TAG", "onDestroy");
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
Log.e("TAG", "onBind");
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.e("TAG", "onUnbind");
return super.onUnbind(intent);
}
}
客戶端
和上面的沒什麼區別,只是多調用了兩個方法
public class MainActivity extends AppCompatActivity {
private StudentAIDL studentAIDL;
private ServiceConnection comn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//綁定
public void bindService(View view){
if(comn==null) {
Intent intent=new Intent("asd");
intent.setPackage("com.example.serviceaidl");
comn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.e("TAG", "onServiceConnected");
// 從連接中獲取Stub對象
studentAIDL = StudentAIDL.Stub.asInterface(service);
try {
//通過該對象調用在MyAIDLService.aidl文件中定義的接口方法,從而實現跨進程通信
studentAIDL.AIDL_Student("hello world");
String s = studentAIDL.reutrnString();
Student student = studentAIDL.getStudent();
Log.e("TAG", student.getName()+"----------"+student.getId());
Log.e("TAG", s+"");
Log.e("TAG", "studentAIDL");
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e("TAG", "onServiceDisconnected");
}
};
bindService(intent, comn, BIND_AUTO_CREATE);
Log.e("TAG", "bindService");
}else{
Log.e("TAG", "Service is bound");
}
}
//解除綁定
public void unbindService(View view){
if(comn!=null) {
unbindService(comn);
//如果不設置null,即使解除了綁定,activity也綁定不了服務
comn=null;
Toast.makeText(this, "unbindservice", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "未bind service", Toast.LENGTH_SHORT).show();
}
}
public void startService(View view){
}
@Override
protected void onDestroy() {
super.onDestroy();
if(comn!=null){
unbindService(comn);
comn=null;
}
}
}
Service:
public class ClientService extends Service {
@Override
public IBinder onBind(Intent intent) {
Log.e("TAG", "onBind");
return new Binder();
}
}