Android camera 篇之拍照

本文是camera系列文章第一篇,預(yù)計(jì)三篇 :一 拍照龄砰;二 視頻;三 自定義相機(jī)
相機(jī)功能是我們最常用的讨衣,屬于andorid基礎(chǔ)能力换棚。本文講述一下Android如何調(diào)用相機(jī)進(jìn)行拍照。

廢話不多說反镇,直接上流程固蚤。

流程介紹

請(qǐng)求權(quán)限

開啟相機(jī)

拍照并處理結(jié)果

先介紹一下請(qǐng)求碼

private int takeCameraCodeOne = 1000; // 獲取縮略圖
private int takeCameraCodeTwo = 1001; // 獲取全尺寸圖
private int cameraCode = 10002; // 權(quán)限請(qǐng)求碼

首先介紹申請(qǐng)權(quán)限

需要相機(jī)、讀歹茶、寫 三個(gè)權(quán)限
 
private String[] permissions = new String[]{"android.permission.CAMERA",
        "android.permission.READ_EXTERNAL_STORAGE",
"android.permission.WRITE_EXTERNAL_STORAGE"};

申請(qǐng)權(quán)限并處理權(quán)限
/**
* 申請(qǐng)權(quán)限
*/
private void requestPermission() {
ActivityCompat.requestPermissions(this,permissions,cameraCode);
}

/**
 * 權(quán)限處理
 * @param requestCode
 * @param permissions
 * @param grantResults
 */
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    /**
     * 權(quán)限處理
     */
    if (requestCode == cameraCode) {
        for (int i = 0; i < grantResults.length; i++) {
            if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                requestPermission();
                return;
            }
        }
    //    openCameraOne();
        openCameraTwo();
    }
}

得到權(quán)限后開始喚醒相機(jī)夕玩,本文介紹兩種拍照處理方式

先說第一種:拍照獲取縮略圖
/**
* 喚醒系統(tǒng)相機(jī)
*/
private void openCameraOne() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent,takeCameraCodeOne);
}
}

/**
* 獲取拍照結(jié)果
* @param requestCode
* @param resultCode
* @param data
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == takeCameraCodeOne) {
if (data != null && data.getExtras() != null) {
Bundle bundle = data.getExtras();
Bitmap bm = (Bitmap) bundle.get("data");
if (bm != null) {
camera_img.setImageBitmap(bm);
}
}
}
}
}

這種方式獲取的圖片你弦,適用于小圖標(biāo),存在像素低的缺點(diǎn)燎孟。

第二種 獲取全尺寸照片

/**
* 喚醒相機(jī)
*/
private void openCameraTwo() {
Uri fileUri;
out = new File(getFileName());
if (Build.VERSION.SDK_INT >= 24){
fileUri = FileProvider.getUriForFile(this,getPackageName()+".provider", out);
}else {
fileUri = Uri.fromFile(out);
}
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
if (Build.VERSION.SDK_INT >= 24) {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent, takeCameraCodeTwo);
}
}

這里兼容了Android 7的行為更變 就是獲取設(shè)備文件使用provider 的問題

/**
* 獲取拍照結(jié)果
* @param requestCode
* @param resultCode
* @param data
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == takeCameraCodeTwo){
Bitmap bm = getBitMap(out.getAbsolutePath(), getFileName());
camera_img.setImageBitmap(bm);

        }
    }
}

這里的全尺寸圖的禽作,像素高占內(nèi)存也大,所以我做了壓縮處理揩页;

/**
* 獲取路徑指定位置 這里是DCIM位置 也可指定其他位置
* @return
*/
public String getFileName() {
String fileName = null;
long currentTimeMillis = System.currentTimeMillis();
String pathName = Environment.getExternalStorageDirectory() + "/DCIM/";
File file = new File(pathName);
file.mkdirs();
fileName = pathName + currentTimeMillis + ".jpg";
return fileName;
}

