前言:

首先这里需要详细叙述一下标题中”监听Android CTS测试项解决方案“的需求。这里的需求是指我们需要精确的监听到当前CTS测试正在测试的测试项。

因为我们知道CTS认证是获得Google推出的 Android 系统中 Android Market 服务的前提。CTS 兼容性测试的主要目的和意义在于使得用户在 Android 系统的应用过程中,有更好的用户体验,并展现出 Android
系统的优越特性;使得 Android 应用程序编写者更容易编写高质量的应用程序;充分展现 Android Market 的优势,让获得CTS认证的终端得到 Android Market 的使用许可。而我们在实际进行的CTS测试中并不是完全一帆风顺的,此时我们就需要掌握一些基本的CTS测试原理和流程。当然google已经开源了CTS Verifier测试工具的源码,从源码入手分析也是我们一个选择。

三思而后行,通过研究和分析这里提供两个方案(这里以Accelerometer Measurement Test测试项为例):

方案一:监听当前正在运行的Activity是否是Accelerometer Measurement Test测试项所处的Activity

方案二:监听当前测试项是否是Accelerometer Measurement Test测试项

一:监听当前正在运行的Activity是否为Accelerometer Measurement Test测试项所处的Activity

这种方式看起来已经跟CTS Verifier测试工具没有什么关系了,因为我们这里监听的是Activity,那么如何监听当前正在运行的Activity呢;从源码中并没发现谷歌提供该接口(至少是我没有找到)。那么我们知道Activity管理师通过task栈进行管理的,而且通过不同的启动方式,Activity的栈也不是唯一的。但是如果我们能够得到顶层栈中栈顶Activity则就可以检测到当前处于活动状态的Activity。

当然谷歌这里已经开放了相关接口,我们先认识一下:

            final ActivityManager am = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> list = am.getRunningTasks(1);
if (list.size() != 0) {
RunningTaskInfo topRunningTask = list.get(0);
ComponentName c= topRunningTask.topActivity;
String packageName=c.getPackageName();
String className=c.getClassName();
android.util.Log.d("ComponentName","packageName-->"+packageName+"--className-->"+className);
}

从上面的代码中我们可以取到顶层栈中栈顶topActivity的信息,该信息被封装在ComponentName中。那么此时是不是完成了需求呢?

答案当然是否定的。

因为我们要时时刻刻监听栈顶Activity,才能确定当前活动的Activity是我们需要监听的Activity,因此除了能够得到栈顶的Activity我们还需要监听Activity的切换,但是此时Android原生代码中并没有提供相关的接口,这个时候有人会想到可以使用线程或者服务反复的去判断栈顶Activity是否已经发生变化。当然这样是不可取的,因为我们还要考虑到该线程或者服务不会被系统回收。因此我们该如何去监听Activity的切换呢?

我们知道,Activity的切换无非有两种,第一种:启动或者创建一个新的Activity;第二种:唤醒后台运行的Activity。因此如果我们能够成功监听到启动或者创建一个Activity,或者唤醒Activity我们就基本完成了Activity的切换的监听。

在源码/frameworks/base/core/java/android/app目录下ActivityThread.java中为我们提供了这样一个方法来帮助我们完成对Activity启动、创建、销毁、暂停、停止,唤醒等生命周期的监听。

