728x90
서비스 C의 코틀린 프로젝트에서 사용하던 웹뷰 카메라, 사진 업로드 코드가 안드로이드 버전 10 이상에서 작동하지 않는 문제가 발생했고, 해당 문제를 조치하는 방법을 담은 글이다.
AndroidManifest.xml
<manifest ...> 바로 아래에 permission을 다음과 같이 추가한다.
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<application...> 아래에 FileProvider 필요한 부분을 넣어준다.
(안드로이드 10 이상부터는 FileProvider를 이용해서 카메라 사진을 관리하는 것 같다.)
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
프로젝트 res 디렉토리 아래에 xml 디렉토리를 만들고 file_paths.xml 파일을 생성한다.
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images" path="Android/data/..프로젝트 도메인../files/Pictures" />
</paths>
MainActivity.kt
먼저 카메라 권한 설정 함수이다.
fun checkPermission (): Boolean {
return (ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)
}
fun askPhonePermissions () {
if (!checkPermission()) {
ActivityCompat.requestPermissions(this, arrayOf(
android.Manifest.permission.CAMERA), 0)
}
}
그 다음은 html input type이 file인 태그를 선택했을 때 실행되는 함수이다.
// html input type file 인 태그를 선택했을 때 실행된다
var cameraImageUri: Uri? = null
var cameraPhotoPath: String? = null
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
override fun onShowFileChooser(view: WebView, filePath: ValueCallback<Array<Uri>>, fileChooserParams: FileChooserParams): Boolean {
// Android 10이상부터 카메라 권한이 켜져 있어야한다 (권한 거부되어 있으면 팝업창 뜨도록)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q &&
ContextCompat.checkSelfPermission(this@NewMainActivity, android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
val dlg: AlertDialog.Builder = AlertDialog.Builder(this@NewMainActivity, android.R.style.Theme_DeviceDefault_Light_Dialog_NoActionBar_MinWidth)
dlg.setTitle("권한 설정 알림")
dlg.setMessage("[설정 > 애플리케이션 > 체킹 > 권한]에서 카메라 권한을 활성화 해주세요")
dlg.setPositiveButton("확인", DialogInterface.OnClickListener{
_, _ ->
})
dlg.show()
return false
}
if (filePathCallback != null) {
filePathCallback!!.onReceiveValue(null)
filePathCallback = null;
}
filePathCallback = filePath
var takePictureIntent: Intent? = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
if (takePictureIntent != null) {
var photoFile: File? = null
try {
photoFile = createImageFile()
takePictureIntent.putExtra("PhotoPath", cameraPhotoPath)
} catch (ex: IOException) {
Log.e(TAG, "Unable to create Image File", ex)
}
if (photoFile != null) {
// For android > 10.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
photoFile?.also{
val strpa = applicationContext.packageName
mCameraPhotoPath = "file:" + photoFile.absolutePath
cameraImageUri = FileProvider.getUriForFile(this@NewMainActivity,
strpa + ".fileprovider", it)
takePictureIntent!!.putExtra(MediaStore.EXTRA_OUTPUT,
cameraImageUri)
}
} else {
cameraPhotoPath = "file:" + photoFile.absolutePath
cameraImageUri = Uri.fromFile(photoFile)
takePictureIntent!!.putExtra(MediaStore.EXTRA_OUTPUT,
cameraImageUri)
}
} else {
takePictureIntent = null
}
}
val contentSelectionIntent = Intent(Intent.ACTION_GET_CONTENT)
contentSelectionIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
contentSelectionIntent.addCategory(Intent.CATEGORY_OPENABLE)
contentSelectionIntent.type = "*/*"
val intentArray: Array<Intent?>
intentArray = takePictureIntent?.let { arrayOf(it) } as Array<Intent?>? ?: arrayOfNulls<Intent>(0)
val chooserIntent = Intent(Intent.ACTION_CHOOSER)
chooserIntent.putExtra(Intent.EXTRA_INTENT, contentSelectionIntent)
chooserIntent.putExtra(Intent.EXTRA_TITLE, "Image Chooser")
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray)
startActivityForResult(chooserIntent, INPUT_FILE_REQUEST_CODE)
return true
}
private fun createImageFile(): File {
val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
val imageFileName = "JPEG_" + timeStamp
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val storageDir: File? = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
return File.createTempFile(
"JPEG_${timeStamp}_",
".jpg",
storageDir
).apply{
currentPhotoPath = absolutePath
}
} else {
val storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
return File.createTempFile(
imageFileName,
".jpg",
storageDir
)
}
}
여기까지가 image chooser를 만드는 과정이었고
이제 사진을 선택하거나 사진을 찍은후 확인을 누르면 실행되는 함수는 아래와 같다
// 사진 선택 후 실행되는 함수(카메라나 사진 폴더에서 사진 선택했을 때)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode != INPUT_FILE_REQUEST_CODE || filePathCallback == null) {
super.onActivityResult(requestCode, resultCode, data)
return
}
var results: Array<Uri>? = null
if (resultCode == Activity.RESULT_OK) {
if (data == null) {
if (cameraPhotoPath != null) {
results = arrayOf(Uri.parse(cameraPhotoPath))
filePathCallback!!.onReceiveValue(results)
}
} else if (data.data == null) {
data.data = cameraImageUri
filePathCallback!!.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data))
} else {
val dataString = data.dataString
var clipData: ClipData? = null
var clipDataItems: ArrayList<Uri> = ArrayList()
if (dataString != null) {
results = arrayOf(Uri.parse(dataString))
} else {
clipData = data.clipData
if (clipData != null) {
for (i in 0 until clipData.itemCount) {
clipDataItems.add(clipData.getItemAt(i).uri)
}
}
val semiResults = arrayOfNulls<Uri>(clipDataItems.size)
clipDataItems.toArray(semiResults)
results = semiResults as Array<Uri>
}
filePathCallback!!.onReceiveValue(results)
}
}
filePathCallback = null
return
}
Reference
https://kangmin1012.tistory.com/22
https://superwony.tistory.com/149
http://www.joshi.co.kr/index.php?mid=board_QBES95&document_srl=306736
728x90
'Kotlin' 카테고리의 다른 글
안드로이드 App Bundle API 수준 31 이상을 타겟팅해야 합니다. 해결방법 (0) | 2022.11.17 |
---|---|
안드로이드 11 URL로 사진 저장, 다운로드 하는 법 (0) | 2022.11.16 |