android 应用程序Activity之间数据传递与共享的几种途径

一、基于消息的通信机制 Intent ---boudle ,extra
Android为了屏蔽进程的概念,利用不同的组件[Activity、Service]来表示进程之间的通信!
组件间通信的核心机制是Intent,通过Intent可以开启一个Activity或Service,不论这个Activity或Service是属于当前应用还是其它应用的!
                                                                 
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

时间: 2024-10-04 20:08:28

android 应用程序Activity之间数据传递与共享的几种途径的相关文章

Android activity之间数据传递和共享的方式之Application

1.基于消息的通信机制  Intent ---bundle ,extra 数据类型有限,比如遇到不可序列化的数据Bitmap,InputStream,或者LinkedList链表等等数据类型就不太好用. 2.利用static静态数据, public static成员变量: 3.基于外部存储的传输,File/Preference/Sqlite 如果要针对第三方应用需要Content Provider 4.基于IPC的通信机制 context 与Service之间的传输,如Activity与Serv

无废话Android之smartimageview使用、android多线程下载、显式意图激活另外一个activity,检查网络是否可用定位到网络的位置、隐式意图激活另外一个activity、隐式意图的配置,自定义隐式意图、在不同activity之间数据传递(5)

1.smartimageview使用 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"

解析activity之间数据传递方法的详解

转自:http://www.jb51.net/article/37227.htm 本篇文章是对activity之间数据传递的方法进行了详细的分析介绍,需要的朋友参考下 1  基于消息的通信机制 Intent--------boudle,extra用这种简单的形式,一般而言传递一些简单的类型是比较容易的,如int.string等详细介绍下Intent机制Intent包含两部分:1 目的[action]-------要去到哪里去2 内容[category.data]----------路上带些什么,

android Activity之间数据传递 Parcelable和Serializable接口的使用

Activity之间传数据时,为了避免麻烦,往往会将一些值封装成对象,然后将整个对象传递过去.传对象的时候有两种情况,一种是实现Parcelable接口,一种是实现Serializable接口.0.解释两种接口:1)实现Serializable接口是JavaSE本身就支持的.2)Parcelable是Android特有的功能,效率比实现Serializable接口高,像用于Intent数据传递也都支持,而且还可以用在进程间通信(IPC),除了基本类型外,只有实现了Parcelable接口的类才能

android 不同Activity之间数据传递

1. 传值Activity package mydemo.mycom.demo2; import android.content.Intent; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.

转-Activity之间数据传递之Intent数据传递

Intent意图 可用于Activity之间的数据传递,一般可分为下面两种情况,从当前Activity传递到目标Activity后有无返回值: 1.传递后无返回值的情况: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50    在起始Activity中,发送数据   

Activity之间数据传递(一)(简单传递,数据包Bundle)

一,简单传递(简单的字符串) 第一个activity通过putExtra()将字符串传入i 1 protected void onCreate(Bundle savedInstanceState) { 2 super.onCreate(savedInstanceState); 3 setContentView(R.layout.activity_main); 4 findViewById(R.id.btnStartAty).setOnClickListener(new View.OnClickL

借助Intent实现Android工程中Activity之间Java对象的传递——实现Parcelable接口

借助Intent实现Android工程中Activity之间Java对象的传递有两种方式:一种所传递对象实现了Serializable接口:另一种是所传递对象实现了Parcelable接口,本博客总结传递对象实现Parcelable接口的情况下如何实现Java对象传递: 代码1.添加名为"User.java"的文件: package com.ghj.vo; import android.os.Parcel; import android.os.Parcelable; public cl

2016.02.20 学习笔记 数据在Activity之间的传递的情况

情况一:一个Activity跳转到另一个Activity时,将第一个Activity的数据传递到第二个Activity里面. 分析:当一个界面跳转到另一个界面的同时还要讲数据传递过去,这种情况需要用Intent类putExtra()方法实现. 具体在Onclick方法中的样例代码如下: Intent i1=new Intent(this,SecondActivity.class); String Message=Edit1.getText().toString(); i1.putExtra("M