/**
* 獲取圖片
* @param path
* @param fileName
* @return
*/
private Bitmap getBitMap(String path, String fileName) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path,options);
options.inSampleSize = calculateInSampleSize(options,2180,2180);
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(path, options);
compressBmpToFile(bitmap,new File(fileName));
return bitmap;
}

/**
 * 計(jì)算比例
 * @param options
 * @param reqWidth
 * @param reqHeight
 * @return
 */
public  int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;
    if (height > reqHeight || width > reqWidth) {
        final int heightRatio = Math.round((float) height
                / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }
    return inSampleSize;
}

/**
 * 壓縮圖片  并保存到指定文件位置
 * @param bmp
 * @param file
 */
String imgpath ;
public  void compressBmpToFile(Bitmap bmp,File file){
    if (file != null) {
        imgpath = file.getAbsolutePath();
    }
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    int options = 80;
    if (bmp == null) {
        return;
    }
    bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
    while (baos.toByteArray().length / 1024 > 500) {
        baos.reset();
        options -= 10;
        bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
    }
    try {
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(baos.toByteArray());
        fos.flush();
        fos.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

然后最后還有一點(diǎn)說明 將照片保存到手機(jī)相冊(cè)

/**
* 加入手機(jī)相冊(cè)
* @param path 圖片路徑
*/
public void addGallery(String path){
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File(path);
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}

好旷偿,兩種拍照方式介紹完畢了。完整代碼隨后加上

/**

  • camera 拍照
  • 流程
  • 請(qǐng)求權(quán)限
  • 開啟相機(jī)
  • 拍照并處理結(jié)果

*/

public class OpenCameraActivity extends AppCompatActivity {

private int takeCameraCodeOne = 1000; // 獲取縮略圖
private int takeCameraCodeTwo = 1001; // 獲取全尺寸圖
private int cameraCode = 10002;  // 權(quán)限請(qǐng)求碼
/**
 * 所需權(quán)限數(shù)組 相機(jī) 讀 寫
 */
private String[] permissions = new String[]{"android.permission.CAMERA",
        "android.permission.READ_EXTERNAL_STORAGE",
        "android.permission.WRITE_EXTERNAL_STORAGE"};
private ImageView camera_img;
private File out;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_camera);
    camera_img = findViewById(R.id.camera_img);
    findViewById(R.id.open_camera).setOnClickListener(v -> {
        requestPermission();
    });
}

/**
 * 申請(qǐng)權(quán)限
 */
private void requestPermission() {
    ActivityCompat.requestPermissions(this,permissions,cameraCode);
}

/**
 * 權(quán)限處理
 * @param requestCode
 * @param permissions
 * @param grantResults
 */
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    /**
     * 權(quán)限處理
     */
    if (requestCode == cameraCode) {
        for (int i = 0; i < grantResults.length; i++) {
            if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                requestPermission();
                return;
            }
        }
        //    openCameraOne();
        openCameraTwo();
    }
}

/**
 * 獲取路徑指定位置  這里是DCIM位置 也可指定其他位置
 * @return
 */
public String getFileName() {
    String fileName = null;
    long currentTimeMillis = System.currentTimeMillis();
    String pathName = Environment.getExternalStorageDirectory() + "/DCIM/";
    File file = new File(pathName);
    file.mkdirs();
    fileName = pathName + currentTimeMillis + ".jpg";
    return fileName;
}

/**
 * 喚醒相機(jī)
 */
private void openCameraTwo() {
    Uri fileUri;
    out = new File(getFileName());
    if (Build.VERSION.SDK_INT >= 24){
        fileUri = FileProvider.getUriForFile(this,getPackageName()+".provider", out);
    }else {
        fileUri = Uri.fromFile(out);
    }
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
    if (Build.VERSION.SDK_INT >= 24) {
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(intent, takeCameraCodeTwo);
    }
}

