Как проверить, предоставил ли пользователь разрешение извне на действие/фрагмент в Android

#android #android-studio #kotlin #android-fragments

Вопрос:

Я использую dexter для предоставления разрешения во время выполнения с помощью компонента навигации.

У меня есть одно действие с несколькими фрагментами.

В этом действии я хочу попросить пользователя предоставить разрешение (хранение).

Затем у меня есть класс (не Действие или фрагмент), которому необходимо проверить, предоставил ли пользователь разрешение, прежде чем обращаться к некоторым кодам, требующим разрешения во время выполнения..

У меня также есть модель представления, которая запускает код, для которого потребуется разрешение во время выполнения

Проблема

Я не могу получить доступ к контексту ни в одном из этих классов/ViewModel. Как мне теперь проверить, предоставил ли пользователь разрешение или нет.

Класс полезности

 fun requestExternalStoragePermission(context: Context, callback: PermissionsCallback) {
    Dexter.withContext(context) //
        .withPermissions(listOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE))
        .withListener(object : MultiplePermissionsListener {
            override fun onPermissionsChecked(p0: MultiplePermissionsReport?) {
                p0?.let {
                    if (p0.areAllPermissionsGranted()) {
                        callback.onPermissionRequest(granted = true)
                    } else {
                        callback.onPermissionRequest(granted = false)
                    }
                }
            }
            override fun onPermissionRationaleShouldBeShown(
                p0: MutableList<PermissionRequest>?,
                p1: PermissionToken?
            ) {
                p1?.continuePermissionRequest()
            }
        })
        .check()
}
 

Интерфейс

  interface PermissionsCallback {
  fun onPermissionRequest(granted: Boolean)
}
 

Основная деятельность

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    checkForPermission()
    setContentView(binding.root)
}

 private fun checkForPermission(){
  Utility.requestExternalStoragePermission(
      this,
      object : PermissionsCallback {
      override fun onPermissionRequest(granted: Boolean) {
      if (granted) {
       //good
       } else {
       //show settings
     }
}
 

UPDATED

MusicService

 class MusicService : MediaBrowserServiceCompat() {

 private val serviceJob = Job()
 private val serviceScope = CoroutineScope(Dispatchers.Main   
serviceJob)

var context: Context? = null
   
    override fun onCreate() {
    super.onCreate()
    context = this
    checkForPermission()
  
 }

  private fun checkForPermission(){
    Utility.requestExternalStoragePermission(
        this,
        object : PermissionsCallback {
            override fun onPermissionRequest(granted: Boolean) {
                if (granted) {
                    //good, load songs
                    serviceScope.launch {
                        musicSource.fetchMediaData()
                    }
                } else {
                    //do something else
                    Toast.makeText(context, "We need permission nowwww", Toast.LENGTH_LONG)
                        .show()
                }
            }
        })
 }

 override fun onDestroy() {
    super.onDestroy()
    serviceScope.cancel()

    exoPlayer.removeListener(musicPlayerEventListener)
    exoPlayer.release()

}

}
 

Модель представления

  init {
    viewModelScope.launch {
        val allArtistes = artisteDatabase.getAllArtiste().....//I need to check here tooo
        _artisteList.value = Resource.success(allArtistes)
    }
}

fun doGetArtisteSongs(long: Long){
    viewModelScope.launch {
         val artisteSongs = artisteDatabase.getArtisteSongs(long).....//I need to check here too
        _artisteSongList.value = Resource.success(artisteSongs)
    }
}
 

Я не смог бы использовать свою служебную функцию для проверки наличия разрешений на этот неактивированный/фрагментный класс и модель представления, потому что для этого требуется «контекст».

Каков правильный выход?

Комментарии:

1. Я мог видеть, что у вас есть функция в вашем служебном классе и имеет параметр контекста, и переход от действия, в чем ошибка?

2. Никакой ошибки… Я хочу проверить, было ли предоставлено такое же разрешение в классе без активности/фрагмента и в модели представления (которая не имеет контекста)

Ответ №1:

Если MusicService является классом обслуживания, вы можете получить контекст из службы.

  Context context;
    
    @Override
    public void onCreate() {
        super.onCreate();
        context = this;
    }
    
 //then you can call requestExternalStoragePermission() using context.

 //If you want context in viewmodel use HILT dependency injection library.

 @ViewModelInject
    public MainViewModel(MainRepository mainRepository, @ApplicationContext Context context) {
        this.repository = mainRepository;
        this.context = context;

    }
 

Комментарии:

1. Это работает… спасибо, но у меня проблема. Когда пользователь нажимает кнопку предоставить разрешение от MainActivity (обычно приложение сразу загружает список песен)… Но прямо сейчас я должен закрыть приложение и снова открыть его, прежде чем появятся песни (из класса MusicService).

2. нет необходимости закрывать и снова открывать приложение. В режиме MainActivity вызовите функцию checkForPermission() с помощью функции OnStart(). @Ибрамазин

3. Я сделал это, но не сработало. Дело в основной активности, если разрешение было предоставлено… Я ничего не делаю. Я пишу тот же код для регистрации (MusicService), но там, если разрешено -> (Затем serviceScope.launch { musicSource. fetchMediaData() } ) //извлечение песен…

4. можете ли вы показать весь код в MusicService?@ Ибрамазин

5. конечно, проверьте обновленный класс MusicService. Я попытался применить ту же логику из MainActivity -> Если предоставлено -> serviceScope.launch{ Музыкальный источник. fetchMediaData ()}, но песни не появляются, если я использую MainActivity