Skip to content

Commit

Permalink
自实现RxPermissions
Browse files Browse the repository at this point in the history
  • Loading branch information
wangzhiyu1 committed Jun 26, 2019
1 parent 83883b8 commit 2a90d29
Show file tree
Hide file tree
Showing 14 changed files with 297 additions and 89 deletions.
35 changes: 34 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,40 @@

![](./images/g_permission_instruction.png)

## Import
第一步,在项目根目录下的`build.gradle`文件中引入`Jitpack`的库路径:
```groovy
allprojects {
repositories {
// Your codes ...
maven { url 'https://jitpack.io' }
}
}
```
第二步,在需要依赖`GPermission``Module`下的`build.gradle`文件中添加依赖:
```groovy
dependencies {
// Your codes ...
// GPermission
implementation "com.github.ITGungnir:GPermission:$permission_version"
}
```

## Usage
第一步,在`AndroidManifest.xml`文件中添加要请求的权限:
```xml
<manifest>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<!-- Your codes -->
</manifest>
```

第二步,在适当的地方请求权限:
```kotlin
// with()方法中的参数可以是 FragmentActivity或Fragment的子类
GPermission.with(this)
// 请求权限成功时的回调
.onGranted {
Expand All @@ -31,9 +53,20 @@ GPermission.with(this)
// 开始请求权限
.request(
Manifest.permission.WRITE_EXTERNAL_STORAGE to "文件读写",
Manifest.permission.READ_PHONE_STATE to "获取手机状态"
Manifest.permission.READ_PHONE_STATE to "获取手机状态",
Manifest.permission.CAMERA to "相机",
Manifest.permission.RECORD_AUDIO to "麦克风录音"
)
```
`GPermission`还提供了验证权限是否已获取的方法:
```kotlin
tvResult.text = GPermission.with(this).allGranted(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO
).toString()
```

