IPC,是指inter-proccess-communication,即进程间通信。
so,要先理解进程线程
1.进程和线程–
进程process是指一个执行单元,一个应用程序,一个虚拟机,可以包含多个线程。
线程thread是指cpu可以调度的最小单元,在Android中分为主线程和子线程。

任何的一个操作系统都有IPC机制。android中IPC机制最主要的就是Binder(messenager,aidl,ContentProvider都是Binder的实现),当然还有socket,通过网络实现任意两个终端,也可以理解为进程,不同应用,之间的通信。
2.多进程的原因
一般情况下,我觉得不推荐使用多进程,因为会存在很多问题,因为进程之间属于不同的内存空间。但是在某些特殊情况下不得不用,比如:
1.每个应用有最大内存限制,需要新开进程,以得到更大的内存空间
2.就是要访问其他应用的数据
3.怎么开
android的四大组件都可以开启多进程模式,通过androidmenifest的androird:process=”:remote”或者android:process=”com.aaa.bb”开启,和JNI fork一个进程(这个还不会)
区别::remote开启的进程名字是 包名:remote,属于私有进程,其他应用组件不能跟他跑在同一个进程
com.aaa.bb开启的进程名字就是它,属于全局进程,其他应用通过shareUID和签名一致后可以和它跑在一个进程(没有测试)
adb shell
$ps |grep com.aaa.bb可以查看进程状态
4.存在的注意问题
1.内存不同,静态变量,单例模式会不同,
2.线程同步失效
3.Application每开一次进程都会调用一次
4.sp由于存在缓存策略,也会存在不稳定情况。
5.主要的原理
主要是通过对象的序列化和反序列化实现进程间的通信。说一下序列化的两种方式:Serializable和Parcelable接口。
Seraialzable中的serialVersionUID主要用来反序列化的时候确保版本相同。当增加了这个参数之后,对象增加或者删除了成员变量,在版本升级之后不会crash,如果没有就会crash。但是发生了毁灭性的改变比如改变类型改变类名还是不行。transient标志的不会参与序列化比如密码信息等。
parcelable建立之后,声明成员变量之后,就可以自动生成那些方法啦。Intent,Bundle,Bitmap都是系统默认实现了这个接口的,可以直接传输。
Parcelable主要用在内存序列化,Serialzable用在本地和网络序列化上。
IInterface接口,所有在Binder中传输的接口都要实现接口
Binder,主角,主要通信方式无非都是返回一个Binder,不管是Messenager还是aidl,都是通过messenager.getBinder和IAIDL.stub然后通过服务的onBinde 返回mBinder.所以说它是进程见通信的桥梁,底层通过binder实现SeriveManager连接各种Manager(ActivityManager,WindowManager等)
当建立好aidl文件荚和xx.aidl之后,系统会自动生成他的Binder实现类。当然这个也可以自己实现,自己建立这个实现类,只不过系统帮助我们通过aidl文件实现了。
这个类内部主要有静态内部类Stub(extends Binder),内部方法有proxy,asinterface,asbinder,ontransact,和接口的实现方法。
Stub就是binder的真正实现类,通过asInterface方法,判断是统一进程不走transact,是多进程走Stub.Proxy进行mRemote.transact.
ontranact结果写入_reply参数后返回true表示调用成功,false表示失败,所以可以通过它来进行权限校验等操作。
远程调用的实现方法都是在Binder线程池进行的操作,所以会存在耗时的情况.

6.主要的方式
首先应该明确,尽量想办法数据在一个进程处理。实在不行再考虑跨进程通信
1.Bundle三大组件。
2.文件共享。要求不要数据同步。
3.Messenager.通过与Handler的配合,传递单条信息,不存在同步问题。不能调方法和自定义对象。
服务端:

 private final Messenger mMessenger = new Messenger(new MessengerHandler());    @Override    public IBinder onBind(Intent intent) {        return mMessenger.getBinder();    }

