JPermissions權限請求框架

6.0以上動態權限

將系統權限區分為正常權限和危險權限。開發者在使用到危險權限相關的功能時,不僅需要在Manifest文件中配置,還需要在代碼中動態獲取權限

需要注意的幾個權限

  • 6.0以上需要檢測懸浮窗權限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

 /**
     * 是否有懸浮窗權限
     */
    static boolean isHasOverlaysPermission(Context context) {
        if (isOverMarshmallow()) {
            return Settings.canDrawOverlays(context);
        }
        return true;
    }

/**
     * 用于6.0懸浮窗權限請求
     */
 // 跳轉到允許安裝未知來源設置頁面
 Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:" + getActivity().getPackageName()));
 startActivityForResult(intent, getArguments().getInt(REQUEST_CODE));
  • 8.0以上需要檢測以下權限
//未知應用安裝權限
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>

 /**
     * 是否有安裝權限
     */
    static boolean isHasInstallPermission(Context context) {
        if (isOverOreo()) {
            return context.getPackageManager().canRequestPackageInstalls();
        }
        return true;
    }
/**
     * 用于8.0安裝第三方應用權限請求
     */
// 跳轉到懸浮窗設置頁面
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getActivity().getPackageName()));
startActivityForResult(intent, getArguments().getInt(REQUEST_CODE));

//允許您的應用通過編程方式接聽呼入電話。要在您的應用中處理呼入電話,您可以使用 acceptRingingCall() 函數。 
ANSWER_PHONE_CALLS 
//允許您的應用讀取設備中存儲的電話號碼。 
READ_PHONE_NUMBERS 

代碼

/**
 * justin
 * 危險權限請求類
 */
class JPermissions {
    private var mActivity:Activity
    private var mPermissions:MutableList<String> = ArrayList()
    private var mRequestAgain: Boolean = false

    private constructor(activity:Activity){
        mActivity = activity
    }

    companion object {
        /**
         * 設置請求的對象
         */
        fun with(activity: Activity): JPermissions {
            return JPermissions(activity)
        }

        /**
         * 檢查某些權限是否全部授予了
         *
         * @param context     上下文對象
         * @param permissions 需要請求的權限組
         */
        fun isHasPermission(context: Context, vararg permissions: String): Boolean {
            val failPermissions = PermissionUtils.getDeniedPermissions(context, Arrays.asList(*permissions))
            return failPermissions == null || failPermissions.isEmpty()
        }

        /**
         * 跳轉到應用權限設置頁面
         *
         * @param context 上下文對象
         */
        fun gotoPermissionSettings(context: Context) {
            PermissionSettingPage.start(context, false)
        }

        /**
         * 跳轉到應用權限設置頁面
         *
         * @param context 上下文對象
         * @param newTask 是否使用新的任務棧啟動
         */
        fun gotoPermissionSettings(context: Context, newTask: Boolean) {
            PermissionSettingPage.start(context, newTask)
        }

    }

    /**
     * 設置需要請求的權限
     */
    fun permissions(vararg permissions: String):JPermissions{
        mPermissions.addAll(permissions)
        return this
    }

    /**
     * 被拒絕后繼續申請,直到授權或者永久拒絕
     */
    fun requestAgain(): JPermissions {
        mRequestAgain = true
        return this
    }

    /**
     * 請求權限
     */
    fun requestPermissions(permissionResult:OnPermissionsResult) {
        // 如果沒有指定請求的權限,就使用清單注冊的權限進行請求
        if (mPermissions.isEmpty()) mPermissions = PermissionUtils.getManifestPermissions(mActivity)
        if (mPermissions.isEmpty()) throw IllegalArgumentException("The requested permission cannot be empty")
        if (mActivity == null) throw IllegalArgumentException("The activity is empty")
        if (permissionResult == null) throw IllegalArgumentException("The permission request callback interface must be implemented")
        val checkTargetSdkVersion = PermissionUtils.checkTargetSdkVersion(mActivity,mPermissions)
        if (!checkTargetSdkVersion) return
        val deniedPermissions = PermissionUtils.getDeniedPermissions(mActivity, mPermissions)
        //權限已經全部授予
        if (deniedPermissions.isEmpty()){
            permissionResult.agreePermission(mPermissions,true)
        }else{
            // 檢測權限有沒有在清單文件中注冊
            PermissionUtils.checkPermissionsIsInManifest(mActivity, mPermissions)
            // 申請沒有授予過的權限
            PermissionFragment.newInstance(ArrayList(mPermissions), mRequestAgain).prepareRequest(mActivity, permissionResult)
        }

    }

}
/**
 *   author:justin
 *   time:2019/04/22
 *   desc:權限請求處理類
 */
