api
checkPermission :检测权限是否授予
isOpenGPS :是否打开gps
isNotifyEnabled :获取是否有通知权限
isNotifyEnabled2 :获取是否有通知权限
startSetting :跳转设置(应用信息),会开启一个新的进程(点回退会回到桌面),使用startActivityForResult不可靠,跳转就会触发onActivityResult
startSettingActivity:打开设置页面(应用信息),和App在同一个进程
startNotifySetting :跳转到通知设置界面
utils
package com.kiwilss.lutils.utils.permission
import android.annotation.SuppressLint
import android.app.Activity
import android.app.AppOpsManager
import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.location.LocationManager
import android.net.Uri
import android.os.Build
import android.provider.Settings
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import java.lang.reflect.Field
import java.lang.reflect.Method
/**
*@author kiwilss
* @email kiwilss@163.com
* @time 2022/7/1
* @desc {权限相关工具类}
*/
object PermissionUtils {
const val SETTING_REQUESTCODE = 6666
private const val CHECK_OP_NO_THROW = "checkOpNoThrow"
private const val OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION"
/**
* 检测是否有权限
* @param context
* @param permissions
* @return
*/
fun checkPermission(context: Context?, vararg permissions: String?): Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true
} else {
if (context == null || permissions.isEmpty()) return false
for (permisson in permissions) {
permisson?.run {
if (ContextCompat.checkSelfPermission(
context,
this
) != PackageManager.PERMISSION_GRANTED
) {
return false
}
}
}
}
return true
}
/**
* 判断GPS是否开启,GPS或者AGPS开启一个就认为是开启的
*
* @param context
* @return true 表示开启
*/
fun isOpenGPS(context: Context?): Boolean {
if (context == null) return false
val locationManager: LocationManager =
context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
// 通过GPS卫星定位,定位级别可以精确到街(通过24颗卫星定位,在室外和空旷的地方定位准确、速度快)
var gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
// 通过WLAN或移动网络(3G/2G)确定的位置(也称作AGPS,辅助GPS定位。主要用于在室内或遮盖物(建筑群或茂密的深林等)密集的地方定位)
// boolean network = false;
// if (locationManager != null) {
// network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
// }
return gps
}
/**
* 跳转设置(应用信息),会开启一个新的进程(点回退会回到桌面),使用startActivityForResult不可靠,跳转就会触发onActivityResult
*
* @param context
*/
fun startSetting(context: Context?) {
context?.run {
try {
val intent = Intent()
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.action = "android.settings.APPLICATION_DETAILS_SETTINGS"
intent.data = Uri.fromParts("package", packageName, null)
startActivity(intent)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
/**
* 打开设置页面(应用信息),和App在同一个进程
*
* @param context
*/
fun startSettingActivity(context: Activity?, requestCode: Int = SETTING_REQUESTCODE) {
if (context == null) return
try {
val intent = Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse(
"package:" +
context.packageName
)
)
intent.addCategory(Intent.CATEGORY_DEFAULT)
context.startActivityForResult(
intent,
requestCode
) //这里的requestCode和onActivityResult中requestCode要一致
} catch (e: Exception) {
e.printStackTrace()
}
}
/**
* 打开设置页面(应用信息),和App在同一个进程
*
* @param context
*/
fun startSettingActivity(fragment: Fragment?, requestCode: Int = SETTING_REQUESTCODE) {
if (fragment == null) return
val context = fragment.context ?: return
try {
val intent = Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.parse(
"package:" +
context.packageName
)
)
intent.addCategory(Intent.CATEGORY_DEFAULT)
fragment.startActivityForResult(
intent,
requestCode
) //这里的requestCode和onActivityResult中requestCode要一致
} catch (e: Exception) {
e.printStackTrace()
}
}
/**
* 跳转到通知设置界面
*/
@SuppressLint("ObsoleteSdkInt")
fun startNotifySetting(context: Context?) {
if (context == null) return
// vivo 点击设置图标>加速白名单>我的app
// 点击软件管理>软件管理权限>软件>我的app>信任该软件
var appIntent = context.packageManager.getLaunchIntentForPackage("com.iqoo.secure")
if (appIntent != null) {
context.startActivity(appIntent)
return
}
// oppo 点击设置图标>应用权限管理>按应用程序管理>我的app>我信任该应用
// 点击权限隐私>自启动管理>我的app
appIntent = context.packageManager.getLaunchIntentForPackage("com.oppo.safe")
if (appIntent != null) {
context.startActivity(appIntent)
return
}
val intent = Intent()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
}
intent.putExtra("app_package", context.packageName)
intent.putExtra("app_uid", context.applicationInfo.uid)
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
intent.data = Uri.fromParts("package", context.packageName, null)
} else {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.action = Intent.ACTION_VIEW
intent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails")
intent.putExtra("com.android.settings.ApplicationPkgName", context.packageName)
}
context.startActivity(intent)
}
/**
* 获取是否有通知权限
*
* @param context
* @return
*/
fun isNotifyEnabled(context: Context?): Boolean {
if (context == null) return false
return NotificationManagerCompat.from(context).areNotificationsEnabled()
}
/**
* 获取是否有通知权限
*
* @param context
* @return
*/
fun isNotifyEnabled2(context: Context): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
isEnableV26(context)
} else {
isEnabledV19(context)
}
}
/**
* 8.0以下判断
*
* @param context api19 4.4及以上判断
* @return
*/
private fun isEnabledV19(context: Context): Boolean {
val mAppOps: AppOpsManager =
context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
val appInfo: ApplicationInfo = context.applicationInfo
val pkg = context.applicationContext.packageName
val uid: Int = appInfo.uid
var appOpsClass: Class<*>? = null
try {
appOpsClass = Class.forName(AppOpsManager::class.java.name)
val checkOpNoThrowMethod: Method = appOpsClass.getMethod(
CHECK_OP_NO_THROW,
Integer.TYPE, Integer.TYPE, String::class.java
)
val opPostNotificationValue: Field = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION)
val value = opPostNotificationValue.get(Int::class.java) as Int
return checkOpNoThrowMethod.invoke(mAppOps, value, uid, pkg) as Int ===
AppOpsManager.MODE_ALLOWED
} catch (e: java.lang.Exception) {
e.printStackTrace()
}
return false
}
/**
* 8.0及以上通知权限判断
*
* @param context
* @return
*/
private fun isEnableV26(context: Context): Boolean {
val appInfo: ApplicationInfo = context.applicationInfo
val pkg = context.applicationContext.packageName
val uid: Int = appInfo.uid
return try {
val notificationManager: NotificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val sServiceField: Method =
notificationManager.javaClass.getDeclaredMethod("getService")
sServiceField.setAccessible(true)
val sService: Any = sServiceField.invoke(notificationManager)
val method: Method = sService.javaClass.getDeclaredMethod(
"areNotificationsEnabledForPackage",
String::class.java,
Integer.TYPE
)
method.setAccessible(true)
method.invoke(sService, pkg, uid) as Boolean
} catch (e: java.lang.Exception) {
true
}
}
}
ktx
package com.kiwilss.lutils.utils.permission
import android.app.Activity
import android.content.Context
import androidx.fragment.app.Fragment
/**
*@author kiwilss
* @email kiwilss@163.com
* @time 2022/7/1
* @desc {权限扩展工具类}
*/
/**
* 检测是否有权限
*
* @param permission
* @return
*/
fun Context?.checkPermission(vararg permission: String?) = PermissionUtils.checkPermission(
this,
*permission
)
/**
* 是否打开gps
*
* @return
*/
fun Context?.isOpenGPS() = PermissionUtils.isOpenGPS(this)
/**
*跳转设置(应用信息),会开启一个新的进程(点回退会回到桌面),使用startActivityForResult不可靠,跳转就会触发onActivityResult
*/
fun Context?.startSetting() = PermissionUtils.startSetting(this)
/**
* 打开设置页面(应用信息),和App在同一个进程
*
* @param requestCode
*/
fun Activity?.startSettingActivity(requestCode: Int = PermissionUtils.SETTING_REQUESTCODE) =
PermissionUtils.startSettingActivity(this, requestCode)
/**
* 打开设置页面(应用信息),和App在同一个进程
*
* @param requestCode
*/
fun Fragment?.startSettingActivity(requestCode: Int = PermissionUtils.SETTING_REQUESTCODE) =
PermissionUtils.startSettingActivity(this, requestCode)
/**
*打开通知设置界面
*/
fun Context?.startNotifySetting() = PermissionUtils.startNotifySetting(this)
/**
*获取通知权限是否打开
*/
fun Context?.isNotifyEnabled() = PermissionUtils.isNotifyEnabled(this)
申请权限
申请单个权限
PermissionsHelper.init(this)
.requestEachPermissions(ACCESS_FINE_LOCATION, new IPermissionListenerWrap.IEachPermissionListener() {
@Override
public void onAccepted(Permission permission) {
if (permission.granted){
//同意
ALog.i(LUtils.tag(this),"grant");
}else if (permission.shouldShowRequestPermissionRationale){
//拒绝
ALog.i(LUtils.tag(this),"reject");
}else {
//拒绝并不再显示
ALog.i(LUtils.tag(this),"reject and not show");
}
}
});
申请多个权限
PermissionsHelper.init(this)
.requestPermissions(new String[]{ACCESS_FINE_LOCATION, RECORD_AUDIO}, new IPermissionListenerWrap.IPermissionListener() {
@Override
public void onAccepted(boolean isGranted, boolean allShould, List<String> rejects, List<String> shoulds) {
if (isGranted){
//全部同意
ALog.i(LUtils.tag(this),"grant");
}else if (allShould){
//有权限不同意
ALog.i(LUtils.tag(this),"reject:" + rejects);
}else {
//有权限不同意,并且设置了不再显示
ALog.i(LUtils.tag(this),"reject and not show : " + shoulds);
}
}
});