Android AIDL跨进程通讯 & 解决bindService无法启动-程序员宅基地

技术标签: java  进程间通讯  android  Service  移动开发  AIDL  

场景:APP-A 服务端,APP-B 客户端。B启动service,通过IBinder,拿到服务端User列表,并向User表中添加人员信息。从而实现两个APP跨进程通讯

一,服务端APP

步骤:1,创建User实体类;2,实现AIDL接口,3,定义service;4,在AndroidManifast.xml配置service
注意:如果通过AIDL传递实体类,必须要继承Parcelable接口

1,创建User实体并实现Parcelable接口

public class User implements Parcelable {
    
    private String name;
    private int age;

    public User(String name, int age) {
    
        this.name = name;
        this.age = age;
    }

    protected User(Parcel in) {
    
        name = in.readString();
        age = in.readInt();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
    
        dest.writeString(name);
        dest.writeInt(age);
    }

    //rebuild project 后会报找不到readFromParce方法 ,需要在实体类中创建
    public void readFromParcel(Parcel in) {
    
        this.name = in.readString();
        this.age = in.readInt();
    }

    @Override
    public int describeContents() {
    
        return 0;
    }

    public static final Creator<User> CREATOR = new Creator<User>() {
    
        @Override
        public User createFromParcel(Parcel in) {
    
            return new User(in);
        }

        @Override
        public User[] newArray(int size) {
    
            return new User[size];
        }
    };

    @Override
    public String toString() {
    
        return "User{" +
            "name='" + name + '\'' +
            ", age=" + age +
            '}';
    }
}

2,实现AIDL接口(User.aidl,IUserService.aidl)

创建过程:右键–>New–>AIDL–>AIDL File
自定义User类,必须声明parcelable类

// User.aidl
package com.example.demo;

// Declare any non-default types here with import statements
parcelable User;

定义接口用来获取User列表,以及添加人员

in:代表数据只能由客户端传递到服务端
out:代表数据只能由服务端传递到客户端
inout:代表数据可以双向流动

// IUserService.aidl
package com.example.demo;

// Declare any non-default types here with import statements
import com.example.demo.User;
interface IUserService {
    
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    List<User> getList();
    void addUser(in User user);
}

创建完成后Rebuid Project。

3,创建UserService

public class UserService extends Service {
    

    private List<User> userList;

    @Override
    public void onCreate() {
    
        userList = new ArrayList<User>();
        Log.i("userService","service is open");
        initData();
    }

    private void initData() {
    
        User user = new User("xiaoming", 10);
        User user1 = new User("lihong", 12);
        userList.add(user);
        userList.add(user1);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    
        return super.onStartCommand(intent, flags, startId);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
    
        return stub;
    }
    
	private final IUserService.Stub stub = new IUserService.Stub() {
    
        @Override
        public List<User> getList() throws RemoteException {
    
        	//向客户端返回的人员列表
            return userList;
        }

        @Override
        public void addUser(User user) throws RemoteException {
    
        	//客户端向服务端添加的人员信息
            userList.add(user);
            Log.i("UserService",user.toString());
        }
    };
}

4,配置AndroidManifast.xml(exported = true 必须要为true,允许跨进程访问

 <service
       android:name="com.example.demo.UserService"
       android:enabled="true"
       android:process=":remote"
       android:exported="true"/>

二,客户端APP

步骤:1,将服务端的aidl文件,以及实体类拷贝到客户端(包名需要和服务端一致);2,bindService启动服务;3,和服务端交互

1,将服务端的aidl文件,和实体类拷贝到客户端。只要保持包名一致就ok。拷贝完毕,Rebuild Project。

2,bindService 启动服务

 serviceConnection = new ServiceConnection() {
    
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
    
            	//绑定成功回调
                iUserService = IUserService.Stub.asInterface(service);
                connected = true;
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
    
                connected = false;
            }
        };

 private void bindService() {
    
 		//第一个参数:服务端包名,第二个参数:服务端UserService类的包名(全路径)
        ComponentName componentName = new ComponentName("com.example.demo", "com.example.demo.UserService");
        Intent intent = new Intent();
        intent.setComponent(componentName);
        boolean result = this.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
        Log.i(TAG, "bindService: " + result);
    }

