Android跨进程通信方式分为4种:

1)直接调用其他进程的Activity。例如调用拨打电话,发短信的服务。
Intent callIntent = new  Intent(Intent.ACTION_CALL, Uri.parse("tel:12345678" ); 
怎么应用到自己的项目中来,如下:
(A)在项目A中新建一个TestActivity来作为实验,重点是配置该Activity的Manifest文件,配置如下:
<activity  
android:name=".TestActivity"  //该activity的class name  
android:exported="true">   
<intent-filter>    
<action android:name="net.blogjava.mobile.MYACTION"/>    
<data android:scheme="info"/>  
<category android:name="android.intent.category.DEFAULT" />            
</intent-filter>  
</activity>  


a.  android:exported="true" :设置为"True"则表示将该Activity暴露给外部;但在本demo中发现,这个属性可以不用设置,demo也是生效。这是因为:设置了intentFilter之后,exported就默认被设置为true了,除非再强制设为false。
b.  <action android:name="net.blogjava.mobile.MYACTION"/> :这里是设置Intent对应的名字,在调用的时候,需要该名字。当然这里也可以为空。(若为空串,调用的时候需要指定调用activity的包名和类名,后文详述)
c.  <data android:scheme="info"/> :data元素用于把数据规范添加到一个Intent过滤器中,如果这里定义了info,那在intent中就需要添加uri为“info://”的字样;如果name为空,这里也就不需要设置;
关于data的详细介绍,参考 http://blog.csdn.net/fireofstar/article/details/7561589
d.  <category android:name="android.intent.category.DEFAULT" /> : 意思是说,每一个通过 startActivity() 方法发出的隐式 Intent 都至少有一个 category,就是 "android.intent.category.DEFAULT",所以只要是想接收一个隐式 Intent 的 Activity 都应该包括 "android.intent.category.DEFAULT" category,不然将导致 Intent 匹配失败。
从上面的论述还可以获得以下信息:  1、一个 Intent 可以有多个 category,但至少会有一个,也是默认的一个 category。 2、只有 Intent 的所有 category 都匹配上,Activity 才会接收这个 Intent。


这四个部分是注册时候的主要动作,但a可以无视,正如前面所说; d是不可缺少的,若少了,则无法调用成功,会提示找不到Activity的错误。


(B)在B项目中启动A项目的TestActivity界面,如下:
Intent i =  new Intent("net.blogjava.mobile.MYACTION", Uri.parse("info://111"));  
this.startActivity(i); 


注意:另外一种方式也可以达到不同应用之间调用Activity,如下:
Mainifest文件配置:
<activity  
            android:name=".TestActivity"  
            android:exported="true"  
           >  
B项目调用A项目的界面:
Intent intent = new Intent();  
ComponentName cn=new ComponentName("com.mytest.main",  
                "com.mytest.main.TestActivity");    
intent.setComponent(cn);  
startActivity(intent);    
只需要指定你需要调用的Activity是在哪个包中,以及类名是什么,即格式为:(包名,包名+类名)
而Mainifest配置中,只需要指定该Activity的名字,并将它暴露给外部就行,可以不用设置Intent-filter。同样,如果你没有设置exported属性,会提示错误权限不允许访问SubActivity。也可以用个设置一个空的intent-filter来打开该属性,这也是网上为什么有的例子添加了intent-filter,但只有一个空串action的缘故。


如何传值,在项目B调用项目A的Activity的时候,如下调用:
Intent i =  new Intent("net.blogjava.mobile.MYACTION", Uri.parse("info://111"));  
                i.putExtra("value" , "调用成功" ); 
                MainActivity.this.startActivity(i);  


在项目A的TestActivity的onCreate方法里面写如下:
if (getIntent().getData() != null) 
       { 
           //  获得Host,也就是info://后面的内容   注意这里!!!! 
           String host = getIntent().getData().getHost(); 
           Bundle bundle = getIntent().getExtras(); 
           //  其他的应用程序会传递过来一个value值,在该应用程序中需要获得这个值 
           String value = bundle.getString("value"); 
           //  将Host和Value组合在一下显示在EditText组件中 
           Toast.makeText(IntentForActivity.this, "值为 : "+value, Toast.LENGTH_SHORT).show(); 
       } 






2)利用发广播的形式,其他应用能收到广播,并进行相对应的处理。
3)利用内容提供者,可以访问系统的一些数据,例如联系人
4)利用AIDL的方式来让不同进程的应用进行共享。
AIDL就叫AIDL语言,怎么应用如下:
(A)首先在A应用里面新建一个XXX.aidl文件(例如IPerson.aidl)。内容可以如下:
package com.main.testforaidl;    
interface IPerson {     
    void registerTestCall(String ma);     
    String invokCallBack();  
    double add(double a,double b);
}    
此时eclipse中会在你的A项目中的gen文件夹下自动生成一个IPerson.java的类文件。
(B)然后在A应用里面新建一个Person.java类,它继承自IPreson。
public class Person extends IPerson.Stub{
private String name;
@Override
public void registerTestCall(String ma) throws RemoteException {
this.name = ma;
}
@Override
public String invokCallBack() throws RemoteException {
return name;
}
@Override
public double add(double a, double b) throws RemoteException {
return a+b;
}
}
(C)这里需要应用到Android中的Service服务,我们在A项目中新建一个服务ServiceC,如下:
把Person类以IBinder的方式返回出去。
public class ServiceC extends Service{
private Stub iPerson = new Person();    

@Override
public IBinder onBind(Intent intent) {
return iPerson;
}
}
记得在Manifest文件中给ServiceC注册一下。
<service android:name="com.main.testforaidl.main.ServiceC" >  
           <intent-filter >  
               <action android:name="forServiceAidl" > </action>  
           </intent-filter>  
       </service>  
