深入Android架构(从线程到AIDL)_06 短程通信 vs. 远程通信

目录

7、 短程通信 vs. 远程通信

範例: 短程通信

撰写步骤

範例: 遠程通信


7、 短程通信 vs. 远程通信

範例: 短程通信
  • 首先出现ac01画面,立即启动myService,定时连续传来数字,如下:
  • 由于定时连续传来数字,所以数字会持续递增,如下 :
// AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.misoo.pkm"
android:versionCode="1"
android:versionName="1.0.0">
<application android:icon="@drawable/icon"
android:label="@string/app_name">
<activity android:name=".ac01“
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".myService" > </service>
</application>
</manifest>
  • 这AndroidManifest.xml指定了: ac01和myService是在同一进程里执行。
撰写步骤

Step-1: 定义 IListener接口:
 

// IListener.java
package com.misoo.ppvv;
public interface IListener {
    public void update(String s);
}

// ac01.java
// …….
public class ac01 extends Activity implements OnClickListener {
    private final int WC =
        LinearLayout.LayoutParams.WRAP_CONTENT;
    private TextView tx;
    private Button btn;

    @Override public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        LinearLayout layout = new LinearLayout(this);
        layout.setOrientation(LinearLayout.VERTICAL);
        LinearLayout.LayoutParams param =
            new LinearLayout.LayoutParams(100, WC);
        param.topMargin = 5;
        tx = new TextView(this); tx.setTextSize(26);
        tx.setTextColor(Color.RED);
        tx.setBackgroundResource(R.drawable.x_yellow);
        layout.addView(tx, param);
        btn = new Button(this); btn.setText("Exit");
        btn.setBackgroundResource(R.drawable.earth);
        btn.setOnClickListener(this);
        layout.addView(btn, param);
        this.setContentView(layout);
        //------------------------------------------------------------------
        myService.setUpdateListener( new UpdateUIListener() );
        Intent svc = new Intent(this, myService.class);
        startService(svc);
    }

    @Override protected void onDestroy() {
        super.onDestroy();
        Intent svc = new Intent(this, myService.class);
        stopService(svc);
    }

    class UpdateUIListener implements IListener {
        public void update(String s) tx.setText(" " + s);
    }

    public void onClick(View v) { this.finish(); }
}
  • 诞生一个UpdateUIListner的对象,然后将此对象之参考值(Reference)传递给myService,存于plis参考变量里。

       

// myService.java
// ……..
public class myService extends Service {
    private static IListener plis;
    private static int k = 0;
    private Timer timer = new Timer();
    public Handler handler = new Handler(){
        public void handleMessage(Message msg) {
            plis.update(String.valueOf(k++));
        }
    };

    @Override public void onCreate() {
        super.onCreate();
        TimerTask task = new TimerTask() {

            @Override public void run() {
                handler.sendEmptyMessage(0);
            }};

            timer.schedule(task,1000, 4000);
        }

    @Override public IBinder onBind(Intent intent)
        { return null; }

    public static void setUpdateListener(IListener listener)
        { plis = listener; }
}

  • 接着,诞生一个Intent对象去要求Android启动myService。就执行到myService的onCreate()函数。
  • 此onCreate()函数诞生一个Timer对象,它会定时呼叫Handler类别的handleMessage()函数。
  • 此onCreate()函数就透过plis而将数据传递给ac01里的UpdateUIListner对象,然后将数字呈现于画面上,并且循环下去。

          

// AndroidManifest.xml

//……..
<service android:name=".myService" android:process=":remote" >
<intent-filter>
<action android:name
="com.misoo.pkm.REMOTE_SERVICE" />
</intent-filter></service>
</manifest>

範例: 遠程通信
  • 兹拿刚才的MP3播放范例,来说明其详细步骤。 Activity类想跨进程去调用MediaPlayer播放引擎,如下图所示:

      

