美文网首页
Android 对Aidl的使用

Android 对Aidl的使用

作者: 蓝库知识 | 来源:发表于2018-10-24 07:39 被阅读12次

    Aidl的使用(跨进程)

    前言

    demo是根据《》中一篇文章实现的,实现效果是,服务端每次有新书时都会通知客户端,客户端也可以实现对服务端书籍的添加和获得。项目结构如下

    项目结构.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自定义权限与动态申请权限

    相关文章

      网友评论

          本文标题:Android 对Aidl的使用

          本文链接:https://www.haomeiwen.com/subject/iwehvxtx.html