У меня есть GridView, к которому применяются разные изображения, связанные с экземплярами объекта. Я использую объект RealPathUtil для обработки получения путей к файлам для декодирования и отображения растровых изображений.
Когда я открываю действие, в котором эти изображения назначены сетке, мое приложение автоматически вылетает и показывает исключение NullPointerException, направленное в строке, где объявлено это предложение if:
else if ("content".equals(uri.scheme!!, ignoreCase = true)) {
// Return the remote address
return if (isGooglePhotosUri(uri)) uri.lastPathSegment else getDataColumn(context, uri, null, null)
}
Я знаком с исключениями NullPointerExceptions и с тем, почему они обычно выбрасываются, но я действительно не понимаю, почему это одно. Ни одно из изображений, которые я пытаюсь назначить, даже не отображается должным образом, так как я переключил метод отображения изображений с URI на Bitmap. Когда я назначал изображения ImageViews с помощью URI, эта проблема не возникала, но мне пришлось переключиться, потому что это вызывало проблемы на других устройствах.
Вот код от адаптера, который обрабатывает GridView, это вызывает эту ошибку. Ошибка возникает, когда значение tempUri установлено ближе к концу:
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val view: View = View.inflate(activity,R.layout.layout_adapter,null)
// Get view data from UI elements - image, name, and count
val tv_lang = view.findViewById(R.id.itemName) as TextView
val imageView = view.findViewById<ImageView>(R.id.itemImage)
val itemCount = view.findViewById(R.id.itemCount) as TextView
// Assign data to UI elements
tv_lang.text = itemList[position].itemNote
itemCount.text = itemList[position].itemCount.toString()
val itemImage = itemList[position].itemImage
// Assign each item image to corresponding grid ImageView
tempUri = Uri.parse(itemImage)
realPathUri = RealPathUtil.getRealPath(parent!!.context, tempUri).toString()
val myBitmap = BitmapFactory.decodeFile(realPathUri)
imageView.setImageBitmap(myBitmap)
return view
}
RealPathUtil
object RealPathUtil {
// SDK <= 11 && SDK < 19
/* Calls either getRealPathFromURIAPI11to19 or getRealPathFromURIAPI19, depending upon which API the software detects the user running the app through. */
@SuppressLint("ObsoleteSdkInt")
fun getRealPath(context: Context, fileUri: Uri): String? {
return if (Build.VERSION.SDK_INT < 19) {
getRealPathFromURIAPI11to18(context, fileUri)
} else {
getRealPathFromURIAPI19(context, fileUri)
}
}
/* Uses other methods within the RealPathUtil object to determine
* location list file path based upon the user's phone's active API (11-18). */
@SuppressLint("NewApi")
fun getRealPathFromURIAPI11to18(context: Context, contentUri: Uri): String? {
val project = arrayOf(MediaStore.Images.Media.DATA)
var result: String? = ""
val cursorLoader = CursorLoader(context, contentUri, project, null, null, null)
val cursor = cursorLoader.loadInBackground()
if (cursor != null) {
val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
cursor.moveToFirst()
result = cursor.getString(columnIndex)
cursor.close()
}
return result
}
/* Uses other methods within the RealPathUtil object to determine location list file
path based upon the user's phone's active API (19). */
@SuppressLint("NewApi")
fun getRealPathFromURIAPI19(context: Context, uri: Uri): String? {
val isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
// Create the DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// Safe cast the ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val type = split[0]
if ("primary".equals(type, ignoreCase = true)) {
return Environment.getExternalStorageDirectory().toString() + "/" + split[1]
}
} else if (isDownloadsDocument(uri)) {
var cursor: Cursor? = null
try {
cursor = context.contentResolver.query(uri, arrayOf(MediaStore.MediaColumns.DISPLAY_NAME), null, null, null)
cursor!!.moveToNext()
val fileName = cursor.getString(0)
val path = Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName
if (!TextUtils.isEmpty(path)) {
return path
}
} finally {
cursor?.close()
}
val id = DocumentsContract.getDocumentId(uri)
if (id.startsWith("raw:")) {
return id.replaceFirst("raw:".toRegex(), "")
}
val contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads"), java.lang.Long.valueOf(id))
return getDataColumn(context, contentUri, null, null)
} else if (isMediaDocument(uri)) {
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
val type = split[0]
var contentUri: Uri? = null
when (type) {
"image" -> contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
"video" -> contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
"audio" -> contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
}
val selection = "_id=?"
val selectionArgs = arrayOf(split[1])
return getDataColumn(context, contentUri, selection, selectionArgs)
} // Media Provider
// Downloads Provider
} else if ("content".equals(uri.scheme!!, ignoreCase = true)) {
// Return the remote address
return if (isGooglePhotosUri(uri))
uri.lastPathSegment
else
getDataColumn(context, uri, null, null) /** Collapse this if-else block into one line if any new, unexplained I/O issues arise. */
} else if ("file".equals(uri.scheme!!, ignoreCase = true)) {
return uri.path
} // File
// MediaStore
return null
}
private fun getDataColumn(context: Context, uri: Uri?, selection: String?, selectionArgs: Array<String>?): String? {
var cursor: Cursor? = null
val column = "_data"
val projection = arrayOf(column)
try {
cursor = context.contentResolver.query(uri!!, projection, selection, selectionArgs, null)
if (cursor != null && cursor.moveToFirst()) {
val index = cursor.getColumnIndexOrThrow(column)
return cursor.getString(index)
}
} finally {
cursor?.close()
}
return null
}
/* Takes the URI being analyzed and determines whether the URI authority is ExternalFileProvider or not. */
private fun isExternalStorageDocument(uri: Uri): Boolean {
return "com.android.externalstorage.documents" == uri.authority
}
/* Takes the URI being analyzed and determines whether the URI authority is DownloadsProvider or not. */
private fun isDownloadsDocument(uri: Uri): Boolean {
return "com.android.providers.downloads.documents" == uri.authority
}
/* Takes the URI being analyzed and determines whether the URI authority is MediaProvider or not. */
private fun isMediaDocument(uri: Uri): Boolean {
return "com.android.providers.media.documents" == uri.authority
}
/* Takes the URI being analyzed and determines whether the URI authority is Google Photos or not. */
private fun isGooglePhotosUri(uri: Uri): Boolean {
return "com.google.android.apps.photos.content" == uri.authority
}
}
Я понимаю, что это связано с тем, как путь извлекается, но я действительно не знаю как. Я давно использую этот объект и никогда не сталкивался с подобной проблемой, поэтому я действительно не знаю, с чего начать отладку. Я не прошу решения моей проблемы, но если бы какой-нибудь проницательный человек с большим опытом, чем я, мог бы сказать мне, откуда эта проблема, я мог бы разобраться. Еще раз спасибо!