110/14 - EasyPermissions与他的快乐伙伴

讲到硬体控制,总有一天要面对权限管理,不过Google有个权限的第三方EasyPermissions,今天就简单讲一下怎麽安装和使用。

安装

https://github.com/googlesamples/easypermissions

dependencies {
    implementation 'pub.devrel:easypermissions:3.0.0'
}    

Activity继承PermissionCallbacks

  • 使用者同意权限onPermissionsGranted会被执行
  • 使用者拒绝权限onPermissionsDenied会被执行
class CropLensActivity : AppCompatActivity(), PermissionCallbacks {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_crop_lens)
    }        
    
    override fun onPermissionsGranted(requestCode: Int, perms: MutableList<String>) {
    
    }
    
    override fun onPermissionsDenied(requestCode: Int, perms: MutableList<String>) {
    
    }
}

手动新增

ctrl + O叫出Override Members页面,寻找onRequestPermissionsResult,点选OK

override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)

}

权限中文化

不管是onPermissionsGrantedonPermissionsDenied,传出来的perms都是一串英文android.permission.CAMERA,所以我们要请使用者去设定开启相对应的权限,所以要把这些中文化。

class PermissionsTransformer {
    companion object {
        const val CALENDAR = "日历"
        const val CAMERA = "相机"
        const val ACCOUNTS = "联络人"
        const val LOCATION = "位置"
        const val AUDIO = "麦克风"
        const val CALLS = "电话"
        const val SENSORS = "人体感应器"
        const val SMS = "简讯"
        const val STORAGE = "储存"
        const val ELSE = "未知的权限"

        const val READ_CALENDAR = "android.permission.READ_CALENDAR"
        const val WRITE_CALENDAR = "android.permission.WRITE_CALENDAR"
        const val PERMISSION_CAMERA = "android.permission.CAMERA"
        const val READ_CONTACTS = "android.permission.READ_CONTACTS"
        const val WRITE_CONTACTS = "android.permission.WRITE_CONTACTS"
        const val GET_ACCOUNTS = "android.permission.GET_ACCOUNTS"
        const val ACCESS_FINE_LOCATION = "android.permission.ACCESS_FINE_LOCATION"
        const val ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION"
        const val RECORD_AUDIO = "android.permission.RECORD_AUDIO"
        const val READ_PHONE_STATE = "android.permission.READ_PHONE_STATE"
        const val CALL_PHONE = "android.permission.CALL_PHONE"
        const val READ_CALL_LOG = "android.permission.READ_CALL_LOG"
        const val WRITE_CALL_LOG = "android.permission.WRITE_CALL_LOG"
        const val VOICEMAIL_ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL"
        const val ADD_VOICEMAIL = "android.permission.ADD_VOICEMAIL"
        const val USE_SIP = "android.permission.USE_SIP"
        const val PROCESS_OUTGOING_CALLS = "android.permission.PROCESS_OUTGOING_CALLS"
        const val BODY_SENSORS = "android.permission.BODY_SENSORS"
        const val RECEIVE_SMS = "android.permission.RECEIVE_SMS"
        const val READ_SMS = "android.permission.READ_SMS"
        const val SEND_SMS = "android.permission.SEND_SMS"
        const val RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH"
        const val RECEIVE_MMS = "android.permission.RECEIVE_MMS"
        const val READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE"
        const val WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE"
    }

    fun getText(perms: String): String {
        when (perms) {
            READ_CALENDAR,
            WRITE_CALENDAR -> return CALENDAR
            PERMISSION_CAMERA -> return CAMERA
            READ_CONTACTS,
            WRITE_CONTACTS,
            GET_ACCOUNTS -> return ACCOUNTS
            ACCESS_FINE_LOCATION,
            ACCESS_COARSE_LOCATION -> return LOCATION
            RECORD_AUDIO -> return AUDIO
            READ_PHONE_STATE,
            CALL_PHONE,
            READ_CALL_LOG,
            WRITE_CALL_LOG,
            VOICEMAIL_ADD_VOICEMAIL,
            ADD_VOICEMAIL,
            USE_SIP,
            PROCESS_OUTGOING_CALLS -> return CALLS
            BODY_SENSORS -> return SENSORS
            RECEIVE_SMS,
            READ_SMS,
            RECEIVE_WAP_PUSH,
            SEND_SMS,
            RECEIVE_MMS -> return SMS
            READ_EXTERNAL_STORAGE,
            WRITE_EXTERNAL_STORAGE -> return STORAGE
            else -> return ELSE
        }
    }

