目录

  • 最近在做悬浮窗相关功能,关于悬浮窗权限问题做一下版本区分的讲解,着急使用的可以直接去完整代码看
    • 版本号>=23
        • 大家最常用的就是获取是否有悬浮窗权限,如果没有就去开启
        • 但是, Vivo是特例,在vivo x20 plusA Android8.1.0的获取到的权限一直是true,但是并没有开启悬浮窗权限,所以需要单端判断是否有权限
        • 不仅如此,vivo获取悬浮窗权限也比较特殊.前面虽然判断出来没有权限了,但是开启悬浮窗权限的intent也不生效,需要再次区分判断.
      • 以上就是vivo手机的适配~
    • 版本号<23
      • 还有Android系统低于26的,我们的最低版本是5.0,所以低于5.0的就不考虑了,嘎嘎~
      • 因为5.0没有直接进入悬浮窗权限页面的intent,所以我目前进入的是项目对应的设置信息
    • 完整代码
      • 判断是否有悬浮窗权限
      • 申请权限
    • 在此希望各大平台最好遵循一定的规范,非必要,不要搞额外的特殊.统一规则,对于应用的适配,用户的体验都是一种享受

最近在做悬浮窗相关功能,关于悬浮窗权限问题做一下版本区分的讲解,着急使用的可以直接去完整代码看

版本号>=23

大家最常用的就是获取是否有悬浮窗权限,如果没有就去开启

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {// 判断是否有悬浮窗权限,版本号>= 23才可return Settings.canDrawOverlays(context);}// 如果没有权限就去申请开启权限if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {try {val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)intent.data = Uri.parse("package:" + context?.packageName)startActivityForResult(intent, REQUEST_CODE)} catch (e: Exception) {L.d(e.message)}}

但是, Vivo是特例,在vivo x20 plusA Android8.1.0的获取到的权限一直是true,但是并没有开启悬浮窗权限,所以需要单端判断是否有权限

public static boolean hasFloatFirstPermission(Context context) {if (context != null) {String packageName = context.getPackageName();try {Cursor query = context.getContentResolver().query(Uri.parse("content://com.iqoo.secure.provider.secureprovider/allowfloatwindowapp"), null,"pkgname = ?", new String[] {packageName}, null);if (query == null) {return hasFloatSecondPermission(context);}query.getColumnNames();if (query.moveToFirst()) {int i = query.getInt(query.getColumnIndex("currentlmode"));query.close();if (i == 0) {return true;}return false;}query.close();return hasFloatSecondPermission(context);} catch (Exception unused) {return hasFloatSecondPermission(context);}} else {throw new IllegalArgumentException("context is null");}}
/*** 判断vivo数据库*/public static boolean hasFloatSecondPermission(Context context) {String packageName = context.getPackageName();try {Cursor query = context.getContentResolver().query(Uri.parse("content://com.vivo.permissionmanager.provider.permission/float_window_apps"),null, "pkgname = ?", new String[] {packageName}, null);if (query != null) {if (query.moveToFirst()) {int i = query.getInt(query.getColumnIndex("currentmode"));query.close();if (i == 0) {return true;}return false;}query.close();}} catch (Exception unused) {}return false;}

不仅如此,vivo获取悬浮窗权限也比较特殊.前面虽然判断出来没有权限了,但是开启悬浮窗权限的intent也不生效,需要再次区分判断.

public static boolean viVoFloatRequest(Activity context, int requestCode) {try {String str = Build.MODEL;if ((!str.contains("Y85") || str.contains("Y85A")) && !str.contains("vivo Y53L") && !str.contains("vivo Y67A")) {Intent intent = new Intent();intent.setClassName("com.vivo.permissionmanager","com.vivo.permissionmanager.activity.SoftPermissionDetailActivity");intent.setAction("secure.intent.action.softPermissionDetail");intent.putExtra("packagename", context.getPackageName());context.startActivityForResult(intent, requestCode);} else {Intent intent2 = new Intent();intent2.setClassName("com.vivo.permissionmanager","com.vivo.permissionmanager.activity.PurviewTabActivity");intent2.putExtra("packagename", context.getPackageName());intent2.putExtra("tabId", "1");context.startActivityForResult(intent2, requestCode);}return true;} catch (Exception unused) {try {Intent intent = getRightIntent(context);if (intent != null) {context.startActivityForResult(intent, requestCode);return true;}} catch (Exception unused2) {}return false;}}/*** 获取符合条件的intent*/public static Intent getRightIntent(Context context) {List<Intent> intentList = getIntentList(context);if (intentList.isEmpty()) {return null;}for (Intent intent : intentList) {if (hasIntent(context, intent)) {return intent;}}return null;}/*** 获取intentList*/public static List<Intent> getIntentList(Context context) {ArrayList arrayList = new ArrayList();Intent intent = new Intent();intent.putExtra("packagename", context.getPackageName());intent.setComponent(new ComponentName("com.vivo.permissionmanager","com.vivo.permissionmanager.activity.SoftPermissionDetailActivity"));arrayList.add(intent);Intent intent2 = new Intent();intent2.putExtra("packagename", context.getPackageName());intent2.setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.FloatWindowManager"));arrayList.add(intent2);Intent intent3 = new Intent();intent3.setComponent(new ComponentName("com.vivo.permissionmanager","com.vivo.permissionmanager.activity.PurviewTabActivity"));arrayList.add(intent3);Intent intent4 = new Intent();intent4.setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.MainActivity"));arrayList.add(intent4);Intent intent5 = new Intent();intent5.setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.MainGuideActivity"));arrayList.add(intent5);return arrayList;}@SuppressLint({"WrongConstant"})public static boolean hasIntent(Context context, Intent intent) {return context.getPackageManager().queryIntentActivities(intent, 4096).size() > 0;}

