Facebook,Evernote,Pocket - 所有应用程序都会自动在Android 6.0上获得此权限,即使它们的目标是23(targetSdkVersion=23).
关于新的Marshmallow权限模型有很多文档.其中一个SYSTEM_ALERT_WINDOW被"提升"为"高于危险"的权限级别,因此需要特殊的用户干预才能授予应用程序这些权限.如果应用程序有targetSdkVersion22或更低,app会自动获得此权限(如果在清单中请求).
但是,我注意到一些获得此权限的应用程序,无需将用户发送到设置特殊页面的Draw over other apps权限.我看到Facebook,Evernote,Pocket - 也许还有更多.
任何人都知道在没有用户通过的情况下如何授予应用程序此权限Settings -> Apps -> Draw over other apps?
谢谢
android android-permissions target-sdk system-alert-window android-6.0-marshmallow
我有一个函数,当触发时,成功显示一个DialogFragment与以下代码
DialogFragment
DialogFragment dialog;
View dialogView;
Context activityContext;
...
dialog = new DialogFragment(){
@Override public Dialog onCreateDialog(Bundle savedInstanceState) {
dialogView = getActivity().getLayoutInflater().inflate(R.layout.customView, null);
...
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setView(dialogView);
return builder.create();
}
};
dialog.show(activityContext.getSupportFragmentManager() , "MyDialog");
Run Code Online (Sandbox Code Playgroud)
问题是,在我添加一个带有以下代码的系统警报窗口后,DialogFragment不再显示,但是如果我传递到另一个应用程序,当我的应用程序最小化时,我可以看到DialogFragment,同时它减小了它的大小
系统警报窗口
WindowManager mWindowManager;
WindowManager.LayoutParams params;
...
mWindowManager = (WindowManager)activityContext.getSystemService(Context.WINDOW_SERVICE);
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT
}
params.gravity = Gravity.CENTER_VERTICAL | Gravity.RIGHT;
addView(((LayoutInflater)activityContext.getSystemService("layout_inflater")).inflate(R.layout.floatingBotton, null));
Run Code Online (Sandbox Code Playgroud)
那么......为什么我不能在顶部看到我的对话框(据我所知,对话框正在显示)为什么它只在显示系统警报窗口时发生
我已尝试使用系统警报窗口的其他标志,但我遇到了与我尝试过的问题相同的问题
android android-dialogfragment dialogfragment system-alert-window
我记得曾经(在谷歌的一个视频中)告诉我,如果应用程序的先前版本更新为在新版本上拥有targetSdk 23,那么之前授予的所有权限 - 现在都将被授予.
因此,例如,如果你安装了一个带有targetSdk 22的应用程序,那需要一个从联系人那里读取的权限,那么即使在升级了应用程序之后,使用targetSdk 23,也会保持这种状态.
原因很简单:用户在安装时已经授予了权限.
根据我的发现,这个规则有一个例外:
如果您的应用具有SYSTEM_ALERT_WINDOW权限,现在您升级到targetSdk 23,它将被撤销(重置),您需要从该用户请求它.
在文档中的任何位置都没有提到此行为:
而且在我看过的任何视频中都没有.
关于SYSTEM_ALERT_WINDOW权限,唯一提到的是你需要以不同的方式处理它们,使用ACTION_MANAGE_OVERLAY_PERMISSION来请求权限,以及Settings.canDrawOverlays(...)来检查是否授予了权限
我试图联系Google了解这个问题,他们说这是故意的:
我与开发团队进行了交谈,您看到的行为正如预期的那样.这在此处记录:http: //developer.android.com/reference/android/Manifest.permission.html#SYSTEM_ALERT_WINDOW
在Android M中提出了SYSTEM_ALERT_WINDOW的保护级别.
是否有其他权限具有此行为?
如果应用程序有targetSdk 22/23,并且操作系统升级到Android 6,会发生什么?SYSTEM_ALERT_WINDOW(或任何其他权限)是否会被撤销?
很确定其他东西会被授予,但我还是想问:其他类似特权的功能如何:SAF,管理,使用访问,辅助功能访问,通知访问,......?
编辑:关于#2,这是谷歌的答案(链接在这里):
在操作系统升级时,应用程序应保留SYSTEM_ALERT_WINDOW.默认情况下,Pre-API 23应用程序具有权限,而默认情况下禁用API 23应用程序.但是,有一个已知的错误,对于API 23应用程序,它们在升级时会丢失SYSTEM_ALERT_WINDOW.对开发人员的建议是始终在开始时检查SYSTEM_ALERT_WINDOW的状态,如果未授予,则将用户定向到"设置".我们将在未来的版本中修复该问题.
permissions android system-alert-window android-6.0-marshmallow
首先是我的问题的一些背景:我正在尝试创建一个系统覆盖类型视图(即在其他应用程序上绘制),它(目前)只是全屏纯色。我通过启动/停止服务来打开/关闭它。
这是我的代码到目前为止的样子(在服务内部):
public void onCreate() {
super.onCreate();
oView = new LinearLayout(this);
oView.setBackgroundColor(0x66ffffff);
PorterDuffColorFilter fil = new PorterDuffColorFilter(0xfff5961b, PorterDuff.Mode.MULTIPLY);
oView.getBackground().setColorFilter(fil);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
0 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT);
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.addView(oView, params);
}
Run Code Online (Sandbox Code Playgroud)
这样,当我启动此服务时,我可以在其余的常规 android 使用中获得纯色。现在,我的具体问题是: 有什么方法可以使这种颜色在其背后的常规 android 使用中进行 MULTIPLY(想想 photoshop 混合模式)?
从我的代码中可以看出,我也尝试使用 PorterDuff 过滤器模式(它们的几种不同组合)来实现它,但徒劳无功。
这里有几个截图,希望能更好地解释这一点:
<-- 在同一屏幕上的预期结果。注意较深的颜色是如何叠加到下面的。
如您所见,我当前的代码仅抛出了一层纯色。我感谢所有的建议。提前致谢!
SAW(系统警报窗口)权限可用于在其他应用程序之上绘制内容。
很久以前我就被告知无障碍服务也可以做到这一点,但我从未找到任何教程、示例、文档,甚至一个应用程序可以做到这一点......直到最近:
https://play.google.com/store/apps/details?id=com.github.ericytsang.screenfilter.app.android
事实上,这个应用程序似乎能够在任何地方绘图,而不是 SAW 许可。它甚至在设置应用程序和系统对话框之上绘制,而 SAW 权限是不允许的。
遗憾的是,由于可访问性是一个非常独特且很少使用的东西,正如我所写的,我无法找到这样的东西如何与其他应用程序之上的绘图一起使用。
我唯一知道的是这个应用程序以某种方式做到了这一点,这就是它在要求授予它时显示的内容:
但这还不够。我知道对于我使用辅助服务制作的一些旧 POC,它显示了相同的内容,并且检查它,我看不出是什么触发了它。很确定这是用户在任何类型的无障碍服务中都会看到的最小的东西,所以这没有帮助。
AccessibilityService 如何在其他应用程序之上进行绘制?
它与 SAW 许可的作用相同吗?例如,您可以处理其绘制内容的触摸事件吗?
如果有的话,使用它有哪些限制?
我知道有一种方法可以检测某些应用程序是否覆盖了我的应用程序,即触摸过滤(标记android:filterTouchesWhenObscured)以防止劫持攻击.如果要创建一些策略来处理触摸,可以覆盖该方法
public boolean onFilterTouchEventForSecurity(MotionEvent event)
视图.例如,如果您的应用被其他窗口遮挡,则需要显示一些对话框.但是,如果用户触摸视图,您可以执行所有这些解决方案.我想在用户打开应用程序时显示一些对话框.可能吗?此外,我尝试模拟触摸事件,但我不知道在哪里可以获得MotionEvent.FLAG_WINDOW_IS_OBSCURED,然后设置为运动事件标志.
第二个问题:有没有办法说出什么应用程序模糊我的应用程序?例如,我知道有很多应用程序,例如黄昏,在显示器上添加了一些过滤器.他们使用特定权限(android.permission.SYSTEM_ALERT_WINDOW)来执行此操作.
谢谢.
我希望能够检测我的活动是否被系统警报或其他叠加层(例如,长按电源按钮时的电源菜单)或检测到我的启动的恶意软件所遮盖活动。我注意到在这种情况下,前台应用程序仍将是我的应用程序,因此我不能简单地将其作为前台应用程序。我还注意到,当我的活动被遮盖时,不会调用onPause(),因此我也无法在onPause()中放入任何逻辑。即使可以,我也必须区分系统警报/覆盖和用户按下“后退” /“主页”按钮。
我还有其他方法可以做到这一点吗?
我正在尝试从这个答案中发出代码来检查是否启用了权限.但即使从设置启用了权限,它也会返回false.
public static boolean canDrawOverlayViews(Context con){
if(Build.VERSION.SDK_INT< Build.VERSION_CODES.LOLLIPOP){return true;}
try {
return Settings.canDrawOverlays(con);
}
catch(NoSuchMethodError e){
return canDrawOverlaysUsingReflection(con);
}
}
public static boolean canDrawOverlaysUsingReflection(Context context) {
try {
AppOpsManager manager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
Class clazz = AppOpsManager.class;
Method dispatchMethod = clazz.getMethod("checkOp", new Class[] { int.class, int.class, String.class });
//AppOpsManager.OP_SYSTEM_ALERT_WINDOW = 24
int mode = (Integer) dispatchMethod.invoke(manager, new Object[] { 24, Binder.getCallingUid(), context.getApplicationContext().getPackageName() });
return AppOpsManager.MODE_ALLOWED == mode;
} catch (Exception e) { return false; }
}
Run Code Online (Sandbox Code Playgroud) 我正在开发一个使用 SYSTEM_ALERT_WINDOW 权限的应用程序。我已将权限添加到清单中。
在我的活动中,我添加了以下代码以在运行时请求许可。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Intent myIntent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
startActivityForResult(myIntent, 5469);
}
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 5469: {
Toast.makeText(this,"Permission Granted!",Toast.LENGTH_SHORT).show();
return;
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,当“绘制其他应用程序”设置页面打开时,允许权限的“切换按钮”变灰(不可点击)。
下面给出的是屏幕截图:
清单代码:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.graphics.unlockbrtest">
<application …Run Code Online (Sandbox Code Playgroud) 如何创建可以像 Facebook 通知一样在整个屏幕上移动的浮动内容?
android drag-and-drop android-windowmanager system-alert-window