参考文章Android 如何监控当前Foreground Activity,如何获知应用程序的启动
提到的4种方式
-
使用 AccessibilityService
需要监听事件TYPE_WINDOW_STATE_CHANGED, 然后根据这个事件解析出Activity的完整名字, 但是依赖的ClassName有时候和当前应用没有关系, 比如android.widget.FrameLayout, 导致PackageManager.NameNotFoundException, 从而失败. 测试手机小米Android11.
代码自己搜吧, 网上一大把, 但是这种方式有问题 -
使用 ActivityManager
如链接所言
在 Android5.0 (API-21)及以上,getRunningTasks将只返回自己和 launcher,getRunningTasks 无法正确判断当前应用是否为front, 不同版本测试的结果也不一样:
- 通过反射"android.app.ActivityThread"的方式获取Top Activity
如链接所言
在有些手机上测试时,发现 It’s API > 19,只能获取当前App的Activities
- 通过 UsageStatsManager -> queryUsageStats方法获取Top Activity
如链接所言
确实能获取顶层Activity, 作者只给了获取包名的方法, 这里补上获取Activity名字的方法
public class PackageProcessUtil {
private static final String TAG = PackageProcessUtil.class.getSimpleName();
public static String getForegroundPackageName(Context context) {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {
return null;
}
//Get the app record in the last minute
Calendar calendar = Calendar.getInstance();
final long end = calendar.getTimeInMillis();
calendar.add(Calendar.HOUR_OF_DAY, -1);
final long start = calendar.getTimeInMillis();
UsageStatsManager usageStatsManager = null;
usageStatsManager = (UsageStatsManager) context.getSystemService(Context.USAGE_STATS_SERVICE);
UsageEvents usageEvents = usageStatsManager.queryEvents(start, end);
UsageEvents.Event event = new UsageEvents.Event();
String packageName = null;
while (usageEvents.hasNextEvent()) {
usageEvents.getNextEvent(event);
if (event.getEventType() == UsageEvents.Event.ACTIVITY_RESUMED) {
packageName = event.getPackageName();
Log.i(TAG, "event: " + JSONObject.toJSONString(event));
}
}
Log.i(TAG, "getForegroundPackageName: " + packageName);
return packageName;
}
public static String getApplicationNameByPackageName(Context context, String packageName) {
PackageManager pm = context.getPackageManager();
String appName;
try {
appName = pm.getApplicationLabel(pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA)).toString();
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
Log.e(TAG, "packageName: " + packageName);
appName = "";
}
return appName;
}
}
关注下面log的打印信息中的className字段, 获取当前的Activity, 包名, ActivityTask的根Activity, 记录的时间戳
Log.i(TAG, "event: " + JSONObject.toJSONString(event));
实际上日志非常多, 取决于代码设置统计时间区间
需要手动开启权限
小米手机(Android10)打开权限开关
设置->隐私保护->保护隐私->特殊应用权限->使用情况访问权限