Android 进程与进程之间的通讯 详解及实现步骤 -- 两个app实现

news2024/10/6 8:34:26

详情如下:

  • 一、Intent
  • 二、Messenger
  • 三、AIDL
  • 四、广播
  • 五、文件

分两个app -- 客户端为:jinc1application、服务端为:jinc2application

在这里插入图片描述

一、Intent

这是 Android 中最常用的通讯方式,主要用于启动 Activity、Service 等

jinc1application 中的代码

  • 1、 jinc1application代码如下:
	    //通过budle传递数据,可以携带序列化数据
        Bundle bundle = new Bundle();
        bundle.putInt("intextra", 1);
        bundle.putString("stringextra", "测试数据");
        Intent intent = new Intent();
        //制定要打开的程序的包名(必须写全包名,不然会报错)和地址(activity名)
        intent.setComponent(new ComponentName("com.example.jinc2application",
                "com.example.jinc2application.MainActivity"));//要启动的目标包名和包名+类名
        intent.putExtras(bundle);
        try{
            startActivity(intent);
        }catch(Exception e){
            Log.e("TAG","没有找到对应文件---------------");
        }
  • 注意:要启动的目标包名和包名+类名如下:

jinc2application 中的代码

  • 2、jinc2application
public class MainActivity extends AppCompatActivity {
    @SuppressLint("MissingInflatedId")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 获取意图对象
        Intent intent = getIntent();
        //获取传递的值
        String stringextra= intent.getStringExtra("stringextra");
        int intextra= intent.getIntExtra("intextra",0);
        //打印获取的数据
        Log.e("TAG","stringextra---------------"+stringextra);
        Log.e("TAG","intextra---------------"+intextra);
    }
}

二、Messenger

这是基于 Binder 的一种轻量级的 IPC 机制,主要用于跨进程发送 Message。

jinc1application 中的代码

  • 1、jinc1application 的代码如下:给一个点击事件
 <Button
        android:onClick="btn7"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Messenger"/>
  • MainActivity 的代码实现
private Messenger mService;
    @SuppressLint("HandlerLeak")
    private Handler mReplyHandler = new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case 22:
                    Log.e("TAG","-------"+msg.getData().get("msg").toString());
                break;
            }
        }
    };
    private Messenger mClientMessenger= new Messenger(mReplyHandler);
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            mService = new Messenger(iBinder);
            //创建消息,通过Bundle传递数据
            Message message = Message.obtain(null, 1111);
            Bundle bundle = new Bundle();
            bundle.putString("msg", "你好我是客户端的数据");
            message.setData(bundle);
            //如果需要服务器返回消息,则需要将客户端的Messenger对象传递给服务端,如果不需要返回消息,则不用加这一句
            message.replyTo = mClientMessenger;
            try {
                //向服务端发送消息
                mService.send(message);
            } catch (RemoteException e) {
                 e.printStackTrace();
            }
        }
        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };
    public void btn7(View view) {
        Intent intent = new Intent();
        intent.setAction("com.example.jinc2application.MyService");
        intent.addCategory(Intent.CATEGORY_DEFAULT);
        PackageManager pm = getPackageManager();
        ResolveInfo info = pm.resolveService(intent, 0);
        if(info != null){
            //如果ResolveInfo不为空,说明我们能通过上面隐式的Intent找到对应的Service
            //我们可以获取将要启动的Service的package信息以及类型
            String packageName = info.serviceInfo.packageName;
            String serviceNmae = info.serviceInfo.name;
            ComponentName componentName = new ComponentName(packageName, serviceNmae);
            intent.setComponent(componentName);
            try{
                bindService(intent,mConnection,BIND_AUTO_CREATE);
            }catch(Exception e){
                e.printStackTrace();
                Log.e("DemoLog", e.getMessage());
            }
        }

    }

jinc2application 中的代码

  • 2、jinc2application代码如下: 创建 MyService