class PermissionFragment : Fragment, Runnable {
    
    constructor() : super()
    companion object {
        private val PERMISSIONS: String = "permissions" // 請求的權限
        private val REQUEST_CODE: String = "request_code" // 請求碼(自動生成)
        private val REQUEST_AGAIN: String = "request_again" // 是否不斷請求
        private val sContainer: SparseArray<OnPermissionsResult> = SparseArray()

        fun newInstance(permissions: ArrayList<String>, requestAgain: Boolean): PermissionFragment {
            val fragment = PermissionFragment()
            val bundle = Bundle()
            var requestCode: Int
            // 請求碼隨機生成,避免隨機產生之前的請求碼,必須進行循環判斷
            do {
                // requestCode = new Random().nextInt(65535); // Studio編譯的APK請求碼必須小于65536
                requestCode = Random().nextInt(255) // Eclipse編譯的APK請求碼必須小于256
            } while (sContainer.get(requestCode) != null)
            bundle.putInt(REQUEST_CODE, requestCode)
            bundle.putStringArrayList(PERMISSIONS, permissions)
            bundle.putBoolean(REQUEST_AGAIN, requestAgain)
            fragment.arguments = bundle
            return fragment
        }
    }

    /**
     * 用于6.0懸浮窗 8.0安裝第三方應用權限請求
     */
    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        val permissions = arguments!!.getStringArrayList(PERMISSIONS)
        if (permissions == null || permissions.isEmpty()) return
        if (permissions.contains(Manifest.permission.SYSTEM_ALERT_WINDOW) && !PermissionUtils.isHasOverlaysPermission(getActivity())
                ||permissions.contains(Manifest.permission.REQUEST_INSTALL_PACKAGES) && !PermissionUtils.isHasInstallPermission(getActivity())) {
            if (permissions.contains(Manifest.permission.SYSTEM_ALERT_WINDOW) && !PermissionUtils.isHasOverlaysPermission(getActivity())) {
                // 跳轉到懸浮窗設置頁面
                val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + activity!!.getPackageName()))
                startActivityForResult(intent, arguments!!.getInt(REQUEST_CODE))
            }

            if (permissions.contains(Manifest.permission.REQUEST_INSTALL_PACKAGES) && !PermissionUtils.isHasInstallPermission(getActivity())) {
                // 跳轉到允許安裝未知來源設置頁面
                val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:" + activity!!.getPackageName()))
                startActivityForResult(intent, arguments!!.getInt(REQUEST_CODE))
            }
            return
        }

        requestPermission()
    }

    /**
     * 準備請求
     */
    fun prepareRequest(activity: Activity, call: OnPermissionsResult) {
        // 將當前的請求碼和對象添加到集合中
        sContainer.put(arguments!!.getInt(REQUEST_CODE), call)
        activity.fragmentManager.beginTransaction().add(this, activity.javaClass.name).commit()
    }

    /**
     * 請求權限
     */
    fun requestPermission() {
        if (PermissionUtils.isOverMarshmallow()) {
            val permissions = arguments!!.getStringArrayList(PERMISSIONS)
            requestPermissions(permissions!!.toTypedArray(), arguments!!.getInt(REQUEST_CODE))
        }
    }

    /**
     * 權限請求結果回調(除過6.0懸浮窗 8.0安裝第三方應用回調)
     */
    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        val onPermissionsResult = sContainer.get(requestCode)
        if (onPermissionsResult == null) return
        for (i in permissions.indices) {
            // 重新檢查懸浮窗權限
            if (Permission.SYSTEM_ALERT_WINDOW == permissions[i]) {
                if (PermissionUtils.isHasOverlaysPermission(activity)) {
                    grantResults[i] = PackageManager.PERMISSION_GRANTED
                } else {
                    grantResults[i] = PackageManager.PERMISSION_DENIED
                }
            }
            // 重新檢查安裝權限
            if (Permission.REQUEST_INSTALL_PACKAGES == permissions[i]) {
                if (PermissionUtils.isHasInstallPermission(activity)) {
                    grantResults[i] = PackageManager.PERMISSION_GRANTED
                } else {
                    grantResults[i] = PackageManager.PERMISSION_DENIED
                }
            }

            // 重新檢查8.0的兩個新權限
            if (permissions[i] == Permission.ANSWER_PHONE_CALLS || permissions[i] == Permission.READ_PHONE_NUMBERS) {

                // 檢查當前的安卓版本是否符合要求
                if (!PermissionUtils.isOverOreo()) {
                    grantResults[i] = PackageManager.PERMISSION_GRANTED
                }
            }
        }

        val deniedPermissions = PermissionUtils.getDeniedPermissions(activity as Context, permissions.asList())
        if (deniedPermissions.isEmpty()) {
            onPermissionsResult.agreePermission(permissions.toList(), true)
        } else {
            // 檢查是否開啟了繼續申請模式,如果是則檢查沒有授予的權限是否還能繼續申請
            if (arguments!!.getBoolean(REQUEST_AGAIN) && PermissionUtils.isRequestDeniedPermission(activity as Activity, deniedPermissions)) {

                // 如果有的話就繼續申請權限,直到用戶授權或者永久拒絕
                requestPermission()
                return
            }

            // 代表申請的權限中有不同意授予的,如果有某個權限被永久拒絕就返回true給開發人員,讓開發者引導用戶去設置界面開啟權限
            onPermissionsResult.disagreePermission(deniedPermissions, PermissionUtils.checkMorePermissionPermanentDenied(activity as Activity, deniedPermissions))

            // 證明還有一部分權限被成功授予,回調成功接口
            if (permissions.size>deniedPermissions.size){
                val succeePermissions = permissions.toMutableList()
                val succeed = succeePermissions.removeAll(deniedPermissions)
                if (succeed) {
                    if (!succeePermissions.isEmpty()) {
                        onPermissionsResult.agreePermission(succeePermissions, false)
                    }
                }
            }

        }
        // 權限回調結束后要刪除集合中的對象,避免重復請求
        sContainer.remove(requestCode)
        fragmentManager!!.beginTransaction().remove(this).commit()
    }

    private var isBackCall: Boolean = false // 是否已經回調了,避免安裝權限和懸浮窗同時請求導致的重復回調

    /**
     * 6.0懸浮窗 8.0安裝第三方應用回調
     * 需要注意第三個Intent參數,kotlin的NULL檢查機制,導致不寫?一直回調不成功(坑)
     */
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
//         super.onActivityResult(requestCode, resultCode, data);
        if (!isBackCall && requestCode == arguments!!.getInt(REQUEST_CODE)) {
            isBackCall = true
            // 需要延遲執行,不然有些華為機型授權了但是獲取不到權限
            Handler(Looper.getMainLooper()).postDelayed(this, 500)
        }
    }

    /**
     * [Runnable.run]
     */
    override fun run() {
        // 請求其他危險權限
        requestPermission()
    }

}

