目標:
假設有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);
......
};
總結:
三種方式的比較:
《待續》