Android 调用系统相机和相册 - 填坑篇

2,995 阅读2分钟

上篇分享了Android调用系统相机和相册,但是由于国内Android机型繁多,各家都自己的rom,调用系统的还是会出现不少问题:

一、拍照照片被旋转

这种情况是使用Camera拍照以后,得到的照片会被自动旋转(90°、180°、270°)。解决方案:

1、读取图片的旋转属性

/**
 * 读取图片的旋转的角度
 *
 * @param path
 *            图片绝对路径
 * @return 图片的旋转角度
 */private int getBitmapDegree(String path) {    
 int degree = 0;    
 try {        
         
        ExifInterface exifInterface = new ExifInterface(path);        
         
        int orientation = exifInterface.
         getAttributeInt(ExifInterface.
        TAG_ORIENTATION,
                ExifInterface.ORIENTATION_NORMAL);        
         switch (orientation) {        
         case ExifInterface.ORIENTATION_ROTATE_90:
            degree = 90;            
         break;        
         case ExifInterface.ORIENTATION_ROTATE_180:
            degree = 180;            
         break;        
         case ExifInterface.ORIENTATION_ROTATE_270:
            degree = 270;            
         break;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }    return degree;
}

2、将图片按照某个角度进行旋转

/**
 * 将图片按照某个角度进行旋转
 *
 * @param bm
 *            需要旋转的图片
 * @param degree
 *            旋转角度
 * @return 旋转后的图片
 */public static Bitmap rotateBitmapByDegree(Bitmap bm,     int degree) {
    Bitmap returnBm = null;    
     
    Matrix matrix = new Matrix();
    matrix.postRotate(degree);    
     try {    
     
        returnBm = Bitmap.createBitmap(bm, 
0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
    } catch (OutOfMemoryError e) {
    }    if (returnBm == null) {
        returnBm = bm;
    }    if (bm != returnBm) {
        bm.recycle();
    }    return returnBm;
}

详见博客:https://www.baidufe.com/item/4bb733d9999c53cb8fed.html

二、调用系统相册,拿不到绝对路径

上篇的方法,我在大部分手机测试是可行,但是一些机型还是拿不到,解决方案:

public class AbsolutePathUtil {    
public static String getAbsolutePath(final Context context
    , final Uri uri) {        
         
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT 
         && DocumentsContract.isDocumentUri(context, uri)) {            
         
            if (isExternalStorageDocument(uri)) {
                 final String docId = DocumentsContract
                 .getDocumentId(uri);                
                 final String[] split = docId.split(":");                
                 final String type = split[0];                
                 if ("primary".equalsIgnoreCase(type)) {                    
                 return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
                 
            }
             
            else if (isDownloadsDocument(uri)) {                
             final String id = DocumentsContract.getDocumentId(uri);                
             final Uri contentUri = ContentUris.withAppendedId(
            Uri.parse("content://downloads/public_downloads"),
              Long.valueOf(id));                
              return getDataColumn(context, contentUri, null, null);
            }            
              
            else if (isMediaDocument(uri)) {                
             final String docId = DocumentsContract
             .getDocumentId(uri);                
             final String[] split = docId.split(":");                
             final String type = split[0];

                Uri contentUri = null;                
                 if ("image".equals(type)) {
                    contentUri = MediaStore.Images
                 .Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video
                 .Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio
                 .Media.EXTERNAL_CONTENT_URI;
                }                
                 final String selection = "_id=?";                
                 final String[] selectionArgs = new String[]{
                        split[1]
                };                
             return getDataColumn(context, contentUri            , selection, selectionArgs);
            }
        }        
             
        else if ("content".equalsIgnoreCase(uri.getScheme())) {            
             return getDataColumn(context, uri, null, null);
        }        
             
        else if ("file".equalsIgnoreCase(uri.getScheme())) {            
             return uri.getPath();
        }        
             return null;
    }    
      /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context       The context.
     * @param uri           The Uri to query.
     * @param selection     (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     */
    public static String getDataColumn(Context context    , Uri uri, String selection, String[] selectionArgs) {

        Cursor cursor = null;        
             final String column = "_data";        
             final String[] projection = {
                column
        };        try {
            cursor = context.getContentResolver()
             .query(uri, projection, selection, selectionArgs,null);            
             if (cursor != null && cursor.moveToFirst()) {                
             final int column_index = cursor
             .getColumnIndexOrThrow(column);  
             return cursor.getString(column_index);
             
            }
        } finally {            
             if (cursor != null)
                cursor.close();
        }        return null;
    }    
      /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    public static boolean isExternalStorageDocument(Uri uri) {        
             return "com.android.externalstorage.documents"            .equals(uri.getAuthority());
    }    
      /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {        
             return "com.android.providers.downloads.documents"            .equals(uri.getAuthority());
    } 
      /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri) {        
             return "com.android.providers.media.documents"            .equals(uri.getAuthority());
    }
}

详见stackoverflow:http://stackoverflow.com/questions/13209494/how-to-get-the-full-file-path-from-uri

三、裁剪

拿到图片的绝对路径,有可能需要对它进行裁剪,这里当然也可以调用系统的裁剪,不过我推荐UCrop,功能好强大,简单的使用方法:

/**
 * 启动裁剪
 */public static String startUCrop(Activity activity,     String sourceFilePath, int requestCode,     float aspectRatioX, float aspectRatioY) {
    Uri sourceUri = Uri.fromFile(new File(sourceFilePath));
    File outDir = Environment.getExternalStoragePublicDirectory(
     Environment.DIRECTORY_PICTURES);    
     if (!outDir.exists()) {
        outDir.mkdirs();
    }
    File outFile = new File(outDir, 
     System.currentTimeMillis() + ".jpg");
    String cameraScalePath = outFile.getAbsolutePath();
    Uri destinationUri = Uri.fromFile(outFile);
    UCrop uCrop = UCrop.of(sourceUri, destinationUri);
    UCrop.Options options = new UCrop.Options();
    options.setAllowedGestures(UCropActivity.SCALE, 
     UCropActivity.ROTATE, UCropActivity.ALL);
    options.setHideBottomControls(true);
    options.setFreeStyleCropEnabled(true);
    uCrop.withOptions(options);
    uCrop.withAspectRatio(aspectRatioX, aspectRatioY);
    uCrop.start(activity, requestCode);    
     return cameraScalePath;
}

详见github:https://github.com/Yalantis/uCrop

微信公众号:AndroidProgrammer

长按二维码识别一键关注