Android进程间通信--消息机制及IPC机制实现_HoldOnedream的博客-程序员宅基地

技术标签: android  基础学习  ipc  



Android为了屏蔽进程的概念,利用不同的组件[Activity、Service]来表示进程之间的通信!
组件间通信的核心机制是Intent,通过Intent可以开启一个Activity或Service,不论这个Activity或Service是属于当前应用还是其它应用的!
                                                                                本文如有bug,请指出啊!!大家一同进步!!
                                                             谢谢!!

Intent包含两部分:
1、目的[action]--要往哪里去
2、内容[category、data]--路上带了些啥,区分性数据或内容性数据

Intent类型:
1、显式--直接指定消息目的地,只适合同一进程内的不同组件之间通信
new Intent(this,Target.class)
2、隐式--AndroidMainifest.xml中注册,一般用于跨进程通信
new Intent(String action)

二、实现-Intent简单进程间通信
显式的Intent较为简单!

如何实现隐式Intent呢?
在AndroidManifest.xml文件中定义<activity>
说明:
1、一个<activity>包括:
零个或多个<intent-filter>

它主要是作为匹配的标准,能否匹配成功由<action>、<category>、<data>三个tag共同决定的。

2、一个<intent-filter>包括:
一个或多个 <action>
零个或多个 <category>
指定<activity>的分类特征
eg:
<category android:name="android.intent.category.LAUNCHER" />
--说明该<activity>是该project运行的第一个界面

<category android:name="android.intent.category.HOME" />
--说明该<activity>可以作为Launcher的,即系统操作界面

<category android:name="android.intent.category.DEFAULT" />
--缺省情况

