很多人遇到過(guò)這個(gè)異常,解決這個(gè)異常很簡(jiǎn)單只要在AndroidManifest.xml里面注冊(cè)這個(gè)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?
除了這樣解決之外就沒(méi)有其他方案了嗎?跟著錯(cuò)誤棧信息深入的看一下為啥會(huì)有這個(gè)異常吧
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;
}
}
}
調(diào)用方式:ActivityManagerNative.getDefault()
調(diào)用地點(diǎn):ActivityManagerNative類
調(diào)用作用:是為了獲取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 這個(gè)字段, 想辦法替換它
Class<?> amnClazz = Class.forName("android.app.ActivityManagerNative");
Field defaultField = amnClazz.getDeclaredField("gDefault");
defaultField.setAccessible(true);
Object gDefaultObj = defaultField.get(null); //所有靜態(tài)對(duì)象的反射可以通過(guò)傳null獲取。如果是實(shí)列必須傳實(shí)例
// 4.x+的gDefault是一個(gè) android.util.Singleton對(duì)象; 取出這個(gè)單例里面的字段
Class<?> singletonClazz = Class.forName("android.util.Singleton");
Field amsField = singletonClazz.getDeclaredField("mInstance");
amsField.setAccessible(true);
// ActivityManagerNative 的gDefault對(duì)象里面原始的 IActivityManager對(duì)象
Object amsObj = amsField.get(gDefaultObj);
// 創(chuàng)建一個(gè)這個(gè)對(duì)象的代理對(duì)象, 然后替換這個(gè)字段, 讓的代理對(duì)象幫忙干活
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);
}
}