#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