public class MyService extends Service {
    /**
    * 处理来自客户端的消息,并用于构建Messenger
    */
    private static class MessengerHandler extends Handler {
        @Override
        public void handleMessage(Message message) {
        switch (message.what) {
            //客户端建立连接
            case 1111://MESSAGE_FROM_CLIENT
                Log.e("TAG", "-------" + message.getData().getString("msg"));
                //向客户端回传消息
                Message msg = Message.obtain(null, 22);//MESSAGE_FROM_SERVICE
                Bundle b = new Bundle();
                b.putString("msg","你好我是服务端的数据");
                msg.setData(b);
                try {
                    //如果服务端需要回复客户端,则需要拿到客户端携带过来的Messenger 对象(即msg.replyTo),通过msg.replyTo.send方法给客户端发送信息
                    message.replyTo.send(msg);
                } catch(RemoteException e){
                     e.printStackTrace();
                }
                break;
            default:
                super.handleMessage(message);
                break;
            }
        }
    }
    /**
     * 构建Messenger对象
    */
    private final Messenger mMessenger = new Messenger(new MessengerHandler());

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mMessenger.getBinder();
    }
}
  • 3、在清单文件中注册
<service android:name=".MyService"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.example.jinc2application.MyService"></action>
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service>

三、AIDL

这是 Android 提供的一种 IPC 机制,主要用于实现跨进程的接口调用。

AIDL 是Android的进程间通信(IPC)比较常用的一种方式,AIDL 是 Android Interface Definition Language 的缩写,即Android接口定义语言。

1、AIDL优点:

  • 1.进程间通信不止有AIDL,我们还有其他选择,例如 BroadcastReceiver , Messenger 等,但是 BroadcastReceiver 存在占用的系统资源比较多和存在延迟问题,在频繁的跨进程通信时是无法满足需求的;Messenger 进行跨进程通信时请求队列是同步进行的,无法并发执行,不能进行多进程通信,局限性比加大,这个时候就需要使用 AIDL 了。

  • 2.编译器通过*.aidl文件的描述信息生成符合通信协议的Java代码,我们无需自己去写这段繁杂的代码,只需要在需要的时候调用即可,通过这种方式我们就可以完成进程间的通信工作。

2、使用步骤详情

jinc2application 中的代码

AIDL的底层是基于Binder实现的,而Binder机制也是一种请求-响应式的通信模型,请求方一般称为Client,响应方称为Server。

  • 1、src\main 目录 右键new一个AIDL文件。
  • 2、输入自定义AIDL名字,点击OK,即可创建出AIDL接口文件,文件中会默认生出一个basicTypes方法,该方法描述了AIDL中可以使用的基本类型(int, long, boolean, float, double, String)。下面是以String为例:
    在这里插入图片描述
  • 3、定义后需要 Rebuild Project
  • 4、创建一个实现类,继承刚才创建的AIDL的名称里的Stub类,并实现接口方法。
public class MyAIDLService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return myBinder;
    }

    private IBinder myBinder=new IMyAidlInterface.Stub() {
        @Override
        public String getMessages() throws RemoteException {
            return "返回测试数据-------------";
        }
    };
}
  • 5、在清单文件里配置service,android:exported=“true”,必须配置成true,才能被其他app调用
    在这里插入图片描述

jinc1application 中的代码

  • 6、将服务端AIDL文件拷贝到客户端相同包的位置,然后Rebuild Project 重新编译
    注意:客户端和服务端AIDL的文件和路径要一致。
    在这里插入图片描述
  • 7、activity_main.xml 写一个点击事件
  <Button
        android:onClick="btn8"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="AIDL"/>
  • 8、MainActivity 里面的处理
 //AIDL
    private static IMyAidlInterface sIAidlServiceInterface;
    public void btn8(View view) {
        Intent intent = new Intent();
        intent.setAction("com.example.jinc2application.MyAIDLService");
        intent.setPackage("com.example.jinc2application");//包名
        bindService(intent, serviceConnection, Service.BIND_AUTO_CREATE);
    }
    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            sIAidlServiceInterface = IMyAidlInterface.Stub.asInterface(service);
            try {
                String message = sIAidlServiceInterface.getMessages();
                Log.e("TAG", "the message:" + message);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e("TAG", "name:" + name);
        }
    };

