Android开发 调用系统相机相册图片功能,解决小米手机拍照或者图片横竖相反问题,及小米手机相册图片路径问题

Android开发 调用系统相机相册图片功能,解决小米手机拍照或者图片横竖相反问题,及小米手机相册图片路径问题

1.调用相机,兼容7.0

AndroidManifest配置

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="xxx.xxx.xxx"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths"/>
</provider>

authorities="applicationId.fileprovider"

如果有其他第三方包配置过provider,可以自定义继承FileProvider例如

public class MyFileProvider extends FileProvider {
}
<provider
            android:name=".MyFileProvider"
            android:authorities="${applicationId}.provider"
            android:grantUriPermissions="true"
            android:exported="false">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />
        </provider>
在资源文件中 新建xml文件夹,然后对应上面的resource 文件名 filepaths

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <paths>
        <external-path
            name="image"
            path="" />
    </paths>
</resources>
file-path 表示你应用内部存储区域的文件的子目录。这个子目录和getFilesDir()的返回值一样。external-path 表示你应用外部存储区域的文件的子目录。这个子目录和getExternalFilesDir()的返回值一样。cache-path 表示你应用内部存储区域的缓存子目录。这个子目录的根目录和getCacheDir()的返回值一样。(如果你修改了provider和paths中的值,需要把应用卸载重装或者开关机一下才能看到变化。)

FileProvider 是 ContentProvider 的一个特殊的子类,它有利于安全地分享应用相关的文件,通过对一个文件创建content:// Uri而不是file:/// Uri。

由于FileProvider的默认功能包括文件的content URI的生成,你并不需要在代码中定义一个子类。相反,你可以在你的应用中包含一个FileProvider通过在XML文件中指定它。对于指定FileProvider,添加一个元素在你应用的清单文件中。设置android:name属性为android.support.v4.content.FileProvider。根据你控制的域名设置android:authorities属性为一个URI authority(authorities可以随意填写,但是要保证使用时与authority保持一致,推荐applicationId.fileprovider,以免定义重复)。设置android:exported属性为false;FileProvider不需要公开。设置android:grantUriPermissions属性为true,为了允许你进行临时访问文件的授权。

一个FileProvider只能生成一个content URI 对应你事先指定目录下的文件。对于指定一个目录,使用元素的子元素,在XML中指定它的存储区域和路径。例如,下面的paths元素告诉FileProvider你打算请求你的私有文件区域的 images/ 子目录的content URIs

<files-path
    name="name"
    path="path"/> <!--相当 Context.getFilesDir() + path, name是分享url的一部分-->

<cache-path
    name="name"
    path="path"/> <!--getCacheDir()-->

<external-path
    name="name"
    path="path"/> <!--Environment.getExternalStorageDirectory()-->

<external-files-path
    name="name"
    path="path"/><!--getExternalFilesDir(String) Context.getExternalFilesDir(null)-->

<external-cache-path
    name="name"
    path="path"/> <!--Context.getExternalCacheDir()-->
拍照
 /**
     * 拍照
     */
    protected void takePic() {
        Intent openCameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        File file = new File(FileConstanse.getCacheImagePath(), FileConstanse.IMAGE_CACHE);
        tempUri = Uri.fromFile(file);
        // 指定照片保存路径(SD卡)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//7.0及以上使用FileProvider获取Uri
            openCameraIntent.setFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            String authority =  getPackageName()+".provider";
            Uri contentUri = FileProvider.getUriForFile(mContext, authority,file);
            openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
        } else {
            openCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, tempUri);
        }

        startActivityForResult(openCameraIntent, TAKE_PICTURE);
    }
 打开相册 以下两种方法即可

 /**
     * 选择相册
     */
    protected void selectPic() {
        Intent intentFromGallery;
//        当sdk版本低于19时使用此方法
        if (Build.VERSION.SDK_INT < 19) {
            intentFromGallery = new Intent(Intent.ACTION_GET_CONTENT);
            intentFromGallery.setType("image/*");
        } else {
            intentFromGallery = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        }
//        Intent intentFromGallery = new Intent(Intent.ACTION_PICK);
//        intentFromGallery.setType("image/*");//相片类型
        startActivityForResult(intentFromGallery, CHOOSE_PICTURE);

    }
然后 onActivityResult

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (RESULT_OK == resultCode) {
            switch (requestCode) {
                case TAKE_PICTURE://相机
                    File file = new File(FileConstanse.getCacheImagePath(), FileConstanse.IMAGE_CACHE_NEW);
                    if (rotaImg(tempUri.getPath(),file)){
                        tempUri =  Uri.fromFile(file);
                    }
                    crop(102, 37);//进行裁剪
                    break;
                case CHOOSE_PICTURE://相册
                    File filePic = new File(FileConstanse.getCacheImagePath(), FileConstanse.IMAGE_CACHE_NEW);
                    tempUri = data.getData();
                    String path = ImageUtils.getRealPathFromUri(mContext, tempUri);
                    if (rotaImg(path,filePic)){
                        tempUri =  Uri.fromFile(filePic);
                    }
                    crop(102, 37);
                    break;
                case Crop.REQUEST_CROP://裁剪
                    ImageLoadConfig.loadNomalPicWithoutChache(mContext, outPutUri, ivPic);
                    break;
             
            }
        }
    }
如愿一切如愿的话,就不会有这篇文章了,奇葩的小米手机出现了图片横竖不分,如果是拍照或者从相册拿出来以前拍照的图片,竖着拍照的图片是横向的。这个想到的方法是将图片按照之前的角度给他再旋转回去。

 /**
     * 获取图片的旋转角度
     * @param imgPath 图片路径
     * @return 返回旋转角度
     */
    public static int getBitmapRotateAngle(String imgPath) {
        // 判断图片方向
        int digree = 0;
        ExifInterface exif = null;
        try {
            exif = new ExifInterface(imgPath);
        } catch (IOException e) {
            e.printStackTrace();

            exif = null;
        }
        if (exif != null) {
            int ori = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_UNDEFINED);
            switch (ori) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    digree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    digree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    digree = 270;
                    break;
                default:
                    digree = 0;
                    break;
            }

        }
        return digree;
    }
 /**
     * 
     * @param path 图片路径
     * @param digree 旋转角度
     * @return
     */
    public static Bitmap creatBitmap(String path,int digree){
        Bitmap bitmap = BitmapFactory.decodeFile(path);
        Bitmap bitmapRe;
        // 旋转图片
        Matrix m = new Matrix();
        m.postRotate(digree);
        bitmapRe = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                bitmap.getHeight(), m, true);
        if (bitmap!=bitmapRe){
            bitmap.recycle();
        }
        return  bitmapRe;

    }
 /**
     * 将bitmap作为一张图片存入到指定路径
     *
     * @param bitmap
     * @param file
     */
    public static void storeImage(Bitmap bitmap, File file) {
        FileOutputStream os;
        try {
            os = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
            os.flush();
            os.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

相册拿到的uri要转换成path,才能得到图片的旋转角度

public static String getRealPathFromUri(Context context, Uri contentUri) {
        Cursor cursor = null;
        try {
            String[] proj = { MediaStore.Images.Media.DATA };
            cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }
至此完成。












评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值