以上就是vivo手机的适配~

版本号<23

还有Android系统低于26的,我们的最低版本是5.0,所以低于5.0的就不考虑了,嘎嘎~

因为5.0没有直接进入悬浮窗权限页面的intent,所以我目前进入的是项目对应的设置信息

val intent = Intent()intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGSintent.data = Uri.parse("package:" + context?.packageName)startActivityForResult(intent, REQUEST_CODE)

完整代码

判断是否有悬浮窗权限

 public static boolean canDrawOverlays(Context context) {// 判断是否是vivo系统,特立独行的猪,单独判断悬浮窗权限if (RomUtils.isVivo()) {return hasFloatFirstPermission(context);} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {return Settings.canDrawOverlays(context);} else {try {Class cls = Class.forName("android.content.Context");Field declaredField = cls.getDeclaredField("APP_OPS_SERVICE");declaredField.setAccessible(true);Object obj = declaredField.get(cls);if (!(obj instanceof String)) {return false;}String str2 = (String) obj;obj = cls.getMethod("getSystemService", String.class).invoke(context, str2);cls = Class.forName("android.app.AppOpsManager");Field declaredField2 = cls.getDeclaredField("MODE_ALLOWED");declaredField2.setAccessible(true);Method checkOp = cls.getMethod("checkOp", Integer.TYPE, Integer.TYPE, String.class);int result = (Integer) checkOp.invoke(obj, 24, Binder.getCallingUid(), context.getPackageName());return result == declaredField2.getInt(cls);} catch (Exception e) {return false;}}}/*** 判断igoo数据库权限*/public static boolean hasFloatFirstPermission(Context context) {if (context != null) {String packageName = context.getPackageName();try {Cursor query = context.getContentResolver().query(Uri.parse("content://com.iqoo.secure.provider.secureprovider/allowfloatwindowapp"), null,"pkgname = ?", new String[] {packageName}, null);if (query == null) {return hasFloatSecondPermission(context);}query.getColumnNames();if (query.moveToFirst()) {int i = query.getInt(query.getColumnIndex("currentlmode"));query.close();if (i == 0) {return true;}return false;}query.close();return hasFloatSecondPermission(context);} catch (Exception unused) {return hasFloatSecondPermission(context);}} else {throw new IllegalArgumentException("context is null");}}/*** 判断vivo数据库*/public static boolean hasFloatSecondPermission(Context context) {String packageName = context.getPackageName();try {Cursor query = context.getContentResolver().query(Uri.parse("content://com.vivo.permissionmanager.provider.permission/float_window_apps"),null, "pkgname = ?", new String[] {packageName}, null);if (query != null) {if (query.moveToFirst()) {int i = query.getInt(query.getColumnIndex("currentmode"));query.close();if (i == 0) {return true;}return false;}query.close();}} catch (Exception unused) {}return false;}public static boolean viVoFloatRequest(Activity context, int requestCode) {try {String str = Build.MODEL;if ((!str.contains("Y85") || str.contains("Y85A")) && !str.contains("vivo Y53L") && !str.contains("vivo Y67A")) {Intent intent = new Intent();intent.setClassName("com.vivo.permissionmanager","com.vivo.permissionmanager.activity.SoftPermissionDetailActivity");intent.setAction("secure.intent.action.softPermissionDetail");intent.putExtra("packagename", context.getPackageName());context.startActivityForResult(intent, requestCode);} else {Intent intent2 = new Intent();intent2.setClassName("com.vivo.permissionmanager","com.vivo.permissionmanager.activity.PurviewTabActivity");intent2.putExtra("packagename", context.getPackageName());intent2.putExtra("tabId", "1");context.startActivityForResult(intent2, requestCode);}return true;} catch (Exception unused) {try {Intent intent = getRightIntent(context);if (intent != null) {context.startActivityForResult(intent, requestCode);return true;}} catch (Exception unused2) {}return false;}}/*** 获取符合条件的intent*/public static Intent getRightIntent(Context context) {List<Intent> intentList = getIntentList(context);if (intentList.isEmpty()) {return null;}for (Intent intent : intentList) {if (hasIntent(context, intent)) {return intent;}}return null;}/*** 获取intentList*/public static List<Intent> getIntentList(Context context) {ArrayList arrayList = new ArrayList();Intent intent = new Intent();intent.putExtra("packagename", context.getPackageName());intent.setComponent(new ComponentName("com.vivo.permissionmanager","com.vivo.permissionmanager.activity.SoftPermissionDetailActivity"));arrayList.add(intent);Intent intent2 = new Intent();intent2.putExtra("packagename", context.getPackageName());intent2.setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.FloatWindowManager"));arrayList.add(intent2);Intent intent3 = new Intent();intent3.setComponent(new ComponentName("com.vivo.permissionmanager","com.vivo.permissionmanager.activity.PurviewTabActivity"));arrayList.add(intent3);Intent intent4 = new Intent();intent4.setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.MainActivity"));arrayList.add(intent4);Intent intent5 = new Intent();intent5.setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.MainGuideActivity"));arrayList.add(intent5);return arrayList;}@SuppressLint({"WrongConstant"})public static boolean hasIntent(Context context, Intent intent) {return context.getPackageManager().queryIntentActivities(intent, 4096).size() > 0;}

申请权限

private fun getSuspendedPermission() {if (!PermissionUtils.canDrawOverlays(context)) {if (RomUtils.isVivo()) {PermissionUtils.viVoFloatRequest(activity, REQUEST_CODE)return}if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {try {val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)intent.data = Uri.parse("package:" + context?.packageName)startActivityForResult(intent, REQUEST_CODE)} catch (e: Exception) {L.d(e.message)}} else {val intent = Intent()intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGSintent.data = Uri.parse("package:" + context?.packageName)startActivityForResult(intent, REQUEST_CODE)}}}

