插件化原理

插件化原理

插桩法实现:使用一个已注册的Activity为壳,加载apk中的Activity

1、定义接口,用于传递上下文和生命周期

public interface PluginAtyInterface {
    	public void onCreate(Bundle savedInstanceState);
   	    public void onDestroy();
        public void onStart();
    public void onStop();
    public void onResume();
    public void onRestart();
    public void attch(Activity context);
}

2、插件中的类实现上面接口并在重写关于上下文类引用的方法,使其使用已注册的aty去加载(抽象基类):

public class BaseActivity extends Activity implements PluginAtyInterface {
    protected Activity that;
 @Override
public void setContentView(int layoutResID) {
    if (that == null) {
        super.setContentView(layoutResID);
    } else {
        that.setContentView(layoutResID);
    }
}
@Override
public <T extends View> T findViewById(int id) {
    if (that == null) {
        return super.findViewById(id);
    } else {
        return that.findViewById(id);
    }
}
@Override
public ClassLoader getClassLoader() {
    if (that == null) {
        return super.getClassLoader();
    } else {
        return that.getClassLoader();
    }
}
@Override
public WindowManager getWindowManager() {
    if (that == null) {
        return super.getWindowManager();
    } else {
        return that.getWindowManager();
    }
}
@Override
public Window getWindow() {
    if (that == null) {
        return super.getWindow();
    } else {
        return that.getWindow();
    }
}
@NonNull
@Override
public LayoutInflater getLayoutInflater() {
    if (that == null) {
        return super.getLayoutInflater();
    } else {
        return that.getLayoutInflater();
    }
}
@Override
public void onCreate(Bundle savedInstanceState) {
    if (that == null) {
        super.onCreate(savedInstanceState);
    }

}
@Override
public void onDestroy() {
    if (that == null) {
        super.onDestroy();
    }
}
@Override
public void onStart() {
    if (that == null) {
        super.onStart();
    }
}
@Override
public void onStop() {
    if (that == null) {
        super.onStop();
    }
}
@Override
public void onResume() {
    if (that == null) {
        super.onResume();
    }
}
@Override
public void onRestart() {
    if (that == null) {
        super.onRestart();
    }
}
public void attch(Activity context) {
    this.that = context;
}
@Override
public void startActivity(Intent intent) {
    if (that != null) {
        Intent intent1 = new Intent();
        intent1.putExtra(PluginApkManger.ClassName, intent.getComponent().getClassName());
        that.startActivity(intent1);
    } else {
        super.startActivity(intent);
    }
}

}

3、创建工具类用于从插件apk中获取到 包名+入口aty名、Resource、ClassLoder:

public class PluginApkManger {
    String TAG = "PluginApkManger";
    public static String ClassName="classname";
    private static PluginApkManger pluginApkManger;
    private String EntryName;
    private String apkPath;
    private AssetManager assetManager;
    private Resources resources;
    private ClassLoader classLoader;
    private Context context;
    public Resources getResources() {
        return resources;
    }
    public static PluginApkManger getInstance() {
        if (pluginApkManger == null) {
            pluginApkManger = new PluginApkManger();
        }
        return pluginApkManger;
    }
    public void setContext(Context context) {
        this.context = context;
    }
    //通过apk存放的路径初始化资源管理和类加载器
    public void loadApk(String apkpath) {
        this.apkPath = apkpath;
        // 初始化Assetmanger和classLoader EntryName
        //1
        try {
            //反射
            AssetManager assetManager = AssetManager.class.newInstance();
            Method getNameMethod = AssetManager.class.getMethod("addAssetPath", String.class);
            Object name = getNameMethod.invoke(assetManager, apkPath);
            if (name.toString().equals("0")) {
                Log.i(TAG, "loadApk: " + "资源加载失败");
            }
            resources=new Resources(assetManager,context.getResources().getDisplayMetrics(),context.getResources().getConfiguration());

        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        //2
        File file = new File(apkPath);
        File optimizedDirectoryFile = new File(file.getParentFile(), "optimizedDirectory");
        if (!optimizedDirectoryFile.exists()) {
            optimizedDirectoryFile.mkdir();
        }
        DexClassLoader dexClassLoader = new DexClassLoader(apkPath, optimizedDirectoryFile.getAbsolutePath(), null, context.getClassLoader());
        this.classLoader = dexClassLoader;
        //3获取入口类名
        if(context!=null){
            PackageManager packageManager=context.getPackageManager();
            PackageInfo packageInfo=packageManager.getPackageArchiveInfo(apkPath,PackageManager.GET_ACTIVITIES);
            EntryName=packageInfo.activities[0].name;
            Log.i(TAG, "loadApk: "+EntryName);
        }else{
            Log.e(TAG, "loadApk: 没有注入上下文,请使用setContext方法" );
        }
    }
    public String getEntryName() {
        return EntryName;
    }
    public ClassLoader getClassLoader() {
        return classLoader;
    }
    public AssetManager getAssetManager() {
        return assetManager;
    }
    public void setApkPath(String apkPath) {
        this.apkPath = apkPath;
    }
    public String getApkPath() {
        return apkPath;
    }
}       

4、用于插桩的aty从先使用上面工具传入apkpath获得Resource和classloder、包名+类名
重写自身的getResource和getclassloder方法,通过反射及apk中的classloder和包名加载到apk包的aty,将其与自身通过attch绑定,将其强转为PluginAtyInterface,在生命周期的各个方法中调用aty强转后的PluginAtyInterface的各个对应方法,实现生命周期的绑定,重写StartActivity方法实现Apk中aty跳转(通过重写apk中的startactivity方法将要跳转的aty名字传给壳aty的StartActivity方法)。

public class KeAty extends Activity {
    private String TAG="keaty";
    private PluginAtyInterface pluginAtyInterface;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    String classname=getIntent().getStringExtra(PluginApkManger.ClassName);

    try {
        //反射加载到类 获取实例
        Class aty = getClassLoader().loadClass(classname);
        Constructor constructor = aty.getConstructor(new Class[]{});
        Object instance = constructor.newInstance(new Object[]{});
        pluginAtyInterface = (PluginAtyInterface) instance;
        pluginAtyInterface.attch(this);
        Bundle bundle = new Bundle();
        pluginAtyInterface.onCreate(bundle);

    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }
}

@Override
public ClassLoader getClassLoader() {
    return PluginApkManger.getInstance().getClassLoader();
}

@Override
protected void onDestroy() {
    super.onDestroy();
    pluginAtyInterface.onDestroy();
}

@Override
protected void onRestart() {
    super.onRestart();
    pluginAtyInterface.onRestart();
}

@Override
protected void onStop() {
    super.onStop();
    pluginAtyInterface.onStop();
}

@Override
protected void onStart() {
    super.onStart();
    pluginAtyInterface.onStart();
}

@Override
public Resources getResources() {
    return PluginApkManger.getInstance().getResources();
}

@Override
protected void onResume() {
    super.onResume();
    pluginAtyInterface.onResume();
}

@Override
public void startActivity(Intent intent) {
    Intent intent1=new Intent(this,KeAty.class);
    Log.i(TAG, "startActivity: "+intent.getStringExtra(PluginApkManger.ClassName));
    intent1.putExtra(PluginApkManger.ClassName,intent.getStringExtra(PluginApkManger.ClassName));
    super.startActivity(intent1);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值