    fun getPermissionsList(perms: List<String>): StringBuilder {
        val permissionsList = HashSet<String>()
        val permissionsText = StringBuilder()

        perms.forEach { it ->
            permissionsList.add(getText(it))
        }

        permissionsList.forEach { it ->
            permissionsText.append(it)
            permissionsText.append("\n")
        }

        return permissionsText
    }
}

顺手写个测试吧

class PermissionsTransformerTest {
    @Test
    fun permissions_text_return_storage() {
        val text = PermissionsTransformer().getText(PermissionsTransformer.WRITE_EXTERNAL_STORAGE)
        assertEquals(PermissionsTransformer.STORAGE, text)
    }
}

然後还需要一个AlertDialog,跟使用者说要开启设定页面的什麽权限

class PermissionsDeniedAlertDialog(val context: Context) {

    companion object {
        const val PACKAGE = "package"
        const val STRING_EMPTY = ""
    }

    fun show(title: String = STRING_EMPTY, message: String = STRING_EMPTY) {
        AlertDialog
            .Builder(context)
            .setTitle(title)
            .setCancelable(false)
            .setMessage(message)
            .setPositiveButton(R.string.confirm) { _, _ ->
                val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
                    val uri = Uri.fromParts(PACKAGE, context.packageName, null)
                    this.data = uri
                }

                context.startActivity(intent)
            }
            .show()
    }
}

基本设定完成後,可以来写程序了

增加程序码

onRequestPermissionsResult的地方新增EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this),把权限控管交给EasyPermissions

override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this)
}

onPermissionsDenied的地方新增PermissionsDeniedAlertDialog(this).show(),当使用者拒绝提供权限时,显示AlertDialog,跟使用者说要开启设定页面的权限。

override fun onPermissionsDenied(requestCode: Int, perms: MutableList<String>) {    
    PermissionsDeniedAlertDialog(this).show(
        "权限不足",
        "请开启以下权限:\n${PermissionsTransformer().getPermissionsList(perms)}"
    )
}

开始要求权限

假设我们要求读取和写入的权限,首先建立阵列

val permissionList = arrayOf(
    Manifest.permission.WRITE_EXTERNAL_STORAGE,
    Manifest.permission.READ_EXTERNAL_STORAGE
)

如果要做的事情没有权限,启动EasyPermissions.requestPermissions(),其中有个100,就是使用者提供权限时,onPermissionsGrantedrequestCode就会有100

if (!EasyPermissions.hasPermissions(this, *permissionList)) {
    EasyPermissions.requestPermissions(
        this,
        "请提供读写档案权限",
        100,
        *permissionList
    )
}

<<:  【Day 20】ECS on Outposts 的限制

>>:  Day 14: Draft

【在厨房想30天的演算法】Day 28 资讯安全与演算法 : 讯息监别码

Aloha!又是我少女人妻 Uerica!今天我家狗狗总算没有一大早叫我起床了,可能之前累爆昨夜一路...

来一道色香味俱全的 JavaScript 吧

终於 进入好想工作室第 131 天 终於 我也迎来了传说中的 it 铁人赛 思考了很久铁人赛的主题要...

未来狂想:金融领域

人的科技文明发展始终来自於人性 在科技的发展与技术的发展之下,在很多的领域都有许多的应用,甚至因为科...

Day17 测试写起乃 - expect() vs expect {}

今天就来说说 expect() 与 expect {} 的差别吧 我们用一个例子来讲 describ...

[Day09] - 未知网址的弹跳视窗 - is 属性

早上查看文章时 , 发现贴到昨天的资料 本鲁立马作文章修改 , 如造成 邦友 的不便 , 请各位海...