四、广播

这是 Android 中的一种广播机制,可以用于实现跨进程的事件通知。

两个app间发送广播和正常发送广播其实差不多
在jinc1application中发广播,在jinc2application中接受广播

jinc2application 中的代码

  • 1、在 jinc2application 创建一个java类继承BroadcastReceiver类,用来在 onReceive()方法中处理获得的广播。
public class MyBoradCast extends BroadcastReceiver  {
    public static final String BROADCAST_ACTION_TEST = "com.example.jinc2application.MyBoradCast";
    @Override
    public void onReceive(Context context, Intent intent) {
        if (BROADCAST_ACTION_TEST .equals(intent.getAction())){
            Bundle bundle = intent.getExtras();
            String test = (String) bundle.get("text");
            Log.e("测试接收到广播:",test );
        }
    }
}
  • 2、在java代码中动态注册,代码如下:
public class MainActivity extends AppCompatActivity {
    private MyBoradCast myReceiver;
    @SuppressLint("MissingInflatedId")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("com.cn.broadcast.test.ACTION");
        myReceiver = new MyBoradCast();
        registerReceiver(myReceiver, intentFilter);
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(myReceiver);
    }
}

jinc1application 中的代码

  • 3、在 jinc1application 在java代码中发送广播,发送的action与jinc2application中接受到的action要一致,代码如下:
 // 通过Intent类的构造方法指定广播的ID
        Intent intent = new Intent("com.example.jinc2application.MyBoradCast" );//测试接收到广播
        // 将要广播的数据添加到Intent对象中
        intent.putExtra("text", "测试发送广播");
        // 发送广播
        sendBroadcast(intent);

五、文件

  • jinc1application 中的代码

  • 页面给个点击事件触发:点击去查询是否有存储权限,如果已授权,直接存数据,否则去获取权限页面,手动赋予

    <Button
        android:onClick="btn11"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="文件"/>
    public void btn11(View view) {
        // 在你的 Activity 中,查询是否有权限
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            // Permission is not granted
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    111);
        }else {//已经授权,写入文件数据
            try {
                File file = new File(Environment.getExternalStorageDirectory(), "ceshi.txt");
                FileWriter writer = new FileWriter(file);
                writer.append("我是测试数据");
                writer.flush();
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    @SuppressLint("MissingSuperCall")
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case 111: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // permission was granted 已授予许可
                    try {
                        File file = new File(Environment.getExternalStorageDirectory(), "ceshi.txt");
                        FileWriter writer = new FileWriter(file);
                        writer.append("我是测试数据");
                        writer.flush();
                        writer.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                } else { // permission denied 权限被拒绝
                }
                return;
            }
        }
    }
  • jinc2application 中的代码
