跨进程通信IPC方式
1.使用Bundle(intent)
四大组件中的三大组件(Activity,Service,Receiver)都支持在intent中传递Bundle数据(Bundle数据实现了Parcelable接口),当我们在一个进程中启动了另一个进程的Activity,Service,Receive,可以在Bundle中附加我们需要传递给远程进程的信息并通过intent发送出去。
重点:
Intent intent=new Intent("vera.CALL", Uri.parse("infovera://woshiInvoke"));
intent.putExtra("value","成功");
startActivity(intent);
示例:
a.在一个进程中设置Main2Activity的action 、data、category。
<activity android:name=".Main2Activity">
<intent-filter>
<action android:name="vera.CALL" />
<data android:scheme="infovera" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
b.在另一个进程中唤醒这个Main2Activity(新建一个项目invokeApp)
public class MainActivity extends AppCompatActivity {
@butterknife.BindView(R.id.invoke)
Button invoke;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
butterknife.ButterKnife.bind(this);
}
@butterknife.OnClick(R.id.invoke)
public void onViewClicked() {
Intent intent=new Intent("vera.CALL", Uri.parse("infovera://woshiInvoke"));
intent.putExtra("value","成功");
startActivity(intent);
}
}
c.在Main2Activity中获取另一个进程传递过来的数据
public class Main2Activity extends AppCompatActivity {
public static final String ACTION_CALL = "vera.CALL";
@BindView(R.id.btn)
Button btn;
@BindView(R.id.edit)
EditText edit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
ButterKnife.bind(this);
if(getIntent().getData()!=null){
// 获得host,就是infovera://后面的内容
String host=getIntent().getData().getHost();
Bundle bundle=getIntent().getExtras();// 与intent.putExtra("value","成功")对应
// 在bundle中附加的信息
String value=bundle.getString("value");
edit.setText(host+";"+value);
}
}
@OnClick(R.id.btn)
public void onViewClicked() {
Toast.makeText(this, edit.getText().toString(), Toast.LENGTH_SHORT).show();
}
}
2.使用文件共享
两个进程通过读写同一个文件来交换数据。除了交换一些文本信息之外,还可以序列化一个对象到文件系统的同时从另一个进程恢复这个对象。
一个序列化对象
package com.example.myapplication;
import java.io.Serializable;
/**
* <p>文件描述:<p>
* <p>创建时间:2019/3/9<p>
*/
public class User implements Serializable {
private static final long serialVersionUID = -4712598323293490897L;
public int userId;
public String name;
@Override
public String toString() {
return "User{" +
"userId=" + userId +
", name='" + name + '\'' +
'}';
}
public User(int userId, String name) {
this.userId = userId;
this.name = name;
}
public static long getSerialVersionUID() {
return serialVersionUID;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
在清单文件中把Main4Activity设置为另一个进程:
<activity android:name=".Main4Activity"
android:process="vera.activity4"></activity>
实现序列化
public class Main3Activity extends AppCompatActivity {
private static final String TAG = "vera";
User user;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
if (ContextCompat.checkSelfPermission(Main3Activity.this, Manifest.permission_group.STORAGE)!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission_group.STORAGE},1);
}
user=new User(1,"zhang1");
persistToFile();
}
private void persistToFile() {
File dir=new File(MyConstants.CHAPTER_2_PATH);
if (!dir.exists())dir.mkdirs();
File cachedFile=new File(MyConstants.CACHE_FILE_PATH);
ObjectOutputStream objectOutputStream=null;
try {
objectOutputStream=new ObjectOutputStream(new FileOutputStream(cachedFile));
} catch (IOException e) {
e.printStackTrace();
}
try {
objectOutputStream.writeObject(user);
Log.e(TAG, "writeObject: user"+user );
} catch (IOException e) {
e.printStackTrace();
}
try {
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.example.myapplication;
import android.os.Environment;
public class MyConstants {
public static final String CHAPTER_2_PATH = Environment
.getExternalStorageDirectory().getPath()
+ "/singwhatiwanna/chapter_2/";
public static final String CACHE_FILE_PATH = CHAPTER_2_PATH + "usercache";
}
反序列化
package com.example.myapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Main4Activity extends AppCompatActivity {
private static final String TAG = "vera";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main4);
Log.e(TAG, "onCreate: " );
recoverFromFile();
}
private void recoverFromFile() {
User user=null;
File cachedFile=new File(MyConstants.CACHE_FILE_PATH);
if(cachedFile.exists()){
ObjectInputStream objectInputStream=null;
try {
objectInputStream=new ObjectInputStream(new FileInputStream(cachedFile));
user= (User) objectInputStream.readObject();
Log.e(TAG, "run: user:"+user );
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally {
try {
objectInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3.使用Messenger
在不同进程中传递Message对象,底层实现是AIDL。Messenger以串行的方式处理客户端的请求,服务端只能一个一个地处理。主要方法是通过Messenger传输message(mMessenger.send(message);)。
a.服务端进程
package com.example.messenger;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.util.Log;
public class MyService extends Service {
public MyService() {
}
private static final String TAG = "vera";
private static class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
Log.e(TAG, "handleMessage:from client : " + msg.getData());
break;
default:
super.handleMessage(msg);
}
}
}
//通过创建一个Handler对象来创建一个Messenger对象,Messenger的作用是将客户端发送过来的消息交给Handler处理
private final Messenger mMessenger = new Messenger(new MyHandler());
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();//返回Messenger对象底层的Binder
}
}
让service运行在单独的进程里:
<service
android:name=".MyService"
android:enabled="true"
android:process=":vera"
android:exported="true"></service>
b.客户端进程
package com.example.messenger;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent=new Intent(this,MyService.class);
bindService(intent,mServiceConnection,BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
}
private Messenger mMessenger;
private ServiceConnection mServiceConnection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mMessenger=new Messenger(service);//用服务端返回的IBinder对象创建一个Messenger
Message message=Message.obtain(null,1);
Bundle bundle=new Bundle();
bundle.putString("value","this is client.");
message.setData(bundle);//通过这个Messenger发送消息messager
try {
mMessenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
}
2019-03-09 18:01:26.916 1806-1806/? E/vera: handleMessage:from client : this is client.
如果让服务端回应客户端:
服务端的改变为
package com.example.messenger;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
public class MyService extends Service {
private static final String TAG = "vera";
private static class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
Log.e(TAG, "handleMessage:from client : " + msg.getData().getString("value"));
Messenger client=msg.replyTo;
Message replyMessage=Message.obtain(null,2);
Bundle bundle=new Bundle();
bundle.putString("reply","this is server");
replyMessage.setData(bundle);
try {
client.send(replyMessage);
} catch (RemoteException e) {
e.printStackTrace();
}
break;
default:
super.handleMessage(msg);
}
}
}
//通过创建一个Handler对象来创建一个Messenger对象,Messenger的作用是将客户端发送过来的消息交给Handler处理
private final Messenger mMessenger = new Messenger(new MyHandler());
@Override
public IBinder onBind(Intent intent) {
return mMessenger.getBinder();//返回Messenger对象底层的Binder
}
}
客户端的改变为
package com.example.messenger;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "vera";
private Messenger mReplyMessenger=new Messenger(new MyHandler());
public static class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 2:
Log.e(TAG, "handleMessage: from server: " + msg.getData().getString("reply"));
break;
default:
super.handleMessage(msg);
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, MyService.class);
bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
}
private Messenger mMessenger;
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mMessenger = new Messenger(service);//用服务端返回的IBinder对象创建一个Messenger
Message message = Message.obtain(null, 1);
Bundle bundle = new Bundle();
bundle.putString("value", "this is client.");
message.setData(bundle);//通过这个Messenger发送消息messager
message.replyTo=mReplyMessenger;
try {
mMessenger.send(message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
}
效果如下:
2019-03-09 18:12:28.014 2076-2076/com.example.messenger:vera E/vera: handleMessage:from client : this is client.
2019-03-09 18:12:28.044 2057-2057/com.example.messenger E/vera: handleMessage: from server: this is server
4.使用AIDL
点击创建aidl文件
Book类实现Parcelable接口
package com.example.aidl_client;
import android.os.Parcel;
import android.os.Parcelable;
/**
* <p>文件描述:<p>
* <p>创建时间:2019/3/9<p>
*/
public class Book implements Parcelable {
public int bookId;
public String bookName;
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.bookId);
dest.writeString(this.bookName);
}
public Book() {
}
protected Book(Parcel in) {
this.bookId = in.readInt();
this.bookName = in.readString();
}
@Override
public String toString() {
return "Book{" +
"bookId=" + bookId +
", bookName='" + bookName + '\'' +
'}';
}
public static final Parcelable.Creator<Book> CREATOR = new Parcelable.Creator<Book>() {
@Override
public Book createFromParcel(Parcel source) {
return new Book(source);
}
@Override
public Book[] newArray(int size) {
return new Book[size];
}
};
}
Book.aidl是Book类在AIDL中的声明,名字一定要一样。
// Book.aidl
package com.example.aidl_client;
// Declare any non-default types here with import statements
parcelable Book;
IMyAidlInterface.aidl中一定要导入Book类(import com.example.aidl_client.Book;)
// IMyAidlInterface.aidl
package com.example.aidl_client;
// Declare any non-default types here with import statements
import com.example.aidl_client.Book;
interface IMyAidlInterface {
List<Book> getBookList();
void addBook(in Book book);
}
点击make,系统自动生成IMyAidlInterface.java
把aidl这个文件夹拷贝到服务端
clean project
服务端:实现IMyAidlInterface文件中定义的方法
package com.example.aidl_server;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import com.example.aidl_client.Book;
import com.example.aidl_client.IMyAidlInterface;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class MyService extends Service {
public MyService() {
}
@Override
public void onCreate() {
super.onCreate();
mBooks.add(new Book(1,"zhang"));
mBooks.add(new Book(2,"xu"));
}
private CopyOnWriteArrayList<Book> mBooks=new CopyOnWriteArrayList<Book>();
private Binder mBinder=new IMyAidlInterface.Stub() {
@Override
public List<Book> getBookList() throws RemoteException {
return mBooks;
}
@Override
public void addBook(Book book) throws RemoteException {
mBooks.add(book);
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
客户端调用服务端的方法,隐式调用一定要加包名。
package com.example.aidl_client;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "vera";
private ServiceConnection mServiceConnection=new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IMyAidlInterface mIMyAidlInterface=IMyAidlInterface.Stub.asInterface(service);
try {
List<Book> mList=mIMyAidlInterface.getBookList();
Log.e(TAG, "onServiceConnected: list type:"+mList.getClass().getCanonicalName() );
Log.e(TAG, "onServiceConnected: list "+mList.toString() );
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent=new Intent();
intent.setAction("vera.aidl");
intent.setPackage("com.example.aidl_server");
// intent.setClassName("com.example.aidl_server","com.example.aidl_server.MyService");
bindService(intent,mServiceConnection,BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
}
}
在build.gradle中加入:
sourceSets {
main {
manifest.srcFile 'src/main/AndroidManifest.xml'
java.srcDirs = ['src/main/java', 'src/main/aidl']
resources.srcDirs = ['src/main/java', 'src/main/aidl']
aidl.srcDirs = ['src/main/aidl']
res.srcDirs = ['src/main/res']
assets.srcDirs = ['src/main/assets']
}
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.aidl_server"
minSdkVersion 19
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
sourceSets {
main {
manifest.srcFile 'src/main/AndroidManifest.xml'
java.srcDirs = ['src/main/java', 'src/main/aidl']
resources.srcDirs = ['src/main/java', 'src/main/aidl']
aidl.srcDirs = ['src/main/aidl']
res.srcDirs = ['src/main/res']
assets.srcDirs = ['src/main/assets']
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
效果如下:
2019-03-09 20:48:36.862 4154-4154/com.example.aidl_client E/vera: onServiceConnected: list [Book{bookId=1, bookName='zhang'}, Book{bookId=2, bookName='xu'}]