Code Monkey home page Code Monkey logo

permissionsdispatcher's People

Contributors

010monkey avatar aurae avatar chibatching avatar egor-n avatar esmasui avatar eyedol avatar horse315 avatar hotchemi avatar intrications avatar jczerski avatar jlleitschuh avatar jmatsu avatar kanat avatar kufear avatar louiscad avatar manijshrestha avatar mannodermaus avatar marciogranzotto avatar patricemueller avatar phicdy avatar punchdrunker avatar shiraji avatar sibelius avatar snkashis avatar technoir42 avatar tomoya0x00 avatar toranokopg avatar twisterrob avatar vdubedout avatar wondercsabo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

permissionsdispatcher's Issues

Generate unique request code

Now, we generate request code from zero per @RuntimePermissions annotated class.
But it may cause conflict when the user annotate base class and extended class or like that at once.
So, we should generate completely unique code in the app or provide a option like this.

@RuntimePermissions(requestCodeBase=100)

Require multiple permissions at once

@NeedsPermission(values = {Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS})
void showContacts() {
    getSupportFragmentManager().beginTransaction()
        .replace(R.id.sample_content_fragment, ContactsPreviewFragment.newInstance())
        .addToBackStack("contacts")
        .commitAllowingStateLoss();
}

SYSTEM_ALERT_WINDOW and WRITE_SETTINGS support

From Android Developers,

There are a couple of permissions that don't behave like normal and dangerous permissions. SYSTEM_ALERT_WINDOW and WRITE_SETTINGS are particularly sensitive, so most apps should not use them. If an app needs one of these permissions, it must declare the permission in the manifest, and send an intent requesting the user's authorization. The system responds to the intent by showing a detailed management screen to the user.

For details on how to request these permissions, see the SYSTEM_ALERT_WINDOW and WRITE_SETTINGS reference entries.

READ_EXTERNAL_STORAGE broken on API 15 device

This will also apply to other permissions that were only introduced in newer Android versions than the app is running on.

A method in my app requires READ_EXTERNAL_STORAGE permission, but this permission was only introduced in API 16. When running the generated ...WithCheck() method on an API 15 device, PermissionsUtils.hasSelfPermissions will never return true (since the READ_EXTERNAL_STORAGE permission doesn't exist), and so the target method will never get called - even though the app will run fine without that permission. PermissionsDispatcher acts as if the permission has been denied.

I'm working around it with

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
    MyActivityPermissionsDispatcher.doThingWithCheck(this);
} else {
    doThing();
}

but that feels broken and it would be much cleaner if I didn't have to.

Support PERMISSION_DENIED_APP_OP

When the app's compileSdkVersion is under 23, onRequestPermissionResult always return GRANTED by default.
So we should modify to check with PermissionChecker.checkSelfPermissions in onRequestPermissionResult when compileSdkVersion < 23.

Duplicated value exception

I have these functions:
@NeedsPermission({Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE})
public void showCamera() {
}
@OnPermissionDenied({Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE})
void onShowCameraDenied() {
}

@OnNeverAskAgain({Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE})
void onShowCameraNeverAsk() {
}

@NeedsPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
void showGetStorage() {
}

@OnPermissionDenied(Manifest.permission.WRITE_EXTERNAL_STORAGE)
void onGetStorageDenied() {
}

@OnNeverAskAgain(Manifest.permission.WRITE_EXTERNAL_STORAGE)
void onGetStorageNeverAsk() {
}

These Functions to show camera and show gallery picker

As you know camera app needs to permissions (Camera,Storage), and gallery app only need storage permission.

In three first functions to manage with camera permissions, and the other function to manage gallery permission

The Bug is:

You provide me to set multiple permission with camera and storage in NeedsPermission annotation, but you prevent me to set them in OnPermissionDenied and OnNeverAskAgain annotations.

This is an error:
Error:Execution failed for task ':app:compileStagingDebugJavaWithJavac'.

permissions.dispatcher.processor.exception.DuplicatedValueException: [android.permission.WRITE_EXTERNAL_STORAGE] is duplicated in 'onGetStorageDenied()' annotated with '@OnPermissionDenied'

Thanks in advance.

Add Permission Denied handling

At the moment, PermissionsDispatcher's generated code for onRequestPermissionsResult verifies the grant results and invokes the positive callback annotated with @NeedsPermission(s) in case the permissions were granted. How about we add support for negative callbacks, accompanied by an annotation named @DeniedPermission(s), invoked when the user denies a requested Runtime Permission? This would be different from @ShowsRationale(s), which triggers an action at the time the permission is already being asked for.