零个或一个 <data>
-- 指定携带的数据的类型,使用MIME类型描述方式来描述
eg:
<data android:mimeType="video/mpeg" />
video/mpeg表示编码格式为mpeg的视频,
也可以使用通配符video/*表示任意格式的视频文件类型;

在查询ContentProvider时,可以使用
<data android:mimeType="vnd.android.cursor.dir/vnd.myq.note" />
查询上来的数据是多个记录
<data android:mimeType="vnd.android.cursor.item/vnd.myq.note" />
查询上来的数据是单个记录
如上设置,要重写SQLiteOpenHelper的getType(Uri uri)方法
eg:
@Override
public String getType(Uri uri) {
  final int match = sUriMatcher.match(uri) ;
  switch(match)
  {
  case NOTES :
  case LIVE_FOLDER_NOTES:
   return "vnd.android.cursor.dir/vnd.myq.note" ;
   
  case NOTES_ID :
   return "vnd.android.cursor.item/vnd.myq.note" ;
   
  default:
   throw new IllegalArgumentException("invalid uri : " + uri) ;
  }
}

数据的URI由scheme(协议),host,port,path四部分:scheme://host:port/path
<data android:scheme=" http://localhost:8080/test.jsp " />

3、一个Intent对应多种匹配结果的处理说明
一个intent有多个可匹配的处理组件,系统如何处理?
分响应消息的组件类型:
1)如果是service那么这些service都可以启动并处理消息。
2)如果是Activity则会弹出一个对话框让用户进行选择。

4、安全性问题
如果不同进程间的组件可以通过隐式消息互相通信,那程序不是可以轻易调用到其他的程序或者系统中的一些敏感程序的组件,这样会不会很不安全呢?
其实Android在安全方面有一个统一,完备和轻便的安全策略模型。

简单一点说就是:权限设置问题
我们可以自己定义permission,然后在需要的组件处设置该permission,那么用户要想该组件,必须要配置该permission,否则访问失败的!

eg:
1、定义permission
<permission-group android:name="android.permission-group.MYQ_INFO"/>
<permission
     android:name="com.myq.android.permission.DATETIME_SERVICE"
     android:permissionGroup="android.permission-group.MYQ_INFO"
     android:protectionLevel="normal"
     />

2、配置permission
<service android:name=".DateTimeService" android:permission="com.myq.android.permission.DATETIME_SERVICE">
   <intent-filter>
<action android:name="com.myq.android.MultiProcessTest.DATETIMESERVICE_ACTION" />
   </intent-filter>
</service>

3、使用permission
<uses-permission android:name="com.myq.android.permission.DATETIME_SERVICE"/>

三、IPC机制
有了Intent这种基于消息的进程内或进程间通信模型,我们就可以通过Intent去开启一个Service,可以通过Intent跳转到另一个Activity,不论上面的Service或Activity是在当前进程还是其它进程内即不论是当前应用还是其它应用的Service或Activity,通过消息机制都可以进行通信!

但是通过消息机制实现的进程间通信,有一个弊端就是,如果我们的Activity与Service之间的交往不是简单的Activity开启Service操作,而是要随时发一些控制请求,那么必须就要保证Activity在Service的运行过程中随时可以连接到Service。

eg :音乐播放程序
后台的播放服务往往独立运行,以方便在使用其他程序界面时也能听到音乐。同时这个后台播放服务也会定义一个控制接口,比如播放,暂停,快进等方法,任何时候播放程序的界面都可以连接到播放服务,然后通过这组控制接口方法对其控制。

如上的需求仅仅通过Intent去开启Service就无法满足了!从而Android的显得稍微笨重的IPC机制就出现了,然而它的出现只适用于Activity与Service之间的通信,类似于远程方法调用,就像是C/S模式的访问,通过定义AIDL接口文件来定义一个IPC接口,Server端实现IPC接口,Client端调用IPC接口的本地代理。

由于IPC调用是同步的,如果一个IPC服务需要超过几毫秒的时间才能完成的话,你应该避免在Activity的主线程中调用,否则IPC调用会挂起应用程序导致界面失去响应。在 这种情况下,应该考虑单起一个线程来处理IPC访问。

两个进程间IPC看起来就象是一个进程进入另一个进程执行代码然后带着执行的结果返回。

IPC机制鼓励我们“尽量利用已有功能,利用IPC和包含已有功能的程序协作完成一个完整的项目”

IPC实现demo:
我的
project --  MultiProcessTest
package --  com.myq.android.MultiProcessTest

1、AIDL文件,我是放在package下,
文件名称为:
IDateTimeService.aidl
文件内容为:
package com.myq.android.MultiProcessTest ;
interface IDateTimeService
{
String getCurrentDateTime(in String format) ;
}

如果正确配置,会在gen下,生成同名的java文件
简单摘要:
//我们需要实现的类Stub
public interface  IDateTimeService  extends android.os.IInterface
{
...
public static abstract class  Stub
extends android.os.Binder
implements com.myq.android.MultiProcessTest.IDateTimeService
{
...
//获取实例的方法asInterface
public static com.myq.android.MultiProcessTest.IDateTimeService  asInterface (android.os.IBinder obj)
{
  ...
}
...
}
//我们自己的业务方法,需要实现的
public java.lang.String  getCurrentDateTime (java.lang.String format) throws android.os.RemoteException;
}

2、Service中实现IDateTimeService.Stub
eg:
package com.myq.android.MultiProcessTest;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class DateTimeService extends Service {

public static final String DATETIME_SERVICE_ACTION = "com.myq.android.MultiProcessTest.DATETIMESERVICE_ACTION" ;

private static final String TAG = "--------DateTimeService-------" ;

private  SimpleDateFormat sdf ;

private final IDateTimeService.Stub stub = new IDateTimeService.Stub()
{
  
  public String getCurrentDateTime(String format) throws RemoteException {
   return getCurrentDateTimeString(format) ;
  }
} ;

private synchronized String getCurrentDateTimeString(String format)
{
     sdf = new SimpleDateFormat(format) ;
     final String temp = sdf.format(new Date()) ;
   Log.i(TAG,"getCurrentDateTimeString--" + Thread.currentThread() + "--" + temp) ;
   return temp ;
}

public IBinder onBind(Intent arg0)
{
  Log.i(TAG, "onBind--" + Thread.currentThread()) ;
  return stub;
}
}

3、Client端代码实现
private ServiceConnection mServiceConn = new ServiceConnection()
{
  
  public void onServiceConnected(ComponentName name, IBinder service) {
   mDateTimeService = IDateTimeService.Stub.asInterface(service) ;
  }
  
  public void onServiceDisconnected(ComponentName name) {
   mDateTimeService = null ;
  }
} ;

说明:
网上的好多资料都没有涉及IPC调用的AIDL的具体说明!
它本质上是Server端和Client端都具有相同的AIDL文件,要位于相同的包下,即package的包名药一样,然后才能正确的通过proxy访问,否则client与server的aidl文件处于不同package会出错的。

aidl模型如下:
                |<--------------------aidl---------------------->|
client端-->proxy  ----------parcel数据包-------- stub<---server端
从而proxy+parcel+stub构成了aidl.
只不过,proxy运行在客户进程,而stub运行在服务端进程。
当你通过aidl去访问服务端时,客户端会阻塞在proxy,服务端处理完后,通知proxy返回。

四、附件及说明
1、
附件是我测试所用的demo,我用的系统是ubuntu9,Android2.2版本
基本功能:
可以根据用户选择的不同输出格式输出当前系统的时间。
2、
运行顺序:
先运行Server端:MultiProcessTest
再运行Client端:MultiProcessTestClient

3、
注意点:
Server和Client端的AIDL文件必须要位于同package下,否则会出错
安全性问题实现,权限控制--定义、配置、使用
异步处理问题--Handler
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/hyl963254113/article/details/37601209

智能推荐

梁力《程序设计与C语言》_第七章 结构体【完】_努力努力再努力0.0的博客-程序员宅基地

#include &lt;iostream&gt;#include &lt;stdio.h&gt;#include &lt;cstdio&gt;#include &lt;string&gt;#include &lt;string.h&gt;#include &lt;math.h&gt;#include &lt;algorithm&gt;#include &lt;stack&gt;...

数据结构:输入一个整数数组,判断它是否为某二叉搜索树的后序遍历,如果是输出YES,否则输出NO,假设数组内任意两个数都不相等_LSFAN0213的博客-程序员宅基地

问题描述:           输入一个整数数组,判断它是否为某二叉搜索树的后序遍历,如果是输出YES,否则输出NO,假设数组内任意两个数都不相等还是先从概念入手:二叉搜索树:它可能是一颗空树若不是空树,则满足:1.若左子树不为空,则左子树上所有结点的值均小于根结点的值2.若右子树不为空,则右子树上所有结点的值均大于根结点的值3.左、右子树也分别是二叉搜索树一颗...

cmd输入java未知指令,Apache Commons CLI选项解析器可以忽略未知的命令行选项吗?..._咸鱼cc的博客-程序员宅基地

I am writing a Java application that takes command line arguments which are processed using Apache Commons CLI with the GnuParser. For reasons that are not interesting to get into, I would like it to...

特别注意Android Q中的非SDK受限变化_手艺人王学明的博客-程序员宅基地

在Android P中,Google限制了非SDK接口。在Android Q中,Google再次更新了限制的非SDK接口。而且,单独将这一块拎出来,着重描述了一篇。可见重要程度增强。浅灰和深灰列表的命名发生变化在 Android 9(API 级别 28)中,灰名单分为以下两个列表:包含非 SDK 接口(无论目标 API 级别是什么,您都可以使用这些接口)的浅灰列表。包含非 SDK 接...

办公游戏本降低风扇转速_青碧凝霜的博客-程序员宅基地

今天遇见一个问题:鄙人自己是一个游戏本 , i7 7850, 内存为32G,两个SSD,日常办公的时候性能肯定够用。但是:在开机自检的时候、在打开一些大文件的时候风扇狂转,自己很尴尬……后来看了一下,逻辑很简单:电脑在处理一些业务的时候,为了提高速度,就自动给电脑CPU加压睿频。这样的话,本来五分钟就可以处理完的,3分钟就处理完了,代价就是这3分钟风扇狂转,100%频率。我百度了大概一个小时,找到一个确定有效的解决方案:禁止睿频。电脑的电源管理里面,设置最大性能是98%(99%还是睿频,100

随便推点

SenchaTouch翻译_wclcck的博客-程序员宅基地

Sencha Touch翻译ComponentsUsing Forms in Sencha Touch大部分需要用户输入的应用都使用表格。在ST中,表格是一个用标准HTML5封装好的表格,并且有数据验证、提交数据并且提供了一个简单的方式去布局,而且布局相当的吸引人。Creating a Form表单面板呈现了一系列的表单字段,而且提供便利的方法去加载保存数据

NB-IoT与eMTC技术的异同_jaczen的博客-程序员宅基地

eMTC是LTE-M(LTE-Machine-to-Machine)在3GPP R13中的叫法,是基于LTE演进的物联网技术。在R12中叫Low-Cost MTC,在R13中被称为LTE enhanced MTC (eMTC),变即Cat-M1,旨在基于现有的LTE载波满足物联网设备需求。NB-IoT则是NB-CIoT(华为、Vodafone、高通、Neul联合提出)和NB-LTE(爱立信

python 文本分析库_python常用文本串处理库学习笔记_weixin_39788451的博客-程序员宅基地

defpre_process(text):"""文本预处理:1. 删除掉符号2. 大写转小写s:param text::return:"""text= del_pun(text) #删除符号text = text.lower() #英文转小写text = text2list(text) #字符串转序列#todo 将itn转换过来returntextdefis_equal(ref,hyp):"...

SqlLoader(Sqlldr) 的用法_ShyTan的博客-程序员宅基地_sqlldr 多个infile

简介:SQL*LOADER是ORACLE的数据加载工具,通常用来将操作系统文件(数据)迁移到ORACLE数据库中。SQL*LOADER是大型数据仓库选择使用的加载方法,因为它提供了最快速的途径(DIRECT,PARALLEL)。目前的理解就是:把文本文件,log文件,excel导入到数据库中写sqlldr只需2步:1:建立一个ctl控制文件OPTIONS (skip=1,rows=128) #sqlldr 命令显示的 选项可以写到这里边来,skip=1 用来跳过数据中的第一行L.

C语言练习题-结构体与联合体_Patio F4的博客-程序员宅基地

用一个数组存放图书信息每本书是一个结构包括下列几项信息书名、作者、出版年月、借出否试写出描述这些信息的说明并编写一个程序读入若干本书的信息然后打印出以上信息。#include&lt;stdio.h&gt;struct book{ char name[50]; char zzname[50]; int year; int month; char flag;}liber[20];int main(){ int i; for(i=0;i&lt;10;i++){ p.

ios::sync_with_stdio(false);_weixin_30745641的博客-程序员宅基地

取消cin与stdin的同步,加快输入速度转载于:https://www.cnblogs.com/Kiven5197/p/6086180.html

推荐文章

热门文章

相关标签