## License
```text
Expand Down
5 changes: 0 additions & 5 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,8 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// Kotlin
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-android-extensions-runtime:$kotlin_version"
implementation "org.jetbrains.anko:anko-sdk25:$anko_version"
implementation "org.jetbrains.anko:anko-appcompat-v7:$anko_version"
// Support
implementation "androidx.appcompat:appcompat:$appcompat_version"
implementation "com.google.android.material:material:$material_version"
implementation "androidx.constraintlayout:constraintlayout:$constraintlayout_version"
// Tools
debugImplementation "com.squareup.leakcanary:leakcanary-android:$leak_canary_version"
debugImplementation "com.squareup.leakcanary:leakcanary-support-fragment:$leak_canary_version"
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />

<application
android:allowBackup="true"
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/java/test/itgungnir/permission/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
package test.itgungnir.permission

import android.Manifest
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
import my.itgungnir.permission.GPermission

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

grantResult.text = GPermission.with(this).allGranted(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO
).toString()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ class SplashActivity : AppCompatActivity() {
.onDenied { finish() }
.request(
Manifest.permission.WRITE_EXTERNAL_STORAGE to "文件读写",
Manifest.permission.READ_PHONE_STATE to "获取手机状态"
Manifest.permission.READ_PHONE_STATE to "获取手机状态",
Manifest.permission.CAMERA to "相机",
Manifest.permission.RECORD_AUDIO to "麦克风录音"
)
}
}
17 changes: 7 additions & 10 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">

<TextView
android:id="@+id/grantResult"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textColor="@android:color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
android:textColor="@android:color/black" />

</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
6 changes: 1 addition & 5 deletions config.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,11 @@ ext {
version_code = 1
version_name = '1.0.0'
// Kotlin
kotlin_version = '1.3.31'
anko_version = '0.10.8'
kotlin_version = '1.3.40'
// Support
appcompat_version = '1.0.2'
material_version = '1.0.0'
constraintlayout_version = '1.1.3'
// ReactiveX
rxjava_version = '2.2.4'
rxpermissions_version = '0.10.2'
// Tools
jitpack_version = '2.1'
leak_canary_version = '1.6.3'
Expand Down
10 changes: 2 additions & 8 deletions permission/build.gradle
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'com.github.dcendents.android-maven'

apply plugin: 'com.github.dcendents.android-maven'
group = 'com.github.ITGungnir'

android {
Expand All @@ -24,14 +24,8 @@ android {
dependencies {
// Kotlin
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-android-extensions-runtime:$kotlin_version"
implementation "org.jetbrains.anko:anko-sdk25:$anko_version"
implementation "org.jetbrains.anko:anko-appcompat-v7:$anko_version"
// Support
implementation "androidx.appcompat:appcompat:$appcompat_version"
implementation "com.google.android.material:material:$material_version"
implementation "androidx.constraintlayout:constraintlayout:$constraintlayout_version"
// ReactiveX
api "io.reactivex.rxjava2:rxjava:$rxjava_version"
implementation "com.github.tbruyelle:rxpermissions:$rxpermissions_version"
implementation "io.reactivex.rxjava2:rxjava:$rxjava_version"
}
30 changes: 20 additions & 10 deletions permission/src/main/java/my/itgungnir/permission/GPermission.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,30 @@ import android.content.pm.PackageManager
import android.net.Uri
import android.provider.Settings
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.tbruyelle.rxpermissions2.RxPermissions
import androidx.lifecycle.ViewModelStoreOwner

class GPermission private constructor() {

private lateinit var context: FragmentActivity

private lateinit var permissionUtil: RxPermissions
private lateinit var permissionUtil: GPermissionProxy

private var grantedCallback: (() -> Unit)? = null
private var deniedCallback: (() -> Unit)? = null

companion object {
fun with(activity: FragmentActivity) = GPermission().apply {
context = activity
permissionUtil = RxPermissions(activity)
fun with(component: ViewModelStoreOwner) = GPermission().apply {
permissionUtil = GPermissionProxy.with(component)
context = when (component) {
is FragmentActivity ->
component
is Fragment ->
component.activity ?: throw IllegalArgumentException("Fragment didn't attach to any Activity.")
else ->
throw IllegalArgumentException("GPermission requested from wrong component.")
}
}
}

Expand All @@ -47,17 +55,19 @@ class GPermission private constructor() {
}
}

private fun lackOnes(vararg permissions: Pair<String, String>): List<String> {
return permissions.filter { granted(permission = it.first) }
fun allGranted(vararg permissions: String) = permissions.all { granted(it) }

private fun lackedOnes(vararg permissions: Pair<String, String>): List<String> {
return permissions.filter { !granted(permission = it.first) }
.map { it.second }
}

private fun granted(permission: String): Boolean =
ContextCompat.checkSelfPermission(context.applicationContext, permission) == PackageManager.PERMISSION_DENIED
ContextCompat.checkSelfPermission(context.applicationContext, permission) == PackageManager.PERMISSION_GRANTED

private fun requestRepeatedly(vararg permissions: Pair<String, String>) {
GPermissionDialog.Builder()
.message("请允许系统获取${lackOnes(*permissions)}权限")
.message("请允许系统获取${lackedOnes(*permissions)}权限")
.onConfirm { request(*permissions) }
.onCancel { deniedCallback?.invoke() }
.create()
Expand All @@ -66,7 +76,7 @@ class GPermission private constructor() {

private fun requestManually(vararg permissions: Pair<String, String>) {
GPermissionDialog.Builder()
.message("由于系统无法获取${lackOnes(*permissions)}权限,不能正常运行,请开启权限后再使用!")
.message("由于系统无法获取${lackedOnes(*permissions)}权限,不能正常运行,请开启权限后再使用!")
.onConfirm { toSystemConfigPage() }
.onCancel { deniedCallback?.invoke() }
.create()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import android.view.ViewGroup
import android.view.Window
import androidx.fragment.app.DialogFragment
import kotlinx.android.synthetic.main.dialog_g_permission.*
import org.jetbrains.anko.backgroundDrawable

class GPermissionDialog private constructor() : DialogFragment() {

Expand All @@ -36,7 +35,7 @@ class GPermissionDialog private constructor() : DialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

view.backgroundDrawable = GradientDrawable().apply {
view.background = GradientDrawable().apply {
setColor(Color.WHITE)
cornerRadius = 10F
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package my.itgungnir.permission

import android.annotation.TargetApi
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import io.reactivex.subjects.PublishSubject

class GPermissionFragment private constructor() : Fragment() {

private val subjects = mutableMapOf<String, PublishSubject<Permission>>()

companion object {
const val PERMISSION_REQUEST_CODE = 0x1F

fun getInstance(manager: FragmentManager): GPermissionFragment =
(manager.findFragmentByTag(GPermissionFragment::class.java.name) ?: GPermissionFragment().apply {
manager.beginTransaction().add(this, GPermissionFragment::class.java.name).commitNow()
}) as GPermissionFragment
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
retainInstance = true
}

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (PERMISSION_REQUEST_CODE != requestCode) {
return
}
for (i in 0 until permissions.size) {
val subject = subjects[permissions[i]] ?: return
subjects.remove(permissions[i])
val granted = grantResults[i] == PackageManager.PERMISSION_GRANTED
subject.onNext(
Permission(
name = permissions[i],
granted = granted,
shouldShowRequestPermissionRationale = shouldShowRequestPermissionRationale(permissions[i])
)
)
subject.onComplete()
}
}

fun requestPermissions(permissions: Array<String>) =
requestPermissions(permissions, PERMISSION_REQUEST_CODE)

fun getPermissionSubject(permission: String) =
subjects[permission]

fun setPermissionSubject(permission: String, subject: PublishSubject<Permission>) {
subjects[permission] = subject
}

fun isPermissionSubjectExist(permission: String) =
subjects.containsKey(permission)

@TargetApi(Build.VERSION_CODES.M)
fun isPermissionGranted(permission: String): Boolean =
activity?.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED

@TargetApi(Build.VERSION_CODES.M)
fun isPermissionRevoked(permission: String): Boolean =
activity?.packageManager?.isPermissionRevokedByPolicy(permission, activity!!.packageName) ?: false
}
Loading

0 comments on commit 2a90d29

Please sign in to comment.