// myActivity.java
// ……..
public class myActivity extends Activity implements OnClickListener
{
    private final int WC = LinearLayout.LayoutParams.WRAP_CONTENT;
    private final int FP = LinearLayout.LayoutParams.FILL_PARENT;
    private Button btn, btn2, btn3;
    public TextView tv;
    private IBinder ib = null;
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        LinearLayout layout = new LinearLayout(this);
        layout.setOrientation(LinearLayout.VERTICAL);
        btn = new Button(this); btn.setId(101); btn.setText("play");
        btn.setBackgroundResource(R.drawable.heart);
        btn.setOnClickListener(this);

        LinearLayout.LayoutParams param = new
        LinearLayout.LayoutParams(80, 50);
        param.topMargin = 10;
        layout.addView(btn, param);
        btn2 = new Button(this); btn2.setId(102); btn2.setText("stop");
        btn2.setBackgroundResource(R.drawable.heart);
        btn2.setOnClickListener(this);
        layout.addView(btn2, param);
        btn3 = new Button(this); btn3.setId(103); btn3.setText("exit");
        btn3.setBackgroundResource(R.drawable.heart);
        btn3.setOnClickListener(this);
        layout.addView(btn3, param);
        tv = new TextView(this); tv.setTextColor(Color.WHITE);
        tv.setText("Ready");
        LinearLayout.LayoutParams param2 = new LinearLayout.LayoutParams(FP, WC);
        param2.topMargin = 10;

        layout.addView(tv, param2);
        setContentView(layout);
        //-------------------------------------------------------------------------------
        // startService(…)
        bindService(new Intent("com.misoo.kx02c.REMOTE_SERVICE"),
        mConnection, Context.BIND_AUTO_CREATE);
    }

    private ServiceConnection mConnection = new ServiceConnection() {
    public void onServiceConnected(ComponentName,className, IBinder ibinder) {
        ib = ibinder;
    }

    public void onServiceDisconnected(ComponentName,className) {}
};