在此希望各大平台最好遵循一定的规范,非必要,不要搞额外的特殊.统一规则,对于应用的适配,用户的体验都是一种享受

Android 悬浮窗适配问题相关推荐

  1. Android悬浮窗适配全机型,包含8.0,小米魅族华为悬浮窗权限适配demo看这一篇就够了

    机型多杂,适配无法完全兼容,不如换种实现方式,性能比悬浮窗好,不需要权限,效果更好:https://blog.csdn.net/m0_38058826/article/details/10399339 ...

  2. android适配华为m5,2019-05-29 Android悬浮窗适配全机型,包含8.0,小米魅族华为悬浮窗权限适配demo看这一篇就够了...

    兼容8.0,小米,魅族,华为等难适配机型都可完美适配. 悬浮窗插入接口 在实现悬浮窗之前,我们需要知道通过什么接口,能够将一个控件放入到屏幕中去. Android的界面绘制,都是通过WindowMan ...

  3. Android悬浮窗适配,无需权限适配全机型,最简单最高性能的实现全局显示圆形悬浮

    github:https://github.com/feiyuu/FloatingView 适配方式就是不用悬浮窗,弹框之类的,在每个页面顶层添加布局.缺点是不能退出app后在手机桌面显示. 想做桌面 ...

  4. Android 悬浮窗权限各机型各系统适配大全(总结)

    原文链接:点击打开链接 ======================================================================================== ...

  5. Android 悬浮窗权限各机型各系统适配大全

    这篇博客主要介绍的是 Android 主流各种机型和各种版本的悬浮窗权限适配,但是由于碎片化的问题,所以在适配方面也无法做到完全的主流机型适配,这个需要大家的一起努力,这个博客的名字永远都是一个将来时 ...

  6. Android悬浮窗开启 适配所有机型(附源码)

    Android悬浮窗开启 适配所有机型(附源码) 1.开启悬浮窗权限 清单文件中添加: <uses-permission android:name="android.permissio ...

  7. Android 悬浮窗,绝对是目前相关悬浮窗开源库最完美的适配方案

    PerfectFloatWindow 项目地址:Alonsol/PerfectFloatWindow 简介: android 全局悬浮窗,目前已经适配华为,小米,vivo,oppo,一加,三星,魅族, ...

  8. Android悬浮窗的实现

    Android悬浮窗的实现 *本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 本文也发布于本人的知乎文章:https://zhuanlan.zhihu.com/p/39421112 ...

  9. Android悬浮窗原理解析(Window)[源码]

    悬浮窗,在大多数应用中还是很少见的,目前我们接触到的悬浮窗,差不多都是一些系统级的应用软件,例如:360安全卫士,腾讯手机管家等:在某些服务行业如金融,餐饮等,也会在应用中添加悬浮窗,例如:美团的偷红 ...

