之前写过:调用摄像头拍照,拿到缩略图,本地图,裁剪 ,在低版本上能运行,7.0+就不行了,需要适配FileProvider。
1,调用隐式Intent 启动系统相机
private static final int REQ_IMAGE = 1024 ;
Intent intentCapturePic = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intentCapturePic.resolveActivity(getPackageManager()) != null) {
startActivityForResult(intentCapturePic,REQ_IMAGE);
}
通过resolveActivity判断有木有对应的Activity做个安全保护。
2,获取拍照的缩略图
系统通过Intent 把一个很小的图片(Bitmap )在onActivityResult 函数中返回,在Extras 以key "data"返回。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case REQ_IMAGE:
if (resultCode == RESULT_OK) {
Bundle bundle = data.getExtras();
Bitmap bitmap = (Bitmap) bundle.get("data");
imageView.setImageBitmap(bitmap);
}
break;
}
}
其实这个图片很小,并不能满足需求。
3,获取系统相机原图
通过系统拍照保存到本地文件,需要申请
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
权限:
if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED)
{
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},0);
}
在7.0+ 的设备上还要适配FileProvider ,关于FileProvider :Android 7.0 行为变更 通过FileProvider在应用间共享文件吧
file_paths:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path
name="files"
path="" />
<cache-path
name="cache"
path="" />
<external-path
name="external"
path="" />
<external-files-path
name="external_file_path"
path="" />
<external-cache-path
name="external_cache_path"
path="" />
</paths>
manifest 配置:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.***.android7.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
启动相机:
public void startCameraOriginal(View view)
{
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//Uri fileUri = FileProvider.getUriForFile(this, "com.dhl.android7.fileprovider", new File(imagePath));
String filename = new SimpleDateFormat("yyyyMMdd-HHmmss", Locale.CHINA)
.format(new Date()) + ".png";
File file = new File(Environment.getExternalStorageDirectory(), filename);
imagePath = file.getAbsolutePath();
Uri fileUri = null ;
if (Build.VERSION.SDK_INT >= 24) {
fileUri = FileProvider.getUriForFile(this, "com.***.android7.fileprovider", file);
}else
{
fileUri = Uri.fromFile(new File(imagePath));
}
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivityForResult(intent,REQ_IMAGE_ORIGINAL);
}
onActivity 拿回图片:
case REQ_IMAGE_ORIGINAL :
if(resultCode == RESULT_OK)
{
//ssetPictureDegreeZero(imagePath,1);
// Glide.with(this).load(imagePath).transform(new RotateTransformation(this,90)).into(imageView);
//String photopath = imagePath;
Bitmap bmp = BitmapFactory.decodeFile(imagePath);
//小米拍照后旋转处理
Matrix matrix = new Matrix();
matrix.postRotate(readPictureDegree(imagePath));//90
bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
FileOutputStream fOut;
try {
fOut = new FileOutputStream(imagePath);
//不压缩
bmp.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
fOut.flush();
fOut.close();
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
FileInputStream fis = null;
try
{
fis = new FileInputStream(imagePath);
Bitmap bitmap = BitmapFactory.decodeStream(fis);
imageView.setImageBitmap(bitmap);
//添加到系统相册
Intent intent = new Intent(
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(new File(imagePath)));
sendBroadcast(intent);
}catch (Exception e)
{
e.printStackTrace();
}finally {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
break;
这里小米拍照的图片是旋转的,所以用到
Android 效率开发之图片旋转处理,如果用Glide加载则不用特殊处理,会帮你处理好图片。最后用到
Android 效率开发之图片保存到图库。
这样就可以拿到系统原图尺寸了。
4,自定义自己的相机
最起码需要一个SurfaceView 布局文件如下
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.dhl.camerademo.CustomCameraActivity">
<SurfaceView
android:id="@+id/surface_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/image_capture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="拍照"
android:onClick="captureCamera"
/>
</RelativeLayout>
这里surfaceView 用来预览相机,ImageView用来展示拍照完成的图片。
自定义自己的相机需要相应的权限:
<uses-permission android:name="android.permission.CAMERA"/>
获取Camera:
/**
* 获取Camera
* @return
*/
private Camera getCamera()
{
Camera camera ;
try
{
camera = Camera.open();
}catch (Exception e)
{
camera = null ;
e.printStackTrace();
}
return camera ;
}
释放相机资源:
/**
* 释放相机资源
*/
private void releaseCamera()
{
// getCamera().release();
if(mCamera != null)
{
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null ;
}
}
设置预览:
/**
* 设置预览
* @param camera
* @param surfaceHolder
*/
private void setStartPreview(Camera camera,SurfaceHolder surfaceHolder)
{
try {
camera.setPreviewDisplay(surfaceHolder);
camera.setDisplayOrientation(90);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
拍照参数:
/**
* 获取照片
* @param view
*/
public void captureCamera(View view)
{
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPictureFormat(ImageFormat.JPEG);
//是否原图
parameters.setJpegQuality(100);
//获取支持的尺寸
List<Camera.Size> list = parameters.getSupportedPictureSizes();
Camera.Size size = list.get(0);
parameters.setPictureSize(size.width, size.height);
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
mCamera.setParameters(parameters);
// parameters.setPictureSize(2592, 1296);
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if(success)
{
mCamera.takePicture(null,null,pictureCallback);
}
}
});
}
拍完照片回调处理图片:
private Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = null;
try {
image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
} catch (IOException e) {
e.printStackTrace();
}
// File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/temp.jpg");
try {
FileOutputStream fileOutputStream = new FileOutputStream(image);
fileOutputStream.write(data);
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
surfaceView.setVisibility(View.GONE);
image_capture.setVisibility(View.VISIBLE);
//添加到系统相册
Glide.with(CustomCameraActivity.this).load(image.getPath()).into(image_capture);
}
};
全部代码:
/**
* 自定义相机
*/
public class CustomCameraActivity extends AppCompatActivity implements SurfaceHolder.Callback {
private Camera mCamera ;
private SurfaceView surfaceView ;
private SurfaceHolder surfaceHolder ;
private ImageView image_capture ;
private Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINA).format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = null;
try {
image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
} catch (IOException e) {
e.printStackTrace();
}
// File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/temp.jpg");
try {
FileOutputStream fileOutputStream = new FileOutputStream(image);
fileOutputStream.write(data);
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
surfaceView.setVisibility(View.GONE);
image_capture.setVisibility(View.VISIBLE);
//添加到系统相册
Glide.with(CustomCameraActivity.this).load(image.getPath()).into(image_capture);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_camera);
surfaceView = (SurfaceView)findViewById(R.id.surface_view);
image_capture = (ImageView)findViewById(R.id.image_capture);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCamera.autoFocus(null);
}
});
}
/**
* 获取照片
* @param view
*/
public void captureCamera(View view)
{
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPictureFormat(ImageFormat.JPEG);
//是否原图
parameters.setJpegQuality(100);
//获取支持的尺寸
List<Camera.Size> list = parameters.getSupportedPictureSizes();
Camera.Size size = list.get(0);
parameters.setPictureSize(size.width, size.height);
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
mCamera.setParameters(parameters);
// parameters.setPictureSize(2592, 1296);
mCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
if(success)
{
mCamera.takePicture(null,null,pictureCallback);
}
}
});
}
@Override
protected void onResume() {
super.onResume();
if(mCamera == null)
{
mCamera = getCamera();
/* if(surfaceHolder != null)
{
setStartPreview(mCamera,surfaceHolder);
}*/
}
}
@Override
protected void onPause() {
super.onPause();
releaseCamera();
}
/**
* 获取Camera
* @return
*/
private Camera getCamera()
{
Camera camera ;
try
{
camera = Camera.open();
}catch (Exception e)
{
camera = null ;
e.printStackTrace();
}
return camera ;
}
/**
* 设置预览
* @param camera
* @param surfaceHolder
*/
private void setStartPreview(Camera camera,SurfaceHolder surfaceHolder)
{
try {
camera.setPreviewDisplay(surfaceHolder);
camera.setDisplayOrientation(90);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 释放相机资源
*/
private void releaseCamera()
{
// getCamera().release();
if(mCamera != null)
{
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null ;
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
setStartPreview(mCamera,surfaceHolder);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
setStartPreview(mCamera,surfaceHolder);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
releaseCamera();
}
}
这就简单实现了自定义相机。