1. 为了让proxy全面接管apk中所有activity的执行,需要为activity定义一个基类BaseActivity,在基类中处理代理相关的事情,同时BaseActivity还对是否使用代理进行了判断,如果不使用代理,那么activity的逻辑仍然按照正常的方式执行,也就是说,这个apk既可以按照执行,也可以由宿主程序来执行。
[java] view plain copy
-
package com.ryg.dynamicloadclient;
-
import android.app.Activity;
-
import android.content.Intent;
-
import android.os.Bundle;
-
import android.util.Log;
-
import android.view.View;
-
import android.view.ViewGroup.LayoutParams;
-
public class BaseActivity extends Activity {
-
private static final String TAG = “Client-BaseActivity”;
-
public static final String FROM = “extra.from”;
-
public static final int FROM_EXTERNAL = 0;
-
public static final int FROM_INTERNAL = 1;
-
public static final String EXTRA_DEX_PATH = “extra.dex.path”;
-
public static final String EXTRA_CLASS = “extra.class”;
-
public static final String PROXY_VIEW_ACTION = “com.ryg.dynamicloadhost.VIEW”;
-
public static final String DEX_PATH = “/mnt/sdcard/DynamicLoadHost/plugin.apk”;
-
protected Activity mProxyActivity;
-
protected int mFrom = FROM_INTERNAL;
-
public void setProxy(Activity proxyActivity) {
-
Log.d(TAG, "setProxy: proxyActivity= " + proxyActivity);
-
mProxyActivity = proxyActivity;
-
}
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
if (savedInstanceState != null) {
-
mFrom = savedInstanceState.getInt(FROM, FROM_INTERNAL);
-
}
-
if (mFrom == FROM_INTERNAL) {
-
super.onCreate(savedInstanceState);
-
mProxyActivity = this;
-
}
-
Log.d(TAG, "onCreate: from= " + mFrom);
-
}
-
protected void startActivityByProxy(String className) {
-
if (mProxyActivity == this) {
-
Intent intent = new Intent();
-
intent.setClassName(this, className);
-
this.startActivity(intent);
-
} else {
-
Intent intent = new Intent(PROXY_VIEW_ACTION);
-
intent.putExtra(EXTRA_DEX_PATH, DEX_PATH);
-
intent.putExtra(EXTRA_CLASS, className);
-
mProxyActivity.startActivity(intent);
-
}
-
}
-
@Override
-
public void setContentView(View view) {
-
if (mProxyActivity == this) {
-
super.setContentView(view);
-
} else {
-
mProxyActivity.setContentView(view);
-
}
-
}
-
@Override
-
public void setContentView(View view, LayoutParams params) {
-
if (mProxyActivity == this) {
-
super.setContentView(view, params);
-
} else {
-
mProxyActivity.setContentView(view, params);
-
}
-
}
-
@Deprecated
-
@Override
-
public void setContentView(int layoutResID) {
-
if (mProxyActivity == this) {
-
super.setContentView(layoutResID);
-
} else {
-
mProxyActivity.setContentView(layoutResID);
-
}
-
}
-
@Override
-
public void addContentView(View view, LayoutParams params) {
-
if (mProxyActivity == this) {
-
super.addContentView(view, params);
-
} else {
-
mProxyActivity.addContentView(view, params);
-
}
-
}
-
}
说明:相信大家一看代码就明白了,其中setProxy方法的作用就是为了让宿主程序能够接管自己的执行,一旦被接管以后,其所有的执行均通过proxy,且Context也变成了宿主程序的Context,也许这么说比较形象:宿主程序其实就是个空壳,它只是把其它apk加载到自己的内部去执行,这也就更能理解为什么资源访问变得很困难,你会发现好像访问不到apk中的资源了,的确是这样的,但是目前我还没有很好的方法去解决。
2. 入口activity的实现
[java] view plain copy
-
public class MainActivity extends BaseActivity {
-
private static final String TAG = “Client-MainActivity”;
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
initView(savedInstanceState);
-
}
-
private void initView(Bundle savedInstanceState) {
-
mProxyActivity.setContentView(generateContentView(mProxyActivity));
-
}
-
private View generateContentView(final Context context) {
-
LinearLayout layout = new LinearLayout(context);
-
layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
-
LayoutParams.MATCH_PARENT));
-
layout.setBackgroundColor(Color.parseColor(“#F79AB5”));
-
Button button = new Button(context);
-
button.setText(“button”);
-
layout.addView(button, LayoutParams.MATCH_PARENT,
-
LayoutParams.WRAP_CONTENT);
-
button.setOnClickListener(new OnClickListener() {
-
@Override
-
public void onClick(View v) {
-
Toast.makeText(context, “you clicked button”,
-
Toast.LENGTH_SHORT).show();
-
startActivityByProxy(“com.ryg.dynamicloadclient.TestActivity”);
-
}
-
});
-
return layout;
-
}
-
}
说明:由于访问不到apk中的资源了,所以界面是代码写的,而不是写在xml中,因为xml读不到了,这也是个大问题。注意到主界面中有一个button,点击后跳到了另一个activity,这个时候是不能直接调用系统的startActivity方法的,而是必须通过宿主程序中的proxy来执行,原因很简单,首先apk本书没有Context,所以它无法调起activity,另外由于这个子activity是apk中的,通过宿主程序直接调用它也是不行的,因为它对宿主程序来说是不可见的,所以只能通过proxy来调用,是不是感觉很麻烦?但是,你还有更好的办法吗?
3. 子activity的实现
[java] view plain copy
-
package com.ryg.dynamicloadclient;
-
import android.graphics.Color;
-
import android.os.Bundle;
-
import android.view.ViewGroup.LayoutParams;
-
import android.widget.Button;
-
public class TestActivity extends BaseActivity{
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
Button button = new Button(mProxyActivity);
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
分享读者
作者2013年java转到Android开发,在小厂待过,也去过华为,OPPO等大厂待过,18年四月份进了阿里一直到现在。
被人面试过,也面试过很多人。深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长,而且极易碰到天花板技术停滞不前!
我们整理了一份阿里P7级别的Android架构师全套学习资料,特别适合有3-5年以上经验的小伙伴深入学习提升。
主要包括腾讯,以及字节跳动,阿里,华为,小米,等一线互联网公司主流架构技术。如果你有需要,尽管拿走好了。
如果你觉得自己学习效率低,缺乏正确的指导,可以点击加入资源丰富,学习氛围浓厚的技术圈一起学习交流吧!
群内有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。
35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。
华为,小米,等一线互联网公司主流架构技术。如果你有需要,尽管拿走好了。
[外链图片转存中…(img-waF6WjPE-1711296867801)]
如果你觉得自己学习效率低,缺乏正确的指导,可以点击加入资源丰富,学习氛围浓厚的技术圈一起学习交流吧!
群内有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的Android交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。
35岁中年危机大多是因为被短期的利益牵着走,过早压榨掉了价值,如果能一开始就树立一个正确的长远的职业规划。35岁后的你只会比周围的人更值钱。