PermissionFragment通過名字也能看出,這里采用了Fragment來處理請求回調,Fragment的妙用有很多,比如解決自定義view綁定生命周期的問題(百度地圖還需要用戶自己去綁定生命周期,不友好啊...)

/**
 * 權限請求工具類
 */
class PermissionUtils {
    companion object {
        /**
         * 獲取清單文件中的權限
         */
        fun getManifestPermissions(context: Context): MutableList<String> {
            return context.packageManager.getPackageInfo(context.packageName,
                    PackageManager.GET_PERMISSIONS).requestedPermissions.toMutableList()
        }

        /**
         * 檢查targetSdkVersion是否符合要求
         *
         * @param context                   上下文對象
         * @param requestPermissions       請求的權限組
         */
        fun checkTargetSdkVersion(context: Context, requestPermissions: List<String>):Boolean {
            if (requestPermissions.contains(Manifest.permission.REQUEST_INSTALL_PACKAGES)
                    || requestPermissions.contains(Manifest.permission.ANSWER_PHONE_CALLS)
                    || requestPermissions.contains(Manifest.permission.READ_PHONE_NUMBERS)) {
                // 必須設置 targetSdkVersion >= 26 才能正常檢測權限
                if (context.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.O) {
                    return true
                }
            }

            if (context.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.M) {
                return true
            }

            return false
        }

        /**
         * 獲取未授權權限
         */
        fun getDeniedPermissions(context: Context, requestPermissions: List<String>):MutableList<String>{
            var deniedList:MutableList<String> = ArrayList()
            for (permission in requestPermissions) {
                //檢測6.0懸浮窗權限
                if (TextUtils.equals(permission,Manifest.permission.SYSTEM_ALERT_WINDOW)){
                    if (!isHasOverlaysPermission(context)) {
                        deniedList.add(permission)
                        continue
                    }
                }
                //檢測8.0以上安裝未知來源應用權限
                if (TextUtils.equals(permission,Manifest.permission.REQUEST_INSTALL_PACKAGES)){
                    if (!isHasInstallPermission(context)){
                        deniedList.add(permission)
                        continue
                    }
                }
                //檢測8.0的兩個新權限
                if (TextUtils.equals(permission,Manifest.permission.ANSWER_PHONE_CALLS)
                        ||TextUtils.equals(permission,Manifest.permission.READ_PHONE_NUMBERS)){
                    if (!isOverOreo()){
                        continue
                    }
                }
                    // 把沒有授予過的權限加入到集合中
                if (ActivityCompat.checkSelfPermission(context,permission) == PackageManager.PERMISSION_DENIED) {
                    deniedList.add(permission)
                }

            }
            return deniedList
        }

        /**
         * 檢測6.0懸浮窗權限
         */
         fun isHasOverlaysPermission(context: Context): Boolean {
            if (isOverMarshmallow()){
                return Settings.canDrawOverlays(context)
            }
            return true
        }

        /**
         * 檢測8.0以上安裝未知來源應用權限
         */
         fun isHasInstallPermission(context: Context): Boolean {
            if (isOverOreo()){
                return context!!.packageManager.canRequestPackageInstalls()
            }
            return true
        }

        /**
         * 是否是6.0以上版本
         */
        fun isOverMarshmallow(): Boolean {
            return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
        }

        /**
         * 是否是8.0以上版本
         */
        fun isOverOreo(): Boolean {
            return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
        }

        /**
         * 檢測權限是否在清單文件中注冊
         */
        fun checkPermissionsIsInManifest(context: Context,requestPermissions: List<String>){
            val manifestPermissions = getManifestPermissions(context)
            if (manifestPermissions != null&&!manifestPermissions.isEmpty()){
                for (permission in requestPermissions) {
                    if (!manifestPermissions.contains(permission)){
                        throw RuntimeException(permission + ": Permissions are not registered in the manifest file")
                    }
                }

            }else{
                throw RuntimeException("No permissions are registered in the manifest file")
            }
        }

        /**
         * 在權限組中檢查是否有某個權限是否被永久拒絕
         *
         * @param activity              Activity對象
         * @param permissions            請求的權限
         */
        fun checkMorePermissionPermanentDenied(activity: Activity, permissions: List<String>): Boolean {
            for (permission in permissions) {
                // 安裝權限和浮窗權限不算,本身申請方式和危險權限申請方式不同,因為沒有永久拒絕的選項,所以這里返回false
                if (permission == Permission.REQUEST_INSTALL_PACKAGES || permission == Permission.SYSTEM_ALERT_WINDOW) {
                    continue
                }
                if (checkSinglePermissionPermanentDenied(activity, permission)) {
                    return true
                }
            }
            return false
        }

        /**
         * 檢查某個權限是否被永久拒絕
         *
         * @param activity              Activity對象
         * @param permission            請求的權限
         */
        fun checkSinglePermissionPermanentDenied(activity: Activity, permission: String): Boolean {

            //        // 安裝權限和浮窗權限不算,本身申請方式和危險權限申請方式不同,因為沒有永久拒絕的選項,所以這里返回false
            //        if (permission.equals(Permission.REQUEST_INSTALL_PACKAGES) || permission.equals(Permission.SYSTEM_ALERT_WINDOW)) {
            //            return false;
            //        }

            // 檢測8.0的兩個新權限
            if (permission == Permission.ANSWER_PHONE_CALLS || permission == Permission.READ_PHONE_NUMBERS) {

                // 檢查當前的安卓版本是否符合要求
                if (!isOverOreo()) {
                    return false
                }
            }

            if (PermissionUtils.isOverMarshmallow()) {
                if (activity.checkSelfPermission(permission) == PackageManager.PERMISSION_DENIED && !activity.shouldShowRequestPermissionRationale(permission)) {
                    return true
                }
            }
            return false
        }

        /**
         * 是否還能繼續申請沒有授予的權限
         *
         * @param activity              Activity對象
         * @param failPermissions       失敗的權限
         */
        fun isRequestDeniedPermission(activity: Activity, failPermissions: List<String>): Boolean {
            for (permission in failPermissions) {
                // 安裝權限和浮窗權限不算,本身申請方式和危險權限申請方式不同,因為沒有永久拒絕的選項,所以這里返回false
                if (permission == Permission.REQUEST_INSTALL_PACKAGES || permission == Permission.SYSTEM_ALERT_WINDOW) {
                    continue
                }

                // 檢查是否還有權限還能繼續申請的(這里指沒有被授予的權限但是也沒有被永久拒絕的)
                if (!checkSinglePermissionPermanentDenied(activity, permission)) {
                    return true
                }
            }
            return false
        }

        /**
         * 獲取已授予的權限
         *
         * @param permissions       需要請求的權限組
         * @param grantResults      允許結果組
         */
        fun getSucceedPermissions(permissions: Array<String>, grantResults: IntArray): List<String> {

            val succeedPermissions = java.util.ArrayList<String>()
            for (i in grantResults.indices) {

                // 把授予過的權限加入到集合中,-1表示沒有授予,0表示已經授予
                if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                    succeedPermissions.add(permissions[i])
                }
            }
            return succeedPermissions
        }
    }
}
/**
 *   author:justin
 *   time:2019/04/24
 *   desc: 權限設置頁(兼容大部分國產手機)
 */