客户端:

  public void onServiceConnected(ComponentName className, IBinder service) {            mService = new Messenger(service);

4.aidl
支持基本类型和String,ArraList,HashMap,Parcelable,AIDL,
其中要显式的import 自定义的parcelable和aidl接口,比如

package com.xxx.xxx.aidl;import com.xxx.xxx.aidl.Book;import com.xxx.xxx.aidl.IOnNewBookArrivedListener;interface IBookManager {     List<Book> getBookList();     void addBook(in Book book);     void registerListener(IOnNewBookArrivedListener listener);     void unregisterListener(IOnNewBookArrivedListener listener);}

其中Book这个类要在java包下一个和aidl文件同名的包下。
每定义一个aidl,然后就定义一个它的.Stub实现类,然后建立一个BinderPool aidl及实现类统一管理,是比较有效的方法

 @Override    public IBinder onBind(Intent intent) {        Log.d(TAG, "onBind");        return mBinderPool;    }
 public static class BinderPoolImpl extends IBinderPool.Stub {        public BinderPoolImpl() {            super();        }        @Override        public IBinder queryBinder(int binderCode) throws RemoteException {            IBinder binder = null;            switch (binderCode) {            case BINDER_SECURITY_CENTER: {                binder = new SecurityCenterImpl();                break;            }            case BINDER_COMPUTE: {                binder = new ComputeImpl();                break;            }            default:                break;            }            return binder;        }    }

7.远程挂掉的监听
1.设置死亡代理
Binder Thread

  IBookManager bookManager=IBookManager.Stub.asInterface(service); mRemoteBookManager.asBinder().linkToDeath(mDeathRecipient, 0);
  private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {        @Override        public void binderDied() {            Log.d(TAG, "binder died. tname:" + Thread.currentThread().getName());            if (mRemoteBookManager == null)                return;            mRemoteBookManager.asBinder().unlinkToDeath(mDeathRecipient, 0);            mRemoteBookManager = null;            // TODO:这里重新绑定远程Service        }    };

2.判断是否存活

        if (mRemoteBookManager != null                && mRemoteBookManager.asBinder().isBinderAlive()) {            try {                Log.i(TAG, "unregister listener:" + mOnNewBookArrivedListener);               //重新连接    }

3.onserviceDisconnected中重连
UIThread

8.解注册方法
RemoteCallbackList 用于删除跨进程listener接口

//配对使用   final int N = mListenerList.beginBroadcast();            mListenerList.finishBroadcast();

9.权限校验
1.onBind
2.OnTranact

//声明权限<uses-permission android:name="com.xxx.PROVIDER" />
//使用权限<permission        android:name="com.xxx.PROVIDER"        android:protectionLevel="normal" />

socket
需要网络权限、。
这个比较简单,开启一个服务,运行ServerSocket

  serverSocket = new ServerSocket(8888);    while (!mIsServiceDestoryed) {                try {                    // 接受客户端请求                    final Socket client = serverSocket.accept();                    System.out.println("accept");                    new Thread() {                        @Override                        public void run() {                            try {                                responseClient(client);                            } catch (IOException e) {                                e.printStackTrace();                            }                        };                    }.start();                } catch (IOException e) {                    e.printStackTrace();                }            }

客户端开一个线程跑:

  private void connectTCPServer() {        Socket socket = null;        while (socket == null) {            try {                socket = new Socket("localhost", 8688);                mClientSocket = socket;                mPrintWriter = new PrintWriter(new BufferedWriter(                        new OutputStreamWriter(socket.getOutputStream())), true);                mHandler.sendEmptyMessage(MESSAGE_SOCKET_CONNECTED);                System.out.println("connect server success");            } catch (IOException e) {                SystemClock.sleep(1000);                System.out.println("connect tcp server failed, retry...");            }        }

contentprovider
android:authoritities 唯一标示
Uri来区分不同的表。
除了OnCreate方法外,其他都是运行在Binder Thread里的
通过返回文件的句柄给外界,支持文件数据,图片和视频等,getType的返回不同。
只通过一个SQLlteDatabase内部对数据有同步处理,但是多个SQLiteDatabase对象的话,就不能实现同步了。

https://github.com/singwhatiwanna/android-art-res

更多相关文章

  1. Android init进程——属性服务
  2. android 进程间通信使用aidl和Messenger类
  3. android实现app通过jni调用C/C++方法
  4. android为按钮添加事件的三种方法
  5. Android在初始化时弹出popwindow的方法 .
  6. android开发环境搭建最新方法
  7. Android自定义属性 及 TypedArray的使用方法
  8. android程序退出当前activity的方法
  9. 获取Android的key的MD5和SHA1的方法

随机推荐

  1. Data + AI Summit 欧洲2020全部超清 PPT
  2. Python爬虫进阶必备 | 某镜像网站分析 -
  3. 开发者可以在Microsoft Teams的移动应用
  4. Python爬虫进阶必备 | RSA 加密案例解析
  5. 一文彻底搞清 Kafka 的副本复制机制
  6. Python少有人走过的坑
  7. 来自 Facebook 的 Spark 大作业调优经验
  8. 你在享受十一长假时,Python 已悄悄地变了
  9. 编程题三:使用指针来打印数组内容
  10. linux防暴力破解ssh(centos8测试)