2017-05-05 31 views
11

如何检查是否有任何系统dialog(如下面的那个或USSD)在Android中显示?如何确定是否显示任何系统对话框?

airplane mode switching dialog

编程方式或CMD根呢? 任何变体。

+2

“系统对话框”只是一个活动,就像任何其他活动一样。没有任何魔法使一个活动成为“系统对话框”,另一个不是“系统对话框”。所以,你首先需要为自己决定“系统对话”和其他一些以对话为主题的活动之间的区别特征。 – CommonsWare

+0

我的意思是类似于关于“飞机模式开启或关闭”或ussd消息或类似东西的消息... – Andreyua

回答

2

系统对话框是一个活动。您可以使用ActivityManager通过顶级活动类名称来检测它。

final ActivityManager manager = (ActivityManager) context 
    .getSystemService(Activity.ACTIVITY_SERVICE); 

与API级别小于23(M)设备:

final List<ActivityManager.RunningTaskInfo> runningTasks = manager.getRunningTasks(1); 
final ComponentName componentName = runningTasks.get(0).topActivity; 
final String className = componentName.getClassName(); 

if (className.equals("YOUR_EXPECTED_ACTIVITY_CLASS_NAME")) { 
    // do something 
} 

在较新的设备:

final List<ActivityManager.AppTask> appTasks = manager.getAppTasks(); 
final ComponentName componentName = appTasks.get(0).getTaskInfo().topActivity; 
final String className = componentName.getClassName(); 

if (className.equals("YOUR_EXPECTED_ACTIVITY_CLASS_NAME")) { 
    // do something 
} 

或在这种情况下,您可以检查设备是否在在开始活动之前的飞行模式:

private boolean isAirplaneModeOn(final Context context) { 
    final int airplaneMode = Settings.System.getInt(
     context.getContentResolver(), 
     Settings.System.AIRPLANE_MODE_ON, 
     0 
    ); 

    return airplaneMode != 0; 
} 

... 

if (!isAirplaneModeOn(this)) { 
    // do something 
} 
+0

谢谢你的努力。但不幸的是,你的选择不适合我。在我的情况下,className总是等于我的主要活动类名称。我之前检查过你的方法,他们甚至都没有为我工作。这就是我问这个问题的原因。 另外,您的isAirplaneModeOn方法不是我所需要的。我只需要跟踪AirplaneMode对话框的外观。 我会投你的答案,但我不能接受它。抱歉。 – Andreyua

+0

我的测试代码: https://gist.github.com/goodandrewsoft/b961c2b6cfc6666bcbbb2a617f6f8d9e – Andreyua

+0

对不起,我误解了。 –

3

理论上你可以使用AccessibilityService来做到这一点,但它很复杂,可能会或可能不会在不同的设备上工作。用户需要为应用程序手动启用辅助功能。您可以在任何窗口打开时从Android获取回调,然后可以询问窗口以确定它是否包含特定文本或属于特定包等。这是一种“暴力”方法,但它可能很有用在某些情况下。

+0

类似的东西http://stackoverflow.com/a/32251469/3478155? – Andreyua

2

您的问题让我想到了Android 6+中的权限管理所使用的解决方案。尝试设置权限时,如果Toast或系统警报对话框打开,您是否曾见过错误消息? Android "Screen Overlay Detected" message if user is trying to grant a permission when a notification is showing

他们这样做的方式是通过覆盖Activity中的dispatchTouchEvent方法。这可以检查是否有任何东西在拦截触摸事件。您可以将您的特殊活动作为您应用中任何想要检测任何叠加层的活动的基类。

@Override 
    public boolean dispatchTouchEvent(MotionEvent event) { 
     mObscured = (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0; 
    return super.dispatchTouchEvent(event); 
} 

添加一个公共的方法来检查,在任何给定的时间,如果你的活动被遮挡

public boolean isObscured() { 
    return mObscured; 
} 

你应该要小心 - 因为它不是从问题明确 -​​ 如果从系统的第二活动或特权应用程序位于堆栈的前端,那么您自己的活动将不再接收触摸事件。这是为了捕获可能共享视图层次的碎片,吐司,浮动小部件和其他项目。

+0

不幸的是,不要在kitkat上工作 – Andreyua