最新文章

  1. 怎么远程虚拟机中的mysql_如何从本地远程访问虚拟机内的Mysql服务器?
  2. mSystems:华中农大郝秀丽组发现稀有/丰富微生物类群对镉污染土壤改良剂的不同反应!...
  3. NYOJ 305 表达式求值
  4. Protobuf之proto文件编写规则
  5. JAVA 抽象与接口的区别与联系
  6. ASP.NET开发资源
  7. Linux0.11 kernel/exit.c中的free_page_tables()
  8. Mysql解决存入表情报错的问题,调整编码为utf8mb4
  9. No rule to make target `/usr/lib/arm-linux-gnueabihf/libopencv_videostab.so.2.4.8'
  10. poj 2309 BST 使用树状数组的lowbit
  11. Jmeter基础篇(01):如何进行post接口压力测试
  12. 华为设备配置备份,配置文件导入导出,设备配置恢复,设备镜像上传
  13. win10+VS2017+DX11踩的那些雷
  14. MySQL5.7 Group Replication (MGR)
  15. HTML5游戏引擎(二)01-egret引擎的安装与hello world
  16. sirikit_iOS 12 Siri捷径SiriKit
  17. 银行储蓄系统 类图 顺序图 E_R图 功能结构图 数据流图 系统流图 逻辑结构设计 关系模式 数据关系表
  18. 3dmax 管子动画_3DMax水管里流水的动画怎么做呢?
  19. python判断一个数是奇数还是偶数_在python中检查一个数字是奇数还是偶数
  20. 6.信息论(一):信息量、熵和最优编码

热门文章

  1. 查询电脑本机ip地址 区分内网外网
  2. 表格、表单、HTML标记语言以及使用canvas来画图 input新属性
  3. vscode中文插件不生效问题解决
  4. 「Do.020」程序员该如何在寒冬中自处
  5. 【运维实战家】无线三建七优之设备选型-锐捷无线
  6. keystore生成 linux_linux下的keystore
  7. 如何完成Nexus 9开机后的激活流程
  8. Linux socket文件系统体现“一切皆文件”
  9. html引入babel-polyfill,babel-polyfill的引用和使用
  10. 高通平台开发板学习教程