美文网首页
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