/**
 * 獲取拍照結(jié)果
 * @param requestCode
 * @param resultCode
 * @param data
 */
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK) {
        if (requestCode == takeCameraCodeOne) {
            if (data != null && data.getExtras() != null) {
                Bundle bundle = data.getExtras();
                Bitmap bm = (Bitmap) bundle.get("data");
                if (bm != null) {
                    camera_img.setImageBitmap(bm);
                }
            }
        }else if (requestCode == takeCameraCodeTwo){
            Bitmap bm = getBitMap(out.getAbsolutePath(), getFileName());
            camera_img.setImageBitmap(bm);
            if (!TextUtils.isEmpty(imgpath)) {
                addGallery(imgpath);
            }
        }
    }
}

/**
 * 獲取圖片
 * @param path
 * @param fileName
 * @return
 */
private Bitmap getBitMap(String path, String fileName) {
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(path,options);
    options.inSampleSize = calculateInSampleSize(options,2180,2180);
    options.inJustDecodeBounds = false;
    Bitmap bitmap = BitmapFactory.decodeFile(path, options);
    compressBmpToFile(bitmap,new File(fileName));
    return bitmap;
}

/**
 * 計(jì)算比例
 * @param options
 * @param reqWidth
 * @param reqHeight
 * @return
 */
public  int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;
    if (height > reqHeight || width > reqWidth) {
        final int heightRatio = Math.round((float) height
                / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }
    return inSampleSize;
}

/**
 * 壓縮圖片  并保存到指定文件位置
 * @param bmp
 * @param file
 */
String imgpath ;
public  void compressBmpToFile(Bitmap bmp,File file){
    if (file != null) {
        imgpath = file.getAbsolutePath();
    }
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    int options = 80;
    if (bmp == null) {
        return;
    }
    bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
    while (baos.toByteArray().length / 1024 > 500) {
        baos.reset();
        options -= 10;
        bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
    }
    try {
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(baos.toByteArray());
        fos.flush();
        fos.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/**
 * 加入手機(jī)相冊(cè)
 * @param path 圖片路徑
 */
public void addGallery(String path){
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    File f = new File(path);
    Uri contentUri = Uri.fromFile(f);
    mediaScanIntent.setData(contentUri);
    this.sendBroadcast(mediaScanIntent);
}


/**
 * 喚醒系統(tǒng)相機(jī)
 */
private void openCameraOne() {
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(intent,takeCameraCodeOne);
    }
}

}
本文完碍沐。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末狸捅,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子累提,更是在濱河造成了極大的恐慌尘喝,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件斋陪,死亡現(xiàn)場(chǎng)離奇詭異朽褪,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)无虚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門缔赠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人友题,你說我怎么就攤上這事嗤堰。” “怎么了度宦?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵踢匣,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我戈抄,道長(zhǎng)离唬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任划鸽,我火速辦了婚禮输莺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘裸诽。我一直安慰自己嫂用,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布崭捍。 她就那樣靜靜地躺著尸折,像睡著了一般。 火紅的嫁衣襯著肌膚如雪殷蛇。 梳的紋絲不亂的頭發(fā)上实夹,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天橄浓,我揣著相機(jī)與錄音,去河邊找鬼亮航。 笑死荸实,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的缴淋。 我是一名探鬼主播准给,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼重抖!你這毒婦竟也來了露氮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤钟沛,失蹤者是張志新(化名)和其女友劉穎畔规,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恨统,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡叁扫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了畜埋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片莫绣。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖悠鞍,靈堂內(nèi)的尸體忽然破棺而出对室,到底是詐尸還是另有隱情,我是刑警寧澤咖祭,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布软驰,位于F島的核電站,受9級(jí)特大地震影響心肪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜纠吴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一硬鞍、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧戴已,春花似錦固该、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至握联,卻和暖如春桦沉,著一層夾襖步出監(jiān)牢的瞬間每瞒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工纯露, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留剿骨,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓埠褪,卻偏偏與公主長(zhǎng)得像浓利,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子钞速,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345