public void onClick(View v) {
    switch (v.getId()) {
    case 101:
        Parcel pc = Parcel.obtain();
        Parcel pc_reply = Parcel.obtain();
        pc.writeString("playing");
        try {
            ib.transact(1, pc, pc_reply, 0);
            tv.setText(pc_reply.readString());
        } catch (Exception e) { e.printStackTrace(); } break;
    case 102:
        pc = Parcel.obtain(); pc_reply = Parcel.obtain();
        pc.writeString("stop");
        try { ib.transact(2, pc, pc_reply, 0);
            tv.setText(pc_reply.readString());
        } catch (Exception e) { e.printStackTrace(); }
        break;
    case 103: finish(); break;
}}}
  • App启动时(就会把App的 load到内存里,此刻通称为loading-time。在这个时刻,就会创建了mConnection对象。
  • 因为mConnection对象不是属于特定函数内的对象,而是属于类的对象,各函数都可用的公用对象。这种static对象(或变量)都是loading-time就创建了。
  • App被load进来之后,才会启动(创建)myActivity对象,之后才会调用myActivity的onCreate()函数。
// myService.java
// …….
public class myService extends Service {
    private IBinder mBinder = null;
    @Override public void onCreate() {
        mBinder = new myBinder(getApplicationContext());
    }

    @Override public IBinder onBind(Intent intent) {
        return mBinder;
    }
}

// myBinder.java
// ……..
public class myBinder extends Binder{
    private MediaPlayer mPlayer = null;
    private Context ctx;
    public myBinder(Context cx)
        { ctx= cx; }

    @Override public boolean onTransact(int code,Parcel data, Parcel reply, int flags)
        throws android.os.RemoteException
    {
        reply.writeString(data.readString()+ " mp3");
        if(code == 1)
            this.play();
        else if(code == 2)
            this.stop();
        return true;
    }

    public void play(){
        if(mPlayer != null) return;
        mPlayer = MediaPlayer.create(ctx, R.raw.test_cbr);
        try { mPlayer.start();
        }catch (Exception e)
        { Log.e("StartPlay", "error: " + e.getMessage(), e);}
    }

    public void stop(){
        if (mPlayer != null) {
            mPlayer.stop(); mPlayer.release(); mPlayer = null; 
        }
    }
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

进销存软件数据库设计

设置 system_config 系统参数配置pricing_policy 价格策略&#xff08;销售采购价格取数优先级&#xff09;code_rule 编码规则account_book 账套checkout 结账admin 管理员role 角色menu 菜单menu_role 角色菜单merchant 商户merchant_menu 商户菜单merchant_user 商户用户资料…

[文献阅读]ReAct: Synergizing Reasoning and Acting in Language Models

文章目录 摘要Abstract:思考与行为协同化Reason(Chain of thought)ReAct ReAct如何协同推理 响应Action&#xff08;动作空间&#xff09;协同推理 结果总结 摘要 ReAct: Synergizing Reasoning and Acting in Language Models [2210.03629] ReAct: Synergizing Reasoning an…

antd-vue - - - - - a-date-picker限制选择范围

antd-vue - - - - - a-date-picker限制选择范围 1. 效果展示2. 代码展示 1. 效果展示 如图&#xff1a;限制选择范围为 今年 & 去年 的 月份. 2. 代码展示 <template><a-date-picker:disabledDate"disabledDate"picker"month"/> &l…

OceanBase到MySQL实时同步方案

概述 本方案基于OceanBase Binlog服务&#xff0c;采用数据库实时复制软件Beedup订阅捕获OceanBase数据库的Binlog事件&#xff0c;复制软件将Binlog事件还原为MySQL支持的DML或DDL&#xff0c;然后交由MySQL数据库执行。 配置Binlog任务 启用OceanBase Binlog服务&#xff…

[QT]控件的核心属性

一、控件的核心属性 1.enable属性 表示一个控件是否可用&#xff0c;可以用isEnabled()接口获取到当前控件的可用状态&#xff0c;同时来提供了setEnabled()接口设置控件是否可用&#xff0c;传递的参数为true和false。 isEnabled(); setEnabled(bool); Demo&#xff1a;通过一…

DRAM 的类型

DRAM&#xff08;Dynamic Random Access Memory&#xff09;&#xff0c;即动态随机存取存储器&#xff0c;是现代计算机系统中不可或缺的存储组件之一。 根据市场情况主要分为以下几种&#xff1a; 一、SDRAM&#xff08;Synchronous Dynamic Random Access Memory&#xff0…

虚拟机中的时统卡功能和性能调优

【写在前面】 飞腾开发者平台是基于飞腾自身强大的技术基础和开放能力&#xff0c;聚合行业内优秀资源而打造的。该平台覆盖了操作系统、算法、数据库、安全、平台工具、虚拟化、存储、网络、固件等多个前沿技术领域&#xff0c;包含了应用使能套件、软件仓库、软件支持、软件适…

创新驱动智能运维,护航军工新时代

随着数字化转型的加速推进&#xff0c;智能运维技术在各行业的重要性愈加凸显。军工行业作为国家安全和技术创新的核心&#xff0c;对运维解决方案的安全性、可靠性及自主可控性提出了严格要求。美信时代科技有限公司以自主创新为基础&#xff0c;推出监控易一体化智能运维管理…

《计算机网络》(B)复习

目录 一、问答题测试 1.论述具有五层协议的网络体系结构的要点&#xff0c;包括各层的主要功能。 2.物理层的接口有哪几个方面的特性&#xff1f;各包含些什么内容&#xff1f; 3.小明想要访问淘宝&#xff0c;当他打开浏览器输入www.taobao.com浏览淘宝的 过程是什么&#…

如何配置【Docker镜像】加速器+【Docker镜像】的使用

一、配置Docker镜像加速器 1. 安装/升级容器引擎客户端​ 推荐安装1.11.2以上版本的容器引擎客户端 2. 配置镜像加速器​ 针对容器引擎客户端版本大于1.11.2的用户 以root用户登录容器引擎所在的虚拟机 修改 "/etc/docker/daemon.json" 文件&#xff08;如果没有…

logback之自定义过滤器

logback有两种过滤器&#xff0c;一种是context中的过滤器叫TurboFilter&#xff0c;是一个全局的过滤器&#xff0c;会影响所有的日志记录。另一种是Appender中的过滤器&#xff0c;只对所在的append有效。两者大同小异&#xff0c;这里我们以Appender的过滤器为例。 &#x…

springboot+vue实现SSE服务器发送事件

思路 一个基于订阅发布机制的SSE事件。客户端可以请求订阅api&#xff08;携带客户端id&#xff09;&#xff0c;与服务器建立SSE链接&#xff1b;后续服务器需要推送消息到客户端时&#xff0c;再根据客户端id从已建立链接的会话中找到目标客户端&#xff0c;将消息推送出去。…

使用XGBoost算法进行机器学习任务:从理论到实践

目录 使用XGBoost算法进行机器学习任务&#xff1a;从理论到实践引言1. XGBoost算法简介2. XGBoost的数学原理3. 环境准备与数据集介绍3.1 环境准备3.2 数据集介绍 4. XGBoost的PyTorch实现4.1 数据预处理4.2 XGBoost模型定义4.3 模型训练与评估 5. 结果分析与可视化5.1 绘制损…

NeurIPS 2024 | 像素级LLM实现图像视频理解、生成、分割和编辑大统一(昆仑万维等)

Accepted by NeurIPS 2024 文章链接&#xff1a;https://arxiv.org/pdf/2412.19806 项目链接&#xff1a;https://vitron-llm.github.io/ Github链接&#xff1a;https://github.com/SkyworkAI/Vitron 亮点直击 首次提出了一种通用的视觉多模态大语言模型&#xff08;MLLM&…

P8打卡——YOLOv5-C3模块实现天气识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 1.检查GPU import torch import torch.nn as nn import torchvision.transforms as transforms import torchvision from torchvision import transforms, dat…

OpenCV-Python实战(16)——单/多模板匹配

一、模板匹配函数 cv2.matchTemplate() result cv2.matchTemplate(image*,templ*,method*,mask*) result&#xff1a;函数返回值&#xff0c;比较结果的数组。 image&#xff1a;原始图像。 templ&#xff1a;模板图像。templ.shape<image.shape。 method&#xff1a;…

分布式 L2 网关下的 OVS 未知单播泛洪

大家读完觉得有意义和帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 目录 1 问题描述 2 基础设施和环境信息 3 故障排除 3.1 确认&#xff1a;单播泛洪 3.2 确认&#xff1a;所有泛洪流量都以 L2 GW 为目标 3.3 验证&#xff1a;容器 ARP 处于活动状态时&…

天猫推荐数据集实践

参考自 https://github.com/xufengtt/recom_teach_code&#xff0c;学习记录。 环境配置&#xff08;maxcomputedataworks&#xff09; 下载天猫推荐数据集&#xff1b;开启 aliyun 的 maxcompute&#xff0c;dataworks&#xff0c;pai&#xff1b;使用 odpscmd 上传本地数据…

库的概念:动态库与静态库

在软件开发中&#xff0c;库是代码复用的核心工具&#xff0c;它帮助开发者避免重复造轮子&#xff0c;提升开发效率。库可以分为动态库和静态库&#xff0c;这两者在程序开发中的使用方式、链接过程和性能上存在显著区别。本文将详细讲解动态库与静态库的定义、区别、链接过程…

Flink源码解析之:如何根据JobGraph生成ExecutionGraph

Flink源码解析之&#xff1a;如何根据JobGraph生成ExecutionGraph 在上一篇Flink源码解析中&#xff0c;我们介绍了Flink如何根据StreamGraph生成JobGraph的流程&#xff0c;并着重分析了其算子链的合并过程和JobGraph的构造流程。 对于StreamGraph和JobGraph的生成来说&…