internal object PermissionSettingPage {
    /**
     * 手機制造商
     */
    private val MARK = Build.MANUFACTURER.toLowerCase()
    /**
     * 跳轉到應用權限設置頁面
     *
     * @param context 上下文對象
     * @param newTask 是否使用新的任務棧啟動
     */
    fun start(context: Context, newTask: Boolean) {

        var intent: Intent? = null
        if (MARK.contains("huawei")) {
            intent = huawei(context)
        } else if (MARK.contains("xiaomi")) {
            intent = xiaomi(context)
        } else if (MARK.contains("oppo")) {
            intent = oppo(context)
        } else if (MARK.contains("vivo")) {
            intent = vivo(context)
        } else if (MARK.contains("meizu")) {
            intent = meizu(context)
        }

        if (intent == null || !hasIntent(context, intent)) {
            intent = google(context)
        }

        if (newTask) {
            //如果用戶在權限設置頁面改動了權限,個別手機請求權限的activity會被重啟,解決該問題
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        }

        try {
            context.startActivity(intent)
        } catch (ignored: Exception) {
            intent = google(context)
            context.startActivity(intent)
        }

    }

    private fun google(context: Context): Intent {
        val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
        intent.data = Uri.fromParts("package", context.packageName, null)
        return intent
    }

    private fun huawei(context: Context): Intent {
        val intent = Intent()
        intent.component = ComponentName("com.huawei.systemmanager", "com.huawei.permissionmanager.ui.MainActivity")
        if (hasIntent(context, intent)) return intent
        intent.component = ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.addviewmonitor.AddViewMonitorActivity")
        if (hasIntent(context, intent)) return intent
        intent.component = ComponentName("com.huawei.systemmanager", "com.huawei.notificationmanager.ui.NotificationManagmentActivity")
        return intent
    }

