插件化实现二 加载未安装apk

通过加载未安装应用的方式实现app插件化

学习应用插件化技术,通过加载未安装apk,实现插件化功能,此处做个笔记,方便查阅

获取未安装应用的信息

/**
 * @param apkDir 未安装应用的路径,包含应用带apk后缀的名称
 * @return 获得未安装应用的信息
 * */
private String[] getUninstallApkInfo(Context context,String apkDir)throws Exception{
    String[] apkInfo = new String[2];
    PackageManager pm = context.getPackageManager();
    PackageInfo packageInfo = pm.getPackageArchiveInfo(apkDir, PackageManager.GET_ACTIVITIES);
    if(packageInfo!=null){
        ApplicationInfo appInfo = packageInfo.applicationInfo;
        String versionName = packageInfo.versionName;
        String packageName = appInfo.packageName;
        Drawable icon = pm.getApplicationIcon(appInfo);
        String appName = pm.getApplicationLabel(appInfo).toString();//此处获取到的appName与应用包名一样
        apkInfo[0] = "plug.apk";	//插件apk名称
        apkInfo[1] = packageName;	//插件apk包名
    }
    return apkInfo;
}

获取未安装应用的Resources对象

/**
 * 反射获取插件apk的Resources对象
 * @para apkDir 插件应用路径,带有.apk的名称后辍
 * @return 得到对应插件应用的Resource对象
 * */
private Resources getPluginResources(Context context,String apkDir) {
    try {
        AssetManager assetManager = AssetManager.class.newInstance();
        Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
        //将未安装的apk添加进AssetManager中,第二个参数是插件apk的路径带apk名
        addAssetPath.invoke(assetManager, apkDir);
        Resources superRes = context.getResources();
        Resources resources = new Resources(assetManager, superRes.getDisplayMetrics(), superRes.getConfiguration());
        return resources;
    }catch (Exception e){
        e.printStackTrace();
        return null;
    }
}

获取插件应用中的图片

/**
 * 获取资源文件
 * */
public Drawable dynamicLoadApk() throws Exception{
	String apkName = "plugin.apk";  //名称随意,记住就行
	String mApkDir = Environment.getExternalStorageDirectory().getPath()+File.separator+"Pictures"+File.separator+apkName;
	String apkPackageName = mApkInfo[1];
    //在应用安装目录下创建一个名为app_dex文件夹目录,如果已经存在则不创建
    File optimizedDirFile = mContext.getDir("dex", Context.MODE_PRIVATE);
    // 参数一:包含dex的apk或jar路径
    // 参数二:apk,jar解压生成dex文件的存储路径
    // 参数三:本地library库目录,一般为null
    // 参数四:父classLoader
    DexClassLoader dexClassLoader = new DexClassLoader(mApkDir, optimizedDirFile.getPath(), null, ClassLoader.getSystemClassLoader());
    //使用apk自己的类加载器,加载图片资源类,其它资源文件类似,修改.R$mipmap中的mipmap为string可获取字符串class对象,,mApkInfo[1]是插件apk的包名
    Class<?> clazz = dexClassLoader.loadClass(Class<?> clazz = dexClassLoader.loadClass(apkPackageName + ".R$mipmap"); + ".R$mipmap");
    //获取名称为one的图片资源***********************
    Field field = clazz.getDeclaredField("one");
    int resId = field.getInt(R.mipmap.class);

    //得到插件apk的resources
    Resources resources = getPluginResources(mContext, mApkDir);
    if(resources!=null){
        Drawable drawable = resources.getDrawable(resId);
        return drawable;
    }
    return null;
}

简单使用

public class MainActivity extends Activity {

    private static final String appName = "plug.apk";
    private Drawable drawable;

    Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 1:
                    bg.setImageDrawable(drawable);
                    break;
            }
        }
    };
    private ImageView bg;
    private LoadUtils loadUtils;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();

    }

    private void init() {

        bg = ((ImageView) findViewById(R.id.bg));
        try {
            loadUtils = new LoadUtils(this, appName);
            drawable = loadUtils.dynamicLoadApk();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu,menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case R.id.update:
                mHandler.sendEmptyMessage(1);
                break;
        }
        return true;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值