Skip to content
This repository has been archived by the owner on Sep 3, 2023. It is now read-only.

Commit

Permalink
3.0.0-RC1
Browse files Browse the repository at this point in the history
  • Loading branch information
afollestad committed Jan 19, 2020
1 parent da81965 commit c5da287
Show file tree
Hide file tree
Showing 56 changed files with 724 additions and 141 deletions.
74 changes: 67 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Assent is designed to make Android's runtime permissions easier and take less co

<img src="https://raw.githubusercontent.com/afollestad/assent/master/showcase2.png" width="750" />

[ ![jCenter](https://api.bintray.com/packages/drummer-aidan/maven/assent/images/download.svg) ](https://bintray.com/drummer-aidan/maven/assent/_latestVersion)
[ ![jCenter](https://api.bintray.com/packages/drummer-aidan/maven/assent%3Acore/images/download.svg) ](https://bintray.com/drummer-aidan/maven/assent%3Acore/_latestVersion)
[![Build Status](https://travis-ci.org/afollestad/assent.svg)](https://travis-ci.org/afollestad/assent)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/f1a2334c4c0349699760391bb71f763e)](https://www.codacy.com/app/drummeraidan_50/assent?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=afollestad/assent&amp;utm_campaign=Badge_Grade)
[![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html)
Expand All @@ -14,25 +14,26 @@ Assent is designed to make Android's runtime permissions easier and take less co
1. [Gradle Dependency](#gradle-dependency)
2. [The Basics](#the-basics)
3. [Using Results](#using-results)
4. [Under the Hood Extras](#under-the-hood-extras)
4. [Request Debouncing](#request-debouncing)
5. [Rationales](#rationales)
6. [Coroutines](#coroutines)

---

## Gradle Dependency
## Core

Add this to your module's `build.gradle` file:

```gradle
dependencies {
implementation 'com.afollestad:assent:2.3.1'
implementation 'com.afollestad.assent:core:3.0.0-RC1'
}
```

---

## The Basics
### The Basics

Runtime permissions on Android are completely reliant on the UI the user is in. Permission requests
go in and out of Activities and Fragments. This library provides its functionality as Kotlin
Expand Down Expand Up @@ -71,7 +72,7 @@ both.**

---

## Using Results
### Using Results

`AssentResult` is provided in request callbacks. It has a few useful fields and methods:

Expand All @@ -93,7 +94,7 @@ val permissionDenied: Boolean = result.isAllDenied(WRITE_EXTERNAL_STORAGE)

---

## Under the Hood Extras
### Request Debouncing

If you were to do this...

Expand All @@ -119,6 +120,19 @@ askForPermissions(CALL_PHONE) { _ -> }

## Rationales

[ ![jCenter](https://api.bintray.com/packages/drummer-aidan/maven/assent%3Arationales/images/download.svg) ](https://bintray.com/drummer-aidan/maven/assent%3Arationales/_latestVersion)

Add this to your module's `build.gradle` file:

```gradle
dependencies {
implementation 'com.afollestad.assent:rationales:3.0.0-RC1'
}
```

---

Google recommends showing rationales for permissions when it may not be obvious to the user why
you need them.

Expand All @@ -142,3 +156,49 @@ askForPermissions(
// Use result
}
```

---

## Coroutines

[ ![jCenter](https://api.bintray.com/packages/drummer-aidan/maven/assent%3Acoroutines/images/download.svg) ](https://bintray.com/drummer-aidan/maven/assent%3Acoroutines/_latestVersion)

Add this to your module's `build.gradle` file:

```gradle
dependencies {
implementation 'com.afollestad.assent:coroutines:3.0.0-RC1'
}
```

---

Kotlin coroutines enable Assent to work without callbacks. If you do not know the basics of
coroutines, you should research them first.

First, `awaitPermissionsResult(...)` is the coroutines equivalent to `askForPermissions(...)`:

```kotlin
// Launch a coroutine in some scope...
launch {
val result: AssentResult = awaitPermissionsResult(
READ_CONTACTS, WRITE_EXTERNAL_STORAGE, READ_SMS,
rationaleHandler = rationaleHandler
)
// Use the result...
}
```

And second, `awaitPermissionsGranted(...)` is the coroutines equivalent to `runWithPermissions(...)`:

```kotlin
// Launch a coroutine in some scope...
launch {
waitPermissionsGranted(
READ_CONTACTS, WRITE_EXTERNAL_STORAGE, READ_SMS,
rationaleHandler = rationaleHandler
)
// All three permissions were granted...
}
```
4 changes: 1 addition & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
apply from: rootProject.file("gradle/versions_plugin_config.gradle")
apply from: rootProject.file("gradle/nebula_lint_config.gradle")

buildscript {
apply from: rootProject.file("dependencies.gradle")
Expand All @@ -13,7 +12,6 @@ buildscript {
classpath deps.gradle_plugins.android
classpath deps.gradle_plugins.bintray_release
classpath deps.gradle_plugins.kotlin
classpath deps.gradle_plugins.nebula_lint
classpath deps.gradle_plugins.spotless
classpath deps.gradle_plugins.versions
}
Expand All @@ -29,7 +27,7 @@ allprojects {
subprojects {
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
kotlinOptions {
freeCompilerArgs += ['-module-name', project.path.replace('/', '.').replace(':', '_')]
freeCompilerArgs += ['-module-name', project.path.substring(1).replace(':', '')]
}
}
}
File renamed without changes.
10 changes: 5 additions & 5 deletions library/build.gradle → core/build.gradle
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
ext.module_group = "com.afollestad"
ext.module_name = "assent"
ext.module_group = "com.afollestad.assent"
ext.module_name = "core"

apply from: rootProject.file("gradle/android_library_config.gradle")

dependencies {
implementation deps.androidx.annotations
implementation deps.androidx.app_compat
api deps.androidx.app_compat

compileOnly deps.androidx.annotations
implementation deps.kotlin.stdlib8
implementation deps.debug.timber

testImplementation deps.kotlin.test.mockito
testImplementation deps.test.junit
testImplementation deps.test.mockito_inline
testImplementation deps.test.robolectric
testImplementation deps.test.truth
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@ import android.content.Context
import android.content.pm.PackageManager.PERMISSION_GRANTED
import androidx.annotation.CheckResult
import androidx.core.content.ContextCompat
import com.afollestad.assent.internal.Assent.Companion.LOCK
import com.afollestad.assent.internal.Assent.Companion.get
import com.afollestad.assent.internal.PendingRequest
import com.afollestad.assent.internal.PermissionFragment
import com.afollestad.assent.internal.equalsPermissions
import com.afollestad.assent.internal.log
import com.afollestad.assent.rationale.RationaleHandler
import timber.log.Timber

/**
* Returns true if ALL given [permissions] have been granted.
Expand All @@ -44,7 +43,7 @@ internal fun <T : Any> T.startPermissionRequest(
requestCode: Int = 20,
rationaleHandler: RationaleHandler? = null,
callback: Callback
) = synchronized(LOCK) {
) {
log("askForPermissions(${permissions.joinToString()})")

if (rationaleHandler != null) {
Expand All @@ -59,7 +58,7 @@ internal fun <T : Any> T.startPermissionRequest(
// Request matches permissions, append a callback
log("Callback appended to existing matching request")
currentRequest.callbacks.add(callback)
return@synchronized
return
}

// Create a new pending request since none exist for these permissions
Expand All @@ -83,10 +82,3 @@ internal fun <T : Any> T.startPermissionRequest(
get().requestQueue += newPendingRequest
}
}

internal fun Any.log(message: String) {
Timber.tag("Assent-${name()}")
Timber.d(message)
}

private fun Any.name() = this::class.java.simpleName
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package com.afollestad.assent

import android.app.Activity
import com.afollestad.assent.internal.Assent.Companion.ensureFragment
import com.afollestad.assent.internal.log
import com.afollestad.assent.rationale.RationaleHandler

typealias Callback = (result: AssentResult) -> Unit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,14 @@ package com.afollestad.assent
import androidx.annotation.CheckResult
import androidx.fragment.app.Fragment
import com.afollestad.assent.internal.Assent.Companion.ensureFragment
import com.afollestad.assent.internal.log
import com.afollestad.assent.rationale.RationaleHandler

/**
* Returns true if ALL given [permissions] have been granted.
*/
@CheckResult fun Fragment.isAllGranted(vararg permissions: Permission) =
activity?.isAllGranted(*permissions) ?: throw IllegalStateException(
"Fragment's Activity is null."
)
activity?.isAllGranted(*permissions) ?: error("Fragment's Activity is null.")

/**
* Performs a permission request, asking for all given [permissions], and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ enum class Permission(val value: String) {
WRITE_CALL_LOG(Manifest.permission.WRITE_CALL_LOG),
ADD_VOICEMAIL(Manifest.permission.ADD_VOICEMAIL),
USE_SIP(Manifest.permission.USE_SIP),
PROCESS_OUTGOING_CALLS(Manifest.permission.PROCESS_OUTGOING_CALLS),

BODY_SENSORS(Manifest.permission.BODY_SENSORS),

Expand All @@ -59,7 +58,12 @@ enum class Permission(val value: String) {
READ_EXTERNAL_STORAGE(Manifest.permission.READ_EXTERNAL_STORAGE),
WRITE_EXTERNAL_STORAGE(Manifest.permission.WRITE_EXTERNAL_STORAGE),

SYSTEM_ALERT_WINDOW(Manifest.permission.SYSTEM_ALERT_WINDOW);
SYSTEM_ALERT_WINDOW(Manifest.permission.SYSTEM_ALERT_WINDOW),

/** @deprecated */
@Suppress("DEPRECATION")
@Deprecated("Manifest.permission.PROCESS_OUTGOING_CALLS is deprecated.")
PROCESS_OUTGOING_CALLS(Manifest.permission.PROCESS_OUTGOING_CALLS);

companion object {
@JvmStatic fun parse(raw: String): Permission {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import androidx.annotation.VisibleForTesting
import androidx.annotation.VisibleForTesting.PRIVATE
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import timber.log.Timber

internal class Assent {

Expand All @@ -29,8 +28,6 @@ internal class Assent {
internal var permissionFragment: PermissionFragment? = null

companion object {

val LOCK = Any()
var instance: Assent? = null

@VisibleForTesting(otherwise = PRIVATE)
Expand Down Expand Up @@ -63,7 +60,7 @@ internal class Assent {
log("Re-using PermissionFragment for Context")
permissionFragment
}
return permissionFragment ?: throw IllegalStateException()
return permissionFragment ?: error("impossible!")
}

fun ensureFragment(context: Fragment): PermissionFragment = with(get()) {
Expand All @@ -76,7 +73,7 @@ internal class Assent {
log("Re-using PermissionFragment for parent Fragment")
permissionFragment
}
return permissionFragment ?: throw IllegalStateException()
return permissionFragment ?: error("impossible!")
}

fun forgetFragment() = with(get()) {
Expand All @@ -86,8 +83,3 @@ internal class Assent {
}
}
}

private fun log(message: String) {
Timber.tag("AssentData")
Timber.d(message)
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ internal fun FragmentActivity.transact(action: FragmentTransaction.(Context) ->
internal fun Fragment.transact(action: FragmentTransaction.(Context) -> Unit) {
childFragmentManager.beginTransaction()
.apply {
action(activity ?: throw IllegalStateException("Fragment's activity is null."))
action(activity ?: error("Fragment's activity is null."))
commit()
}
childFragmentManager.executePendingTransactions()
Expand Down
43 changes: 43 additions & 0 deletions core/src/main/java/com/afollestad/assent/internal/Logger.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Designed and developed by Aidan Follestad (@afollestad)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.afollestad.assent.internal

import android.util.Log
import com.afollestad.assent.BuildConfig

internal fun Any.log(
message: String,
vararg args: Any?
) {
if (BuildConfig.DEBUG) {
try {
Log.d(this::class.java.simpleName, message.format(*args))
} catch (_: Exception) {
}
}
}

internal fun Any.warn(
message: String,
vararg args: Any?
) {
if (BuildConfig.DEBUG) {
try {
Log.w(this::class.java.simpleName, message.format(*args))
} catch (_: Exception) {
}
}
}
Loading

0 comments on commit c5da287

Please sign in to comment.