Aidl的使用(跨进程)
前言
demo是根据《》中一篇文章实现的,实现效果是,服务端每次有新书时都会通知客户端,客户端也可以实现对服务端书籍的添加和获得。项目结构如下
![](https://img.haomeiwen.com/i4739155/c11ceb45b30f0b35.jpeg)
实现步骤
1.创建aidl文件
创建接口的aidl文件
// IBookManagerUpdate.aidl
package com.example.lcc.myaidl;
import com.example.lcc.myaidl.MyBook;
import com.example.lcc.myaidl.NotificationNewBook;
interface IBookManagerUpdate {
List<MyBook> getBookList();
void addBook(in MyBook book);
void registerListener(in NotificationNewBook newBook);
void unRegisterListener(NotificationNewBook newBook);
}
如果有自定义的实体类,实体类需要实现Parcelable接口
package com.example.lcc.myaidl;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by lcc on 2018/3/2.
*/
public class MyBook implements Parcelable {
private String name;
private String index;
public MyBook() {
}
public MyBook(String name, String index) {
this.name = name;
this.index = index;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getIndex() {
return index;
}
public void setIndex(String index) {
this.index = index;
}
protected MyBook(Parcel in) {
name = in.readString();
index = in.readString();
}
public static final Creator<MyBook> CREATOR = new Creator<MyBook>() {
@Override
public MyBook createFromParcel(Parcel in) {
return new MyBook(in);
}
@Override
public MyBook[] newArray(int size) {
return new MyBook[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(name);
parcel.writeString(index);
}
@Override
public String toString() {
return "MyBook{" +
"name='" + name + '\'' +
", index='" + index + '\'' +
'}';
}
}
!勿忘记要为每个自定义的类创建aidl文件
// MyBook.aidl
package com.example.lcc.myaidl;
parcelable MyBook;
// Declare any non-default types here with import statements
2.创建service类,由于实现的是进程间通信,所以服务需要在新的进程中
Manifests注册
<service
android:name=".BookService"
android:process=":remote">
<intent-filter>
<action android:name="com.example.remote.BookService" />
</intent-filter>
</service>
具体service的实现
package com.example.lcc.myaidl;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
/**
* Created by lcc on 2018/3/7.
*/
public class BookService extends Service {
private List<MyBook> books = new ArrayList<>();
private RemoteCallbackList<NotificationNewBook> notificationNewBooks = new RemoteCallbackList<>();
@Override
public void onCreate() {
books.clear();
books.add(new MyBook("钢铁是怎么样炼成的", "1"));
books.add(new MyBook("等风人", "2"));
new Thread(mRunnable).start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
private IBinder mBinder = new IBookManagerUpdate.Stub() {
@Override
public List<MyBook> getBookList() throws RemoteException {
return books;
}
@Override
public void addBook(MyBook book) throws RemoteException {
books.add(book);
}
@Override
public void registerListener(NotificationNewBook newBook) throws RemoteException {
notificationNewBooks.register(newBook);
}
@Override
public void unRegisterListener(NotificationNewBook newBook) throws RemoteException {
notificationNewBooks.unregister(newBook);
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
int i = books.size();
private Runnable mRunnable = new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(2000);
MyBook book = new MyBook("新书一本", i + "");
i++;
showNewBook(book);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
};
private void showNewBook(MyBook book) throws RemoteException {
books.add(book);
//通知客户端来新书了
int N=notificationNewBooks.beginBroadcast();
for (int i = 0; i < N; i++) {
notificationNewBooks.getBroadcastItem(i).showNewBook(book);
}
notificationNewBooks.finishBroadcast();
}
@Override
public void onDestroy() {
super.onDestroy();
notificationNewBooks.kill();
}
}
3.客户端的调用,添加了通知提醒的操作,记得要检查您的通知是否开启。
package com.example.lcc.myaidl;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.support.v4.app.NotificationCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private Button mBindService;
private Button mstartService;
private IBookManagerUpdate mBookManager;
private MyBook myBook = new MyBook();
private List<MyBook> lists = new ArrayList<>();
private NotificationManager manager;
private Notification myNotification;
private static final int NOTIFICATION_ID_1 = 1;
private Bitmap largeIcon;
private Boolean isBind=false;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
myBook = (MyBook) msg.obj;
//发送通知
sendNotification(myBook);
}
};
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mBookManager = IBookManagerUpdate.Stub.asInterface(iBinder);
try {
lists.addAll(mBookManager.getBookList());
Log.d("Tina===>", "书库中的书:" + lists.toString());
MyBook book3 = new MyBook("撒哈拉的沙漠", "3");
MyBook book4 = new MyBook("雨季不再来", "4");
mBookManager.addBook(book3);
mBookManager.addBook(book4);
lists.addAll(mBookManager.getBookList());
Log.d("Tina===>", "书库中的书:" + lists.toString());
//注册通知事件
mBookManager.registerListener(mBinder);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
};
//通知事件
private NotificationNewBook mBinder = new NotificationNewBook.Stub() {
@Override
public void showNewBook(MyBook book) throws RemoteException {
Message message = new Message();
message.obj = book;
mHandler.sendMessage(message);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mBindService = findViewById(R.id.bind_service);
mstartService = findViewById(R.id.start_service);
mBindService.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
isBind=true;
Intent serviceIntent = new Intent();
serviceIntent.setAction("com.example.remote.BookService");
serviceIntent.setPackage(MainActivity.this.getPackageName());
bindService(serviceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
if(isBind){
unbindService(mServiceConnection);
}
}
private void sendNotification(MyBook book) {
largeIcon = ((BitmapDrawable) getResources().getDrawable(R.drawable.d_025)).getBitmap();
//3.定义一个PendingIntent,点击Notification后启动一个Activity
PendingIntent pi = PendingIntent.getActivity(
this,
100,
new Intent(this, MainActivity.class),
PendingIntent.FLAG_CANCEL_CURRENT
);
//2.通过Notification.Builder来创建通知
NotificationCompat.Builder myBuilder = new NotificationCompat.Builder(MainActivity.this);
myBuilder.setContentTitle("亲,有新书了")
.setContentText("《" + book.getName() + "》点击开始阅读")
.setTicker("您收到新的消息")
.setLargeIcon(largeIcon)
//设置状态栏中的小图片,尺寸一般建议在24×24,这个图片同样也是在下拉状态栏中所显示
.setSmallIcon(R.mipmap.ic_launcher)
//设置默认声音和震动
.setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
.setAutoCancel(true)//点击后取消
.setWhen(System.currentTimeMillis())//设置通知时间
.setPriority(Notification.PRIORITY_HIGH)//高优先级
.setContentIntent(pi); //3.关联PendingIntent
myNotification = myBuilder.build();
//4.通过通知管理器来发起通知,ID区分通知
manager.notify(NOTIFICATION_ID_1, myNotification);
}
}
注意点:
1>即使自定义类和接口方法在同一个包中,也要倒入自定义类,否则将找不到
2>写完aidl文件后,生成java文件的方法是build-->make
3>注意绑定service时候的参数的正确性
动态代理模式
java层面对动态代理的解读,很好
http://blog.csdn.net/l2show/article/details/46992495
http://blog.csdn.net/self_study/article/details/51628486
http://blog.csdn.net/sbsujjbcy/article/details/50554116
看了一些资料,对动态代理的感觉是:利用InvocationHandler、Proxy实现动态代理
eg:
o = (T) Proxy.newProxyInstance(Retrofit.class.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
原理分析
这篇文章写的真的特别到位
图文详解 Binder跨进程通信 原理
Android自定义权限与动态申请权限
网友评论