注意:在写Demo的时候,一直无法启动service,最后发现需要在AndroidManifest.xml配置queries标签,声明我们App与其交互的包名,配置后即可启动

	//配置服务端的包名	
  <queries>
        <package android:name="com.example.demo" />
  </queries>

3,启动成功后即可数据交互

通过IUserService.Stub.asInterface(service); 将IBinder转成aidl接口,可直接调用其方法

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    

    private static final String TAG = "MainActivity";
    boolean connected = false; //是否链接
    private IUserService iUserService;
    private ServiceConnection serviceConnection;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.getUserList).setOnClickListener(this);
        findViewById(R.id.sendUser).setOnClickListener(this);
        findViewById(R.id.start_service).setOnClickListener(this);
        init();
    }

    private void init(){
    
        serviceConnection = new ServiceConnection() {
    
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
    
                iUserService = IUserService.Stub.asInterface(service);
                connected = true;
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
    
                connected = false;
            }
        };
    }

    private void bindService() {
    
        ComponentName componentName = new ComponentName("com.example.demo", "com.example.demo.UserService");
        Intent intent = new Intent();
        intent.setComponent(componentName);
        boolean result = this.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
        Log.i(TAG, "bindService: " + result);
    }

    @Override
    protected void onDestroy() {
    
        super.onDestroy();
        unbindService(serviceConnection);
    }

    @Override
    public void onClick(View v) {
    
        switch (v.getId()) {
    
            case R.id.start_service:
                bindService();
                break;
            case R.id.getUserList:
                if (connected) {
    
                    try {
    
                    	//获取服务器端User列表
                        List<User> userList = iUserService.getList();
                        for (User user : userList) {
    
                            Log.i("MainActivity", user.toString());
                        }
                    } catch (RemoteException e) {
    
                        e.printStackTrace();
                    }
                }
                break;
            case R.id.sendUser:
                if (connected) {
    
                    User user = new User("hanleilei", 15);
                    try {
    
                    	//向服务器端传递人员信息
                        iUserService.addUser(user);
                    } catch (RemoteException e) {
    
                        e.printStackTrace();
                    }
                }
                break;
            default:
                break;
        }
    }
}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/baidu_29483093/article/details/123067690

智能推荐

Python编写一个程序,对给定字符串中出现的a~z字母频率进行分析,忽略大小写,采用 降序方式输出。_英文字符频率统计,a~z字母频率统计,采取降序输出-程序员宅基地

文章浏览阅读1.1w次,点赞7次,收藏16次。编写一个程序,对给定字符串中出现的a~z字母频率进行分析,忽略大小写,采用 降序方式输出。##################################################txt=input("请输入一段英文文本:")txt=txt.lower()counts={}for i in txt: if i in "abcdefghijklmnopqrstuvwx..._英文字符频率统计,a~z字母频率统计,采取降序输出

记录一个傻错误:“error: expected identifier before string constant“-程序员宅基地

文章浏览阅读840次。然后我 在类的属性中定义了一个 ofstream 类型的变量,指定了路径,然后就会给我抱着个错误,号和,真够傻的:"error: expected identifier before string constant"就是 : 在类中,类的 无论什么属性 public private 等,都是不可以在定义的时候赋初值 的。_error: expected identifier before string constant

WPF 遍历DataTemplate(获取所有控件)_获取datatemplate里空间-程序员宅基地

文章浏览阅读1.5w次,点赞5次,收藏10次。情况1:在设定DataTemplate的Name,并且他是在前台表示时,获取DataTemplate里的指定控件。方法:http://blog.csdn.net/wackelbh/article/details/6003947(参考这篇文章)_获取datatemplate里空间

2021年最棒的10款Java框架,你喜欢哪个?_什么框架最好用-程序员宅基地

文章浏览阅读3.7k次,点赞3次,收藏7次。Java是一种强大的语言,当与框架相结合时,Java可以为您提供电子商务,银行,云计算,财务,大数据,股票市场,且更多的任何域的最佳解决方案。如果您刚刚从Java开始,请参阅Java Live Active使用此博客将通过您需要知道的所有重要概念来开始使用框架。什么是Java框架?作为模板或骨架的预先写代码的正文,其中一个开发人员可以根据需要填写其代码来使用和重用以创建应用程序,以便在他们打算引用其作为框架时使用的代码来创建应用程序。重用框架使开发人员能够在没有手动开销的情况下从头开始创建每.._什么框架最好用

