Skip to content

Commit

Permalink
rxpermissions
Browse files Browse the repository at this point in the history
  • Loading branch information
lunxinfeng committed Sep 15, 2018
1 parent 227ca7f commit 18ddd0d
Show file tree
Hide file tree
Showing 14 changed files with 294 additions and 3 deletions.
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ dependencies {
implementation project(':recyclerhelper')
implementation project(':rxretrofit')
implementation project(':dialog')
implementation project(':rxpermissions')
}
15 changes: 13 additions & 2 deletions app/src/main/java/com/lxf/tools/ui/RetrofitActivity.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package com.lxf.tools.ui

import android.icu.lang.UCharacter.GraphemeClusterBreak.L
import android.Manifest
import android.os.Bundle
import android.util.Log
import com.lxf.rxpermissions.RxPermissions
import com.lxf.rxretrofit.RetrofitHelper
import com.lxf.rxretrofit.callback.BaseView
import com.lxf.rxretrofit.callback.ProgressObserver
Expand Down Expand Up @@ -30,7 +31,7 @@ class RetrofitActivity : BaseActivity() {

btnObject.setOnClickListener { getVersion() }
btnMap.setOnClickListener { map() }
btnDownload.setOnClickListener { download() }
btnDownload.setOnClickListener { permission() }
}

private fun init(){
Expand Down Expand Up @@ -94,6 +95,16 @@ class RetrofitActivity : BaseActivity() {
})
}

private fun permission(){
RxPermissions.newInstance(this)
.request(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
)
.subscribe { if (it) download() else toast("权限被拒绝") }

}

private fun download(){
RetrofitHelper.newInstance()
.debug(true)
Expand Down
1 change: 1 addition & 0 deletions rxpermissions/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
38 changes: 38 additions & 0 deletions rxpermissions/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'

android {
compileSdkVersion rootProject.ext.build_version.compileSdkVersion

defaultConfig {
minSdkVersion rootProject.ext.build_version.minSdkVersion
targetSdkVersion rootProject.ext.build_version.targetSdkVersion
versionCode 1
versionName "1.0"

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}

}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])

implementation rootProject.ext.dependencies.appcompatV7
testImplementation rootProject.ext.dependencies.test_junit
androidTestImplementation rootProject.ext.dependencies.test_runner
androidTestImplementation rootProject.ext.dependencies.test_espresso
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation rootProject.ext.dependencies.rxJava
}
repositories {
mavenCentral()
}
21 changes: 21 additions & 0 deletions rxpermissions/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.lxf.rxpermissions;

import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;

import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.*;

/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();

assertEquals("com.lxf.rxpermissions.test", appContext.getPackageName());
}
}
2 changes: 2 additions & 0 deletions rxpermissions/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.lxf.rxpermissions" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.lxf.rxpermissions



data class Permission(
val name: String,
val granted: Boolean,
val showShowRequestPermissionRational: Boolean = false
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.lxf.rxpermissions

import android.content.pm.PackageManager
import android.os.Bundle
import android.support.v4.app.Fragment
import io.reactivex.subjects.PublishSubject
import java.util.HashMap


internal class PermissionFragment: Fragment() {

/**
* 保存所有的权限请求,一旦有请求结果就将改请求移除,不论是允许还是拒绝
*/
private val mSubjects = HashMap<String, PublishSubject<Permission>>()
companion object {
const val PERMISSION_REQUEST_CODE = 1001
}

internal fun requestPermissions(vararg permissions: String){
requestPermissions(permissions, PERMISSION_REQUEST_CODE)
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//activity重建时保留fragment实例
retainInstance = true
}

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

if (requestCode!= PERMISSION_REQUEST_CODE) return

val shouldShowRequestPermissionRationale = mutableListOf<Boolean>()
for ( i in permissions.indices){
shouldShowRequestPermissionRationale.add(shouldShowRequestPermissionRationale(permissions[i]))
}

onPermissionsResult(
permissions,
grantResults,
shouldShowRequestPermissionRationale.toBooleanArray()
)
}

fun onPermissionsResult(
permissions: Array<out String>,
grantResults: IntArray,
shouldShowRequestPermissionRationale:BooleanArray
){
for ((index,permission) in permissions.withIndex()){
val subject = mSubjects[permission]
subject?.let{
mSubjects.remove(permission)
val granted = grantResults[index] == PackageManager.PERMISSION_GRANTED
it.onNext(Permission(
permission,
granted,
shouldShowRequestPermissionRationale[index]
))
it.onComplete()
}
}
}

fun getSubject(permission: String) = mSubjects[permission]

fun addSubjectForPermission(permission: String){
mSubjects[permission] = PublishSubject.create()
}
}
32 changes: 32 additions & 0 deletions rxpermissions/src/main/java/com/lxf/rxpermissions/RxPermissions.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.lxf.rxpermissions