(D)最后在A项目中新建MainActivity一个Activity类,如下:
public class MainActivity extends Activity {

private Button btn;
private Button btn2;
private IPerson person;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button)findViewById(R.id.btn);    
    btn.setOnClickListener(new OnClickListener() {    
        @Override    
        public void onClick(View arg0) {    
            //该应用中不需要在manifest中配置RemoteService    
            bindService(new Intent("forServiceAidl"), conn, Service.BIND_AUTO_CREATE);    
        }    
    }); 
    btn2 = (Button)findViewById(R.id.btn2);    
    btn2.setOnClickListener(new OnClickListener() {    
        @Override    
        public void onClick(View arg0) {    
        try {
        Toast.makeText(MainActivity.this, "远程进程调用成功!ADD 值为 : "+person.add(5, 2), Toast.LENGTH_SHORT).show();  
} catch (RemoteException e) {
e.printStackTrace();
}
        }    
    }); 
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private ServiceConnection conn = new ServiceConnection() {    
    @Override    
    public void onServiceDisconnected(ComponentName arg0) {    
    }    
    //因为有可能有多个应用同时进行RPC操作,所以同步该方法    
    @Override    
    public synchronized void onServiceConnected(ComponentName arg0, IBinder binder) {    
        //获得IPerson接口    
        person = IPerson.Stub.asInterface(binder);    
        if(person != null){    
            try {    
                //RPC方法调用    
                String name = person.invokCallBack();    
                Toast.makeText(MainActivity.this, "远程进程调用成功!值为 : "+name, Toast.LENGTH_SHORT).show();    
            } catch (RemoteException e) {    
                e.printStackTrace();      
                Toast.makeText(MainActivity.this, "远程进程调用失败! ", Toast.LENGTH_SHORT).show();    
            }    
        }    
    }  
}; 
}


服务端的代码就差不多了,接下来就建立客户端的代码;
(A)首先在B项目中,建立一个和A项目中相同名称的包:package com.main.testforaidl,再将A项目中的IPerson.aidl文件拷贝到B项目中来,B项目中也会自动生成一个gen文件夹下的IPerson类。
(B)然后在B项目中,新建一个Activity,例如:MainActivity,如下:
public class MainActivity extends Activity {

private Button btn;
private Button btn2;
private IPerson person;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button)findViewById(R.id.btn);    
    btn.setOnClickListener(new OnClickListener() {    
        @Override    
        public void onClick(View arg0) {    
            //该应用中不需要在manifest中配置RemoteService    
            bindService(new Intent("forServiceAidl"), conn, Service.BIND_AUTO_CREATE);    
        }    
    }); 
    btn2 = (Button)findViewById(R.id.btn2);    
    btn2.setOnClickListener(new OnClickListener() {    
        @Override    
        public void onClick(View arg0) {    
        try {
        Toast.makeText(MainActivity.this, "远程进程调用成功!ADD 值为 : "+person.add(5, 2), Toast.LENGTH_SHORT).show();  
} catch (RemoteException e) {
e.printStackTrace();
}
        }    
    }); 
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private ServiceConnection conn = new ServiceConnection() {    
    @Override    
    public void onServiceDisconnected(ComponentName arg0) {    
    }    
    //因为有可能有多个应用同时进行RPC操作,所以同步该方法    
    @Override    
    public synchronized void onServiceConnected(ComponentName arg0, IBinder binder) {    
        //获得IPerson接口    
        person = IPerson.Stub.asInterface(binder);    
        if(person != null){    
            try {    
                //RPC方法调用    
                String name = person.invokCallBack();    
                Toast.makeText(MainActivity.this, "远程进程调用成功!值为 : "+name, Toast.LENGTH_SHORT).show();    
            } catch (RemoteException e) {    
                e.printStackTrace();      
                Toast.makeText(MainActivity.this, "远程进程调用失败! ", Toast.LENGTH_SHORT).show();    
            }    
        }    
    }  
}; 
}


简单的说就是在服务端的app应用中,开启一个服务,让另一个应用去调用,并在返回的IBinder类中调用服务端应用所写的方法或者常量。















































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值