ActivityNotFoundException
很多人遇到过这个异常,解决这个异常很简单只要在AndroidManifest.xml里面注册这个activity就好了。
android.content.ActivityNotFoundException: Unable to find explicit activity class {com.tule.androidhookstartactivity/com.tule.androidhookstartactivity.TestActivity}; have you declared this activity in your AndroidManifest.xml?
除了这样解决之外就没有其他方案了吗?跟着错误栈信息深入的看一下为啥会有这个异常吧
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.tule.androidhookstartactivity, PID: 19159
android.content.ActivityNotFoundException: Unable to find explicit activity class {com.tule.androidhookstartactivity/com.tule.androidhookstartactivity.TestActivity}; have you declared this activity in your AndroidManifest.xml?
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1805)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1523)
at android.app.Activity.startActivityForResult(Activity.java:4224)
at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java:54)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:75)
at android.app.Activity.startActivityForResult(Activity.java:4183)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:708)
at android.app.Activity.startActivity(Activity.java:4507)
at android.app.Activity.startActivity(Activity.java:4475)
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
背景
android.util.Singleton 单例的帮助类延迟初始化。
package android.util;
/**
* Singleton helper class for lazily initialization.
*
* Modeled after frameworks/base/include/utils/Singleton.h
*
* @hide
*/
public abstract class Singleton<T> {
private T mInstance;
protected abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}
调用方式:ActivityManagerNative.getDefault()
调用地点:ActivityManagerNative类
调用作用:是为了获取ActivityManagerProxy
ActivityManagerNative类
/**
* Retrieve the system's default/global activity manager.
*/
static public IActivityManager getDefault() {
return gDefault.get();
}
……
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
- Hook AMS
// 获取 gDefault 这个字段, 想办法替换它
Class<?> amnClazz = Class.forName("android.app.ActivityManagerNative");
Field defaultField = amnClazz.getDeclaredField("gDefault");
defaultField.setAccessible(true);
Object gDefaultObj = defaultField.get(null); //所有静态对象的反射可以通过传null获取。如果是实列必须传实例
// 4.x+的gDefault是一个 android.util.Singleton对象; 取出这个单例里面的字段
Class<?> singletonClazz = Class.forName("android.util.Singleton");
Field amsField = singletonClazz.getDeclaredField("mInstance");
amsField.setAccessible(true);
// ActivityManagerNative 的gDefault对象里面原始的 IActivityManager对象
Object amsObj = amsField.get(gDefaultObj);
// 创建一个这个对象的代理对象, 然后替换这个字段, 让的代理对象帮忙干活
amsObj = Proxy.newProxyInstance(MainActivity.class.getClass().getClassLoader(),
amsObj.getClass().getInterfaces(),
new HookInvocationHandler(amsObj, proxyActivity, originallyActivity));
amsField.set(gDefaultObj, amsObj);
- hook ActivityThreadHandlerCallBack
Class<?> activityThreadClazz = Class.forName("android.app.ActivityThread");
Field sCurrentActivityThreadField = activityThreadClazz.getDeclaredField("sCurrentActivityThread");
sCurrentActivityThreadField.setAccessible(true);
Object sCurrentActivityThreadObj = sCurrentActivityThreadField.get(null);
Field mHField = activityThreadClazz.getDeclaredField("mH");
mHField.setAccessible(true);
Handler mH = (Handler) mHField.get(sCurrentActivityThreadObj);
Field callBackField = Handler.class.getDeclaredField("mCallback");
callBackField.setAccessible(true);
callBackField.set(mH, new ActivityThreadHandlerCallBack())
- hook ApplicationPackageMangerService
private static class PackageManagerHandler implements InvocationHandler {
private Object mActivityManagerObject;
public PackageManagerHandler(Object mActivityManagerObject) {
this.mActivityManagerObject = mActivityManagerObject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("getActivityInfo")) {
ComponentName componentName = new ComponentName(App.getApp().getPackageName(), HostActivity.class.getName());
args[0] = componentName;
}
return method.invoke(mActivityManagerObject, args);
}
}