Я разрабатываю мультиплатформенное приложение Compose, которое корректно работает на Android, но сталкивается с проблемами при доступе к библиотеке фотографий на iOS. Приложение использует ImagePicker, позволяющее пользователям выбирать изображения, и реализует обработку разрешений для доступа к библиотеке фотографий.
В журнале ошибок показано:
[PAAccessLogger] Failed to log access with error: access=
accessor: identifier:0284C142-B9D2-4134-99B0-337308EC891E kind:intervalEnd timestampAdjustment:0 tccService:kTCCServicePhotos, error=Error Domain=PAErrorDomain Code=10 "Possibly incomplete access interval automatically ended by daemon"
[core] "Error returned from daemon: Error Domain=com.apple.accounts Code=7 "(null)""
Эта ошибка предполагает, что могут быть проблемы с тем, как приложение обрабатывает разрешения на доступ к библиотеке фотографий или как оно взаимодействует с API библиотеки фотографий iOS.
Я реализовал запросы разрешений. и функциональность выбора изображений в моем проекте Compose Multiplatform с отдельными реализациями для iOS в исходном наборе iosMain. Несмотря на эти реализации, приложение по-прежнему сталкивается с ошибками при попытке доступа к библиотеке фотографий на устройствах iOS.
Я ищу информацию о том, что может быть причиной этой проблемы, специфичной для iOS, и как ее решить, сохраняя при этом перекрестный доступ. совместимость платформ в моем проекте Compose Multiplatform.
CommonMain:
@Composable
fun PostScreen(onEventSubmitted: () -> Unit) {
val viewModel: PostsViewModel = KoinPlatform.getKoin().get()
val imagePicker: ImagePicker = KoinPlatform.getKoin().get()
val cameraPermissionManager = remember { RequestPhotoLibraryPermission() }
val uiState by viewModel.uiState.collectAsState()
var selectedImage by remember { mutableStateOf(null) }
rememberCoroutineScope()
if (uiState.pickImage) {
imagePicker.PickImage { imageBytes ->
viewModel.setEvent(PostsEvents.OnPickImage(false))
selectedImage = imageBytes
}
}
cameraPermissionManager.RequestCameraPermission(
onPermissionGranted = {
AddPostEvent(
selectedImage = selectedImage,
onEventSubmitted = onEventSubmitted,
setEvent = { event ->
viewModel.setEvent(event)
})
},
onPermissionDenied = {
BodyMedium(text = "La fotocamera non è disponibile senza permessi")
})
LaunchedEffect(viewModel) {
viewModel.effect.collect { effect ->
when (effect) {
is PostsUIEffects.ShowSuccess -> {
println("XXXXX success")
}
is PostsUIEffects.ShowErrorMessage -> {
println("XXXXX error: ${effect.message}")
}
}
}
}
}
iosMain:
запрос разрешения
actual class RequestPhotoLibraryPermission {
@Composable
actual fun RequestCameraPermission(
onPermissionGranted: @Composable () -> Unit,
onPermissionDenied: @Composable () -> Unit
) {
var permissionStatus by remember { mutableStateOf(PHAuthorizationStatusNotDetermined) }
LaunchedEffect(Unit) {
permissionStatus = PHPhotoLibrary.authorizationStatus()
if (permissionStatus == PHAuthorizationStatusNotDetermined) {
permissionStatus = requestPhotoLibraryPermission()
}
}
when (permissionStatus) {
PHAuthorizationStatusAuthorized,
PHAuthorizationStatusLimited -> onPermissionGranted()
else -> onPermissionDenied()
}
}
private suspend fun requestPhotoLibraryPermission(): PHAuthorizationStatus =
suspendCancellableCoroutine { continuation ->
PHPhotoLibrary.requestAuthorization { status ->
continuation.resume(status)
}
}
}
iosMain ImagePicker:
actual class ImagePicker {
private var onImagePickedCallback: ((ByteArray?) -> Unit)? = null
private val pickerController = UIImagePickerController()
init {
pickerController.sourceType = UIImagePickerControllerSourceType.UIImagePickerControllerSourceTypePhotoLibrary
pickerController.setDelegate(object : NSObject(), UIImagePickerControllerDelegateProtocol, UINavigationControllerDelegateProtocol {
override fun imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo: Map) {
val image = didFinishPickingMediaWithInfo[UIImagePickerControllerOriginalImage] as? UIImage
picker.dismissViewControllerAnimated(true) {
if (image != null) {
val data = UIImageJPEGRepresentation(image, 0.8)
val bytes = data?.toByteArray()
onImagePickedCallback?.invoke(bytes)
} else {
onImagePickedCallback?.invoke(null)
}
onImagePickedCallback = null
}
}
override fun imagePickerControllerDidCancel(picker: UIImagePickerController) {
picker.dismissViewControllerAnimated(true) {
onImagePickedCallback?.invoke(null)
onImagePickedCallback = null
}
}
})
}
@Composable
actual fun PickImage(onImagePicked: (ByteArray?) -> Unit) {
val scope = rememberCoroutineScope()
LaunchedEffect(Unit) {
scope.launch(Dispatchers.Main) {
showImagePicker(onImagePicked)
}
}
}
private suspend fun showImagePicker(onImagePicked: (ByteArray?) -> Unit) = suspendCancellableCoroutine { continuation ->
onImagePickedCallback = { bytes ->
onImagePicked(bytes)
continuation.resume(Unit)
}
UIApplication.sharedApplication.keyWindow?.rootViewController?.let { rootViewController ->
rootViewController.presentViewController(pickerController, animated = true, completion = null)
} ?: run {
onImagePickedCallback?.invoke(null)
continuation.resume(Unit)
}
}
}
@OptIn(ExperimentalForeignApi::class)
fun NSData.toByteArray(): ByteArray = ByteArray(this.length.toInt()).apply {
usePinned {
memcpy(it.addressOf(0), this@toByteArray.bytes, this@toByteArray.length)
}
}
Подробнее здесь: https://stackoverflow.com/questions/789 ... atform-app
Проблемы доступа к библиотеке фотографий iOS в многоплатформенном приложении Compose ⇐ IOS
Программируем под IOS
1727393169
Anonymous
Я разрабатываю мультиплатформенное приложение Compose, которое корректно работает на Android, но сталкивается с проблемами при доступе к библиотеке фотографий на iOS. Приложение использует ImagePicker, позволяющее пользователям выбирать изображения, и реализует обработку разрешений для доступа к библиотеке фотографий.
В журнале ошибок показано:
[PAAccessLogger] Failed to log access with error: access=
accessor: identifier:0284C142-B9D2-4134-99B0-337308EC891E kind:intervalEnd timestampAdjustment:0 tccService:kTCCServicePhotos, error=Error Domain=PAErrorDomain Code=10 "Possibly incomplete access interval automatically ended by daemon"
[core] "Error returned from daemon: Error Domain=com.apple.accounts Code=7 "(null)""
Эта ошибка предполагает, что могут быть проблемы с тем, как приложение обрабатывает разрешения на доступ к библиотеке фотографий или как оно взаимодействует с API библиотеки фотографий iOS.
Я реализовал запросы разрешений. и функциональность выбора изображений в моем проекте Compose Multiplatform с отдельными реализациями для iOS в исходном наборе iosMain. Несмотря на эти реализации, приложение по-прежнему сталкивается с ошибками при попытке доступа к библиотеке фотографий на устройствах iOS.
Я ищу информацию о том, что может быть причиной этой проблемы, специфичной для iOS, и как ее решить, сохраняя при этом перекрестный доступ. совместимость платформ в моем проекте Compose Multiplatform.
CommonMain:
@Composable
fun PostScreen(onEventSubmitted: () -> Unit) {
val viewModel: PostsViewModel = KoinPlatform.getKoin().get()
val imagePicker: ImagePicker = KoinPlatform.getKoin().get()
val cameraPermissionManager = remember { RequestPhotoLibraryPermission() }
val uiState by viewModel.uiState.collectAsState()
var selectedImage by remember { mutableStateOf(null) }
rememberCoroutineScope()
if (uiState.pickImage) {
imagePicker.PickImage { imageBytes ->
viewModel.setEvent(PostsEvents.OnPickImage(false))
selectedImage = imageBytes
}
}
cameraPermissionManager.RequestCameraPermission(
onPermissionGranted = {
AddPostEvent(
selectedImage = selectedImage,
onEventSubmitted = onEventSubmitted,
setEvent = { event ->
viewModel.setEvent(event)
})
},
onPermissionDenied = {
BodyMedium(text = "La fotocamera non è disponibile senza permessi")
})
LaunchedEffect(viewModel) {
viewModel.effect.collect { effect ->
when (effect) {
is PostsUIEffects.ShowSuccess -> {
println("XXXXX success")
}
is PostsUIEffects.ShowErrorMessage -> {
println("XXXXX error: ${effect.message}")
}
}
}
}
}
iosMain:
запрос разрешения
actual class RequestPhotoLibraryPermission {
@Composable
actual fun RequestCameraPermission(
onPermissionGranted: @Composable () -> Unit,
onPermissionDenied: @Composable () -> Unit
) {
var permissionStatus by remember { mutableStateOf(PHAuthorizationStatusNotDetermined) }
LaunchedEffect(Unit) {
permissionStatus = PHPhotoLibrary.authorizationStatus()
if (permissionStatus == PHAuthorizationStatusNotDetermined) {
permissionStatus = requestPhotoLibraryPermission()
}
}
when (permissionStatus) {
PHAuthorizationStatusAuthorized,
PHAuthorizationStatusLimited -> onPermissionGranted()
else -> onPermissionDenied()
}
}
private suspend fun requestPhotoLibraryPermission(): PHAuthorizationStatus =
suspendCancellableCoroutine { continuation ->
PHPhotoLibrary.requestAuthorization { status ->
continuation.resume(status)
}
}
}
iosMain ImagePicker:
actual class ImagePicker {
private var onImagePickedCallback: ((ByteArray?) -> Unit)? = null
private val pickerController = UIImagePickerController()
init {
pickerController.sourceType = UIImagePickerControllerSourceType.UIImagePickerControllerSourceTypePhotoLibrary
pickerController.setDelegate(object : NSObject(), UIImagePickerControllerDelegateProtocol, UINavigationControllerDelegateProtocol {
override fun imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo: Map) {
val image = didFinishPickingMediaWithInfo[UIImagePickerControllerOriginalImage] as? UIImage
picker.dismissViewControllerAnimated(true) {
if (image != null) {
val data = UIImageJPEGRepresentation(image, 0.8)
val bytes = data?.toByteArray()
onImagePickedCallback?.invoke(bytes)
} else {
onImagePickedCallback?.invoke(null)
}
onImagePickedCallback = null
}
}
override fun imagePickerControllerDidCancel(picker: UIImagePickerController) {
picker.dismissViewControllerAnimated(true) {
onImagePickedCallback?.invoke(null)
onImagePickedCallback = null
}
}
})
}
@Composable
actual fun PickImage(onImagePicked: (ByteArray?) -> Unit) {
val scope = rememberCoroutineScope()
LaunchedEffect(Unit) {
scope.launch(Dispatchers.Main) {
showImagePicker(onImagePicked)
}
}
}
private suspend fun showImagePicker(onImagePicked: (ByteArray?) -> Unit) = suspendCancellableCoroutine { continuation ->
onImagePickedCallback = { bytes ->
onImagePicked(bytes)
continuation.resume(Unit)
}
UIApplication.sharedApplication.keyWindow?.rootViewController?.let { rootViewController ->
rootViewController.presentViewController(pickerController, animated = true, completion = null)
} ?: run {
onImagePickedCallback?.invoke(null)
continuation.resume(Unit)
}
}
}
@OptIn(ExperimentalForeignApi::class)
fun NSData.toByteArray(): ByteArray = ByteArray(this.length.toInt()).apply {
usePinned {
memcpy(it.addressOf(0), this@toByteArray.bytes, this@toByteArray.length)
}
}
Подробнее здесь: [url]https://stackoverflow.com/questions/78995414/ios-photo-library-access-issues-in-compose-multiplatform-app[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия