Android APK之間的調用

目標:

    假設有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);
 ......
};


總結:

三種方式的比較:

《待續》

通過反射方式或Intent方式調用,對比於jar方式調用,2個APK耦合性更低,有益於各自應用的獨立升級













發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章