Android新API下如何识别当前Activity的包名?旧方案已废弃
我太懂你这种困扰了——五六年前的老方法在新Android API下基本都废了,但既然AppBlock、AppLocker这类应用还能在Play商店好好跑着,说明肯定有适配新系统的靠谱方案。下面我就结合Android 12+的规范,给你拆解具体的实现思路:
一、检测应用启动(Android 12+适配方案)
目前最可靠的实现方式是借助**辅助功能(AccessibilityService)**监听窗口状态变化,这也是Play商店里同类应用的核心方案:
- 核心逻辑:在自定义的AccessibilityService中重写
onAccessibilityEvent方法,捕获TYPE_WINDOW_STATE_CHANGED事件,通过event.getPackageName()获取当前前台应用的包名,对比之前记录的包名就能判断是否有新应用启动。 - 权限要求:必须申请
android.permission.BIND_ACCESSIBILITY_SERVICE权限,并且需要引导用户到系统设置中手动开启你的应用的辅助功能(这是这类应用的常规操作,比如AppBlock就是这么引导用户的)。 - 代码示例:
public class AppMonitorService extends AccessibilityService { private String lastForegroundPackage; @Override public void onAccessibilityEvent(AccessibilityEvent event) { if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) { String currentPackage = event.getPackageName().toString(); // 对比上次记录的包名,判断是否为新应用启动 if (lastForegroundPackage == null || !currentPackage.equals(lastForegroundPackage)) { // 这里处理应用启动的逻辑,比如记录日志、触发PIN锁浮层 lastForegroundPackage = currentPackage; } } } @Override public void onInterrupt() { // 服务被中断时的处理逻辑 } }
- 辅助验证方案:可以搭配
UsageStatsManager补全盲区(比如某些特殊场景下窗口事件没触发),需要申请android.permission.PACKAGE_USAGE_STATS权限,引导用户到应用使用统计设置页面授权,通过queryUsageStats获取历史使用记录来验证前台应用。
二、检测返回主页操作
返回主页本质是切换到系统Launcher应用,所以同样可以用AccessibilityService实现:
- 核心逻辑:先获取系统默认Launcher的包名,然后在窗口切换事件中判断当前包名是否等于Launcher包名,若是则判定用户返回了主页。
- 代码示例:
private String getSystemLauncherPackage(Context context) { Intent homeIntent = new Intent(Intent.ACTION_MAIN); homeIntent.addCategory(Intent.CATEGORY_HOME); ResolveInfo resolveInfo = context.getPackageManager() .resolveActivity(homeIntent, PackageManager.MATCH_DEFAULT_ONLY); return resolveInfo.activityInfo.packageName; }
在onAccessibilityEvent中加入判断:
String launcherPackage = getSystemLauncherPackage(this); if (currentPackage.equals(launcherPackage)) { // 用户返回了主页,执行对应逻辑 }
三、AppLocker风格的PIN锁浮层实现
要在应用启动时弹出PIN锁浮层,需要借助WindowManager创建悬浮窗,适配Android 12+的权限要求:
- 权限要求:申请
android.permission.SYSTEM_ALERT_WINDOW权限,Android 10+需要引导用户到设置页面开启“显示在其他应用上层”权限。 - 实现步骤:
- 当检测到目标应用启动时,通过
LayoutInflater加载PIN锁布局。 - 配置
WindowManager.LayoutParams,设置type为TYPE_APPLICATION_OVERLAY(Android 8+推荐),确保浮层能覆盖在目标应用之上。 - 添加PIN验证逻辑,验证通过后移除浮层,允许用户操作应用;验证失败则保持浮层显示。
- 当检测到目标应用启动时,通过
- 简化版代码示例:
private void showPinLockOverlay(Context context) { WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); View pinLockView = LayoutInflater.from(context).inflate(R.layout.layout_pin_lock, null); WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN, PixelFormat.TRANSLUCENT ); params.gravity = Gravity.CENTER; windowManager.addView(pinLockView, params); // 这里添加PIN输入验证逻辑,验证通过后移除浮层 // windowManager.removeView(pinLockView); }
- 注意事项:要处理屏幕旋转、多窗口模式下的浮层适配,避免出现错位或失效的情况。
四、关键权限的引导逻辑
这类应用的权限都是需要用户手动授权的,一定要做友好的引导:
- 辅助功能权限:跳转到
Settings.ACTION_ACCESSIBILITY_SETTINGS页面引导用户开启。 - 悬浮窗权限:跳转到
Settings.ACTION_MANAGE_OVERLAY_PERMISSION页面引导用户授权。 - 应用使用统计权限:跳转到
Settings.ACTION_USAGE_ACCESS_SETTINGS页面引导用户开启。
这些方案都是目前Play商店中同类应用的主流实现方式,完全适配Android 12及以上的API规范,你可以根据自己的需求组合调整。
内容的提问来源于stack exchange,提问作者Abdo Getrick




