Android 5.0.2图库选图无法显示ImageView及版本适配问题求助
嘿,针对你遇到的Android版本适配问题——尤其是Android 5.0.2里从图库选的Bitmap没法显示在ImageView的情况,结合你贴的代码片段,我整理了具体的排查和解决办法,希望能帮到你:
Android 5.0.2选图显示异常及版本适配解决方案
一、先解决Android 5.0.2的Bitmap显示问题
从你提供的StartActivity代码来看,核心问题大概率是Uri路径解析不兼容或者Bitmap加载导致的内存溢出,毕竟Android 5.0(API 21)开始,系统对图库返回的content://类型Uri处理逻辑有了变化,旧的路径解析方式在这个版本会失效。
1. 适配不同版本的Uri路径解析
替换你原来的路径获取逻辑,用这个兼容方法来拿到图片的真实路径:
private String getRealPathFromUri(Context context, Uri uri) { String path = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // 处理Android 4.4及以上的document类型Uri if (DocumentsContract.isDocumentUri(context, uri)) { String docId = DocumentsContract.getDocumentId(uri); // 区分媒体库和下载库的Uri if ("com.android.providers.media.documents".equals(uri.getAuthority())) { String id = docId.split(":")[1]; String selection = MediaStore.Images.Media._ID + "=" + id; path = getPathFromCursor(context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection); } else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) { Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId)); path = getPathFromCursor(context, contentUri, null); } } else if ("content".equalsIgnoreCase(uri.getScheme())) { // 普通content类型Uri path = getPathFromCursor(context, uri, null); } else if ("file".equalsIgnoreCase(uri.getScheme())) { // 直接是文件Uri,直接拿路径 path = uri.getPath(); } } else { // Android 5.0以下用旧方法解析 path = getPathFromCursor(context, uri, null); } return path; } // 从Cursor中获取图片路径的工具方法 private String getPathFromCursor(Context context, Uri uri, String selection) { String[] projection = {MediaStore.Images.Media.DATA}; Cursor cursor = context.getContentResolver().query(uri, projection, selection, null, null); if (cursor != null) { int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); String path = cursor.getString(columnIndex); cursor.close(); return path; } return null; }
然后在onActivityResult里用这个方法获取路径,再加载Bitmap:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) { Uri imageUri = data.getData(); String realImagePath = getRealPathFromUri(this, imageUri); if (realImagePath != null) { // 加载Bitmap时记得压缩,避免Android 5.0设备内存不足导致OOM Bitmap bitmap = getScaledBitmap(realImagePath, imgprofile.getWidth(), imgprofile.getHeight()); imgprofile.setImageBitmap(bitmap); } } }
2. 避免Bitmap加载OOM(内存溢出)
Android 5.0.2的设备普遍内存较小,直接加载原图很容易导致Bitmap无法显示甚至崩溃,用下面的方法压缩Bitmap:
private Bitmap getScaledBitmap(String imagePath, int reqWidth, int reqHeight) { BitmapFactory.Options options = new BitmapFactory.Options(); // 先只获取图片尺寸,不加载Bitmap到内存 options.inJustDecodeBounds = true; BitmapFactory.decodeFile(imagePath, options); // 计算合适的采样率 options.inSampleSize = calculateSampleSize(options, reqWidth, reqHeight); // 开始加载压缩后的Bitmap options.inJustDecodeBounds = false; return BitmapFactory.decodeFile(imagePath, options); } // 计算采样率的工具方法 private int calculateSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { final int imageWidth = options.outWidth; final int imageHeight = options.outHeight; int sampleSize = 1; if (imageHeight > reqHeight || imageWidth > reqWidth) { final int halfHeight = imageHeight / 2; final int halfWidth = imageWidth / 2; // 找到最大的采样率,保证压缩后的图片尺寸不小于目标尺寸 while ((halfHeight / sampleSize) >= reqHeight && (halfWidth / sampleSize) >= reqWidth) { sampleSize *= 2; } } return sampleSize; }
二、通用版本适配建议(解决部分功能异常)
针对你提到的「部分功能在部分Android手机异常」,除了上面的具体问题,还可以从这几点排查:
- API兼容性检查:用
Build.VERSION.SDK_INT判断版本,避免在低版本调用高版本才有的API(比如Android 6.0的动态权限、Android 8.0的通知渠道)。 - 权限适配:Android 6.0(API 23)开始需要动态申请危险权限,如果你只在Manifest里声明,6.0+设备上会导致功能失效;而5.0及以下只需要Manifest声明即可。
- 第三方库兼容:检查你用的第三方SDK最低支持版本,有些新库已经放弃了对Android 5.0的支持,可能需要降级或者找替代方案。
- 布局适配:Android 5.0引入的Material Design属性(比如
android:elevation)在低版本不生效,需要用AndroidX或support库的兼容属性替代。
内容的提问来源于stack exchange,提问作者shinmin
相关产品推荐
相关产品推荐

