本文是camera系列文章第一篇,预计三篇 :一 拍照;二 视频;三 自定义相机
相机功能是我们最常用的,属于andorid基础能力。本文讲述一下Android如何调用相机进行拍照。
废话不多说,直接上流程。
流程介绍
请求权限
开启相机
拍照并处理结果
先介绍一下请求码
private int takeCameraCodeOne = 1000; // 获取缩略图
private int takeCameraCodeTwo = 1001; // 获取全尺寸图
private int cameraCode = 10002; // 权限请求码
首先介绍申请权限
需要相机、读、写 三个权限
private String[] permissions = new String[]{"android.permission.CAMERA",
"android.permission.READ_EXTERNAL_STORAGE",
"android.permission.WRITE_EXTERNAL_STORAGE"};
申请权限并处理权限
/**
* 申请权限
*/
private void requestPermission() {
ActivityCompat.requestPermissions(this,permissions,cameraCode);
}
/**
* 权限处理
* @param requestCode
* @param permissions
* @param grantResults
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
/**
* 权限处理
*/
if (requestCode == cameraCode) {
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
requestPermission();
return;
}
}
// openCameraOne();
openCameraTwo();
}
}
得到权限后开始唤醒相机,本文介绍两种拍照处理方式
先说第一种:拍照获取缩略图
/**
* 唤醒系统相机
*/
private void openCameraOne() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent,takeCameraCodeOne);
}
}
/**
* 获取拍照结果
* @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);
}
}
}
}
}
这种方式获取的图片,适用于小图标,存在像素低的缺点。
第二种 获取全尺寸照片
/**
* 唤醒相机
*/
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的行为更变 就是获取设备文件使用provider 的问题
/**
* 获取拍照结果
* @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);
}
}
}
这里的全尺寸图的,像素高占内存也大,所以我做了压缩处理;
/**
* 获取路径指定位置 这里是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;
}
/**
* 计算比例
* @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();
}
}
然后最后还有一点说明 将照片保存到手机相册
/**
* 加入手机相册
* @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 拍照
- 流程
- 请求权限
- 开启相机
- 拍照并处理结果
*/
public class OpenCameraActivity extends AppCompatActivity {
private int takeCameraCodeOne = 1000; // 获取缩略图
private int takeCameraCodeTwo = 1001; // 获取全尺寸图
private int cameraCode = 10002; // 权限请求码
/**
* 所需权限数组 相机 读 写
*/
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();
});
}
/**
* 申请权限
*/
private void requestPermission() {
ActivityCompat.requestPermissions(this,permissions,cameraCode);
}
/**
* 权限处理
* @param requestCode
* @param permissions
* @param grantResults
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
/**
* 权限处理
*/
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;
}
/**
* 唤醒相机
*/
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);
}
}
/**
* 获取拍照结果
* @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;
}
/**
* 计算比例
* @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();
}
}
/**
* 加入手机相册
* @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);
}
/**
* 唤醒系统相机
*/
private void openCameraOne() {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intent,takeCameraCodeOne);
}
}
}
本文完。