diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..e0e267b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,7 @@ +[*.{kt,kts}] +indent_size=2 +continuation_indent_size=2 +insert_final_newline=true +ij_kotlin_allow_trailing_comma=true +ij_kotlin_allow_trailing_comma_on_call_site=true +disabled_rules=annotation,argument-list-wrapping,spacing-between-declarations-with-annotations,filename diff --git a/build.gradle b/build.gradle index e07e783..d86e670 100644 --- a/build.gradle +++ b/build.gradle @@ -50,6 +50,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:7.2.2' + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10' classpath 'com.vanniktech:gradle-code-quality-tools-plugin:0.22.0' classpath 'com.vanniktech:gradle-maven-publish-plugin:0.21.0' classpath 'app.cash.licensee:licensee-gradle-plugin:1.5.0' diff --git a/rxpermission-testing/dependencies/releaseRuntimeClasspath.txt b/rxpermission-testing/dependencies/releaseRuntimeClasspath.txt index aaf03e7..4fa7748 100644 --- a/rxpermission-testing/dependencies/releaseRuntimeClasspath.txt +++ b/rxpermission-testing/dependencies/releaseRuntimeClasspath.txt @@ -1,6 +1,8 @@ androidx.annotation:annotation:1.4.0 io.reactivex.rxjava2:rxjava:2.2.21 -org.jetbrains.kotlin:kotlin-stdlib-common:1.6.21 -org.jetbrains.kotlin:kotlin-stdlib:1.6.21 +org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10 +org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10 +org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10 +org.jetbrains.kotlin:kotlin-stdlib:1.7.10 org.jetbrains:annotations:13.0 org.reactivestreams:reactive-streams:1.0.3 diff --git a/rxpermission-testing/src/main/java/com/vanniktech/rxpermission/testing/MockRxPermission.java b/rxpermission-testing/src/main/java/com/vanniktech/rxpermission/testing/MockRxPermission.java index 95dd49b..3df10ed 100644 --- a/rxpermission-testing/src/main/java/com/vanniktech/rxpermission/testing/MockRxPermission.java +++ b/rxpermission-testing/src/main/java/com/vanniktech/rxpermission/testing/MockRxPermission.java @@ -8,6 +8,8 @@ import io.reactivex.annotations.NonNull; import io.reactivex.annotations.Nullable; import io.reactivex.functions.Function; +import java.util.HashSet; +import java.util.Set; import static com.vanniktech.rxpermission.Permission.State.GRANTED; import static com.vanniktech.rxpermission.Permission.State.REVOKED_BY_POLICY; @@ -20,6 +22,8 @@ public final class MockRxPermission implements RxPermission { private final Permission[] permissions; + private final Set requestedPermissions = new HashSet<>(); + public MockRxPermission(final Permission... permissions) { this.permissions = permissions; } @@ -66,6 +70,8 @@ public MockRxPermission(final Permission... permissions) { @Nullable Permission get(@NonNull final String name) { for (final Permission permission : permissions) { + requestedPermissions.add(name); + if (permission.name().equals(name)) { return permission; } @@ -73,4 +79,8 @@ public MockRxPermission(final Permission... permissions) { return null; } + + @Override public boolean hasRequested(@NonNull final String permission) { + return requestedPermissions.contains(permission); + } } diff --git a/rxpermission-testing/src/test/java/com/vanniktech/rxpermission/testing/MockRxPermissionTest.java b/rxpermission-testing/src/test/java/com/vanniktech/rxpermission/testing/MockRxPermissionTest.java index 53779f4..169f3d9 100644 --- a/rxpermission-testing/src/test/java/com/vanniktech/rxpermission/testing/MockRxPermissionTest.java +++ b/rxpermission-testing/src/test/java/com/vanniktech/rxpermission/testing/MockRxPermissionTest.java @@ -8,6 +8,7 @@ import static android.Manifest.permission.CALL_PHONE; import static android.Manifest.permission.CAMERA; import static org.assertj.core.api.Java6Assertions.assertThat; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; public final class MockRxPermissionTest { @@ -149,6 +150,28 @@ public final class MockRxPermissionTest { .assertResult(callPhoneGranted, cameraGranted); } + @Test public void hasRequested() { + final MockRxPermission mockRxPermission = new MockRxPermission(callPhoneGranted, cameraGranted); + assertEquals(false, mockRxPermission.hasRequested(CALL_PHONE)); + assertEquals(false, mockRxPermission.hasRequested(CAMERA)); + + mockRxPermission + .request(CALL_PHONE) + .test() + .assertResult(callPhoneGranted); + + assertEquals(true, mockRxPermission.hasRequested(CALL_PHONE)); + assertEquals(false, mockRxPermission.hasRequested(CAMERA)); + + mockRxPermission + .requestEach(CAMERA) + .test() + .assertResult(cameraGranted); + + assertEquals(true, mockRxPermission.hasRequested(CALL_PHONE)); + assertEquals(true, mockRxPermission.hasRequested(CAMERA)); + } + @Test public void isGranted() { assertThat(new MockRxPermission().isGranted(CAMERA)).isFalse(); assertThat(new MockRxPermission(cameraGranted).isGranted(CAMERA)).isTrue(); diff --git a/rxpermission/build.gradle b/rxpermission/build.gradle index a33f7aa..9fe9aa7 100644 --- a/rxpermission/build.gradle +++ b/rxpermission/build.gradle @@ -1,10 +1,10 @@ plugins { id("app.cash.licensee") id("com.dropbox.dependency-guard") + id("com.android.library") + id("org.jetbrains.kotlin.android") } -apply plugin: 'com.android.library' - licensee { allow("Apache-2.0") allow("CC0-1.0") diff --git a/rxpermission/dependencies/releaseRuntimeClasspath.txt b/rxpermission/dependencies/releaseRuntimeClasspath.txt index aaf03e7..4fa7748 100644 --- a/rxpermission/dependencies/releaseRuntimeClasspath.txt +++ b/rxpermission/dependencies/releaseRuntimeClasspath.txt @@ -1,6 +1,8 @@ androidx.annotation:annotation:1.4.0 io.reactivex.rxjava2:rxjava:2.2.21 -org.jetbrains.kotlin:kotlin-stdlib-common:1.6.21 -org.jetbrains.kotlin:kotlin-stdlib:1.6.21 +org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10 +org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10 +org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10 +org.jetbrains.kotlin:kotlin-stdlib:1.7.10 org.jetbrains:annotations:13.0 org.reactivestreams:reactive-streams:1.0.3 diff --git a/rxpermission/src/main/java/com/vanniktech/rxpermission/RealRxPermission.java b/rxpermission/src/main/java/com/vanniktech/rxpermission/RealRxPermission.java index 3c73dd0..6ab2274 100644 --- a/rxpermission/src/main/java/com/vanniktech/rxpermission/RealRxPermission.java +++ b/rxpermission/src/main/java/com/vanniktech/rxpermission/RealRxPermission.java @@ -3,6 +3,7 @@ import android.annotation.TargetApi; import android.app.Application; import android.content.Context; +import android.content.SharedPreferences; import androidx.annotation.ChecksSdkIntAtLeast; import io.reactivex.Observable; import io.reactivex.ObservableSource; @@ -13,9 +14,14 @@ import io.reactivex.functions.Function; import io.reactivex.subjects.PublishSubject; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; +import org.jetbrains.annotations.NotNull; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.Build.VERSION.SDK_INT; @@ -29,6 +35,8 @@ public final class RealRxPermission implements RxPermission { static final Object TRIGGER = new Object(); static RealRxPermission instance; + static final String PREF_REQUESTED_PERMISSIONS = "requested-permissions"; + /** * @param context any context * @return a Singleton instance of this class @@ -165,6 +173,15 @@ public static RealRxPermission getInstance(final Context context) { } void startShadowActivity(final String[] permissions) { + final SharedPreferences sharedPreferences = getSharedPreferences(); + final Set requestedPermission = new HashSet<>(sharedPreferences.getStringSet(PREF_REQUESTED_PERMISSIONS, Collections.emptySet())); + requestedPermission.addAll(Arrays.asList(permissions)); + + sharedPreferences + .edit() + .putStringSet(PREF_REQUESTED_PERMISSIONS, requestedPermission) + .apply(); + ShadowActivity.start(application, permissions); } @@ -201,4 +218,14 @@ void onRequestPermissionsResult(@NonNull final int[] grantResults, @NonNull fina void cancelPermissionsRequests() { currentPermissionRequests.clear(); } + + @Override public boolean hasRequested(@NotNull String permission) { + final SharedPreferences sharedPreferences = getSharedPreferences(); + final Set requestedPermission = sharedPreferences.getStringSet(PREF_REQUESTED_PERMISSIONS, Collections.emptySet()); + return requestedPermission.contains(permission); + } + + private SharedPreferences getSharedPreferences() { + return application.getSharedPreferences("RxPermission", Context.MODE_PRIVATE); + } } diff --git a/rxpermission/src/main/java/com/vanniktech/rxpermission/RxPermission.java b/rxpermission/src/main/java/com/vanniktech/rxpermission/RxPermission.java deleted file mode 100644 index f3ab689..0000000 --- a/rxpermission/src/main/java/com/vanniktech/rxpermission/RxPermission.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.vanniktech.rxpermission; - -import io.reactivex.Observable; -import io.reactivex.Single; -import io.reactivex.annotations.CheckReturnValue; -import io.reactivex.annotations.NonNull; - -public interface RxPermission { - /** Requests a single permission. */ - @NonNull @CheckReturnValue Single request(@NonNull String permission); - - /** Requests multiple permissions. */ - @NonNull @CheckReturnValue Observable requestEach(@NonNull String... permissions); - - /** Returns true when the given permission is granted. */ - @CheckReturnValue boolean isGranted(@NonNull String permission); - - /** Returns true when the given permission is revoked by a policy. */ - @CheckReturnValue boolean isRevokedByPolicy(@NonNull String permission); -} diff --git a/rxpermission/src/main/java/com/vanniktech/rxpermission/RxPermission.kt b/rxpermission/src/main/java/com/vanniktech/rxpermission/RxPermission.kt new file mode 100644 index 0000000..d3c03a9 --- /dev/null +++ b/rxpermission/src/main/java/com/vanniktech/rxpermission/RxPermission.kt @@ -0,0 +1,22 @@ +package com.vanniktech.rxpermission + +import io.reactivex.Observable +import io.reactivex.Single +import io.reactivex.annotations.CheckReturnValue + +interface RxPermission { + /** Requests a single permission. */ + @CheckReturnValue fun request(permission: String): Single + + /** Requests multiple permissions. */ + @CheckReturnValue fun requestEach(vararg permissions: String): Observable + + /** Returns true when the given permission is granted. */ + @CheckReturnValue fun isGranted(permission: String): Boolean + + /** Returns true when the given permission is revoked by a policy. */ + @CheckReturnValue fun isRevokedByPolicy(permission: String): Boolean + + /** Returns tue when the given permission has been request at least once using either [request] or [requestEach]. */ + @CheckReturnValue fun hasRequested(permission: String): Boolean +} diff --git a/sample/dependencies/releaseRuntimeClasspath.txt b/sample/dependencies/releaseRuntimeClasspath.txt index b07df99..0bfb091 100644 --- a/sample/dependencies/releaseRuntimeClasspath.txt +++ b/sample/dependencies/releaseRuntimeClasspath.txt @@ -35,8 +35,8 @@ androidx.viewpager:viewpager:1.0.0 com.google.guava:listenablefuture:1.0 io.reactivex.rxjava2:rxjava:2.2.21 org.jetbrains.kotlin:kotlin-stdlib-common:1.7.10 -org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.0 -org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.0 +org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.7.10 +org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.10 org.jetbrains.kotlin:kotlin-stdlib:1.7.10 org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1 org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.6.1 diff --git a/sample/src/main/java/com/vanniktech/rxpermission/sample/MainActivity.java b/sample/src/main/java/com/vanniktech/rxpermission/sample/MainActivity.java index 80fd744..bd3a9dd 100644 --- a/sample/src/main/java/com/vanniktech/rxpermission/sample/MainActivity.java +++ b/sample/src/main/java/com/vanniktech/rxpermission/sample/MainActivity.java @@ -1,20 +1,19 @@ package com.vanniktech.rxpermission.sample; import android.Manifest; +import android.annotation.SuppressLint; import android.os.Bundle; -import android.view.View; +import android.widget.TextView; import android.widget.Toast; -import com.vanniktech.rxpermission.Permission; -import com.vanniktech.rxpermission.RealRxPermission; -import com.vanniktech.rxpermission.RxPermission; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; +import com.vanniktech.rxpermission.RealRxPermission; +import com.vanniktech.rxpermission.RxPermission; import io.reactivex.disposables.CompositeDisposable; -import io.reactivex.functions.Consumer; public class MainActivity extends AppCompatActivity { + private static final String PERMISSION = Manifest.permission.CAMERA; RxPermission rxPermission; @NonNull final CompositeDisposable compositeDisposable = new CompositeDisposable(); @@ -24,17 +23,18 @@ public class MainActivity extends AppCompatActivity { rxPermission = RealRxPermission.getInstance(getApplication()); setContentView(R.layout.activity_main); + updateTextView(); + + findViewById(R.id.enableCamera).setOnClickListener(v -> compositeDisposable.add(rxPermission.requestEach( + PERMISSION) + .subscribe(granted -> { + updateTextView(); + Toast.makeText(this, granted.toString(), Toast.LENGTH_LONG).show(); + }))); + } - findViewById(R.id.enableCamera).setOnClickListener(new View.OnClickListener() { - @Override public void onClick(final View v) { - compositeDisposable.add(rxPermission.requestEach(Manifest.permission.CAMERA) - .subscribe(new Consumer() { - @Override public void accept(final Permission granted) throws Exception { - Toast.makeText(MainActivity.this, granted.toString(), Toast.LENGTH_LONG).show(); - } - })); - } - }); + @SuppressLint("SetTextI18n") private void updateTextView() { + this.findViewById(R.id.textView).setText("Has requested: " + rxPermission.hasRequested(PERMISSION)); } @Override protected void onDestroy() { diff --git a/sample/src/main/res/layout/activity_main.xml b/sample/src/main/res/layout/activity_main.xml index c96f768..455c55f 100644 --- a/sample/src/main/res/layout/activity_main.xml +++ b/sample/src/main/res/layout/activity_main.xml @@ -1,10 +1,26 @@ -