安装oracle克隆数据库卡死,oracle数据库之克隆方法-程序员宅基地

文章浏览阅读729次。Oracle 数据库之克隆方法Oracle 8.1.7 for Linux系统,在安装上存在一切困难,尤其在Redhat7.2系统下安装的时候会出现很多意想不到的事情,譬如图形界面无法显示、xwin无法远程连接,在编译的过程中如果没有安装GCC,Glibc等等一些库文件,容易出现无法link的错误,而全部安装又会造成其他困难。因此在Oracle安装过程中总结出来了一些经验。介绍如下::Oracle..._fmw_home/oracle_common/bin/pasteconfig.sh 克隆 timeout

计算机考研408每日一题 day67_用足够容量的一维数组b对nxn阶-程序员宅基地

文章浏览阅读899次,点赞2次,收藏3次。将一个n×n的对称矩阵A的下三角部分按行存放在一个一维数组B中,A[0][0]存放在B[0]中,那么第i行的对角元素A[i][i]在B中的存放位置是___(中国科学院大学 2016)如果分时系统的时间片固定,那么___,则响应时间越长。(兰州大学 2005年)关于路由器说法正确的是___。(中国科学院大学 2015)通常所说的“溢出”,是指___(哈尔滨工程大学 2004年)_用足够容量的一维数组b对nxn阶

随便推点

python中将xml格式转json格式-程序员宅基地

文章浏览阅读845次。一、简介 在用python写脚本时,通常需要处理xml格式的文件或字符串。由于json格式处理的方便性, 我们可将其转为json格式进行处理。 二、步骤 1、安装工具包xmltodict 在命令行输入:pip install xmltodict 2、在代码使用xmltodict.parse(xml_str)进行处理 如 def load_json(xml_path): #获取xml文件 xml_f..._python xml 转json 格式

用了smarty两年多,才知道在模板中可以直接调用PHP内置函数_smarty中的内置函数可以实现邮件链接的是-程序员宅基地

文章浏览阅读661次。比如说:模板书写:{'param1'|functionName:'param2':'param3'}php函数原型:echo functionName('param1','param2','param3');实例:{'1234567'|substr_smarty中的内置函数可以实现邮件链接的是

深度学习笔记~集成方法bagging, boosting和stacking_bagging方法结合深度学习模型-程序员宅基地

文章浏览阅读2.4k次。转载:https://towardsdatascience.com/ensemble-methods-bagging-boosting-and-stacking-c9214a10a205作者:Joseph Rocca Ensemble methods: bagging, boosting andstackingIntroduction“Unity is ..._bagging方法结合深度学习模型

java 开发 文件夹创建和删除_文件的创建和删除java-程序员宅基地

文章浏览阅读6.7k次。//返回文件名称(文件夹读取文件)public static ArrayList<String> getFilesPath(String path) throws Exception {//目标集合fileListArrayList<String> fileList = new ArrayList<String>();File file = new ..._文件的创建和删除java

鸿蒙-南向轻内核开发实战系列(一)基于小熊派鸿蒙季开发板环境搭建_鸿蒙系统内核开发环境的搭建方法-程序员宅基地

文章浏览阅读1.9k次,点赞6次,收藏12次。前言前一段时间,我写过一篇关于LiteOS-A开发环境搭建的文章(实际上是将其作为独立的RTOS来开发的),今天正式讲一讲LiteOS作为鸿蒙内核子系统该如何开发。对于HarmonyOS,开发工作大致可以分为南向开发(内核、驱动)和北向开发(App应用)。我们主讲南向开发。在目前的鸿蒙2.0版本下,南向轻内核开发的资料相对更加完善,主要是针对LiteOS内核。讲到这里,能完整编译到手机上运行的鸿蒙镜像,可能大家还要再等一等了(笔者也很期待)。概述为了帮大家理清楚鸿蒙开发的套路,我们从头再梳理一遍相关_鸿蒙系统内核开发环境的搭建方法

推荐文章

热门文章

相关标签