    private fun xiaomi(context: Context): Intent {
        val intent = Intent("miui.intent.action.APP_PERM_EDITOR")
        intent.putExtra("extra_pkgname", context.packageName)
        if (hasIntent(context, intent)) return intent

        intent.setPackage("com.miui.securitycenter")
        if (hasIntent(context, intent)) return intent

        intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.AppPermissionsEditorActivity")
        if (hasIntent(context, intent)) return intent

        intent.setClassName("com.miui.securitycenter", "com.miui.permcenter.permissions.PermissionsEditorActivity")
        return intent
    }

    private fun oppo(context: Context): Intent {
        val intent = Intent()
        intent.putExtra("packageName", context.packageName)
        intent.setClassName("com.color.safecenter", "com.color.safecenter.permission.floatwindow.FloatWindowListActivity")
        if (hasIntent(context, intent)) return intent

        intent.setClassName("com.coloros.safecenter", "com.coloros.safecenter.sysfloatwindow.FloatWindowListActivity")
        if (hasIntent(context, intent)) return intent

        intent.setClassName("com.oppo.safe", "com.oppo.safe.permission.PermissionAppListActivity")
        return intent
    }

    private fun vivo(context: Context): Intent {
        val intent = Intent()
        intent.setClassName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.FloatWindowManager")
        intent.putExtra("packagename", context.packageName)
        if (hasIntent(context, intent)) return intent

        intent.component = ComponentName("com.iqoo.secure", "com.iqoo.secure.safeguard.SoftPermissionDetailActivity")
        return intent
    }

