안드로이드 10 을 열지 못했습니다:기술(허가 거부)

을 위해 최근에는 응용 프로그램 중 하나는 내가 일하던에서,우리는 변경의 대상 SDK API 수준 29 일(안드로이드 10). 변경 된 이후 우리의 워크플로 중 하나 파산. 워크 플로우는 간단합니다,그들은 자신의 프로필에 로고를 업로드 할 경우 우리는 사용자에게. 우리는 사용자가 자신의 미디어 갤러리에서 파일을 선택하고 서버에이 이미지를 업로드 할 수 있습니다.

안드로이드 10 장치에서 이 워크플로를 실행하면 이미지를 업로드하지 못했습니다. 우리가 본 오류가 열려 실패했습니다.

안드로이드 문서에 따르면.

안드로이드 10 이상을 대상으로하는 앱은 기본적으로 외부 저장 장치 또는 범위 저장 장치에 대한 범위 액세스 권한이 부여됩니다. 이러한 앱은 앱별 디렉터리

설명서

“다운로드”디렉터리의 파일을 포함하여 다른 앱이 만든 다른 파일에 액세스하려면 앱에서 사용자가 특정 파일을 선택할 수 있는 저장소 액세스 프레임워크를 사용해야 합니다.

워크플로우로 돌아가서 사용자가 갤러리에서 파일을 선택하면 선택한 파일이 다른 앱에서 추가 또는 편집되었다는 보장은 없습니다. 따라서 사용자가 다른 앱에 속한다고 말하는 파일을 선택하면 권한 문제가 발생합니다. 그래서,우리는 이것을 어떻게 해결합니까?

이 작업을 수행하는 몇 가지 방법이 있습니다,이 문서에서 우리는 두 가지 방법으로 볼 것이다.

응용 프로그램 안 드 로이드 10 에 대 한 오고 있는 변경에 대 한 준비가 되지 않은 경우”옵트 아웃”수 있습니다.

<manifest ... > <application android:requestLegacyExternalStorage="true" ... >
...
</application></manifest>

최근 안드로이드 개발 정상 회담에서 개인 정보 보호 팀의 개발자 중 한 명과 이야기를 나누었으며,이 솔루션을 임시 솔루션으로 사용하는 것이 좋습니다.

오픈 파일 설명자 사용

아이디어는 사용자가 미디어 갤러리에서 선택하는 파일의 복사본을 만들어 응용 프로그램 캐시 디렉토리에 추가하는 것입니다.

그래서,첫 번째 단계는 오픈 파일 설명자를 사용하여 파일을 여는 것입니다

val parcelFileDescriptor = context.contentResolver.openFileDescriptor(fileUri, "r", null)

의 그것에서 입력 스트림을 만들 수 있습니다.다음 단계는 우리 나라에서 파일 이름을 얻는 것입니다,우리는이를 위해 콘텐츠 솔버 클래스에 확장 함수를 작성할 수 있습니다. 아래의 논리는 안드로이드 문서 도구의 샘플 코드에서 영감을 참고하시기 바랍니다.

fun ContentResolver.getFileName(fileUri: Uri): String {
var name = ""
val returnCursor = this.query(fileUri, null, null, null, null)
if (returnCursor != null) {
val nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
returnCursor.moveToFirst()
name = returnCursor.getString(nameIndex)
returnCursor.close()
}
return name
}

또는 언제든지 생성된 파일 이름을 지정할 수 있습니다.

이제 우리는 파일 이름을 얻는 방법을 알고,우리의 응용 프로그램의 캐시 디렉토리에 파일을 만들 수 있습니다.

val file = File(context.cacheDir, getFileName(context.contentResolver, fileUri))

이제 이 파일의 출력 스트림을 만들어 보겠습니다.

val outputStream = FileOutputStream(file)

마지막 단계는 원본 파일의 내용을 캐시 디렉토리의 새로 만든 파일에 복사하는 것입니다.

여러 가지 방법으로 이 단계를 수행할 수 있습니다.).

IOUtils.copy(inputStream, outputStream)

모두 함께 조립할,최종 코드는 다음과 같은 것입니다.

val parcelFileDescriptor = context.contentResolver.openFileDescriptor(fileUri, "r", null)
parcelFileDescriptor?.let {
val inputStream = FileInputStream(parcelFileDescriptor.fileDescriptor)
val file = File(context.cacheDir, context.contentResolver.getFileName(fileUri))
val outputStream = FileOutputStream(file)
IOUtils.copy(inputStream, outputStream)
}

이제 앱에 업로드해야 하는 파일 복사본이 있으므로 이제 이 파일을 백엔드 서버에 안전하게 업로드할 수 있습니다.

presenter.uploadLogo(file, ....)

이것은 당신이 직면 할 수있는 권한 문제를 해결해야합니다.

답글 남기기

이메일 주소는 공개되지 않습니다.