Android 不同应用之间互相通信以及读取资源

来源:互联网 发布:ubuntu mate 安装pyqt 编辑:程序博客网 时间:2024/06/05 10:06
一.应用之间通信
  Android系统应用程序之间不能共享内存,他们之间的通信是需要特殊的机制。Android SDK提供了4中跨进程的通讯方式,对应Android系统中的4个组件:Activity,Content Provider,Broadcast,Service。
1.Activity
  a. Activity可以是进程内以及跨进程访问,在同一个应用程序内访问,需要提供Context对象和Activity的Class对象,例如:     
 Intent intent = new  Intent(this , Test.class );   startActivity(intent);
  b. 跨进程访问需要提供Activity对应Action字符串,例如:Intent.ACTION_CALL,Intent.ACTION_SEND,这是系统提供的Action。当然我们也可以定义我们自己的Action来分享Activity,在AndroidManifest.xml中配置如下。
<activity android:name=".Main">    <intent-filter>            <action android:name="net.blogjava.mobile.MYACTION"  />        <data android:scheme="info"  /> //指定URI协议,用于Activity之间传递参数                    <category android:name="android.intent.category.DEFAULT"  />    </intent-filter>  </activity>
  c.还有一种方式可以直接启动一个应用,通过PackageManager来实现,代码如下:
 PackageManager pm = context.getPackageManager(); Intent intent = pm.getLaunchIntentForPackage(pkgName); startActivity(intent);
2.Content Provider
  a.Content Provider提供一种数据共享的方式,把应用中的数据共享给其他应用,允许其他应用程序对数据进行增、删、改操作,在应用第一次对其访问时创建。在使用Content Provider对外共享时,首先应该继承ContentProvider重写相应的方法,代码如下:
 public class PersonContentProvider extends ContentProvider{    public boolean onCreate() //该方法在ContentProvider被创建后被调用    public Uri insert(Uri uri, ContentValues values)     public int delete(Uri uri, String selection, String[] selectionArgs)     public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)     public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)     public String getType(Uri uri) //用于返回当前Url所代表数据的MIME类型。对集合操作返回:vnd.android.cursor.dir/person,对非集合操作返回:       vnd.android.cursor.item/person   }
  其次,在AndroidManifest.xml中注册,ContentProvider利用authorities进行标志,让其他应用能够找到自己,并且ContentProvider的Scheme已经由Android规定好了,为;content://
<manifest.... >    <application android:icon="@drawable/icon" android:label="@string/app_name">      <provider android:name=".PersonContentProvider"            android:authorities="com.ljq.providers.personprovider"/>    </application></manifest>
  b.分析URI:content://com.ljq.provider.personprovider/person/10/name,其中content://是Scheme,com.ljq.provider.personprovider表示主机名或者authorities,person/10/name表示路径,此URI要操作person表中id为10的name字段。
  c.使用ContentResolver来实现对ContentProvider中的数据的操作,要获取ContentResolver 对象,可以使用Activity提供的getContentResolver()方法,ContentResolver提供了与ContentProvider对应的增删改查的方法。<br />具体ContentProvider和ContentResolver的实现可以参考[http://my.eoe.cn/lqgyt1/archive/1978.html]
  d.监听ContentProvider中数据变化。如果ContentProvider在数据发生变化时想要通知它的访问者,就需要在数据变化时调用getContentResolver().notifyChange(uri, null),例如:
public class PersonContentProvider extends ContentProvider {   public Uri insert(Uri uri, ContentValues values) {      db.insert("person", "personid", values);      getContext().getContentResolver().notifyChange(uri, null);   }}
  如果ContentProvider的访问者需要接受数据变化通知,就必须使用ContentResolver进行监听,例如:
getContentResolver().registerContentObserver(Uri.parse("content://com.ljq.providers.personprovider/person"),       true, new PersonObserver(new Handler()));public class PersonObserver extends ContentObserver{   public PersonObserver(Handler handler) {      super(handler);   }   public void onChange(boolean selfChange) {      //此处可以进行相应的业务处理   }}
3.Broadcast
  Broadcast的使用方法跟平常我们用到的一样,需要注册解注册。不过在广播接收器中不能做耗时的操作,耗时操作可以通过Service来做。例子:weather主程序和数据源插件的通讯
4.AIDL服务
  Service有两个主要作用后台运行以及跨进程通讯,Service的跨进程服务就是AIDL服务,AIDL是一种接口定义语言,编译器通过aidl文件生成一段代码,通过预先定义好的接口实现两个进程间的通讯。<br />简单的代码实现可以参考:[http://blog.csdn.net/android_tutor/article/details/6427680]。
二、读取其他应用的资源
  获取其他应用的资源首先要通过createPackageContext(String pkgName,int flag)获得相关Context,其中flag表示Option flag,one of CONTEXT_INCLUDE_CODE or CONTEXT_IGNORE_SECURITY,相关代码如下:
 try {        Context otherContext=this.createPackageContext (pkgName, Context.CONTEXT_IGNORE_SECURITY);     } catch (NameNotFoundException e) {        e.printStackTrace();     }
1.利用ShareUserId共享数据
  两个应用的ShareUserId相同,则共享对方的data目录下的文件,包括SharePreference, file, lib等文件。例如,在ShareUserId相同的情况下,读取另一个应用的SharePreference文件。
    //第一个应用程序为的menifest文件代码如下:    <manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.mythou.serviceID"    android:sharedUserId="com.mythou.share"    >    //第二个应用程序的menifest文件代码如下:    <manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.mythou.clientID"    android:sharedUserId="com.mythou.share"    >
  读取SharePreference配置代码:
try {     Context ct=this.createPackageContext ("com.mythou.serviceID", Context.CONTEXT_IGNORE_SECURITY);     SharedPreferences sp = ct.getSharedPreferences("appInfo", MODE_PRIVATE);     String str2 = sp.getString("appname", "service");     Log.d("test", "share preference-->" + str2);} catch (NameNotFoundException e) {     // TODO Auto-generated catch block     e.printStackTrace();} 
2.不利用ShareUserId
  应用程序A和B,A要读取B中的资源文件(图片,layout, string等),有两种方法:
  a.A应用读取B应用中名字相同的资源文件,直接利用普通的方法就能得到。
  b.A应用读取B应用中的任意资源,或者调用B应用中的method,这时候就需要利用反射机制,通过Context得到相关类的实例。
2 0