Android Open Source - dynamic-load-apk D L Plugin Manager






From Project

Back to project page dynamic-load-apk.

License

The source code is released under:

Apache License

If you think the Android project dynamic-load-apk listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (C) 2014 singwhatiwanna(???) <singwhatiwanna@gmail.com>
 */*from   w  w  w.  j  ava2 s . c om*/
 * collaborator:??,????
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.ryg.dynamicload.internal;

import java.io.File;
import java.lang.reflect.Method;
import java.util.HashMap;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.os.Build;
import android.util.Log;

import com.ryg.dynamicload.DLBasePluginActivity;
import com.ryg.dynamicload.DLBasePluginFragmentActivity;
import com.ryg.dynamicload.DLProxyActivity;
import com.ryg.dynamicload.DLProxyFragmentActivity;
import com.ryg.utils.DLConstants;

import dalvik.system.DexClassLoader;

public class DLPluginManager {

    private static final String TAG = "DLPluginManager";

    /**
     * return value of {@link #startPluginActivity(Activity, DLIntent)} start success
     */
    public static final int START_RESULT_SUCCESS = 0;

    /**
     * return value of {@link #startPluginActivity(Activity, DLIntent)} package not found
     */
    public static final int START_RESULT_NO_PKG = 1;

    /**
     * return value of {@link #startPluginActivity(Activity, DLIntent)} class not found
     */
    public static final int START_RESULT_NO_CLASS = 2;

    /**
     * return value of {@link #startPluginActivity(Activity, DLIntent)} class type error
     */
    public static final int START_RESULT_TYPE_ERROR = 3;


    private static DLPluginManager sInstance;
    private Context mContext;
    private final HashMap<String, DLPluginPackage> mPackagesHolder = new HashMap<String, DLPluginPackage>();

    private int mFrom = DLConstants.FROM_INTERNAL;

    private DLPluginManager(Context context) {
        mContext = context.getApplicationContext();
    }

    public static DLPluginManager getInstance(Context context) {
        if (sInstance == null) {
            synchronized (DLPluginManager.class) {
                if (sInstance == null) {
                    sInstance = new DLPluginManager(context);
                }
            }
        }
        return sInstance;
    }

    /**
     * Load a apk. Before start a plugin Activity, we should do this first.<br/>
     * NOTE : will only be called by host apk.
     * @param dexPath
     */
    public DLPluginPackage loadApk(String dexPath) {
        // when loadApk is called by host apk, we assume that plugin is invoked by host.
        mFrom = DLConstants.FROM_EXTERNAL;

        PackageInfo packageInfo = mContext.getPackageManager().
                getPackageArchiveInfo(dexPath, PackageManager.GET_ACTIVITIES);
        if (packageInfo == null)
            return null;

        final String packageName = packageInfo.packageName;
        DLPluginPackage pluginPackage = mPackagesHolder.get(packageName);
        if (pluginPackage == null) {
            DexClassLoader dexClassLoader = createDexClassLoader(dexPath);
            AssetManager assetManager = createAssetManager(dexPath);
            Resources resources = createResources(assetManager);
            pluginPackage = new DLPluginPackage(packageName, dexPath, dexClassLoader, assetManager,
                    resources, packageInfo);
            mPackagesHolder.put(packageName, pluginPackage);
        }
        return pluginPackage;
    }

    private DexClassLoader createDexClassLoader(String dexPath) {
        File dexOutputDir = mContext.getDir("dex", Context.MODE_PRIVATE);
        final String dexOutputPath = dexOutputDir.getAbsolutePath();
        DexClassLoader loader = new DexClassLoader(dexPath, dexOutputPath, null, mContext.getClassLoader());
        return loader;
    }

