????????????????????Support????????????úúò??????????????????????????????????????????????????????????“??????Activity???????????”??????
????Idea 1 - ??????????MonekyRunner
????aapt?????????????????apk?? AndroidManifest ????????????????????
????aapt dump xmltree ${apkpath} AndroidManifest.xml
????????????????????????? ?????????????
N: android=http://schemas.android.com/apk/res/android
E: manifest (line=2)
A: android:versionCode(0x0101021b)=(type 0x10)0x68fb0
A: android:versionName(0x0101021c)="4.30.0-preview" (Raw: "4.30.0-preview")
A: package="tv.danmaku.bili" (Raw: "tv.danmaku.bili")
E: uses-permission (line=17)
A: android:name(0x01010003)="android.permission.READ_EXTERNAL_STORAGE" (Raw: "android.permission.READ_EXTERNAL_STORAGE")
E: application (line=41)
A: android:theme(0x01010000)=@0x7f0d0007
E: activity (line=51)
A: android:theme(0x01010000)=@0x7f0d0047
A: android:name(0x01010003)="com.desmond.test.MainActivity" (Raw: "tv.danmaku.bili.ui.splash.SplashActivity")
????????????????? AndroidManifest.xml ???????????????????????????????python????????????????????????????????????????Activity?????????У?????????Activity?????г?????
defparseActivities():
pattern = re.compile(r'A: android:name(?:([^)]*))="([^"]*)"')
result = [] #???????Activity????
output = os.popen('aapt dump xmltree ' + apk + ' AndroidManifest.xml')
content = output.readlines()
target_line = -1
for i in range(len(content)):
line = content[i]
strip = line.rstrip(' ').lstrip(' ')
if i == target_line:
match = pattern.match(strip)
if match:
activity = match.groups()[0]
print "Found activity : " + activity
result.append(activity)
if strip.startswith('E: activity'):
target_line = i + 2
return result
?????????????????Android?? MonkeyRunner ????????????Activity?????????棬???????pythonд??????????????????棬?? ????????export??Activity???????? ??
??????????????????????????????????????????????????????д??????????
????Idea 2 - Instrument????
??????????????Instrument Test???????????????????????????????????
????Android??test support????????? ActivityTestRule ?????????????????test??????????Activity????к????Activity?????????????ο?????????????????? ??? ???Activity???
??????????????????? Instrumentation ????????????Activity?????????????????????????
????Activity activity = mInstrumentation.startActivitySync(intent);
????if (activity == null) {
????throw new ActivityNotFoundException("Cannot find activity for:" + intent.getComponent().getClassName());
????}
????mInstrumentation.waitForIdleSync();
????????? startActivitySync ????????????????? startActivity ?????? wait ??????????Activity????????? Instrumentation.prePerformCreate ????????????????????? IdleHandler ?????????? notify ???????????????Ч????
???????????????????δ???????????飬??InstrumentTest??????????????context?????????????????δ???
@Test
publicvoidtestActivities(){
Context targetContext = InstrumentationRegistry.getTargetContext();
PackageManager pm = targetContext.getPackageManager();
PackageInfo info = null;
try {
info = pm.getPackageInfo(targetContext.getPackageName()?? PackageManager.GET_ACTIVITIES);
} catch (PackageManager.NameNotFoundException e) {
fail(e.getMessage());
}
ActivityInfo[] activities = info.activities;
for (int i = 0?? length = activities.length; i < length; i++) {
ActivityInfo aInfo = activities[i];
Log.i(TAG?? "[" + i + "] Try launch activity:" + aInfo.name);
try {
tryStartActivity(targetContext?? aInfo.name);
} catch (Exception e) {
Log.w(TAG?? "Error in " + aInfo.name + " : " + e.getMessage());
}
}
}
????????????????? PackageManager ??API?????APK???????????Activity????? ActivityInfo ?????name????????Activity??class????????????????Intent??????????????????????????
?????????? ActivityThread ???濴???? performLaunchActivity ???????????????????Χ??try/catch????????????Activity?? onCreate / onStart / onResume ??????????????? Instrumentation.onException ????????Android?????????????Instrumentation?? AndroidJUnitRunner ?????????????????????????????????????
//AndroidJUnitRunner
@Override
publicbooleanonException(Object obj?? Throwable e){
InstrumentationResultPrinter instResultPrinter = getInstrumentationResultPrinter();
if (instResultPrinter != null) {
// report better error message back to Instrumentation results.
instResultPrinter.reportProcessCrash(e);
}
return super.onException(obj?? e);
}
?????????????????????????Activity???????????? ????????????????????????Ч?? ??
???????????????????????????????????????????????Activity????????Intent???洫???Щ???????????????????Intent?? ?????????????????????? ?????????????????????????????????????????????????????????????????????????£???????????????д?Щ??????????????????
??????????????Activity???????????static?? createIntent ?????????????????????????????????Intent?????????????????????С????????????????Activity??class??????????????????
??????????????????????÷??????????????
????1??д??????????????????????????? -> ???primitive/String???????????????????????
????2??д???????Activity???Intent???????????????????????????????????????Intent????ЩActivity????????????????? WXEntryActivity ??????ЩActivity??????start?????ЩActivity????????????????ЩActivity????????С?
????????????????????????????????????д??????????????????????
for (Method method : activityClass.getDeclaredMethods()) {
if (method.getName().equals("createIntent") &&
!Modifier.isPrivate(method.getModifiers()) &&
Modifier.isStatic(method.getModifiers())) {
Log.d(TAG?? "try start intent by method: " + method.toGenericString());
method.setAccessible(true);
haveCreateIntent = true;
Class[] clzs = method.getParameterTypes();
Object[] parameters = new Object[clzs.length];
for (int i = 0?? length = clzs.length; i < length; i++) {
Class clz = clzs[i];
parameters[i] = GeneratorRegistry.newInstance(clz); // ????class??????????
}
Intent startIntent = (Intent) method.invoke(null?? parameters);
startIntent.setClassName(mTargetContext.getPackageName()?? activityClass.getName());
launchActivitySync(startIntent);
}
}
????????????????λ??????????????????Ч?????£?

???????????????????????????????????????Щ???????????????????????????????Activity????????????????????????????????????Activity…???????鷳??????к?????????????????鷳????????????á?