public class MainActivity extends AppCompatActivity {
    @SuppressLint("MissingInflatedId")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 在你的 Activity 中
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            // Permission is not granted
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    111);
        }else {
            //获取文件内容
            try {
                File file = new File(Environment.getExternalStorageDirectory(), "ceshi.txt");
                BufferedReader reader = new BufferedReader(new FileReader(file));
                String line = reader.readLine();
                while (line != null) {
                    Log.e("App2", line);
                    line = reader.readLine();
                }
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    @SuppressLint("MissingSuperCall")
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case 111: {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // permission was granted 已授予许可
                    try {
                        File file = new File(Environment.getExternalStorageDirectory(), "ceshi.txt");
                        BufferedReader reader = new BufferedReader(new FileReader(file));
                        String line = reader.readLine();
                        while (line != null) {
                            Log.e("App2", line);
                            line = reader.readLine();
                        }
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                } else {
                    // permission denied 权限被拒绝
                }
                return;
            }
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/745204.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

校园网免认证/校园网pojie

我们的目标是xiao yuan wang pojie 我们使用一个简单的python脚本&#xff0c;用于jiechu /pojie校园网只能登录一台手机和一台电脑的限制&#xff0c;仅供学习。 原理 我们利用已有可正常上网的校园网账户作为跳板&#xff0c;连上网后在后台下线账号所登录的设备&#xff0…

CNVnator软件的安装

1. 下载CNVvator CNVvator软件比较难安装&#xff0c;其依赖root软件等 下载地址 点击其release&#xff0c;下载最新版本v0.4.1(CNVnator_v0.4.1.zip) 2. 安装依赖 root 软件 root 的下载地址 root , 选择下列Ubuntu 20版本 解压root压缩包&#xff1a; ##解压 tar -zxv…

pdf转图片操作方法是什么?分享两个简单的方法!

PDF转图片是一个常见的需求&#xff0c;无论是为了方便编辑、共享&#xff0c;还是为了其他用途&#xff0c;我们需要简单而有效的方法来实现这个目标。本文将介绍两种简单的PDF转图片方法&#xff1a;记灵在线工具和截图方法。 记灵在线工具是一个强大而易于使用的在线工具&a…

如何结合云原生和低代码

前言 云原生和低代码是当今IT领域最流行的两个概念。云原生是一种应用架构设计、应用部署乃至应用开发过程的方式&#xff0c;而低代码是一种快速开发应用的方法。这两者有什么关系&#xff1f;如何结合呢&#xff1f; 先思考一个问题——一个杯子和一个苹果如何结合&#xf…

七牛云的使用(图片超详讲解)

一、为什么要使用七牛云的OSS(对象存储服务)&#xff1f; 二、七牛云使用&#xff1a; 登录七牛云官网&#xff0c;注册并认证 (初次认证有30天免费使用权限)新建存储空间 点击创建的空间名字&#xff0c;进入 空间概括如下&#xff1a; 阅读帮助文档&#xff0c;在自己的…

JavaCV实现byte[]转RTMP流

需求&#xff1a;通过私有的api我可以不断收到byte[]形式的视频数据&#xff0c;现在我需要处理这些数据&#xff0c;最终推送出RTMP流。 实现&#xff1a;通过管道流将不断收到的byte[]视频数据转化为输入流然后提供给JavaCV的FFmpegFrameGrabber使用&#xff0c;然后通过FFmp…

两种传输层协议TCP和UDP【图解TCP/IP(笔记十二)】

文章目录 两种传输层协议TCP和UDPTCP与UDP区分UDP的特点及其目的TCP的特点及其目的 两种传输层协议TCP和UDP 在TCP/IP中能够实现传输层功能的、具有代表性的协议是TCP和UDP。 ■ TCP TCP是面向连接的、可靠的流协议。流就是指不间断的数据结构&#xff0c;你可以把它想象成排…

【C++】C++11 (2): 右值引用、移动构造、移动赋值和模板的可变参数

一、右值引用和移动语义 C11更新后&#xff0c;容器中增加的新方法有插入接口函数的右值引用版本 这些接口的意义在哪&#xff1f;网上都说它们能提高效率&#xff0c;它们是如何提高效率的&#xff1f; 请看下面的右值引用和移动语义的介绍。另外emplace还涉及模板的可变参…

开发跨平台APP,是用Flutter还是React Native开发框架?

随着移动互联网的飞速发展&#xff0c;对于开发人员而言&#xff0c;如何快速地开发出兼容不同平台&#xff08;iOS、Android&#xff09;的应用&#xff0c;成为了一个重要的问题。 跨平台应用程序开发框架的好处&#xff1a; 1. 一个App适用于多个设备&#xff1b; 2. 一个…

问一下路过的大神keil5与keil5mdk 的区别是什么?

从Keil C51都Keil5 MDK&#xff0c;不知不觉已经用了Keil十几年。 虽然现在新增了一些开发环境&#xff0c;不过keil对于老工程师来说&#xff0c;应该是最亲切的了… Keil出过很多个版本&#xff0c;很多人最熟悉的是Keil C51和Keil5 MDK。 我们在做STM32程序开发编译的时候…

Centos7安装SDWebui

Centos7安装SDWebui 1.nvidia显卡驱动安装 #查看显卡编号 lspci | grep -i vga#查询显卡型号 http://pci-ids.ucw.cz/mods/PC/10de?actionhelp?helppci#安装依赖包 yum install kernel-devel gcc -y #查看nouveau是否已禁用&#xff0c;如果有内容说明没有禁用 lsmod | gre…

记录一下2023.2kali的默认密码和修改root用户密码的方法

要水一篇博客了…… 默认登录用户名/密码&#xff1a; kali/kali 切换root用户&#xff1a; sudo su 这时输入的密码是kali 然后就切换到了root用户 输入passwd root 提示修改新密码 根据提示输入两遍新密码就修改了root用户的密码啦 &#xff08;感觉改不改的其实也……无所…

大华监控前端实时预览(踩坑)

难点在后端&#xff0c;前端主要是文档太少了&#xff0c;前端难点主要是接入摄像头&#xff0c;摄像头接入了&#xff0c;剩下什么对讲、调整方向、变焦之类的就简单了。 大华官网&#xff1a;https://open-icc.dahuatech.com/#/home 1.到官网下载插件或者demo&#xff0c;我是…

Xamarin.Android实现界面自动添加控件

目录 1、背景说明2、效果3、代码3.1、UI代码3.2、实现代码 4、代码下载5、相关知识点5.1、原理说明5.2、其他说明 6、参考资料 1、背景说明 有时需要在APP中动态的添加控件&#xff0c;因此记录下在Xamarin中的实现步骤。 VS2022社区版 2、效果 3、代码 3.1、UI代码 UI的代…

文件块读写

写文件&#xff1a; size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); 功能&#xff1a;以数据块的方式给文件写入内容 参数&#xff1a; &#xff1a;准备写入文件数据的地址ptr &#xff1a; 为 类型&#xff0c;此参数指定写入文件内容的块数据大…

面试官:说说Redis的持久化以及主从同步呗

目录 1、秃顶面试官&#xff1a;今天我们聊了聊redis的主从模式啊~ 2、秃顶面试官&#xff1a;Redis有哪几种方式进行数据的持久化&#xff1f; 3、秃顶面试官&#xff1a;RDB持久化是什么呢&#xff1f;触发机制又是什么呢&#xff1f; 4、秃顶面试官&#xff1a;嗯&#…

海外问卷调查怎么做?要准备什么?

科思创业汇 大家好&#xff0c;这里是科思创业汇&#xff0c;一个轻资产创业孵化平台。赚钱的方式有很多种&#xff0c;我希望在科思创业汇能够给你带来最快乐的那一种&#xff01; 海外问卷调查业务一直存在。与国内不同&#xff0c;国外有大量的支付问卷资源&#xff0c;所…

一招永久解决github上不去问题,秒开

步骤 进入如下路径&#xff0c;把hosts复制到桌面 在桌面将hosts以记事本方式打开&#xff0c;复制下面内容&#xff0c;退出保存 20.205.243.166 github.com # GitHub Start 140.82.114.4 github.com 199.232.69.194 github.global.ssl.fastly.net # GitHub End3. 将修改好…

S7-200 SMART PLC PID向导详细介绍(如何实现P、PD、PID控制器)

这篇博客主要介绍SMART PLC PID向导的使用,PID控制相关的其它内容请查看专栏系列文章,常用链接如下: SMART PLC PID负压控制(过程量为负数)_负压控制pid控制程序_RXXW_Dor的博客-CSDN博客1、如何实现PID反作用调节? 在有些控制中需要PID反作用调节。例如:在夏天控制空调…

doubletrouble1靶场详解

doubletrouble1靶场复盘 首先扫描到ip后对ip单独一个全面扫描。 nmap -sP 192.168.102.0/24同时扫描一下目录&#xff0c;扫到一个secret&#xff0c;打开看一下。 dirsearch -u http://192.168.102.165发现里面是一个图片&#xff0c;下载到我们kali 中去&#xff0c;因为都…