public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
/// M: enable profiling @{
if ( true == mEnableAppLaunchLog && !mIsUserBuild && false == mTraceEnabled ) {
try {
FileInputStream fprofsts_in = new FileInputStream("/proc/mtprof/status");
if ( fprofsts_in.read()== '3' ) {
Log.v(TAG, "start Profiling for empty process");
mTraceEnabled = true;
Debug.startMethodTracing("/data/data/applaunch"); //applaunch.trace
}
} catch (FileNotFoundException e) {
Slog.e(TAG, "mtprof entry can not be found", e);
} catch (java.io.IOException e) {
Slog.e(TAG, "mtprof entry open failed", e);
}
}
/// @}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER | Trace.TRACE_TAG_PERF, "activityStart"); /// M: add TRACE_TAG_PERF for performance debug
ActivityClientRecord r = (ActivityClientRecord)msg.obj; r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER | Trace.TRACE_TAG_PERF); /// M: add TRACE_TAG_PERF for performance debug
} break;
case RELAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
handleRelaunchActivity(r);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case PAUSE_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case PAUSE_ACTIVITY_FINISHING:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case STOP_ACTIVITY_SHOW:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
handleStopActivity((IBinder)msg.obj, true, msg.arg2);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case STOP_ACTIVITY_HIDE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
handleStopActivity((IBinder)msg.obj, false, msg.arg2);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SHOW_WINDOW:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityShowWindow");
handleWindowVisibility((IBinder)msg.obj, true);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case HIDE_WINDOW:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityHideWindow");
handleWindowVisibility((IBinder)msg.obj, false);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case RESUME_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER | Trace.TRACE_TAG_PERF, "activityResume"); /// M: add TRACE_TAG_PERF for performance debug
handleResumeActivity((IBinder)msg.obj, true,
msg.arg1 != 0, true);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER | Trace.TRACE_TAG_PERF); /// M: add TRACE_TAG_PERF for performance debug
break;
case SEND_RESULT:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDeliverResult");
handleSendResult((ResultData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case DESTROY_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");
handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
msg.arg2, false);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case EXIT_APPLICATION:
if (mInitialApplication != null) {
mInitialApplication.onTerminate();
}
Looper.myLooper().quit();
break;
case NEW_INTENT:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityNewIntent");
handleNewIntent((NewIntentData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case RECEIVER:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
handleReceiver((ReceiverData)msg.obj);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case CREATE_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case BIND_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
handleBindService((BindServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case UNBIND_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind");
handleUnbindService((BindServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SERVICE_ARGS:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStart");
handleServiceArgs((ServiceArgsData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case STOP_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");
handleStopService((IBinder)msg.obj);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case REQUEST_THUMBNAIL:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "requestThumbnail");
handleRequestThumbnail((IBinder)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case CONFIGURATION_CHANGED:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");
mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi;
handleConfigurationChanged((Configuration)msg.obj, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case CLEAN_UP_CONTEXT:
ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
cci.context.performFinalCleanup(cci.who, cci.what);
break;
case GC_WHEN_IDLE:
scheduleGcIdler();
break;
case DUMP_SERVICE:
handleDumpService((DumpComponentInfo)msg.obj);
break;
case LOW_MEMORY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "lowMemory");
handleLowMemory();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case ACTIVITY_CONFIGURATION_CHANGED:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityConfigChanged");
handleActivityConfigurationChanged((IBinder)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case PROFILER_CONTROL:
handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj, msg.arg2);
break;
case CREATE_BACKUP_AGENT:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupCreateAgent");
handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case DESTROY_BACKUP_AGENT:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupDestroyAgent");
handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SUICIDE:
Process.killProcess(Process.myPid());
break;
case REMOVE_PROVIDER:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "providerRemove");
completeRemoveProvider((ProviderRefCount)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case ENABLE_JIT:
ensureJitEnabled();
break;
case DISPATCH_PACKAGE_BROADCAST:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastPackage");
handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SCHEDULE_CRASH:
throw new RemoteServiceException((String)msg.obj);
case DUMP_HEAP:
handleDumpHeap(msg.arg1 != 0, (DumpHeapData)msg.obj);
break;
case DUMP_ACTIVITY:
handleDumpActivity((DumpComponentInfo)msg.obj);
break;
case DUMP_PROVIDER:
handleDumpProvider((DumpComponentInfo)msg.obj);
break;
case SLEEPING:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "sleeping");
handleSleeping((IBinder)msg.obj, msg.arg1 != 0);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SET_CORE_SETTINGS:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setCoreSettings");
handleSetCoreSettings((Bundle) msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case UPDATE_PACKAGE_COMPATIBILITY_INFO:
handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj);
break;
case TRIM_MEMORY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "trimMemory");
handleTrimMemory(msg.arg1);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case UNSTABLE_PROVIDER_DIED:
handleUnstableProviderDied((IBinder)msg.obj, false);
break;
case REQUEST_ASSIST_CONTEXT_EXTRAS:
handleRequestAssistContextExtras((RequestAssistContextExtras)msg.obj);
break;
case TRANSLUCENT_CONVERSION_COMPLETE:
handleTranslucentConversionComplete((IBinder)msg.obj, msg.arg1 == 1);
break;
case INSTALL_PROVIDER:
handleInstallProvider((ProviderInfo) msg.obj);
break;
}
if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
/// M: ActivityThread log enhancement @{
if(!mIsUserBuild && isDebuggableMessage(msg.what)){
Slog.d(TAG, codeToString(msg.what) + " handled "
+ ": " + msg.arg1 + " / " + msg.obj);
}
/// @}
}

这里我们可以看到,我们可以通过监听LAUNCH_ACTIVITY和RESUME_ACTIVITY来判断Activity的切换,因此我们可以将通过在ActivityThread.java中将获得顶层栈栈顶Activity的方法在这里调用以实现我们的需求。

那么这样是否能够完成我们的需求呢?

答案依旧是否定的。即使我们能够编译通过,但是在我们测试观察log的时候,并不能得到当前处于活动状态的Activity。那么为什么会出现这种情况呢?

通过观察log我们发现,这里我们需要GET_TASK权限,当然我们可以通过添加权限的方式,但这样有风险,那么有没有一个更可靠的方式呢。

依旧是通过观察log,我们发现Android系统会使用一个ActivityClientRecoder类来记录Activity的信息,而这个类在ActivityThread中也得到了应用,因此我们可以通过得到ActivityClientRecoder的对象r来获得Activity对象,在通过Activity对象的getComponent()来得到ComponentName的对象,在ComponentName对象中便封装了应用程序包名和当前处于活动状态的Activity。

具体实现方式这里不再赘述。

此外还有一种备用的方式,就是我们可以通过得到当前处于活动状态进程信息来判断当前处以活动状态的进程。

实现方式如下:

        final ActivityManager am = (ActivityManager)mAppContextImpl.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningAppProcessInfo> list = am.getRunningAppProcesses(); if (list.size() != 0) {
RunningAppProcessInfo topRunningProcess = list.get(0);
if(topRunningProcess.processName.equals("com.android.xx.xxxxx")){
return true;
}
}
return false;

注意!

我们如何得到我们需要判断的那个Activity的名字呢,当然如果那个Activity是你开发定义的就无所谓了,如果不是,或者是第三方的APK,也没关系,google提供了一个工具可以对apk进行反编译,因此我们可以从反编译的AndroidManifest.xml文件中得到相关Activity的name。

监听Android CTS测试项解决方案(一)的更多相关文章

  1. 监听Android CTS测试项解决方案(二)

    二,监听当前测试项是否是Accelerometer Measurement Test测试项 通过第一种方式介绍的,我们可以得到当前处于活动状态的Activity类似监听CTS测试当前的测试项.但是由于 ...

  2. vue 定义全局函数,监听android返回键事件

    vue 定义全局函数,监听android返回键事件 方法一:main.js 注入(1)在main.js中写入函数Vue.prototype.changeData = function (){ aler ...

  3. 【Android代码片段之八】监听Android屏幕是否锁屏

    实现方法:1)通过BroadcastReceiver接收广播Intent.ACTION_SCREEN_ON和Intent.ACTION_SCREEN_OFF可以判断屏幕状态是否锁屏,但是只有屏幕状态发 ...

  4. 【转】Android CTS 测试

    http://blog.csdn.net/zxm317122667/article/details/8508013 Android-CTS 4.0.3测试基本配置 1. Download CTS CT ...

  5. 从网页监听Android设备的返回键

    最近搞Android项目的时候,遇到一个比较蛋疼的需求,需要从Client App调用系统浏览器打开一个页面,进行杂七杂八的一些交互之后,返回到App.如何打开浏览器和如何返回App这里就不说了,有兴 ...

  6. 服务器重启后Oracle监听服务没有自动启动的解决方案

    最近一直在被这样一个问题烦恼,就是服务器断电重启后,Oracle监听服务没有正常自动启动(监听服务已经设置为自启动). 具体是这样的,监听服务设置为开机自启动,Oracle数据库服务设置为开机延时启动 ...

  7. android CTS测试

    CTS认证是获得Google推出的Android系统中Android Market服务的前提 CTS兼容性测试的主要目的和意义在于使得用户在Android系统的应用过程中,有更好的用户体验,并展现出A ...

  8. Android开发——监听Android手机的网络状态

    0. 前言 在Android开发中监听手机的网络状态是一个常见的功能,比如在没网的状态下进行提醒并引导用户打开网络设置,或者在非wifi状态下开启无图模式等等.因此本篇将网上的资料进行了整理总结,方便 ...

  9. Android 监听 Android中监听系统网络连接打开或者关闭的实现代码

    本篇文章对Android中监听系统网络连接打开或者关闭的实现用实例进行了介绍.需要的朋友参考下 很简单,所以直接看代码 复制代码 代码如下: package xxx; import android.c ...

随机推荐

  1. (28)odoo中css可用颜色对照表

    颜色 颜色英文代码 形像颜色 HEX格式 RGB格式 LightPink 浅粉红 #FFB6C1 255,182,193 Pink 粉红 #FFC0CB 255,192,203 Crimson 猩红 ...

  2. hdu-----(1150)Machine Schedule(最小覆盖点)

    Machine Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  3. asp.net 奇淫技巧

    VS2013自动注释插件 分享一个Visual Studio的背景插件,让堆码更富情趣 工欲善其事必先利其器系列之:更换Visual Studio代码风格. 为Visual Studio更换皮肤和背景 ...

  4. struts2 <s:iterator> status属性

    struts2 <s:iterator> status属性 转载▼   iterator标签主要是用于迭代输出集合元素,如list set map 数组等,在使用标签的时候有三个属性值得我 ...

  5. 使用DD_belatedPNG让IE6支持PNG透明图片

    使用DD_belatedPNG让IE6支持PNG透明图片 众所周知IE6不支持透明的PNG图片,而PNG图片在Web设计方面表现力上,具有其它图形格式所达不到的效果,IE6这一致命缺陷极大地限制了We ...

  6. pycharm 导包

    如果需要requests包,python没有自带.可以执行命令:pip install requests,自动安装导入.

  7. 又一个提示框思密达,腾讯UED

    demo <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf- ...

  8. 如果解决ubuntu tab键不能提示命令

    /bin/sh is symlinked to /bin/dashTo change it, do:sudo rm /bin/shsudo ln -s /bin/bash /bin/sh 原文:htt ...

  9. bzoj 2326: [HNOI2011]数学作业

    #include<cstdio> #include<iostream> #include<cstring> #include<cmath> #defin ...

  10. Linux中如何让命令在后台运行

    1.在下达的命令后面加上&,就可以使该命令在后台进行工作,这样做最大的好处就是不怕被ctrl+c这个中断指令所中断. 2. 那大家可能又要问了,在后台执行的程序怎么使它恢复到前台来运行呢?很简 ...