美文网首页Android AndroidAndroid多媒体技术
android选择系统相机拍照和系统相册,裁剪图片并保存和设置头

android选择系统相机拍照和系统相册,裁剪图片并保存和设置头

作者: 风中旅途 | 来源:发表于2017-02-15 17:11 被阅读1941次

    项目用到了选择系统相机拍照和系统相册,裁剪图片并设置头像,找了找网上大神们的博客,解决了选取相册在android4.4崩溃和升级到android7.0后系统选取照片路径的不同。(用的是Fresco设置圆形头像)第一次做分享,不喜勿喷。代码有点乱....

    1. 首先在建立相机存储的缓存的路径,在onCreate()方法里面设置:
      SimpleDraweeView mSimpleDraweeView =(SimpleDraweeView)findViewById(R.id.user_avatar) ;
      file = new File(FileUtil.getCachePath(this), "user-avatar.jpg");
      if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
      uri = Uri.fromFile(file);
      } else {
      //通过FileProvider创建一个content类型的Uri(android 7.0需要这样的方法访问)
      uri = FileProvider.getUriForFile(TTApplication.getApp(), "com.yf.toutiao", file);//使用在manifest里面设置的包名
      }

    2. 使用FileProvider要在在manifest中添加provider,参考来至:(http://www.jianshu.com/p/3f9e3fc38eae

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

      还要在资源文件下创建相应的xml文件(如上:则创建filepaths.xml)。
      <?xml version="1.0" encoding="utf-8"?>
      <paths>
      <external-path path="" name="camera_photos" />
      </paths>
      3.按钮点击响应系统相机和选取相册
      case R.id.take_camera:
      if (PermissionUtil.hasCameraPermission(UserEditActivity.this)) {
      uploadAvatarFromPhotoRequest();
      }
      break;
      case R.id.take_photo:
      uploadAvatarFromAlbumRequest();
      break;

       调用相机和相册的方法
      
         /**
          *  camera
          */
         private void uploadAvatarFromPhotoRequest() {
           Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
           intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
           intent.putExtra(MediaStore.Images.Media.ORIENTATION, 0);
           intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
           startActivityForResult(intent, REQUEST_CODE_TAKE_PHOTO);
         }
      
         /**
          *  album
          */
           private void uploadAvatarFromAlbumRequest() {
           Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
           photoPickerIntent.setType("image/*");
           startActivityForResult(photoPickerIntent, REQUEST_CODE_ALBUM);
         }
      

    4.回调方法里面裁剪照片(调用系统的裁剪方法)

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode != -1) {
            return;
        }
        if (requestCode == REQUEST_CODE_ALBUM && data != null) {
            Uri newUri;
              //android7.0和7.0以下的不同的uri
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
                newUri = Uri.parse("file:///" + CropUtils.getPath(this, data.getData()));
            } else {
                newUri = data.getData();
            }
            if (newUri != null) {
                startPhotoZoom(newUri);
            } else {
                ToastUtil.showToast(this, "没有得到相册图片", 0);
            }
        } else if (requestCode == REQUEST_CODE_TAKE_PHOTO) {
                //调用系统裁剪方法进行裁剪
                startPhotoZoom(uri);
        } else if (requestCode == REQUEST_CODE_CROUP_PHOTO) {
                //获取图片路径进行设置
                compressAndUploadAvatar(file.getPath());
        }
    }
    /**
     * 裁剪方法
     *
     * @param uri
     */
    public void startPhotoZoom(Uri uri) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.putExtra("crop", "true");// crop=true 有这句才能出来最后的裁剪页面.
        intent.putExtra("aspectX", 1);// 这两项为裁剪框的比例.
        intent.putExtra("aspectY", 1);// x:y=1:1
        // intent.putExtra("outputX", Constants.USER_AVATAR_MAX_SIZE);//图片输出大小,可以不需要
        //intent.putExtra("outputY", Constants.USER_AVATAR_MAX_SIZE);
        //注意这里的输出的是上面的文件路径的Uri格式,这样在才能获取图片
        intent.putExtra("output", Uri.fromFile(file));
        intent.putExtra("outputFormat", "JPEG");// 返回格式
        startActivityForResult(intent, REQUEST_CODE_CROUP_PHOTO);
    }
    

    5.设置头像和上传服务器(用Retrofit,代码没有展示)

      private void compressAndUploadAvatar(String fileSrc) {
        //压缩图片
        final File cover = FileUtil.getSmallBitmap(this, fileSrc);
        //利用Fresco进行缓存图片和设置圆形图片
        GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(getResources());
        GenericDraweeHierarchy hierarchy = builder
                .setDesiredAspectRatio(1.0f)
                .setFailureImage(R.mipmap.user_avatar_bg)//失败设置的图片
                .setRoundingParams(RoundingParams.fromCornersRadius(100f))
                .build();
    
        //加载本地图片,设置头像
        Uri uri = Uri.fromFile(cover);
        DraweeController controller = Fresco.newDraweeControllerBuilder()
                .setOldController(mSimpleDraweeView.getController())
                .setUri(uri)
                .build();
        mSimpleDraweeView.setHierarchy(hierarchy);
        mSimpleDraweeView.setController(controller);
    }
    

    6.存储文件方法

     public class FileUtil {
    /**
     * 获取缓存路径
     * @param context
     * @return
     */
    public static String getCachePath(Context context) {
        String cachePath = null;
        if (Environment.MEDIA_MOUNTED.equals(Environment
                .getExternalStorageState())
                || !Environment.isExternalStorageRemovable()) {
            cachePath = context.getExternalCacheDir().getPath();
        } else {
            cachePath = context.getCacheDir().getPath();
        }
        return cachePath;
      }
    
    * 压缩图片方法
     *
     * @param context
     * @param fileSrc
     * @return
     */
    public static File getSmallBitmap(Context context, String fileSrc) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(fileSrc, options);
        options.inSampleSize = calculateInSampleSize(options, 480, 800);
        DebugUtil.i(DebugUtil.TAG_YF, "options.inSampleSize-->" + options.inSampleSize);
        options.inJustDecodeBounds = false;
        Bitmap img = BitmapFactory.decodeFile(fileSrc, options);
        DebugUtil.i(DebugUtil.TAG_YF, "file size after compress-->" + img.getByteCount() / 256);
        String filename = context.getFilesDir() + File.separator + "video-" + img.hashCode() + ".jpg";
        saveBitmap2File(img, filename);
        return new File(filename);
    }
    /**
     * 设置压缩的图片的大小设置的参数
     *
     * @param options
     * @param reqWidth
     * @param reqHeight
     * @return
     */
    public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        int height = options.outHeight;
        int width = options.outWidth;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            int heightRatio = Math.round(height) / reqHeight;
            int widthRatio = Math.round(width) / reqWidth;
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
          }
        return inSampleSize;
        }
     }
    
     /**
     * 保存bitmap到文件
     *
     * @param bmp
     * @param filename
     * @return
     */
    public static boolean saveBitmap2File(Bitmap bmp, String filename) {
        Bitmap.CompressFormat format = Bitmap.CompressFormat.JPEG;
        int quality = 50;//压缩50% 100表示不压缩
        OutputStream stream = null;
        try {
            stream = new FileOutputStream(filename);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return bmp.compress(format, quality, stream);
    }
    

    android4.4获取相册路径的方法(参考:http://blog.csdn.net/tempersitu/article/details/20557383

    public class CropUtils {
    @SuppressLint("NewApi")
    public static String getPath(final Context context, final Uri uri) {
    
        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
    
    // DocumentProvider
          if (isKitKat && DocumentsContract.isDocumentUri(context, uri))   {
            // ExternalStorageProvider
            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];
                }
            }
            // DownloadsProvider
            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);
            }
            // MediaProvider
            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);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            return getDataColumn(context, uri, null, null);
        }
        // File
        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.
     */
    private 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.
     */
    private 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.
     */
    private 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.
     */
    private static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
      }
    }
    

    7.当然需要权限处理(部分文件未写)

        @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        switch (requestCode) {
            case PermissionUtil.REQUEST_SHOWCAMERA:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // Permission Granted
                    uploadAvatarFromPhotoRequest();
                } else {
                    if (!SharedPreferenceMark.getHasShowCamera()) {
                        SharedPreferenceMark.setHasShowCamera(true);
                        new DialogPermission(this, "关闭摄像头权限影响扫描功能");//自定义Dialog
                    } else {
                        Toast.makeText(this, "未获取摄像头权限", Toast.LENGTH_SHORT)
                                .show();
                    }
                }
                break;
            default:
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }
    

    PS:部分代码没有上传,(小米4.4系统上选取系统相册有报图库停止,但不影响选取图片,未找到解决办法,有大神解决了求留言告知),还有一个就是在裁剪方法里面设置输出的大小会让图片变得更清晰,不过图片大小也会变大。喜欢的请关注。有错请指出,不吝赐教。
    源码: https://github.com/yangfang521314/UserAvatar
    如果你喜欢文章希望能顺手在Github点个star哦!谢谢!

    相关文章

      网友评论

      • 記憶裏_的冬季:小米5拍照裁剪是崩溃
        风中旅途:怎么会,我就是一直用小米5开发测试的啊,你是不是哪里写错了
      • 2c24f281b158:终于找到一个没问题的了,非常感谢。:smile:
      • lsys:求源码
        lsys:@风中旅途 没事 分享出来学习学习呀
        风中旅途:https://github.com/yangfang521314/UserAvatar,,还有小问题,压缩的图片质量不清晰。大小可以是为了上传服务器的
      • 啊耀:求代码
        风中旅途:@啊耀 https://github.com/yangfang521314/UserAvatar,压缩图片后质量很不好,不清晰,正在换方法解决。
        啊耀:@风中旅途 好,上传了吱一声
        风中旅途:我一会上传在github上 :blush:

      本文标题:android选择系统相机拍照和系统相册,裁剪图片并保存和设置头

      本文链接:https://www.haomeiwen.com/subject/nvippttx.html