使用 MediaStore 存储图像会导致特定三星设备上的应用程序崩溃
Storing images using MediaStore crashes app on specific Samsung devices
我已经为这个问题苦苦挣扎了一段时间,不幸的是其他答案没有给我任何线索。
我的应用程序允许用户拍照并存储在本地。大多数设备一切正常,但是我在 特定的三星设备上遇到崩溃 运行 Android 9 (API 28).
设备示例为:
三星 SM-G955F
三星 SM-G973F
下面是我用来存储图片的方法:
fun saveMedia(context: Context, uri: Uri) {
val values = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, IMAGE_PREFIX + Date().toString(DATE_FORMAT) + ".$FILE_EXTENSION")
put(MediaStore.Images.Media.MIME_TYPE, MIME_TYPE)
put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis())
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
put(MediaStore.Images.Media.IS_PENDING, 1)
} else {
@Suppress("deprecation")
put(MediaStore.Images.Media.DATA, uri.toString())
}
}
val imageCollection = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
} else {
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
}
//Crashes here
val newImageUri = context.contentResolver.insert(imageCollection, values)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (newImageUri == null) {
Log.e(TAG, "unable to insert image: " + values.get(MediaStore.Images.Media.DISPLAY_NAME))
throw IOException("Failed to create new MediaStore record: "
+ values.get(MediaStore.Images.Media.DISPLAY_NAME))
}
val bitmapSource = ImageDecoder.createSource(context.applicationContext.contentResolver, uri)
val bitmap = ImageDecoder.decodeBitmap(bitmapSource)
context.contentResolver.openOutputStream(newImageUri).use { out ->
bitmap.compress(BITMAP_COMPRESS_FORMAT, 90, out)
}
values.clear()
values.put(MediaStore.Images.Media.IS_PENDING, 0)
context.contentResolver.update(newImageUri, values, null, null)
}
load(context)
cameraFile = null
}
在这些特定设备上,应用程序在 context.contentResolver.insert(imageCollection, values)
时崩溃
作为附加信息,saveMedia 方法将其作为 uri 接收:content://media/external/images/media
这是错误
02-07 00:48:05.666: E/AndroidRuntime(18495):FATAL EXCEPTION: main Process:
02-07 00:48:05.666: E/AndroidRuntime(18495):com.myapp.myapp, PID: 3773 java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=196677, result=-1, data=Intent { (has extras) }} to activity {com.myapp.myapp/com.myapp.ui.MainActivity}:
02-07 00:48:05.666: E/AndroidRuntime(18495):java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.String.toLowerCase(java.util.Locale)' on a null object reference
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.app.ActivityThread.deliverResults(ActivityThread.java:4604)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.app.ActivityThread.handleSendResult(ActivityThread.java:4646)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:49)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1947)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.os.Handler.dispatchMessage(Handler.java:106)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.os.Looper.loop(Looper.java:214)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.app.ActivityThread.main(ActivityThread.java:7032)
02-07 00:48:05.666: E/AndroidRuntime(18495): at java.lang.reflect.Method.invoke(Native Method)
02-07 00:48:05.666: E/AndroidRuntime(18495): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
02-07 00:48:05.666: E/AndroidRuntime(18495): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
02-07 00:48:05.666: E/AndroidRuntime(18495):Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.String.toLowerCase(java.util.Locale)' on a null object reference
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.os.Parcel.createException(Parcel.java:1972)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.os.Parcel.readException(Parcel.java:1934)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.content.ContentProviderProxy.insert(ContentProviderNative.java:476)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.content.ContentResolver.insert(ContentResolver.java:1594)
02-07 00:48:05.666: E/AndroidRuntime(18495): at com.myapp.ui.tabs.progress.ProgressViewModel.saveMedia(ProgressViewModel.kt:97)
02-07 00:48:05.666: E/AndroidRuntime(18495): at com.myapp.ui.tabs.progress.ProgressFragment.onActivityResult(ProgressFragment.kt:185)
02-07 00:48:05.666: E/AndroidRuntime(18495): at androidx.fragment.app.FragmentActivity.onActivityResult(FragmentActivity.java:170)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.app.Activity.dispatchActivityResult(Activity.java:7759)
我找不到它尝试应用的位置 toLowerCase()
也找不到什么对象为空。
我错过了什么吗?
非常感谢任何提示
谢谢
我最终通过更改这一行解决了这个问题
put(MediaStore.Images.Media.DATA, uri.toString())
至此
put(MediaStore.Images.Media.DATA, uri.path)
然后使用以下区分特定 Android 版本的图像加载图像
fun loadPicture(uri: Uri, date: Date) {
val request = Glide.with(this@ProgressFragment)
val builder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
request.load(uri)
} else {
request.load(File(uri.path!!))
}
builder.centerCrop().into(picture)
pictureDate.text = date.toString(getString(R.string.fragment_progress_date))
}
我已经为这个问题苦苦挣扎了一段时间,不幸的是其他答案没有给我任何线索。
我的应用程序允许用户拍照并存储在本地。大多数设备一切正常,但是我在 特定的三星设备上遇到崩溃 运行 Android 9 (API 28).
设备示例为:
三星 SM-G955F
三星 SM-G973F
下面是我用来存储图片的方法:
fun saveMedia(context: Context, uri: Uri) {
val values = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, IMAGE_PREFIX + Date().toString(DATE_FORMAT) + ".$FILE_EXTENSION")
put(MediaStore.Images.Media.MIME_TYPE, MIME_TYPE)
put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis())
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES)
put(MediaStore.Images.Media.IS_PENDING, 1)
} else {
@Suppress("deprecation")
put(MediaStore.Images.Media.DATA, uri.toString())
}
}
val imageCollection = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
} else {
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
}
//Crashes here
val newImageUri = context.contentResolver.insert(imageCollection, values)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (newImageUri == null) {
Log.e(TAG, "unable to insert image: " + values.get(MediaStore.Images.Media.DISPLAY_NAME))
throw IOException("Failed to create new MediaStore record: "
+ values.get(MediaStore.Images.Media.DISPLAY_NAME))
}
val bitmapSource = ImageDecoder.createSource(context.applicationContext.contentResolver, uri)
val bitmap = ImageDecoder.decodeBitmap(bitmapSource)
context.contentResolver.openOutputStream(newImageUri).use { out ->
bitmap.compress(BITMAP_COMPRESS_FORMAT, 90, out)
}
values.clear()
values.put(MediaStore.Images.Media.IS_PENDING, 0)
context.contentResolver.update(newImageUri, values, null, null)
}
load(context)
cameraFile = null
}
在这些特定设备上,应用程序在 context.contentResolver.insert(imageCollection, values)
时崩溃
作为附加信息,saveMedia 方法将其作为 uri 接收:content://media/external/images/media
这是错误
02-07 00:48:05.666: E/AndroidRuntime(18495):FATAL EXCEPTION: main Process:
02-07 00:48:05.666: E/AndroidRuntime(18495):com.myapp.myapp, PID: 3773 java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=196677, result=-1, data=Intent { (has extras) }} to activity {com.myapp.myapp/com.myapp.ui.MainActivity}:
02-07 00:48:05.666: E/AndroidRuntime(18495):java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.String.toLowerCase(java.util.Locale)' on a null object reference
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.app.ActivityThread.deliverResults(ActivityThread.java:4604)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.app.ActivityThread.handleSendResult(ActivityThread.java:4646)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:49)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1947)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.os.Handler.dispatchMessage(Handler.java:106)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.os.Looper.loop(Looper.java:214)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.app.ActivityThread.main(ActivityThread.java:7032)
02-07 00:48:05.666: E/AndroidRuntime(18495): at java.lang.reflect.Method.invoke(Native Method)
02-07 00:48:05.666: E/AndroidRuntime(18495): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
02-07 00:48:05.666: E/AndroidRuntime(18495): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)
02-07 00:48:05.666: E/AndroidRuntime(18495):Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.String.toLowerCase(java.util.Locale)' on a null object reference
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.os.Parcel.createException(Parcel.java:1972)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.os.Parcel.readException(Parcel.java:1934)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:135)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.content.ContentProviderProxy.insert(ContentProviderNative.java:476)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.content.ContentResolver.insert(ContentResolver.java:1594)
02-07 00:48:05.666: E/AndroidRuntime(18495): at com.myapp.ui.tabs.progress.ProgressViewModel.saveMedia(ProgressViewModel.kt:97)
02-07 00:48:05.666: E/AndroidRuntime(18495): at com.myapp.ui.tabs.progress.ProgressFragment.onActivityResult(ProgressFragment.kt:185)
02-07 00:48:05.666: E/AndroidRuntime(18495): at androidx.fragment.app.FragmentActivity.onActivityResult(FragmentActivity.java:170)
02-07 00:48:05.666: E/AndroidRuntime(18495): at android.app.Activity.dispatchActivityResult(Activity.java:7759)
我找不到它尝试应用的位置 toLowerCase()
也找不到什么对象为空。
我错过了什么吗?
非常感谢任何提示 谢谢
我最终通过更改这一行解决了这个问题
put(MediaStore.Images.Media.DATA, uri.toString())
至此
put(MediaStore.Images.Media.DATA, uri.path)
然后使用以下区分特定 Android 版本的图像加载图像
fun loadPicture(uri: Uri, date: Date) {
val request = Glide.with(this@ProgressFragment)
val builder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
request.load(uri)
} else {
request.load(File(uri.path!!))
}
builder.centerCrop().into(picture)
pictureDate.text = date.toString(getString(R.string.fragment_progress_date))
}