Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android系統教程 >> Android開發教程 >> Android類裝載器DexClassLoader的簡單使用:制作android插件

Android類裝載器DexClassLoader的簡單使用:制作android插件

編輯:Android開發教程

一、裝載器簡介

“類裝載器”(ClassLoader),顧名思義,就是用來動態裝載class文件的。標准的Java SDK中有個ClassLoader類,借助此類可以裝載需要的class文件,前提是

ClassLoader類初始化必須制定class文件的路徑。

import關鍵字引用的類文件和ClassLoader動態加載類的區別:

import引用類的兩個特點:1、必須存在於本地,當程序運行該類時,內部類裝載器會自動裝載該類。

2、編譯時必須在現場,否則編譯過程會因找不到引用文件而不能正常編譯。

classLoader的特點正好於import相反,而且更自由靈活。

每一個ClassLoader必須有一個父ClassLoader,在裝載Class文件時,子ClassLoader會先請求其父ClassLoader加載該文件,只有當其父ClassLoader找不到該文件時,子ClassLoader才會繼承裝載該類。這是一種安全機制。對於Android而言,最終的apk文件包含的是dex類型的文件,dex文件是將class文件重新打包,打包的規則又不是簡單地壓縮,而是完全對class文件內部的各種函數表,變量表進行優化,產生一個新的文件,即dex文件。因此加載這種特殊的Class文件就需要特殊的類加載器DexClassLoader。

二、DexClassLoader的方法的實用

假設有兩個apk,第一個叫做Host,第二個叫Plugin。Plugin中第一個一個類Plugin,該類中定義了一個addition函數。

package com.david.plugin;
    
import android.util.Log;
    
public class Plugin {
        
    private static final String TAG=Plugin.class.getSimpleName();
        
    public Plugin(){
        Log.i(TAG, "PluginClass is initialized");
    }
        
    public int addition(int a,int b){
        return a+b;
    }
        
}

plugin的apk中AndroidManifest文件中,activity必須聲明一個action。

<activity
            android:name="com.david.plugin.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="com.david.plugin.client" />
                <action android:name="android.intent.action.MAIN"  />
                <category android:name="android.intent.category.LAUNCHER"  />
            </intent-filter>
        </activity>

 

將plugin.apk裝載進Android設備中。Host.apk中主activity調用的代碼如下:

package com.david.host;
    
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
    
import dalvik.system.DexClassLoader;
import android.support.v7.app.ActionBarActivity;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
    
    
public class MainActivity extends ActionBarActivity implements OnClickListener{
    
    private static final String plugin_package = "com.david.plugin.client";
    private PackageManager pm;
    private ResolveInfo resolveInfo;
    private Button btn_classLoader;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
//        useDexClassLoader();
        btn_classLoader=(Button) findViewById(R.id.btn_classLoader);
        btn_classLoader.setOnClickListener(this);
    }
    
    @SuppressLint("NewApi")
    public void useDexClassLoader() {
        Intent classIntent = new Intent(plugin_package, null);
        pm = getPackageManager();
        List<ResolveInfo> activities = pm.queryIntentActivities(classIntent, 0);
        resolveInfo = activities.get(0);
        ActivityInfo activityInfo = resolveInfo.activityInfo;
    
        String div = System.getProperty("path.separator");
        String packageName = activityInfo.packageName;
        String sourceDir = activityInfo.applicationInfo.sourceDir;
        System.out.println(sourceDir);
        String outDir = getApplicationInfo().dataDir;
        System.out.println(outDir);
        String libraryDir = activityInfo.applicationInfo.nativeLibraryDir;
        System.out.println(libraryDir);
    
        DexClassLoader dexcl = new DexClassLoader(sourceDir, outDir,
                libraryDir, this.getClass().getClassLoader());
        try {
            Class<?> loadClass = dexcl.loadClass(packageName+".Plugin");
            Object instance = loadClass.newInstance();
            Class[] params = new Class[2];
            params[0]=Integer.TYPE;
            params[1]=Integer.TYPE;
            Method method = loadClass.getMethod("addition", params);
            Integer result = (Integer) method.invoke(instance, 12,32);
            System.out.println(result);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } 
    
    }
    
    @Override
    public void onClick(View v) {
        useDexClassLoader();
    }
}

運行後得到的結果是:

類加載器在應用中還是用到比較多,還可以基於它設計一種“插件”架構。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved