【中级——高级迈不过去?】Android高级工程师进阶学习——VirtualApk解析(系列篇13

ContextWrapper

@Override
public AssetManager getAssets() {
return mBase.getAssets();
}

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

@Override
public PackageManager getPackageManager() {
return mBase.getPackageManager();
}

@Override
public ContentResolver getContentResolver() {
return mBase.getContentResolver();
}

直接替换为:

PluginContext

@Override
public Resources getResources() {
return this.mPlugin.getResources();
}

@Override
public AssetManager getAssets() {
return this.mPlugin.getAssets();
}

@Override
public ContentResolver getContentResolver() {
return new PluginContentResolver(getHostContext());
}

看得出来还是非常巧妙的。可以做的事情也非常多,后面对ContentProvider的描述也会提现出来。

好了,到此Activity就可以正常启动了。

下面看Service。

三、Service的支持

Service和Activity有点不同,显而易见的首先我们也会将要启动的Service类替换为占坑的Service类,但是有一点不同,在Standard模式下多次启动同一个占坑Activity会创建多个对象来对象我们的目标类。而Service多次启动只会调用onStartCommond方法,甚至常规多次调用bindService,seviceConn对象不变,甚至都不会多次回调bindService方法(多次调用可以通过给Intent设置不同Action解决)。

还有一点,最明显的差异是,Activity的生命周期是由用户交互决定的,而Service的声明周期是我们主动通过代码调用的。

也就是说,start、stop、bind、unbind都是我们显示调用的,所以我们可以拦截这几个方法,做一些事情。

Virtual Apk的做法,即将所有的操作进行拦截,都改为startService,然后统一在onStartCommond中分发。

下面看详细代码:

(1) hook IActivityManager

再次来到PluginManager,发下如下方法:

private void hookSystemServices() {
try {
Singleton defaultSingleton = (Singleton) ReflectUtil.getField(ActivityManagerNative.class, null, “gDefault”);
IActivityManager activityManagerProxy = ActivityManagerProxy.newInstance(this, defaultSingleton.get());

// Hook IActivityManager from ActivityManagerNative
ReflectUtil.setField(defaultSingleton.getClass().getSuperclass(), defaultSingleton, “mInstance”, activityManagerProxy);

if (defaultSingleton.get() == activityManagerProxy) {
this.mActivityManager = activityManagerProxy;
}
} catch (Exception e) {
e.printStackTrace();
}
}

首先拿到ActivityManagerNative中的gDefault对象,该对象返回的是一个Singleton<IActivityManager>,然后拿到其mInstance对象,即IActivityManager对象(可以理解为和AMS交互的binder的client对象)对象。

然后通过动态代理的方式,替换为了一个代理对象。

那么重点看对应的InvocationHandler对象即可,该代理对象调用的方法都会辗转到其invoke方法:

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (“startService”.equals(method.getName())) {
try {
return startService(proxy, method, args);
} catch (Throwable e) {
Log.e(TAG, “Start service error”, e);
}
} else if (“stopService”.equals(method.getName())) {
try {
return stopService(proxy, method, args);
} catch (Throwable e) {
Log.e(TAG, “Stop Service error”, e);
}
} else if (“stopServiceToken”.equals(method.getName())) {
try {
return stopServiceToken(proxy, method, args);
} catch (Throwable e) {
Log.e(TAG, “Stop service token error”, e);
}
}
// 省略bindService,unbindService等方法
}

当我们调用startService时,跟进代码,可以发现调用流程为:

startService->startServiceCommon->ActivityManagerNative.getDefault().startService

这个getDefault刚被我们hook,所以会被上述方法拦截,然后调用:startService(proxy, method, args)

private Object startService(Object proxy, Method method, Object[] args) throws Throwable {
IApplicationThread appThread = (IApplicationThread) args[0];
Intent target = (Intent) args[1];
ResolveInfo resolveInfo = this.mPluginManager.resolveService(target, 0);
if (null == resolveInfo || null ==

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值