Android拍照或從系統(tǒng)相冊獲取圖片

概述

在做Android開發(fā)中還是會經常選擇照片然后做上傳操作的。但是其中選擇照片系統(tǒng)的有兩種方式,第一種是拍照、第二種是從相冊中選擇。這里分別介紹下。

其中拍照有兩種方法,從系統(tǒng)相冊選擇有兩種方法,會分別介紹和分析。

拍照獲取照片的方法

剛才說過會介紹兩種方法,其實無論幾種方法原理都是一個。就是通過intent發(fā)出隱式意圖調用系統(tǒng)的照相機,然后在獲取到從相機返回的圖片,這里的兩種主要是返回方式有兩種。

1、直接返回圖片。

2、提前創(chuàng)建好存放圖片的Uri然后拍照返回后存儲起來。

第一種拍照方法:

 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                startActivityForResult(intent, TAKE_PHOTO_REQUEST);

沒錯,簡單的兩行代碼就可以調取攝像頭進行拍照了,這時候我們是通過Intent指定activion: MediaStore.ACTION_IMAGE_CAPTURE去查找符合條件的程序。相機里面會對這個action做處理,這一步屬于intent的操作了,這里不再贅述。

case TAKE_PHOTO_REQUEST:
                if (resultCode == RESULT_CANCELED) {
                    Toast.makeText(MainActivity.this, "取消了拍照", Toast.LENGTH_LONG).show();
                    return;
                }
                Bitmap  photo = data.getParcelableExtra("data");
                iv_image.setImageBitmap(photo);

                break;

上面的代碼是onActivityResult中的處理,判斷request后做拍照返回處理,其中data直接返回Bitmap,不過這里要注意一點就是,這個Bitmap會經過系統(tǒng)壓縮。所以有時候可能看起來照片并沒有那么清晰。也正是由于是系統(tǒng)壓縮的原因,這個圖片基本不會很大,基本不會OOM。

第二種拍照獲取照片方法:

第二種方法其實也是一樣的,只不過我們事先定義好uri,然后圖片會存儲到這個uri中,然后我們可以通過這個uri在本地找到具體的圖片,然后做處理,展示。

  private static Uri createImageUri(Context context) {
        String name = "takePhoto" + System.currentTimeMillis();
        ContentValues contentValues = new ContentValues();
        contentValues.put(MediaStore.Images.Media.TITLE, name);
        contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, name + ".jpeg");
        contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
        Uri uri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
        return uri;
    }

上述代碼是創(chuàng)建一個uri用來存儲拍照后的照片。

public static void delteImageUri(Context context, Uri uri) {
        context.getContentResolver().delete(uri, null, null);

    }

上述代碼是用來刪除一個本地uri

   btn_take_photo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                imageUri = createImageUri(MainActivity.this);
                Intent intent = new Intent();
                intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
                intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//如果不設置EXTRA_OUTPUT getData()  獲取的是bitmap數據  是壓縮后的
                startActivityForResult(intent, TAKE_PHOTO_REQUEST_ONE);


            }
        });

然后通過上述代碼創(chuàng)建imageUri然后發(fā)起拍照,方式同樣用Intent,可參第一種方法。

   if (resultCode == RESULT_CANCELED) {
            delteImageUri(MainActivity.this,imageUri);
                    return;
                }
  case TAKE_PHOTO_REQUEST_ONE:
                 iv_image.setImageURI(imageUri);
                    break;

最后就是獲取拍照的照片做處理或者顯示。

其中如果取消的話就刪除創(chuàng)建的rui。

Bitmap bitmap=MediaStore.Images.Media.getBitmap(getContentResolver(),imageUri);
iv_image.setImageBitmap(bitmap);

還可以直接通過MediaStore獲取bitmap進行設置。

以上方法經測試在可以正常獲取照片。

但是這樣還會有個問題,就是如果圖片過大的情況下,會有異常。

W/OpenGLRenderer: Bitmap too large to be uploaded into a texture (3120x4208, max=4096x4096)

如上代碼所示,會直接報bitmap的過大而無法顯示圖片。

第一種處理方法就是對圖片進行處理。
這里介紹第二種處理方式,就是用不同的方式去創(chuàng)建存儲圖片的文件。

public class TakePhotoUtils {