import android.support.v4.app.FragmentActivity
import io.reactivex.Observable


class RxPermissions private constructor(
activity: FragmentActivity
) {
internal val fragment: PermissionFragment = getPermissionFragment(activity.supportFragmentManager)

companion object {
internal const val TAG_FRAGMENT = "RxPermissions_lxf"
fun newInstance(activity: FragmentActivity) = RxPermissions(activity)
}

fun request(vararg permissions: String): Observable<Boolean> {
return requestImplementation(*permissions)
.buffer(permissions.size)
.flatMap {
if (permissions.isEmpty())
return@flatMap Observable.empty<Boolean>()

return@flatMap Observable.just(it.none { !it.granted })
}

}

fun requestEach(vararg permissions: String):Observable<Permission>{
return requestImplementation(*permissions)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.lxf.rxpermissions

import android.annotation.TargetApi
import android.content.pm.PackageManager
import android.os.Build
import android.support.v4.app.FragmentManager
import io.reactivex.Observable


internal fun getPermissionFragment(fragmentManager: FragmentManager):PermissionFragment{
var fragment = fragmentManager.findFragmentByTag(RxPermissions.TAG_FRAGMENT) as? PermissionFragment
if (fragment == null){
fragment = PermissionFragment()
fragmentManager.beginTransaction()
.add(fragment,RxPermissions.TAG_FRAGMENT)
.commitNow()
}
return fragment
}

internal fun RxPermissions.requestImplementation(vararg permissions: String):Observable<Permission>{
val list = mutableListOf<Observable<Permission>>()
val unRequestPermissions = mutableListOf<String>()

for (item in permissions){
if (isGranted(item)){
list.add(Observable.just(Permission(item,true,false)))
continue
}

if (isRevoked(item)) {
// Revoked by a policy, return a denied Permission object.
list.add(Observable.just(Permission(item, false, false)))
continue
}

if (fragment.getSubject(item) == null) {
unRequestPermissions.add(item)
fragment.addSubjectForPermission(item)
}
list.add(fragment.getSubject(item)!!)
}

if (unRequestPermissions.isNotEmpty()){
fragment.requestPermissions(*unRequestPermissions.toTypedArray())
}
return Observable.concat(Observable.fromIterable(list))
}

@TargetApi(Build.VERSION_CODES.M)
internal fun RxPermissions.isGranted(permission:String) = !isMarshmallow()
|| fragment.activity.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED

@TargetApi(Build.VERSION_CODES.M)
internal fun RxPermissions.isRevoked(permission: String) = isMarshmallow()
&& fragment.activity.let { it.packageManager.isPermissionRevokedByPolicy(permission,it.packageName) }

internal fun isMarshmallow() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
3 changes: 3 additions & 0 deletions rxpermissions/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<resources>
<string name="app_name">RxPermissions</string>
</resources>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.lxf.rxpermissions;

import org.junit.Test;

import static org.junit.Assert.*;

/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
2 changes: 1 addition & 1 deletion settings.gradle
Original file line number Diff line number Diff line change
@@ -1 +1 @@
include ':app', ':recyclerhelper', ':dialog', ':rxretrofit'
include ':app', ':recyclerhelper', ':dialog', ':rxretrofit', ':rxpermissions'

0 comments on commit 18ddd0d

Please sign in to comment.