Here's an example I threw together:

@RuntimePermissions
public class MyActivity extends AppCompatActivity {

    // The usual constants and members (...)

    @Override public void onCreate(Bundle savedInstanceState) {
        // Some other setup code (...)

        // Add a click listener to some button, initializing a "dangerous action" requiring a Runtime Permission
        someButton.setOnClickListener(v -> MyActivityPermissionsDispatcher.setupCameraWithCheck(this));
    }

    @NeedsPermission(Manifest.permission.CAMERA) void setupCamera() {
        // Perform "dangerous action", now that permission is granted
    }

    @ShowsRationale(Manifest.permission.CAMERA) void showRationaleForCamera() {
        // Show a small message accompanying the permission dialog
    }

    @DeniedPermission(Manifest.permission.CAMERA) void onCameraPermissionDenied() {
        // React to the user denying the permission, maybe show a dialog?
    }

    @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        // Propagate the result
        MyActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode, grantResults);
    }
public final class MyActivityPermissionsDispatcher {
    private static final int REQUEST_SETUPCAMERA = 0;

    private static final String[] PERMISSION_SETUPCAMERA = new String[]{"android.permission.CAMERA"};

    private MyActivityPermissionsDispatcher() {
    }

    public static void setupCameraWithCheck(MyActivity target) {
        if (PermissionUtils.hasSelfPermissions(target, PERMISSION_SETUPCAMERA)) {
            target.setupCamera();
        } else {
            if (PermissionUtils.shouldShowRequestPermissionRationale(target, PERMISSION_SETUPCAMERA)) {
                target.showRationaleForCamera();
            }
            ActivityCompat.requestPermissions(target, PERMISSION_SETUPCAMERA, REQUEST_SETUPCAMERA);
        }
    }

    public static void onRequestPermissionsResult(MyActivity target, int requestCode, int[] grantResults) {
        switch (requestCode) {
            case REQUEST_SETUPCAMERA:
                if (PermissionUtils.verifyPermissions(grantResults)) {
                    target.setupCamera();
                } else {
                    // Invoke the "permission denied" callback
                    target.onCameraPermissionDenied();
                }
                break;
        default:
                break;
        }
    }
}

Add embedded lint checks to prevent direct access to permission-protected methods

This enhancement is derived from #56, in which the OP asked for a more convenient way to use PermissionDispatcher's delegate pattern. In my opinion, it would make sense to embed custom lint checks that prevent users from directly invoking methods annotated with @NeedsPermission. Furthermore, another check would raise a warning (preferably an error) if the call to the delegate object's onRequestPermissionsResult() method is omitted in the respective Activity / Fragment method.

@NeedsPermission(Manifest.permission.CAMERA)
void useCamera() {
}

// Somewhere else...
void onCameraButtonClicked() {
    this.useCamera();    // This line would raise a lint error ("Trying to access permission-protected method directly", for instance)
}

Futher reading (tools.android.com)

Call the WithCheck method from Fragment. onRequestPermissionsResult is not called back

Generated Diapatcher.java withCheck method

ActivityCompat.requestPermissions(target.getActivity(), PERMISSION_METHOD, REQUEST_METHOD);

If the target is a fragment it is expected to be referred to as the FragmentCompat class below

FragmentCompat.requestPermissions(target, PERMISSION_METHOD, REQUEST_METHOD);

not called as well shouldShowRequestPermissionRationale method
It is necessary to call in FragmentCompat

We hope that you add the fragment for the method to PermissionsUtils.java

 public static boolean shouldShowRequestPermissionRationale(Fragment fragment, String... permissions) {
        String[] var2 = permissions;
        int var3 = permissions.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            String permission = var2[var4];
            if(FragmentCompat.shouldShowRequestPermissionRationale(fragment, permission)) {
                return true;
            }
        }

        return false;
    }

But if you make this change, there is a need to up the MinSDKVersion to 15

Thanks

Allow multiple methods to use same @NeedsPermission (and avoid DuplicatedValueException)

Say that you have multiple methods that each require the identical permission to, say, write to external storage. Because you don't know what the user is going to do, you want to make sure that if either method is called, the appropriate permissions is checked and a request is made to the user...

So--- you annotate with @NeedsPermission("android.permission.WRITE_EXTERNAL_STORAGE")
on each. But now, you get one of these:

Error:Execution failed for task ':compileDebugJavaWithJavac'. > permissions.dispatcher.processor.exceptions.DuplicatedValueException: [android.permission.WRITE_EXTERNAL_STORAGE] is duplicated in interface permissions.dispatcher.NeedsPermission

Unfortunately, the documentation for the new runtime permissions kind of assume that there's only one occasion in which you'll be asking for a permission-- you can set various request codes in @onRequestPermissionResult-- supposedly one per permission, right? But in the above case you'd have to set them to account for each method that might be using each permission. And handle the result for every possible combination of methods/permissions/responses right there.

Sigh. This could easily become a logistical nightmare. Maybe PermissionsDispatcher could make it easier by allowing more than one method to use @NeedsPermission for the same permission(s) and do the right thing?

It can't be used with Dagger 2

Hi, when I try to use it in a project with Dagger 2, I get this exception during build:

Error:Execution failed for task ':app:compileDebugJavaWithJavac'.

permissions.dispatcher.processor.exceptions.WrongClassException: Annotated class must be finished with 'Activity' or 'Fragment'

Support "never ask again"

We can check the user has checked "never ask again" or not by the following code.

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
    int[] grantResults) {
  super.onRequestPermissionsResult(requestCode, permissions, grantResults);

  switch (requestCode) {
    case REQUEST_CODE:
      if (!verifyPermissions(grantResults)) {
        if (shouldShowRequestPermissionRationale(REQUIRE_PERMISSION)) {
          // show error
        } else {
          // Never ask again.
          // show app settings guide.
        }
      } else {
        // do something.
      }
  }
}

public boolean verifyPermissions(@NonNull int... grantResults) {
  for (int result : grantResults) {
    if (result != PackageManager.PERMISSION_GRANTED) {
      return false;
    }
  }
  return true;
}

And in these case, we should lead the user to system setting activity to grant the permission.

Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);

Allow parameters

It would be nice if it could allow parameters for the function that needs permission.

For example, if the function is
@NeedsPermission(the permission)
void myFunc(Object aParamater) {
...

could be called by
MyActivityPermissionDispatcher.myFuncWithCheck(this, theObjectParameter);

Btw, any ETA on version 2.0?

Service support

It's more convenient to support Service or something on those lines which has no ui.

[Discuss] Move to Java8 from Kotlin

I'm definitely not sure this movement is good for product...so I'd like to discuss about it.

Yes, Kotlin is the nice language. But when it comes to the performance, it's still less faster than Java8.
I've not verify at all but I saw one blog post which tastes the performance of each JVM languages.

image

If it's true, I'd like to focus on the merit of the user.
And some other famous libraries that use apt don't adopt better JVM language for processor.

Umm, actually I'm just saying but how do you think about it?

Request Permission About Dialog

if we request two permission at the same time ,we agree one deny the other one , the next time , we request permission ,Should we only request the last time we deny this permission , but not all , how do you think ?

Could this support methods that return values?

First off this is very cool, so thanks for implementing it!

Right now, PermissionsDispatcher only seems to work if the method annotated with @NeedsPermission is of type void and doesn't return anything. (It actually does let you annotate a method that returns a value, but the resulting ...WithCheck methods arestatic void so you can't use it in place of the original call).

Would it be possible to make this work while the original method was blocking, ie, synchronously-- to allow for methods which may return, say, boolean on success/failure (as in loading/saving files to external storage, checking if a contact exists, etc.)?

If so, awesome!! If not, there should probably be a warning/error if you try to use @NeedsPermission on a method when a value is returned.

Thanks again, I wish I had seen this sooner. This is great!

Include Build.VERSION_CODES into library-sources.jar

At the moment, test cases are failing because of a missing link inside the JAR file which is generated for the processor's test suite:

processor\src\test\libs\library-sources.jar(permissions/dispatcher/PermissionUtils.java):18: error: cannot find symbol
import static android.os.Build.VERSION_CODES.KITKAT_WATCH;
^
  symbol:   static KITKAT_WATCH
  location: class

This is related to the recent addition of SDK-level-dependent auto-granting of permissions on devices older than the permission itself. We should either remove the dependency on these constants (and replace them with their actual values), or bundle Build.VERSION_CODES into the generated jar.

Asks for already granted permissions

I have 2 methods, both need multiple permissions:

@NeedsPermissions({WRITE_EXTERNAL_STORAGE, RECORD_AUDIO})
void recordAudio() { ... }

@NeedsPermissions({WRITE_EXTERNAL_STORAGE, CAMERA})
void takePhoto() { ... }

Even after granting the WRITE_EXTERNAL_STORAGE permission at the first method, the app still asks about this permission at the second method.

Multiple Permission Request Issue

Now I am using PermissionsDispatcher and write the following code

@NeedsPermission({Manifest.permission.READ_PHONE_STATE, Manifest.permission.WRITE_EXTERNAL_STORAGE})
    public void useDeviceId() {
        TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
        String deviceId = telephonyManager.getDeviceId();
        Log.i(LOGTAG, "useDeviceId deviceId=" + deviceId);
    }

When you call the method MainActivityPermissionsDispatcher.useDeviceIdWithCheck()
This will request two permissions at once. There are two permission in the dialog. And then you grant the first and deny the second.

Once again you call the method MainActivityPermissionsDispatcher.useDeviceIdWithCheck() the two permissions are still including the already-granted permission. This should be improved, only the denied permission should be in the dialog.

For better understanding, I did a demo, see this repo. https://github.com/androidyue/PermissionsDispatcherMutiplePermissionIssue

or use this apk:http://7u2rgp.com1.z0.glb.clouddn.com/multiple-permission-issue.apk

Can This Lib work in a background Service?

Hello, that's my question pretty much. I need to check for location permissions in my background service so I thought this lib could save me a lot of time (and code).

Processor throws IllegalArgumentException

Using version 2.0.0, I am getting the following error from the processor.

Caused by: java.lang.IllegalArgumentException: ()void
        at com.sun.tools.javac.model.JavacTypes.validateTypeNotIn(JavacTypes.java:290)
        at com.sun.tools.javac.model.JavacTypes.isSubtype(JavacTypes.java:91)
        at permissions.dispatcher.processor.util.ExtensionsKt.isSubtypeOf(Extensions.kt:67)
        at permissions.dispatcher.processor.util.ValidatorsKt.findAndValidateProcessorUnit(Validators.kt:20)
        at permissions.dispatcher.processor.PermissionsProcessor.process(PermissionsProcessor.kt:68)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:793)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java
:722)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1700(JavacProcessingEnvironment.java:97)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1029)
        at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1163)
        at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1106)
        at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:824)
        at com.sun.tools.javac.main.Main.compile(Main.java:417)

When I force version 1.2.1 everything works fine.

I am not sure how to debug this, so if you need any more information, I am happy to provide it for you.

@OnPermissionDenied and @OnNeverAskAgain not working properly

When I try to use @OnPermisionDenied like this:

@OnPermissionDenied({
            Manifest.permission.READ_PHONE_STATE,
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.RECORD_AUDIO})
public void showDeniedMessage() {}

It doesn't generate the correct code, and not even reference my method from PermissionDispatcher.
The behavior that I expected is to call showDeniedMessage for any of these permissions.

The same happens for @OnNeverAskAgain

I will try to work on this tomorrow

Update sample app and doc

Actually I ported codes from google official sample but it's a little bit complicated to understand.

  • Delete fragment
  • Rich shouldShowRationale implementation
  • never ask again handling
  • WRITE_SETTINGS and SYSTEM_ALERT_WINDOW example

Incorrect handling of interrupted permissions flow

It seems like this library should handle the case where the flow doesn't get a chance to complete. As per the API docs, when this happens, onRequestPermissionsResult() is called with an empty list of permissions and grants. This is to be treated as a cancel.

However PermissionUtils.verifyPermissions() interprets the empty grant list as valid (since there aren't any items with rejected permissions in the list). We can easily work around this by embedding the check in our code but it's a bit redundant to do every time.

ShowsRationales callback

Hi,

it would be nice, when we could show Dialog (or do any other action) on calling ShowsRationales. Now it's possible show some Toast, but you can not interact on it.
Everything what you open is overlap by permission dialog, which is called immediately.

In some cases is better show dialog with OK button than toast. When you make app for older people, they like Click on button after read a message, than autohide message like Toast.

Handling permission is denied/prohibited case in onRequestPermissionResult

Current implementation of PermissionDIspatcher generates code that executes @ShowsRationale annotated method inside onRequestPermissionResult when the permission is not granted. I think it's a bit weird (well, the Activity#shouldShowRequestPermissionRationale() is weird API in the first place...)

The doc explains the motivation behind Activity#shouldShowRequestPermissionRationale() is to help developers show custom message to explain users why the permission is necessary. IMO, this message only makes sense if you show permission dialog just after the message (see sample code by google)

On the other hand, onRequestPermissionResult() is called after developer requested permission. Additionally, at the time of onRequestPermissionResult(), developer may not be able to re-ask the permission (e.g., user select 'never ask me' option, the device policy prohibits the permission) so showing rational for permission doesn't actually help users :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.