android選擇系統(tǒng)相機(jī)拍照和系統(tǒng)相冊,裁剪圖片并保存和設(shè)置頭像

項目用到了選擇系統(tǒng)相機(jī)拍照和系統(tǒng)相冊机隙,裁剪圖片并設(shè)置頭像纽谒,找了找網(wǎng)上大神們的博客证膨,解決了選取相冊在android4.4崩潰和升級到android7.0后系統(tǒng)選取照片路徑的不同。(用的是Fresco設(shè)置圓形頭像)第一次做分享鼓黔,不喜勿噴央勒。代碼有點亂....

  1. 首先在建立相機(jī)存儲的緩存的路徑,在onCreate()方法里面設(shè)置:
    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創(chuàng)建一個content類型的Uri(android 7.0需要這樣的方法訪問)
    uri = FileProvider.getUriForFile(TTApplication.getApp(), "com.yf.toutiao", file);//使用在manifest里面設(shè)置的包名
    }

  2. 使用FileProvider要在在manifest中添加provider澳化,參考來至:(http://www.reibang.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>
    

    還要在資源文件下創(chuàng)建相應(yīng)的xml文件(如上:則創(chuàng)建filepaths.xml)订歪。
    <?xml version="1.0" encoding="utf-8"?>
    <paths>
    <external-path path="" name="camera_photos" />
    </paths>
    3.按鈕點擊響應(yīng)系統(tǒng)相機(jī)和選取相冊
    case R.id.take_camera:
    if (PermissionUtil.hasCameraPermission(UserEditActivity.this)) {
    uploadAvatarFromPhotoRequest();
    }
    break;
    case R.id.take_photo:
    uploadAvatarFromAlbumRequest();
    break;

     調(diào)用相機(jī)和相冊的方法
    
       /**
        *  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.回調(diào)方法里面裁剪照片(調(diào)用系統(tǒng)的裁剪方法)

@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) {
            //調(diào)用系統(tǒng)裁剪方法進(jìn)行裁剪
            startPhotoZoom(uri);
    } else if (requestCode == REQUEST_CODE_CROUP_PHOTO) {
            //獲取圖片路徑進(jìn)行設(shè)置
            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.設(shè)置頭像和上傳服務(wù)器(用Retrofit肆捕,代碼沒有展示)

  private void compressAndUploadAvatar(String fileSrc) {
    //壓縮圖片
    final File cover = FileUtil.getSmallBitmap(this, fileSrc);
    //利用Fresco進(jìn)行緩存圖片和設(shè)置圓形圖片
    GenericDraweeHierarchyBuilder builder = new GenericDraweeHierarchyBuilder(getResources());
    GenericDraweeHierarchy hierarchy = builder
            .setDesiredAspectRatio(1.0f)
            .setFailureImage(R.mipmap.user_avatar_bg)//失敗設(shè)置的圖片
            .setRoundingParams(RoundingParams.fromCornersRadius(100f))
            .build();

    //加載本地圖片刷晋,設(shè)置頭像
    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);
}
/**
 * 設(shè)置壓縮的圖片的大小設(shè)置的參數(shù)
 *
 * @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.當(dāng)然需要權(quán)限處理(部分文件未寫)

    @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, "關(guān)閉攝像頭權(quán)限影響掃描功能");//自定義Dialog
                } else {
                    Toast.makeText(this, "未獲取攝像頭權(quán)限", Toast.LENGTH_SHORT)
                            .show();
                }
            }
            break;
        default:
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

PS:部分代碼沒有上傳,(小米4.4系統(tǒng)上選取系統(tǒng)相冊有報圖庫停止慎陵,但不影響選取圖片眼虱,未找到解決辦法,有大神解決了求留言告知)席纽,還有一個就是在裁剪方法里面設(shè)置輸出的大小會讓圖片變得更清晰捏悬,不過圖片大小也會變大。喜歡的請關(guān)注润梯。有錯請指出过牙,不吝賜教。
源碼: https://github.com/yangfang521314/UserAvatar
如果你喜歡文章希望能順手在Github點個star哦纺铭!謝謝寇钉!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市舶赔,隨后出現(xiàn)的幾起案子扫倡,更是在濱河造成了極大的恐慌,老刑警劉巖竟纳,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件撵溃,死亡現(xiàn)場離奇詭異,居然都是意外死亡锥累,警方通過查閱死者的電腦和手機(jī)缘挑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來桶略,“玉大人语淘,你說我怎么就攤上這事鬼悠。” “怎么了亏娜?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵焕窝,是天一觀的道長。 經(jīng)常有香客問我维贺,道長它掂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任溯泣,我火速辦了婚禮虐秋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘垃沦。我一直安慰自己客给,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布肢簿。 她就那樣靜靜地躺著靶剑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪池充。 梳的紋絲不亂的頭發(fā)上桩引,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機(jī)與錄音收夸,去河邊找鬼坑匠。 笑死,一個胖子當(dāng)著我的面吹牛卧惜,可吹牛的內(nèi)容都是我干的厘灼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼咽瓷,長吁一口氣:“原來是場噩夢啊……” “哼设凹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起忱详,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤席噩,失蹤者是張志新(化名)和其女友劉穎匣吊,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蛋辈,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡桶错,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年航唆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片院刁。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡糯钙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情任岸,我是刑警寧澤再榄,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站享潜,受9級特大地震影響困鸥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜剑按,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一疾就、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧艺蝴,春花似錦猬腰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至缩擂,卻和暖如春厢拭,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背撇叁。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工供鸠, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人陨闹。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓楞捂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親趋厉。 傳聞我的和親對象是個殘疾皇子寨闹,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容