    private AssetManager createAssetManager(String dexPath) {
        try {
            AssetManager assetManager = AssetManager.class.newInstance();
            Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
            addAssetPath.invoke(assetManager, dexPath);
            return assetManager;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

    public DLPluginPackage getPackage(String packageName) {
        return mPackagesHolder.get(packageName);
    }

    private Resources createResources(AssetManager assetManager) {
        Resources superRes = mContext.getResources();
        Resources resources = new Resources(assetManager, superRes.getDisplayMetrics(),
                superRes.getConfiguration());
        return resources;
    }

    /**
     * {@link #startPluginActivityForResult(Activity, DLIntent, int)}
     */
    public int startPluginActivity(Context context, DLIntent dlIntent) {
        return startPluginActivityForResult(context, dlIntent, -1);
    }

    /**
     * @param context
     * @param dlIntent
     * @param requestCode
     * @return One of below: {@link #START_RESULT_SUCCESS} {@link #START_RESULT_NO_PKG}
     *         {@link #START_RESULT_NO_CLASS} {@link #START_RESULT_TYPE_ERROR}
     */
    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    public int startPluginActivityForResult(Context context, DLIntent dlIntent, int requestCode) {
        if (mFrom == DLConstants.FROM_INTERNAL) {
            dlIntent.setClassName(context, dlIntent.getPluginClass());
            performStartActivityForResult(context, dlIntent, requestCode);
            return DLPluginManager.START_RESULT_SUCCESS;
        }

        String packageName = dlIntent.getPluginPackage();
        if (packageName == null) {
            throw new NullPointerException("disallow null packageName.");
        }
        DLPluginPackage pluginPackage = mPackagesHolder.get(packageName);
        if (pluginPackage == null) {
            return START_RESULT_NO_PKG;
        } 

        DexClassLoader classLoader = pluginPackage.classLoader;
        String className = dlIntent.getPluginClass();
        className = (className == null ? pluginPackage.getDefaultActivity() : className);
        if (className.startsWith(".")) {
            className = packageName + className;
        }
        Class<?> clazz = null;
        try {
            clazz = classLoader.loadClass(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return START_RESULT_NO_CLASS;
        }

        Class<? extends Activity> activityClass = null;
        if (DLBasePluginActivity.class.isAssignableFrom(clazz)) {
            activityClass = DLProxyActivity.class;
        } else if (DLBasePluginFragmentActivity.class.isAssignableFrom(clazz)) {
            activityClass = DLProxyFragmentActivity.class;
        } else {
            return START_RESULT_TYPE_ERROR;
        }

        dlIntent.putExtra(DLConstants.EXTRA_CLASS, className);
        dlIntent.putExtra(DLConstants.EXTRA_PACKAGE, packageName);
        dlIntent.setClass(mContext, activityClass);
        performStartActivityForResult(context, dlIntent, requestCode);
        return START_RESULT_SUCCESS;
    }

    private void performStartActivityForResult(Context context, DLIntent dlIntent, int requestCode) {
        Log.d(TAG, "launch " + dlIntent.getPluginClass());
        if (context instanceof Activity) {
            ((Activity) context).startActivityForResult(dlIntent, requestCode);
        } else {
            context.startActivity(dlIntent);
        }
    }

}




Java Source Code List

com.ryg.dynamicload.DLBasePluginActivity.java
com.ryg.dynamicload.DLBasePluginFragmentActivity.java
com.ryg.dynamicload.DLPlugin.java
com.ryg.dynamicload.DLProxyActivity.java
com.ryg.dynamicload.DLProxyFragmentActivity.java
com.ryg.dynamicload.internal.DLIntent.java
com.ryg.dynamicload.internal.DLPluginManager.java
com.ryg.dynamicload.internal.DLPluginPackage.java
com.ryg.dynamicload.internal.DLProxyImpl.java
com.ryg.dynamicload.sample.docommon.HostInterfaceManager.java
com.ryg.dynamicload.sample.docommon.HostInterface.java
com.ryg.dynamicload.sample.doihost.MainActivity.java
com.ryg.dynamicload.sample.doihost.component.HostComponent.java
com.ryg.dynamicload.sample.doihost.interfacee.HostInterfaceImp.java
com.ryg.dynamicload.sample.doiplugin.MainActivity.java
com.ryg.dynamicload.sample.mainhost.MainActivity.java
com.ryg.dynamicload.sample.mainhost.TestHostClass.java
com.ryg.dynamicload.sample.mainplugin.MainActivity.java
com.ryg.dynamicload.sample.mainplugin.ResourceConstants.java
com.ryg.dynamicload.sample.mainplugin.TestButton.java
com.ryg.dynamicload.sample.mainplugin.TestFragmentActivity.java
com.ryg.dynamicload.sample.mainplugin.TestFragment.java
com.ryg.dynamicload.sample.mainpluginb.MainActivity.java
com.ryg.utils.DLConstants.java
com.ryg.utils.DLUtils.java