android中相機與相冊的詳細使用

目前主流app都具有上傳頭像啊,上傳圖片的功能,看起來好簡單的需求,但是其實這里面有一點點不同的地方。先說一下我的思路,因為開發周期的問題,并沒有打算自定義相機與圖片查詢工具,打算采用系統相機和圖片查看工具,最開始我打算調用系統的剪裁并且取得的效果還是不錯的,因為我最開始做的是系統頭像上傳的這個功能,后來我采用同樣的方法做了上傳商品圖片的功能,但是這個時候就暴露了之前的隱患。

我先說一下,安卓系統的默認的機制,Intent觸發Camera程序,拍好照片后,將會返回數據,但是考慮到內存問題,Camera不會將全尺寸的圖像返回給調用的Activity,一般情況下,有可能返回的是縮略圖,比如120*160px。這看起來就像是一個縮略圖一樣了,這樣的效果是讓我們非常不滿意的,因為我們想要上傳的明明是一個高清的圖片,但是這樣我們上傳的竟然是一個特別模糊的圖片啦,所以我們不能采用這種辦法了。

我們的思路:調用系統相機,拍照完將拍完的照片存在sd卡的某一個地方,然后我們調用自己的剪裁工具,不調用系統的剪裁工具了,這樣我們剪裁完的圖片也就是一張高清的圖片了,這樣就完美的解決了所遇到的問題。


順便給大家介紹一款,比較不錯的剪裁工具:ucrop

鏈接:https://github.com/Yalantis/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配置
        UCrop.Options options = new UCrop.Options();
        //設置裁剪圖片可操作的手勢
        options.setAllowedGestures(UCropActivity.SCALE, UCropActivity.ROTATE, UCropActivity.ALL);
        //是否隱藏底部容器,默認顯示
        options.setHideBottomControls(true);
        //設置toolbar顏色
        options.setToolbarColor(ActivityCompat.getColor(activity, R.color.colorPrimary));
        //設置狀態欄顏色
        options.setStatusBarColor(ActivityCompat.getColor(activity, R.color.colorPrimary));
        //是否能調整裁剪框
        options.setFreeStyleCropEnabled(true);
        //UCrop配置
        uCrop.withOptions(options);
        //設置裁剪圖片的寬高比,比如16:9
        uCrop.withAspectRatio(aspectRatioX, aspectRatioY);
        //uCrop.useSourceImageAspectRatio();
        //跳轉裁剪頁面
        uCrop.start(activity, requestCode);
        return cameraScalePath;
    }


軟件使用截圖1
軟件使用截圖2

看了圖片之后,應該不用我說這個庫有多強大了吧,通過簡單的設置之后,可以輕松的實現圖片的旋轉啊,圖片的縮放啊,和各種實用的操作,特別的實用。

下面展示一下我們調用系統的拍照,和系統的相冊的代碼:


    /**
     * 啟動手機相冊
     */
     
    private void fromGallery() {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("image/*");
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory(), IMAGE_NAME)));

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            startActivityForResult(intent, GALLERY_KITKAT_REQUEST);
        } else {
            startActivityForResult(intent, GALLERY_REQUEST);
        }
    }

    /**
     * 啟動手機相機
     */
    private void fromCamera() {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (FileUtil.hasSdcard()) {
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory(), IMAGE_NAME)));
            startActivityForResult(intent, CAMERA_REQUEST);
        } else {
            Log.i("sys", "--lin--> SD not exist");
        }
    }

//如果我們采取的是,調用相冊中的照片,我們只需要這樣便可以獲取到圖片,并且直接加載到我們的第三方剪裁庫里面。
String url = getPath(ReleaseOrderActivity.this, data.getData());
Log.i("lin", "----lin---- url :" + url);
startUCrop(ReleaseOrderActivity.this, url, 1000, 300, 300);


//如果我們采用的是調用系統的相機的話,采用這種方式便可以獲取到照片,并且加載到我們的剪裁的工具里面啦。
startUCrop(ReleaseOrderActivity.this, Environment.getExternalStorageDirectory() + "/" + IMAGE_NAME, 1000, 300, 300);


當然,上面我們應用到了一個,getPath的方法,當然顧名思義嘛,就是要找到圖片的所在位置,但是怕大家懶得自己寫,在這里我就給出來:


    //以下是關鍵,原本uri返回的是file:///...來著的,android4.4返回的是content:///...
    @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 the remote address
            if (isGooglePhotosUri(uri)) {
                return uri.getLastPathSegment();
            }
            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }
        return null;
    }

    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 index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(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());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }

好了,以上便是我們的解決方案了。

如果大家感覺總結的還不錯,可以給我點個心,或者關注筆者一下~ 有什么問題,也隨時歡迎大家留言和我討論。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,556評論 25 708
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,255評論 4 61
  • 上一篇介紹了如何使用系統相機簡單、快速的進行拍照,本篇將介紹如何使用框架提供的API直接控制攝像機硬件。 你還在為...
    Xiao_Mai閱讀 7,250評論 4 18
  • 來來往往復又去去來來 何處方能安吾身? 舟車勞頓 留下的只是一聲聲嘆息 走走停停復又躊躇不前 何方留有一方凈土? ...
    十畝之間亦傾城閱讀 81評論 0 0
  • 前言 神經網絡,聽起來高大上的一個名詞,他是人工智能領域不可或缺的組成部分。作為一個自學的小白,我跟大家一...
    安靜的大白閱讀 188評論 0 0