    private fun meizu(context: Context): Intent {
        val intent = Intent("com.meizu.safe.security.SHOW_APPSEC")
        intent.putExtra("packageName", context.packageName)
        intent.component = ComponentName("com.meizu.safe", "com.meizu.safe.security.AppSecActivity")
        return intent
    }

    private fun hasIntent(context: Context, intent: Intent): Boolean {
        return !context.packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).isEmpty()
    }
}
/**
 * 權限請求結果回調接口
 */
interface OnPermissionsResult {

    fun agreePermission(granted:List<String> , agreeAll:Boolean )

    fun disagreePermission(disagree:List<String> , never:Boolean )
}

使用

 JPermissions.with(this)
                .permissions(Manifest.permission.CAMERA,Manifest.permission.CALL_PHONE)//如果不設置,自動獲取manifest文件下權限
                .requestAgain()//拒絕后再次請求,直到用戶永久拒絕
                .requestPermissions(object :OnPermissionsResult{
                    override fun agreePermission(granted: List<String>, agreeAll: Boolean) {
                       if (agreeAll){
                           //獲取所有權限成功
                           Toast.makeText(this@MainActivity,"全部請求成功",Toast.LENGTH_LONG).show()
                       }else{
                           //獲取部分權限成功

                           Toast.makeText(this@MainActivity,granted.toString()+"部分請求成功",Toast.LENGTH_LONG).show()
                       }
                    }

                    override fun disagreePermission(disagree: List<String>, never: Boolean) {
                        if (never){
                          
                            Toast.makeText(this@MainActivity,disagree.toString()+"永久拒絕",Toast.LENGTH_LONG).show()
                            //被永久拒絕就跳轉到應用權限系統設置頁面
                            JPermissions.gotoPermissionSettings(this@MainActivity)
                        }else{
                            //獲取權限失敗
                            Toast.makeText(this@MainActivity,disagree.toString()+"獲取失敗",Toast.LENGTH_LONG).show()
                        }
                    }

                })
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容