本文主要采用AIDL实现,概念不讲,只说明具体搭建步骤,想了解AIDL的介绍和使用可以参考:

官方AIDL简介及使用指南

1、Android studio新建项目,创建2个module,一个命名serverApp,一个命名clientApp。

server端配置:

2、server端main目录下创建aidl目录,New->AIDL文件,完成后效果如下:

Android 多个APP间通信 安卓跨应用通信_ide

3、在IMyAidlInterface.aidl创建一个方法测试,如果想使用参数,和java一样,写好后编译一下,生成对应的java文件以便后面使用

interface IMyAidlInterface {
    String ipcMsg();
}

 4、在java目录创建service实现IMyAidlInterface接口

override fun onBind(intent: Intent): IBinder {
    return myBinder
}

private val myBinder = object: IMyAidlInterface.Stub(){
    override fun ipcMsg(): String {
        return "服务端返回消息"
    }
}

5、在AndroidManifest里配置service,android:exported="true",必须配置成true,才能被其他app调用

<service
    android:name=".IpcService"
    android:enabled="true"
    android:exported="true"/>

client端配置: 

6、把刚才创建的aidl整个目录内容全拷贝到clientApp相同目录下,不要修改任何内容,同理,后期如果在server端修改了此文件,在client端需要同步一下,同样编译后生成对应java文件:

Android 多个APP间通信 安卓跨应用通信_ide_02

7、在MainActivity绑定service,注意ComponentName的第一个参数需要和serverApp的applicationId保持一致,第二个参数是service路径,编码过程中,遇到过几种bindService为false的情况,会在后面单独说明

private val serviceConnection = object : ServiceConnection {
        override fun onServiceConnected(p0: ComponentName?, iBinder: IBinder?) {
            ipcAidl = IMyAidlInterface.Stub.asInterface(iBinder)
        }

        override fun onServiceDisconnected(p0: ComponentName?) {
            ipcAidl = null
        }
    }

    private fun bindService() {
        val mIntent = Intent()
        mIntent.component = ComponentName("com.ninjuli.ipc", "com.ninjuli.ipc.IpcService")
        bindFlag = bindService(mIntent, serviceConnection, Context.BIND_AUTO_CREATE)
    }

 8、最后进行测试,先安装serverApp,再安装clientApp,点击按钮,效果如下:

Android 多个APP间通信 安卓跨应用通信_ide_03

一个简单的跨app通信传递消息完成了,思考:如何传递对象?如何传递超过1M的数据?(为什么1M,去看看binder),会单独开一篇说明

传递对象

1、在serverApp的java目录创建类Person,实现Parcelable,由于这里用的kotlin,简化代码如下

@Parcelize
data class Person(val name: String, val age: Int) : Parcelable

需要在build.gradle配置

plugins {
    id 'kotlin-parcelize'
}

2、在aidl目录创建相同Person的aidl文件

import com.ninjuli.ipc.Person;

parcelable Person;

注意这里一定要导入Person的路径,不然会报错

3、在IMyAidlInterface.aidl添加

List<Person> addPerson(in Person person);

 完成后编译,把刚才java目录创建的Person类和aidl目录文件同样的拷贝一份到clientApp,名字无需修改。

4、修改IpcService,实现添加的addPerson方法

private val myBinder = object: IMyAidlInterface.Stub(){
        override fun ipcMsg(): String {
            return "服务端返回消息"
        }

        override fun addPerson(person: Person): MutableList<Person> {
            return mutableListOf(person)
        }
    }

5、client添加按钮事件

findViewById<Button>(R.id.btn1).setOnClickListener {
    val addPerson = ipcAidl?.addPerson(Person("小青", 21))
    findViewById<TextView>(R.id.text).text = addPerson?.toString()
}

 最终效果

Android 多个APP间通信 安卓跨应用通信_android_04

突破binder只能传递小于1M数据,参考下面文章

android多个app跨进程通信(IPC)实现(二)

特别说明编码过程中遇到的问题:

1、bindService总是返回false,百度搜索,会发现很多重复的,我出现的问题都对不上号,最后发现在安卓10以下正常,10以上就出现绑定失败,就得引申出来一个包的可见性,在manifest加上以下配置解决


<queries>
    <package android:name="com.ninjuli.ipc" />
</queries>


2、刚开始先安装client,再安装server,就会出现闪退问题,后来发现是在manifest配置service的时候多加了android:permission造成,去掉即可

项目地址:https://github.com/ninjuli/MultipleIPC