在 Android 开发中,由于某些需求常常需要获取当前顶层的 Activity 信息。比如 App 中获取顶层 Activity 界面信息来判断某一个 app 是否在前台运行、统计某一个 app 的使用时长、更有恶意程序通过监听界面伪造 app 进行盗号以及欺诈、自动化开发中通过顶层 Activity 进行页面元素定位点击(比如基于辅助功自动化、uiautomator 自动化)等等操作。 在逆向工程中,获取当前运行 app 运行顶层 activity 也比较常用。通过顶层 Activity 可以快速定位界面中的功能在哪一个页面。
在 Android app 开发中,获取顶层 Activity 有以下方式:
首先需要在 Androidmanifest 中添加权限
代码如下:
在AndroidManifest文件中添加权限:
启动授权页面,需要用户授权app获取应用使用情况统计权限。跳转授权页面参考:
获取顶层 activity 参考代码:
除了 app 中使用代码获取顶层 Activity,也可以通过 adb 命令获取当前顶层的 Activity 信息,比如 windows 系统下 Android 10 手机可以用如下 adb 命令:
由于 ActivityManager->getRunningTasks 获取顶层 Activity 比较准确一些,以下将采用 ActivityManager->getRunningTasks 方式来进行研究实现。
ActivityManager源码路径位于:
frameworks/base/core/java/android/app/ActivityManager.java
ActivityManager 中 getRunningTask 调用如下:
由以上代码分析可知,最终调用的是 ActivityTaskManager.getService().getTasks。接下来分析 ActivityTaskManager 中的调用情况。
ActivityTaskManager 源码路径:
frameworks/base/core/java/android/app/ActivityTaskManager.java
ActivityTaskManager 中 getService 实现如下:
ActivityTaskManager.getService().getTasks 调用最终变成了 IActivityTaskManager.getTasks。在安卓源码中没有找到 IActivityTaskManager.java 文件,只找到 IActivityTaskManager.aidl 文件,说明 IActivityTaskManager.getTasks 调用最终转化了 binder 的进程间调用。安卓中 aidl 是用于 binder 通信定义服务器和客户端通信接口的一种描述语言,源码编译的时候会将 aidl 文件转化为 java 文件。
IActivityTaskManager.aidl 文件路径如下:
frameworks/base/core/java/android/app/IActivityTaskManager.aidl
在源码中搜索关键字“extends IActivityTaskManager"找到 ActivityTaskManagerService 文件使用了。那么说明 ActivityTaskManagerService 最终实现了 getTasks 的函数功能。以下追踪 ActivityTaskManagerService 中的调用情况:
ActivityTaskManagerService 代码路径:
frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
ActivityTaskManagerService 中 getTasks 代码如下:
通过以上分析,已经知道系统如何实现 getRunningTask 函数功能的流程。借鉴 getRunningTask 实现,要增加一个获取顶层 Activity 的接口,只需要在 IActivityTaskManager.aidl 中增加一个接口,仿照 ActivityTaskManagerService 中 getTasks 的实现方式即可。
ActivityManager getRunningTasks大概的一个调用流程总结如下,图中省略了许多binder交互的细节:
以上工作做好之后,我们就可以通过如下代码调用获取顶层 activity 了。代码如下:
源码根目录执行编译:
source build/envsetup.sh</br>
breakfast oneplus3</br>
brunch oneplus3 </br>
刷机测试效果:
<uses
-
permission android:name
=
"android.permission.GET_TASKS"
/
>
<uses
-
permission android:name
=
"android.permission.GET_TASKS"
/
>
ActivityManager mAm
=
(ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
String activity_name
=
mAm.getRunningTasks(
1
).get(
0
).topActivity.getClassName();
ActivityManager mAm
=
(ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
String activity_name
=
mAm.getRunningTasks(
1
).get(
0
).topActivity.getClassName();
<uses
-
permission android:name
=
"android.permission.PACKAGE_USAGE_STATS"
/
>
<uses
-
permission android:name
=
"android.permission.PACKAGE_USAGE_STATS"
/
>
Intent intent
=
new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
context.startActivity(intent);
Intent intent
=
new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
context.startActivity(intent);
public static getTopActivity()
{
long
endTime
=
System.currentTimeMillis();
long
beginTime
=
endTime
-
10000
;
UsageStatsManager sUsageStatsManager
=
null;
if
(sUsageStatsManager
=
=
null) {
sUsageStatsManager
=
(UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
}
String result
=
"";
UsageEvents.Event event
=
new UsageEvents.Event();
UsageEvents usageEvents
=
sUsageStatsManager.queryEvents(beginT ime, endTime);
while
(usageEvents.hasNextEvent()) {
usageEvents.getNextEvent(event);
if
(event.getEventType()
=
=
UsageEvents.Event.MOVE_TO_FOREGROUND) {
result
=
event.getPackageName()
+
"/"
+
event.getClassName();
}
}
if
(!android.text.TextUtils.isEmpty(result)) {
return
result;
}
}
return
"";
}
public static getTopActivity()
{
long
endTime
=
System.currentTimeMillis();
long
beginTime
=
endTime
-
10000
;
UsageStatsManager sUsageStatsManager
=
null;
if
(sUsageStatsManager
=
=
null) {
sUsageStatsManager
=
(UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
}
String result
=
"";
UsageEvents.Event event
=
new UsageEvents.Event();
UsageEvents usageEvents
=
sUsageStatsManager.queryEvents(beginT ime, endTime);
while
(usageEvents.hasNextEvent()) {
usageEvents.getNextEvent(event);
if
(event.getEventType()
=
=
UsageEvents.Event.MOVE_TO_FOREGROUND) {
result
=
event.getPackageName()
+
"/"
+
event.getClassName();
}
}
if
(!android.text.TextUtils.isEmpty(result)) {
return
result;
}
}
return
"";
}
C:\Users\Qiang>adb shell dumpsys activity |findstr
"mResume"
mResumedActivity: ActivityRecord{
12f93fd
u0 com.sohu.inputmethod.sogou
/
.SogouIMEHomeActivity t50}
C:\Users\Qiang>adb shell dumpsys activity |findstr
"mResume"
mResumedActivity: ActivityRecord{
12f93fd
u0 com.sohu.inputmethod.sogou
/
.SogouIMEHomeActivity t50}
/
/
getRunningTasks 方法实现
/
/
最终调用 getTaskService().getTasks
public
List
<RunningTaskInfo> getRunningTasks(
int
maxNum) throws SecurityException {
try
{
return
getTaskService().getTasks(maxNum);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
private static IActivityTaskManager getTaskService() {
return
ActivityTaskManager.getService();
}
/
/
getRunningTasks 方法实现
/
/
最终调用 getTaskService().getTasks
public
List
<RunningTaskInfo> getRunningTasks(
int
maxNum) throws SecurityException {
try
{
return
getTaskService().getTasks(maxNum);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
private static IActivityTaskManager getTaskService() {
return
ActivityTaskManager.getService();
}
/
/
getService 实现代码
public static IActivityTaskManager getService() {
return
IActivityTaskManagerSingleton.get();
}
/
/
IActivityTaskManagerSingleton 初始化代码
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton
=
new Singleton<IActivityTaskManager>() {
@Override
protected IActivityTaskManager create() {
final IBinder b
=
ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
return
IActivityTaskManager.Stub.asInterface(b);
}
};
/
/
getService 实现代码
public static IActivityTaskManager getService() {
return
IActivityTaskManagerSingleton.get();
}
/
/
IActivityTaskManagerSingleton 初始化代码
private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton
=
new Singleton<IActivityTaskManager>() {
@Override
protected IActivityTaskManager create() {
final IBinder b
=
ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
return
IActivityTaskManager.Stub.asInterface(b);
}
};
/
/
getTasks 实现代码,调用了 getFilteredTasks
@Override
public
List
<ActivityManager.RunningTaskInfo> getTasks(
int
maxNum) {
return
getFilteredTasks(maxNum, ACTIVITY_TYPE_UNDEFINED, WINDOWING_MODE_UNDEFINED);
}
/
/
getFilteredTasks 实现代码
@Override
public
List
<ActivityManager.RunningTaskInfo> getFilteredTasks(
int
maxNum,@WindowConfiguration.ActivityType
int
ignoreActivityType,@WindowConfiguration.WindowingMode
int
ignoreWindowingMode) {
final
int
callingUid
=
Binder.getCallingUid();
final
int
callingPid
=
Binder.getCallingPid();
final boolean crossUser
=
isCrossUserAllowed(callingPid, callingUid);
final
int
[] profileIds
=
getUserManager().getProfileIds(UserHandle.getUserId(callingUid), true);
ArraySet<Integer> callingProfileIds
=
new ArraySet<>();
for
(
int
i
=
0
; i < profileIds.length; i
+
+
) {
callingProfileIds.add(profileIds[i]);
}
ArrayList<ActivityManager.RunningTaskInfo>
list
=
new ArrayList<>();
synchronized (mGlobalLock) {
if
(DEBUG_ALL) Slog.v(TAG,
"getTasks: max="
+
maxNum);
final boolean allowed
=
isGetTasksAllowed(
"getTasks"
, callingPid, callingUid);
mRootActivityContainer.getRunningTasks(maxNum,
list
, ignoreActivityType,
ignoreWindowingMode, callingUid, allowed, crossUser, callingProfileIds);
}
return
list
;
}
/
/
getTasks 实现代码,调用了 getFilteredTasks
@Override
public
List
<ActivityManager.RunningTaskInfo> getTasks(
int
maxNum) {
return
getFilteredTasks(maxNum, ACTIVITY_TYPE_UNDEFINED, WINDOWING_MODE_UNDEFINED);
}
/
/
getFilteredTasks 实现代码
@Override
public
List
<ActivityManager.RunningTaskInfo> getFilteredTasks(
int
maxNum,@WindowConfiguration.ActivityType
int
ignoreActivityType,@WindowConfiguration.WindowingMode
int
ignoreWindowingMode) {
final
int
callingUid
=
Binder.getCallingUid();
final
int
callingPid
=
Binder.getCallingPid();
final boolean crossUser
=
isCrossUserAllowed(callingPid, callingUid);
final
int
[] profileIds
=
getUserManager().getProfileIds(UserHandle.getUserId(callingUid), true);
ArraySet<Integer> callingProfileIds
=
new ArraySet<>();
for
(
int
i
=
0
; i < profileIds.length; i
+
+
) {
callingProfileIds.add(profileIds[i]);
}
ArrayList<ActivityManager.RunningTaskInfo>
list
=
new ArrayList<>();
synchronized (mGlobalLock) {
if
(DEBUG_ALL) Slog.v(TAG,
"getTasks: max="
+
maxNum);
final boolean allowed
=
isGetTasksAllowed(
"getTasks"
, callingPid, callingUid);
mRootActivityContainer.getRunningTasks(maxNum,
list
, ignoreActivityType,
ignoreWindowingMode, callingUid, allowed, crossUser, callingProfileIds);
}
return
list
;
}
/
/
/
ADD START
String getTopActivity();
/
/
/
ADD END
/
/
/
ADD START
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2021-4-12 22:05
被蟑螂一号编辑
,原因: