canelmas / let Goto Github PK
View Code? Open in Web Editor NEWAnnotation based simple API flavored with AOP to handle new Android runtime permission model
License: Apache License 2.0
Annotation based simple API flavored with AOP to handle new Android runtime permission model
License: Apache License 2.0
Hi, I am trying to implement your library. I get "Making permission request" but no dialog is showing. How do I get the dialog to show? I am using support fragment. Thanks
I tried updating Let from 0.1.11
to the new beta version 1.0.0-beta1
(also tested 1.0.0-beta2
). Gradle build the APK without any errors but for some reason it included the wrong Javax.activation.* files, this is giving me errors for the JavaMail library that I am using.
I have no idea why this is happening, and after downgrading back to 0.1.11
it was fixed. I made a ticket in JavaMail first because I thought there was an issue with JavaMail: jakartaee/mail-api#378
Even though after downgrading it was fixed for me I would like to know if this can be investigated and fixed in future versions.
If you need any info please let me know.
Consider using Transform API to have a more robust structure and to support kotlin as well.
Right now, weaving is hooked to javaCompile task which is not triggered for kotlin.
According to some crash reports I'm receiving, there is an issue happening in Android O when a method annotated with @AskPermission
is called.
This is the crash stacktrace:
Fatal Exception: com.canelmas.let.LetException: Proceeding with the annotated method failed!
at com.canelmas.let.RuntimePermissionRequest.proceed(RuntimePermissionRequest.java:139)
at com.canelmas.let.RuntimePermissionRequest.proceed(RuntimePermissionRequest.java:52)
at com.canelmas.let.LetAspect.ajc$inlineAccessMethod$com_canelmas_let_LetAspect$com_canelmas_let_RuntimePermissionRequest$proceed(LetAspect.java:1)
at com.canelmas.let.LetAspect.annotatedMethods(LetAspect.java:57)
EDIT: This happens only if the permissions is granted. Looks like the crash happens when the library tries to invoke the method.
I am currently using this library in an activity written in kotlin. I think it is not taking annotations
@AskPermission(Manifest.permission.READ_SMS) private fun checkSMSPermission() { permissionListener?.permissionGranted() // this method is called }
It is calling listener but not checking for permissions. Is this library not compatible with kotlin?
[isPermissionRevokedByPolicy](http://developer.android.com/intl/ko/reference/android/content/pm/PackageManager.html#isPermissionRevokedByPolicy%28java.lang.String, java.lang.String%29)
I get the same issue getAnnotation(java.lang.class) on a null object reference as posted in this issue
@AskPermission({Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.ACCESS_FINE_LOCATION})
public void onEvent(NewTastingEvent event) {
// Si pas d'internet
if (MilleZimU.getInstance().isOnline()) {
// Si app trop vielle
if (AppManager.getInstance().isAbleToWork()) {
// Si connecté
if (MilleZimU.getInstance().getUserInstance() != null) {
// Si degust pas finie
DateTime thirtyMinAgo = DateTime.now().minusMinutes(30);
if (getUser().hasIncompletedVoucher(thirtyMinAgo) && getUser().getOptions().getRetrieve().getStatus() == UserOption.ENABLE) {
TastingVoucher incompleteVoucher = getUser().getUncompletedVoucher(thirtyMinAgo);
new UncompletedTastingDialog(this, incompleteVoucher.id).show();
}
// Si encore des coupon
else {
if (MilleZimU.getInstance().getUserInstance().hasValidVoucher() > 0 || getUser().getOptions().getFree().getStatus() == UserOption.ENABLE) {
// Si Permission
// Attention ordre important
startPhotoActivity();
EventBus.getDefault().post(new PrepareVoucherEvent(MilleZimU.getInstance().getUserInstance().getClosestValidVoucher()));
}
// Si Pas de coupon
else
new UnpaidedTastingStartDialog(this).show();
}
}
// Si pas connecté
else {
new UnloggedTastingStartDialog(this).show();
// Si essai
// Si enregistrement
}
} else {
AppManager.getInstance().impactVersionChange(this);
}
} else {
new InternetLessDialog(this).show();
}
}
public void startPhotoActivity() {
Intent i = new Intent(this, NavigationActivity.class);
startActivity(i);
finish();
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
Let.handle(this, requestCode, permissions, grantResults);
}
@Override
public void onShowPermissionRationale(List<String> permissionList, RuntimePermissionRequest permissionRequest) {
new PermissionGrantingDialog(HomeActivity.this, "Gestion des permissions", "MilleZimU a besoin de la fonction STOCKAGE (sauvegarde du compte), APPAREIL PHOTO (enregistrement de l'étiquette) et POSITION (lieu de dégustation) pour pouvoir continuer. Veuillez accepter les demandes qui suivent", permissionRequest).show();
}
@Override
public void onPermissionDenied(List<DeniedPermission> deniedPermissionList) {
}
This is working fine on:
This failed on Nexus 5 on Android M
Hey there,
Thought you'd like to know about this crash on Android N:
java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.String[] com.canelmas.let.AskPermission.value()' on a null object reference
at com.canelmas.let.RuntimePermissionRequest.proceed(RuntimePermissionRequest.java:61)
at com.canelmas.let.RuntimePermissionRequest.proceed(RuntimePermissionRequest.java:52)
at com.canelmas.let.LetAspect.ajc$inlineAccessMethod$com_canelmas_let_LetAspect$com_canelmas_let_RuntimePermissionRequest$proceed(LetAspect.java:1)
at com.canelmas.let.LetAspect.annotatedMethods(LetAspect.java:57)
Here's the line of code where it crashed:
@AskPermission({ Manifest.permission.ACCESS_FINE_LOCATION })
Just thought I'd give you a heads up for when the full OS release actually comes out. Love the library!
Add InstantAppPlugin
and FeaturePlugin
I have come across a new issue today with this brilliant library
The library works perfectly in debug mode, but it will not work in release
the problem is that the function that is annotated by "@AskPermission" will not trigger the permission dialog at all
I have all the mentioned pro guard rules but the problem still exists
what do you think is the problem?
tested on Android 7.0 galaxy s8 and galaxy a7 2017
The first load is slow on my Moto G 2014, take about 10 seconds.
is there any way to speed it up?
Running 6.0.1 on a Nexus 6, I noticed that my methods were not called right after granting permissions. After a few debug, I can clearly see that the request code given to onRequestPermissionsResult()
has an offset of 256 compared to the task number in DelayedTasks
- resulting in a "No delayed task to execute.
It looks like requestPermissions()
is adding 256 to the given request code (or ORing it with 0x100 since only first 8 bits can be used as request code).
As a quick and dirty fix, I had to write the following to make it works:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
Let.handle(this, requestCode & 0xff, permissions, grantResults);
}
Hi,
When using this library, com.canelmas.let.DelayedTasks.tasks
appears to leak an instance of the fragment that uses it. Below is a LeakCanary log. Please let me know if I can provide any additional information to help debug this issue.
Thanks!
In com.sample.android.debug:0.0.1:1.
* com.sample.android.ui.storelocator.StoreLocatorFragment has leaked:
* GC ROOT static com.canelmas.let.DelayedTasks.tasks
* references java.util.Collections$SynchronizedMap.m
* references java.util.HashMap.table
* references array java.util.HashMap$HashMapEntry[].[2]
* references java.util.HashMap$HashMapEntry.value
* references com.canelmas.let.DelayedTasks$Task.joinPoint
* references org.aspectj.runtime.reflect.JoinPointImpl._this
* leaks com.sample.android.ui.storelocator.StoreLocatorFragment instance
* Retaining: 0.92 KB.
* Reference Key: ecf51f74-d8fa-428e-9fbc-6779906aa8e6
* Device: Huawei google Nexus 6P angler
* Android Version: 6.0.1 API: 23 LeakCanary: 1.4-beta1 02804f3
* Durations: watch=5071ms, gc=181ms, heap dump=6489ms, analysis=58273ms
* Details:
* Class com.canelmas.let.DelayedTasks
| static $staticOverhead = byte[8]@326231041 (0x1371e401)
| static tasks = java.util.Collections$SynchronizedMap@326207008 (0x13718620)
* Instance of java.util.Collections$SynchronizedMap
| static $staticOverhead = byte[8]@1874459337 (0x6fb9fac9)
| static serialVersionUID = 1978198479659022715
| m = java.util.HashMap@326184768 (0x13712f40)
| mutex = java.util.Collections$SynchronizedMap@326207008 (0x13718620)
| shadow$_klass_ = java.util.Collections$SynchronizedMap
| shadow$_monitor_ = 0
* Instance of java.util.HashMap
| static MINIMUM_CAPACITY = 4
| static serialPersistentFields = java.io.ObjectStreamField[1]@1873718864 (0x6faeae50)
| static EMPTY_TABLE = java.util.HashMap$HashMapEntry[2]@1873718408 (0x6faeac88)
| static serialVersionUID = 362498820763181265
| static $staticOverhead = byte[48]@1874489281 (0x6fba6fc1)
| static MAXIMUM_CAPACITY = 1073741824
| static DEFAULT_LOAD_FACTOR = 0.75
| entryForNullKey = null
| entrySet = null
| keySet = null
| modCount = 4
| size = 2
| table = java.util.HashMap$HashMapEntry[4]@326288640 (0x1372c500)
| threshold = 3
| values = null
| keySet = null
| valuesCollection = null
| shadow$_klass_ = java.util.HashMap
| shadow$_monitor_ = 0
* Array of java.util.HashMap$HashMapEntry[]
| [0] = null
| [1] = null
| [2] = java.util.HashMap$HashMapEntry@329076224 (0x139d4e00)
| [3] = null
* Instance of java.util.HashMap$HashMapEntry
| hash = 1262722378
| key = java.lang.Integer@1873706008 (0x6fae7c18)
| next = java.util.HashMap$HashMapEntry@326288672 (0x1372c520)
| value = com.canelmas.let.DelayedTasks$Task@329076192 (0x139d4de0)
| shadow$_klass_ = java.util.HashMap$HashMapEntry
| shadow$_monitor_ = 0
* Instance of com.canelmas.let.DelayedTasks$Task
| joinPoint = org.aspectj.runtime.reflect.JoinPointImpl@329074624 (0x139d47c0)
| permissionList = java.util.ArrayList@329076032 (0x139d4d40)
| requestCode = 1
| shadow$_klass_ = com.canelmas.let.DelayedTasks$Task
| shadow$_monitor_ = 0
* Instance of org.aspectj.runtime.reflect.JoinPointImpl
| _this = com.sample.android.ui.storelocator.StoreLocatorFragment@327039024 (0x137e3830)
| arc = com.sample.android.ui.storelocator.StoreLocatorFragment$AjcClosure1@329074688 (0x139d4800)
| args = java.lang.Object[0]@321742640 (0x132d6730)
| staticPart = org.aspectj.runtime.reflect.JoinPointImpl$StaticPartImpl@322750176 (0x133cc6e0)
| target = com.sample.android.ui.storelocator.StoreLocatorFragment@327039024 (0x137e3830)
| shadow$_klass_ = org.aspectj.runtime.reflect.JoinPointImpl
| shadow$_monitor_ = 0
* Instance of com.sample.android.ui.storelocator.StoreLocatorFragment
| static PIN_LABELS = java.lang.String[5]@322750400 (0x133cc7c0)
| static ajc$tjp_0 = org.aspectj.runtime.reflect.JoinPointImpl$StaticPartImpl@322750176 (0x133cc6e0)
| static MAX_PINS_ON_MAP = 5
| static $staticOverhead = byte[32]@320919553 (0x1320d801)
| static $change = null
| analytics = com.google.firebase.analytics.FirebaseAnalytics@319747056 (0x130ef3f0)
| api = $Proxy0@315108288 (0x12c82bc0)
| googleMap = com.google.android.gms.maps.GoogleMap@328919184 (0x139ae890)
| locationName = java.lang.String@321788944 (0x132e1c10)
| mapView = com.google.android.gms.maps.MapView@328363008 (0x13926c00)
| searchBoxView = com.sample.android.ui.widget.FilterableSearchBoxView@328364032 (0x13927000)
| subscriptions = rx.subscriptions.CompositeSubscription@326522400 (0x13765620)
| view = android.support.percent.PercentRelativeLayout@328361984 (0x13926800)
| unbinder = butterknife.Unbinder$1@321742608 (0x132d6710)
| mAdded = false
| mAllowEnterTransitionOverlap = null
| mAllowReturnTransitionOverlap = null
| mAnimatingAway = null
| mArguments = null
| mBackStackNesting = 0
| mCalled = true
| mCheckedForLoaderManager = false
| mChildFragmentManager = null
| mContainer = null
| mContainerId = 0
| mDeferStart = false
| mDetached = false
| mEnterTransition = null
| mEnterTransitionCallback = null
| mExitTransition = null
| mExitTransitionCallback = null
| mFragmentId = 0
| mFragmentManager = null
| mFromLayout = false
| mHasMenu = false
| mHidden = false
| mHost = null
| mInLayout = false
| mIndex = -1
| mInnerView = null
| mLoaderManager = null
| mLoadersStarted = false
| mMenuVisible = true
| mNextAnim = 0
| mParentFragment = null
| mReenterTransition = java.lang.Object@321742496 (0x132d66a0)
| mRemoving = false
| mRestored = false
| mRetainInstance = false
| mRetaining = false
| mReturnTransition = java.lang.Object@321742496 (0x132d66a0)
| mSavedFragmentState = null
| mSavedViewState = android.util.SparseArray@321537568 (0x132a4620)
| mSharedElementEnterTransition = null
| mSharedElementReturnTransition = java.lang.Object@321742496 (0x132d66a0)
| mState = 0
| mStateAfterAnimating = 0
| mTag = null
| mTarget = null
| mTargetIndex = -1
| mTargetRequestCode = 0
| mUserVisibleHint = true
| mView = null
| mWho = null
| shadow$_klass_ = com.sample.android.ui.storelocator.StoreLocatorFragment
| shadow$_monitor_ = 0
* Excluded Refs:
| Field: android.view.inputmethod.InputMethodManager.mNextServedView
| Field: android.view.inputmethod.InputMethodManager.mServedView
| Field: android.view.inputmethod.InputMethodManager.mServedInputConnection
| Field: android.view.Choreographer$FrameDisplayEventReceiver.mMessageQueue (always)
| Thread:FinalizerWatchdogDaemon (always)
| Thread:main (always)
| Thread:LeakCanary-Heap-Dump (always)
| Class:java.lang.ref.WeakReference (always)
| Class:java.lang.ref.SoftReference (always)
| Class:java.lang.ref.PhantomReference (always)
| Class:java.lang.ref.Finalizer (always)
| Class:java.lang.ref.FinalizerReference (always)
| Root Class:android.os.Binder (always)
Hi,
Thanks for great library which really makes it easier working with runtime permissions.
However I have discovered really big leak using that library. It might be similar to already reported issue #12.
The problem is directly connected to killing activity and recreating state by Android OS. (For making that easy reproducible enable "Do not keep activities" in Developer settings.)
Really simple code for reproducing mentioned issue:
public class MainActivity extends AppCompatActivity implements RuntimePermissionListener {
private static final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i(TAG, "Created " + this.hashCode());
final Button cameraButton = (Button) findViewById(R.id.camera);
cameraButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
Log.i(TAG, "Access prompted for " + MainActivity.this.hashCode());
someMethodWhichUsesCamera();
}
});
}
@AskPermission({Manifest.permission.CAMERA})
private void someMethodWhichUsesCamera() {
Log.i(TAG, "Camera accessible for " + this.hashCode());
}
@Override
public void onShowPermissionRationale(List<String> permissionList, RuntimePermissionRequest permissionRequest) {
//do nothing
}
@Override
public void onPermissionDenied(List<DeniedPermission> deniedPermissionList) {
//do nothing
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
Let.handle(this, requestCode, permissions, grantResults);
}
}
As you can this code does nothing, but important thing is the hashCode value printed in logs.
For normal flow result is following:
sample.android.let.activityleak I/MainActivity: Created 48167139
sample.android.let.activityleak I/MainActivity: Access prompted for 48167139
sample.android.let.activityleak I/MainActivity: Camera accessible for 48167139
By normal flow I mean: user clicks button which asks for permission and permission is granted immediately.
That flow is in 99% correct, but imagine following scenario: (with "Do not keep activities")
The output for such scheme is:
sample.android.let.activityleak I/MainActivity: Created 190272224
sample.android.let.activityleak I/MainActivity: Access prompted for 190272224
sample.android.let.activityleak I/MainActivity: Created 125354589
sample.android.let.activityleak I/MainActivity: Camera accessible for 190272224
Let is calling someMethodWhichUsesCamera
on killed Activity instance, thus besides this leak other exception may arrive like NPE.
Thanks
Hi, it seems there is a problem while I'm trying to update the text of the button in a method like this :
@AskPermission({
Manifest.permission.SEND_SMS,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.INTERNET
})
private void ChangeServiceRunning() {
btn.setText("Stop Service!");
btn.setBackgroundResource(R.drawable.round_active_button);
}
I have @AskPermission in my fragment that implemented RuntimePermissionListener
, something like this:
@AskPermission({CAMERA, WRITE_EXTERNAL_STORAGE}) private void startCamera() {
//Display camera view
}
It works when the permissions got granted, but when I tried to handle denied situation, onPermissionDenied()
never gets called . Just wonder when it calls onPermissionDenied()
?
After click on "show first contact" button, if I rotate the device, the activity is recreated losing the data shown.
Has anyone experienced this problem after installing this plugin?
I have updated my application to compatible java 8. After this changes runtime permission related alert not showing anymore.
Hey, I like using your library, it's super convenient, thank you for your work!
But can you please remove the logger or add the possibility to turn it off? It's really annoying.
Best Regards!
Ever since adding the AskPermissions annotations I've been getting the VerifyError below:
java.lang.VerifyError: ActivityWelcome$AjcClosure1
This is honestly my first time seeing an error of this sort so I'll keep digging to see if there's a way to resolve on my own. Posting here just incase others experience a similar issue or have suggestions for resolving.
@AskPermission(Manifest.permission.ACCESS_FINE_LOCATION)
private void startTrackingLocation() {
mTracker = LocationTracker.getInstance(this);
mTracker.startTracking();
}
EDIT
Forgot to mention this is happening on android 4.4.1 and 4.4.2 from what I can tell so far.
For your reference.
FATAL EXCEPTION: main
Process: com.mobility.iz.tstar, PID: 13347
java.lang.RuntimeException: Failure delivering result ResultInfo{who=@android:requestPermissions:, request=0, result=-1, data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }} to activity {com.mobility.iz.tstar/com.mobility.ui.DashboardActivity}: com.canelmas.let.LetException: Delayed Execution Failed!
at android.app.ActivityThread.deliverResults(ActivityThread.java:3699)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
at android.app.ActivityThread.-wrap16(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: com.canelmas.let.LetException: Delayed Execution Failed!
at com.canelmas.let.Let.handle(Let.java:74)
at com.mobility.ui.DashboardActivity.onRequestPermissionsResult(DashboardActivity.java:71)
at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:6582)
at android.app.Activity.dispatchActivityResult(Activity.java:6460)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3695)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
at android.app.ActivityThread.-wrap16(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: com.canelmas.let.LetException: Future Task execution failed!
at com.canelmas.let.DelayedTasks$Task.call(DelayedTasks.java:68)
at com.canelmas.let.DelayedTasks$Task.execute(DelayedTasks.java:59)
at com.canelmas.let.Let.handle(Let.java:72)
at com.mobility.ui.DashboardActivity.onRequestPermissionsResult(DashboardActivity.java:71)
at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:6582)
at android.app.Activity.dispatchActivityResult(Activity.java:6460)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3695)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
at android.app.ActivityThread.-wrap16(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1489)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1507)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:634)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:613)
at com.mobility.ui.DashboardActivity.init_aroundBody0(DashboardActivity.java:65)
at com.mobility.ui.DashboardActivity$AjcClosure1.run(DashboardActivity.java:1)
at org.aspectj.runtime.reflect.JoinPointImpl.proceed(JoinPointImpl.java:149)
at com.canelmas.let.DelayedTasks$Task.call(DelayedTasks.java:66)
at com.canelmas.let.DelayedTasks$Task.execute(DelayedTasks.java:59)
at com.canelmas.let.Let.handle(Let.java:72)
at com.mobility.ui.DashboardActivity.onRequestPermissionsResult(DashboardActivity.java:71)
at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:6582)
at android.app.Activity.dispatchActivityResult(Activity.java:6460)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3695)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
at android.app.ActivityThread.-wrap16(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
P.S. Thanks a ton for the library! 👍
I'm getting following error using let:
`Fatal Exception: java.lang.RuntimeException: Failure delivering result ResultInfo{who=@android:requestPermissions:, request=0, result=-1, data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }} to activity {de.fsrfb4.fb4/de.fsrfb4.fb4.TicketActivity}: com.canelmas.let.LetException: Delayed Execution Failed!
at android.app.ActivityThread.deliverResults(ActivityThread.java:3758)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3801)
at android.app.ActivityThread.access$1400(ActivityThread.java:157)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1405)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5551)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
Caused by com.canelmas.let.LetException: Delayed Execution Failed!
at com.canelmas.let.Let.handle(Let.java:74)
at de.fsrfb4.fb4.TicketActivity.onRequestPermissionsResult(TicketActivity.java:161)
at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:6588)
at android.app.Activity.dispatchActivityResult(Activity.java:6467)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3754)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3801)
at android.app.ActivityThread.access$1400(ActivityThread.java:157)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1405)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5551)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
Caused by com.canelmas.let.LetException: Future Task execution failed!
at com.canelmas.let.DelayedTasks$Task.call(DelayedTasks.java:68)
at com.canelmas.let.DelayedTasks$Task.execute(DelayedTasks.java:59)
at com.canelmas.let.Let.handle(Let.java:72)
at de.fsrfb4.fb4.TicketActivity.onRequestPermissionsResult(TicketActivity.java:161)
at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:6588)
at android.app.Activity.dispatchActivityResult(Activity.java:6467)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3754)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3801)
at android.app.ActivityThread.access$1400(ActivityThread.java:157)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1405)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5551)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)`
This is the corresponding code:
@AskPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
private void selectFile()
{
showFileChooserDialog();
}
private void showFileChooserDialog()
{
new FileChooserDialog.Builder(TicketActivity.this)
.mimeType("application/pdf")
.chooseButton(R.string.wählen)
.cancelButton(R.string.abbrechen)
.show();
}
What am i doing wrong?
Only 8 bits request codes should be used for requestPermissions(Activity activity, String[] permissions, int requestCode)
Otherwise java.lang.IllegalArgumentException: Can only use lower 8 bits for requestCode
is thrown.
Fix : #10
This'll stop this warning from appearing when Let is used in a project:
WARNING: Configuration 'compile' is obsolete and has been replaced with 'implementation' and 'api'.
Using Let with an android library, there is this error:
Transforms with scopes '[EXTERNAL_LIBRARIES]' cannot be applied to library projects.
I'm having this problem with that the annotated method is only executed the second time it's called.
What I mean is that upon the first call to the annotated method the permission dialog is shown correctly but after tapping on Allow
the actual method is not executed. I have to rerun the activity for it to actually run.
When I try to ask for "WRITE_EXTERNAL_STORAGE" before I initiate a download session using the built-in download manager, the "screen overlay detected" message shows up. Look at the code below:
@AskPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
private void downloadFile() {
String downloadDir = "/photo";
File direct = new File(Environment.getExternalStorageDirectory()
+ downloadDir);
if (!direct.exists())
direct.mkdirs();
String fileExtension = ".jpg";
String filename = name;
DownloadManager downloadManager = (DownloadManager) getActivity().getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setTitle("title");
request.setDescription("downloading...");
request.setDestinationInExternalPublicDir(downloadDir,
filename + fileExtension);
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
downloadManager.enqueue(request);
Toast toast = Toast.makeText(getActivity(), "download started", Toast.LENGTH_LONG);
LinearLayout toastLayout = (LinearLayout) toast.getView();
TextView toastTV = (TextView) toastLayout.getChildAt(0);
toastTV.setTypeface(Typeface.createFromAsset(getActivity().getAssets(), "RoyaBold.ttf"));
toast.show();
}
If you play with the screen and deny the permission one time, and dismiss the "screen overlay detected" dialog, I can then grant the permission. Strangely if I go to settings, disable the permission, and run this method again, it will bring the permission dialog successfully this time (without showing the screen overlay detected dialog)
What is the problem?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.