Android 悬浮窗适配问题
目录
- 最近在做悬浮窗相关功能,关于悬浮窗权限问题做一下版本区分的讲解,着急使用的可以直接去完整代码看
- 版本号>=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 悬浮窗适配问题相关推荐
- Android悬浮窗适配全机型,包含8.0,小米魅族华为悬浮窗权限适配demo看这一篇就够了
机型多杂,适配无法完全兼容,不如换种实现方式,性能比悬浮窗好,不需要权限,效果更好:https://blog.csdn.net/m0_38058826/article/details/10399339 ...
- android适配华为m5,2019-05-29 Android悬浮窗适配全机型,包含8.0,小米魅族华为悬浮窗权限适配demo看这一篇就够了...
兼容8.0,小米,魅族,华为等难适配机型都可完美适配. 悬浮窗插入接口 在实现悬浮窗之前,我们需要知道通过什么接口,能够将一个控件放入到屏幕中去. Android的界面绘制,都是通过WindowMan ...
- Android悬浮窗适配,无需权限适配全机型,最简单最高性能的实现全局显示圆形悬浮
github:https://github.com/feiyuu/FloatingView 适配方式就是不用悬浮窗,弹框之类的,在每个页面顶层添加布局.缺点是不能退出app后在手机桌面显示. 想做桌面 ...
- Android 悬浮窗权限各机型各系统适配大全(总结)
原文链接:点击打开链接 ======================================================================================== ...
- Android 悬浮窗权限各机型各系统适配大全
这篇博客主要介绍的是 Android 主流各种机型和各种版本的悬浮窗权限适配,但是由于碎片化的问题,所以在适配方面也无法做到完全的主流机型适配,这个需要大家的一起努力,这个博客的名字永远都是一个将来时 ...
- Android悬浮窗开启 适配所有机型(附源码)
Android悬浮窗开启 适配所有机型(附源码) 1.开启悬浮窗权限 清单文件中添加: <uses-permission android:name="android.permissio ...
- Android 悬浮窗,绝对是目前相关悬浮窗开源库最完美的适配方案
PerfectFloatWindow 项目地址:Alonsol/PerfectFloatWindow 简介: android 全局悬浮窗,目前已经适配华为,小米,vivo,oppo,一加,三星,魅族, ...
- Android悬浮窗的实现
Android悬浮窗的实现 *本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 本文也发布于本人的知乎文章:https://zhuanlan.zhihu.com/p/39421112 ...
- Android悬浮窗原理解析(Window)[源码]
悬浮窗,在大多数应用中还是很少见的,目前我们接触到的悬浮窗,差不多都是一些系统级的应用软件,例如:360安全卫士,腾讯手机管家等:在某些服务行业如金融,餐饮等,也会在应用中添加悬浮窗,例如:美团的偷红 ...
最新文章
- 怎么远程虚拟机中的mysql_如何从本地远程访问虚拟机内的Mysql服务器?
- mSystems:华中农大郝秀丽组发现稀有/丰富微生物类群对镉污染土壤改良剂的不同反应!...
- NYOJ 305 表达式求值
- Protobuf之proto文件编写规则
- JAVA 抽象与接口的区别与联系
- ASP.NET开发资源
- Linux0.11 kernel/exit.c中的free_page_tables()
- Mysql解决存入表情报错的问题,调整编码为utf8mb4
- No rule to make target `/usr/lib/arm-linux-gnueabihf/libopencv_videostab.so.2.4.8'
- poj 2309 BST 使用树状数组的lowbit
- Jmeter基础篇(01):如何进行post接口压力测试
- 华为设备配置备份,配置文件导入导出,设备配置恢复,设备镜像上传
- win10+VS2017+DX11踩的那些雷
- MySQL5.7 Group Replication (MGR)
- HTML5游戏引擎(二)01-egret引擎的安装与hello world
- sirikit_iOS 12 Siri捷径SiriKit
- 银行储蓄系统 类图 顺序图 E_R图 功能结构图 数据流图 系统流图 逻辑结构设计 关系模式 数据关系表
- 3dmax 管子动画_3DMax水管里流水的动画怎么做呢?
- python判断一个数是奇数还是偶数_在python中检查一个数字是奇数还是偶数
- 6.信息论(一):信息量、熵和最优编码