目标:
假设有2个APK,A和B,A需要调用B里面的一些函数。
方法:
一、反射方式:
假设B里面有一个函数:
package com.ccc.bb;
public class B{
public static String CMSform(String content,String pin,int filtertype,String certfilt)throws Exception
{
return "OK";
}
}
A的调用方法:
public static String CMSform(Context thisatv,String challenge,String pin) throws Exception
{
Context c = thisatv.createPackageContext("com.ccc.bApp", Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
Class<?> clazz = c.getClassLoader().loadClass("com.ccc.bb.B");
Class<?>[] partypes = new Class[4];
partypes[0]= String.class; //challenge
partypes[1]= String.class; //pin
partypes[2]= int.class; //filtertype
partypes[3]= String.class; //certfilt
Method method= clazz.getMethod("CMSform",partypes);
Object[] args = new Object[4];
args[0]= challenge;
args[1]= pin;
args[2]= 0;
args[3]= null;
String ret= (String)method.invoke(clazz,args);
return ret;
}
二、Intent+ComponentName方式:
调用者:startActivityForResult(Intent intent, Int requestCode)
被调用者setResut(int resultCode, Intent intent)设置返回值
调用者被回调:onActivityResult(int requestCode, int resultCode, Intent intent)
在bApp的AndroidManifest.xml:
......
<activity
android:label="CA证书"
android:name=".CACertsAtv"
android:exported="true"/>
在A中调用:
public static void DebugTest2(Context thisatv)
{
Intent intent = new Intent();
ComponentName cName = new ComponentName("com.ccc.bApp","com.ccc.bApp.CACertsAtv");
intent.setComponent(cName);
Bundle bundle = new Bundle();
bundle.putString("arge1", "from class A");
intent.putExtras(bundle); //传递参数
thisatv.startActivityForResult(intent,0);
}
A的回调:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (resultCode) { //resultCode为回传的标记,我在B中回传的是RESULT_OK
case RESULT_OK:
Bundle b=data.getExtras(); //data为B中回传的Intent
String str=b.getString("str1");//str即为回传的值
break;
default:
break;
}
}
B:
public class CACertsAtv extends Activity {
......
protected void onCreate(Bundle savedInstanceState) {
......
Intent intent= getIntent();
String value=intent.getStringExtra("arge1"); //从A传过来的参数
Bundle b=intent.getExtras();
b.putString("str1","return string");
setResult(RESULT_OK, intent); //intent为A传来的带有Bundle的intent,当然也可以自己定义新的Bundle
finish();//此处一定要调用finish()方法
......
}
......
三、Intent方式:
在bApp的AndroidManifest.xml:
......
<activity android:name=".CACertsAtv">
<intent-filter>
<action android:name="myintent.becalled"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
在A中调用:
public static void DebugTest2(Context thisatv)
{
Intent intent = new Intent("myintent.becalled");
thisatv.startActivity(intent);
}
四、服务方式:
1)先建立服务接口声明文件AIDL
2)AIDL生成java接口文件,接口包含抽象方法及Stub、Proxy类
3)在B端实现服务接口,并通过一个实现类来实现android.app.Service接口的方法,来管理服务的生命周期
bApp的mainfest.xml:
......
<service android:name=".MyService"
android:process=":remote"
>
<intent-filter>
<action android:name="com.sample.IStockQuoteService"/>
</intent-filter>
</service>
B的代码:
//实现AIDL文件定义的服务接口方法
private class MyServiceImpl extends IStockQuoteService.Stub{
@Override
public double getPrice(String ticker) throws RemoteException {
Log.e(TAG, "getPrice");
return 10.5;
}
}
//实现服务类,对服务生命周期进行管理
public class MyService extends Service {
static final String TAG="MyService";
@Override
public IBinder onBind(Intent arg0) {
//返回AIDL实现
return new MyServiceImpl();
}
@Override
public void onDestroy(){
Log.e(TAG, "Release MyService");
super.onDestroy();
}
}
A端调用:
public class MYyActivity extends Activity impletents ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//返回AIDL接口对象,然后可以调用AIDL方法
IStockQuoteService iService=IStockQuoteService.Stub.asInterface(service);
double value=0.0;
try {
value=iService.getPrice("");
}
catch (RemoteException e) {
Log.e(TAG,"调用出错!");
e.printStackTrace();
}
Log.e(TAG, "返回数值为:"+value);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "释放Service");
}
......
Intent intent=new Intent("com.sample.IStockQuoteService");
startService(intent);
bindService(intent, conn, Context.BIND_AUTO_CREATE);
......
};
总结:
三种方式的比较:
《待续》