    /**
     * 拍照
     */
    public static Uri takePhoto(Activity mActivity, int flag) throws IOException {
        //指定拍照intent
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        Uri imageUri = null;
        if (takePictureIntent.resolveActivity(mActivity.getPackageManager()) != null) {
            String sdcardState = Environment.getExternalStorageState();
            File outputImage = null;
            if (Environment.MEDIA_MOUNTED.equals(sdcardState)) {
                outputImage = createImageFile(mActivity);
            } else {
                Toast.makeText(mActivity.getApplicationContext(), "內存異常", Toast.LENGTH_SHORT).show();
            }
            try {
                if (outputImage.exists()) {
                    outputImage.delete();
                }
                outputImage.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (outputImage != null) {
                imageUri = Uri.fromFile(outputImage);
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
                mActivity.startActivityForResult(takePictureIntent, flag);
            }
        }

        return imageUri;
    }





    public static  File createImageFile(Activity mActivity) throws IOException {
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "JPEG_" + timeStamp;//創(chuàng)建以時間命名的文件名稱
        File storageDir = getOwnCacheDirectory(mActivity, "takephoto");//創(chuàng)建保存的路徑
        File image = new File(storageDir.getPath(), imageFileName + ".jpg");
        if (!image.exists()) {
            try {
                //在指定的文件夾中創(chuàng)建文件
                image.createNewFile();
            } catch (Exception e) {
            }
        }

        return image;
    }


    /**
     * 根據目錄創(chuàng)建文件夾
     * @param context
     * @param cacheDir
     * @return
     */
    public static File getOwnCacheDirectory(Context context, String cacheDir) {
        File appCacheDir = null;
        //判斷sd卡正常掛載并且擁有權限的時候創(chuàng)建文件
        if ( Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) && hasExternalStoragePermission(context)) {
            appCacheDir = new File(Environment.getExternalStorageDirectory(), cacheDir);
        }
        if (appCacheDir == null || !appCacheDir.exists() && !appCacheDir.mkdirs()) {
            appCacheDir = context.getCacheDir();
        }
        return appCacheDir;
    }


    /**
     * 檢查是否有權限
     * @param context
     * @return
     */
    private static boolean hasExternalStoragePermission(Context context) {
        int perm = context.checkCallingOrSelfPermission("android.permission.WRITE_EXTERNAL_STORAGE");
        return perm == 0;
    }


}

代碼沒什么難點,簡單寫了一個工具類,里面封裝了一個拍照的方法,并返回一個存儲拍照后的路徑。
路徑是自己制定文件夾后創(chuàng)建一個文件,用于存儲照片。文件名是根據時間命名的,以免重復。

    if (resultCode == RESULT_CANCELED) {
                    Toast.makeText(MainActivity.this, "點擊取消從相冊選擇", Toast.LENGTH_LONG).show();
                    return;
                }


                Bitmap bitmap = BitmapFactory.decodeFile(imageUri.getPath(), getOptions(imageUri.getPath()));
                iv_image.setImageBitmap(bitmap);

然后在onActivityResult的方法中進行處理,這里也最好對圖片進行下壓縮處理。然后就可以正常顯示拍照后的圖片了。


    /**
     * 獲取壓縮圖片的options
     *
     * @return
     */
    public static BitmapFactory.Options getOptions(String path) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        options.inSampleSize = 4;      //此項參數可以根據需求進行計算  
        options.inJustDecodeBounds = false;

        return options;
    }

這里的只是簡單的處理方法,按照指定參數壓縮下,這里的inSapleSizes是需要根據自己需求進行算法的。

這樣基本就可以通過拍照來獲取照片了

從相冊選擇照片來展示

其實拍照主要也是通過intent來調用系統(tǒng)相冊,然后通過返回數據在onActivityResult中進行處理。


    public void pickImageFromAlbum() {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_GET_CONTENT);
        intent.setType("image/*");
        startActivityForResult(intent, 111);

    }

    public void pickImageFromAlbum2() {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_PICK);
        intent.setData(MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        startActivityForResult(intent, 222);

    }

如圖兩種方式均可以調用系統(tǒng)相冊進行選擇照片。

  if (resultCode == RESULT_CANCELED) {
                    Toast.makeText(MainActivity.this, "點擊取消從相冊選擇", Toast.LENGTH_LONG).show();
                    return;
                }

                try {
                    Uri imageUri = data.getData();
                    Log.e("TAG", imageUri.toString());
                    iv_image.setImageURI(imageUri);
                } catch (Exception e) {
                    e.printStackTrace();
                }
    

然后返回的處理方式基本是一樣的 拿到uri后進行對圖片處理就好了。這里說明下如果圖片過大可能也需要進行二次處理。

如本篇有錯誤歡迎大家留言指正。

demo源碼地址:https://github.com/xuanguofeng/TakeAndChoosePhoto

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容