googlesamples / easypermissions

Simplify Android M system permissions
https://firebaseopensource.com/projects/googlesamples/easypermissions/
Apache License 2.0
9.87k stars 1.46k forks source link

Rationale callback when not using Fragment or Activity #218

Open Dkhusainov opened 6 years ago

Dkhusainov commented 6 years ago

Basic Information

Device type: ____ OS version: 25 EasyPermissions version: 1.0.1

Describe the problem

What happened?
I don't use Fragment or Activity as my PermissionCallback. If the user denies rationale, I don't get the callback in onRequestPermissionsResult

What did you expect to happen? Get the callback

samtstern commented 6 years ago

@Dkhusainov can you show the code that you're using to request permissions and some of the class where you expect to get the callback?

Dkhusainov commented 6 years ago

My "PermissionService" implements PermissionCallbacks, then I just delegate onRequestPermissionsResult callback manually from Activity

samtstern commented 6 years ago

@Dkhusainov please show the code where you request permissions and how you "delegate" the callback.

Dkhusainov commented 6 years ago

image

image

act variable is an Activity from which I delegate the callback

samtstern commented 6 years ago

@Dkhusainov I don't think this is a good idea, Service classes should not hold references to Activities. Also permissions should only be requested when the user is inside of your app, which means you should have an Activity or Fragment context at that time.

So I don't think EasyPermissions should support this request.

Dkhusainov commented 6 years ago
  1. It's not an android Service. Just a class that I suffixed with Service
  2. Obviously I have activitity context, otherwiouse how would I request permissions?

I simply ask you to maybe overload EasyPermissions and add another param(explicit PermissionCallbacks), instead of casting things left and right the usual Google/Android way.

image

Dkhusainov commented 6 years ago

Any updates on this issue?

aantoniv commented 5 years ago

Any updates on this issue?

Dkhusainov commented 5 years ago

I ended up just using this hack. Hope this helps anyone

  private val main = Handler(Looper.getMainLooper())

  inline fun <reified T> Any.castOrNull(): T? = if (this is T) this else null
  fun Any.getFieldValue(name: String): Any? {
    val cls = this::class.java
    val obj = this
    return cls.getDeclaredField(name).run {
      isAccessible = true
      get(obj)
    }
  }

  fun hackRationaleCallback(act: Activity, cb: EasyPermissions.RationaleCallbacks) {
    main.post {
      try {
        act
          .castOrNull<AppCompatActivity>()
          ?.supportFragmentManager
          ?.findFragmentByTag(RationaleDialogFragmentCompat.TAG)
          ?.castOrNull<RationaleDialogFragmentCompat>()
          ?.dialog
          ?.getFieldValue("mAlert")
          ?.getFieldValue("mButtonNegativeMessage")
          ?.getFieldValue("obj")
          ?.let { obj ->
            obj::class.java.getDeclaredField("mRationaleCallbacks").apply {
              isAccessible = true
              set(obj, cb)
            }
          }
        act
          .fragmentManager
          ?.findFragmentByTag(RationaleDialogFragment.TAG)
          ?.castOrNull<RationaleDialogFragment>()
          ?.dialog
          ?.getFieldValue("mAlert")
          ?.getFieldValue("mButtonNegativeMessage")
          ?.getFieldValue("obj")
          ?.let { obj ->
            obj::class.java.getDeclaredField("mRationaleCallbacks").apply {
              isAccessible = true
              set(obj, cb)
            }
          }
      } catch (e: Throwable) {
        Timber.e(e, "Failed to hack EasyPermission rationale callback")
      }
    }
  }
java1developer commented 5 years ago

For make permission request from service or worker - use Notification.