在APP中使用Camera的两种方式
- 调用系统相机,或者是具有相机功能的应用
- 自定义相机
1. 调用系统相机
- 1)隐式调用系统的相机
XML代码:
Activity代码:
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivity(intent);
- 2)让Activity可以作为其他程序可调用的拍照程序
配置Manifest.xml文件
<intent-filter>
<action android:name="android.media.action.IMAGE_CAPTURE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
- 3)拍照后返回图片( 返回缩略图 和 返回原图 )
XML布局文件
<LinearLayout 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"
android:orientation="vertical"
tools:context="com.example.mytest.MainActivity">
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="StartCamera"
android:text="调用系统拍照" />
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:srcCompat="@mipmap/ic_launcher" />
</LinearLayout>
Activity代码:
public class MainActivity extends AppCompatActivity {
private static int REQ_1 = 1;
private ImageView mInageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mInageView = (ImageView) findViewById(R.id.imageView);
}
public void StartCamera(View view){
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent,REQ_1);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK){
if(requestCode == REQ_1){
Bundle bundle = data.getExtras();
//拍照使用系统自带的相机
//可能引起拍照完返回调用onActivityResult()时intent携带的数据过大,android已经将data压缩,返回的是图片的缩略图。
Bitmap bitmap = (Bitmap) bundle.get("data");
mInageView.setImageBitmap(bitmap);
}
}
}
}
但是:通过调用系统相机拍照获取的图像是缩略图,像素比较低(图片模糊),防止内存溢出。
解决方法:采用另外一种方案(文件路径读取)
XML布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context="com.example.mytest.MainActivity">
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="StartCamera"
android:text="调用系统拍照返回缩略图" />
<Button
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="StartCamera2"
android:text="调用系统拍照返回原图" />
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:srcCompat="@mipmap/ic_launcher" />
</LinearLayout>
Activity代码:
public class MainActivity extends AppCompatActivity {
private static int REQ_1 = 1;
private static int REQ_2 = 2;
private ImageView mInageView;
private String mFilePath;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mInageView = (ImageView) findViewById(R.id.imageView);
// 需要添加SDCard的读取权限
mFilePath = Environment.getExternalStorageDirectory().getPath();
mFilePath = mFilePath + "/" + "temp.png";
}
//返回缩略图
public void StartCamera(View view){
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent,REQ_1);
}
//返回原图
public void StartCamera2(View view){
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 注意:使用的是 android.net.Uri;
Uri photoUri = Uri.fromFile(new File(mFilePath));
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);//保存到指定的Uri中
startActivityForResult(intent,REQ_2);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK){
if(requestCode == REQ_1){
Bundle bundle = data.getExtras();
Bitmap bitmap = (Bitmap) bundle.get("data");
mInageView.setImageBitmap(bitmap);
}else if(requestCode == REQ_2){
FileInputStream fis = null;
try {
fis = new FileInputStream(mFilePath);
Bitmap bitmap = BitmapFactory.decodeStream(fis);
mInageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
try {
fis.close();
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
}
}
manifest配置文件代码:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2. 自定义相机(综合案例)
XML界面布局
<LinearLayout 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"
android:orientation="vertical"
tools:context="com.example.mytest.MainActivity">
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="StartCamera"
android:text="调用系统拍照返回缩略图" />
<Button
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="StartCamera2"
android:text="调用系统拍照返回原图" />
<Button
android:id="@+id/button3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="CustomCamera"
android:text="自定义相机" />
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:srcCompat="@mipmap/ic_launcher" />
</LinearLayout>
MainActivity代码:
public class MainActivity extends AppCompatActivity {
private static int REQ_1 = 1;
private static int REQ_2 = 2;
private ImageView mInageView;
private String mFilePath;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mInageView = (ImageView) findViewById(R.id.imageView);
// 需要添加SDCard的读取权限
mFilePath = Environment.getExternalStorageDirectory().getPath();
mFilePath = mFilePath + "/" + "temp.png";
}
//返回缩略图
public void StartCamera(View view){
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent,REQ_1);
}
//返回原图
public void StartCamera2(View view){
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 注意:使用的是 android.net.Uri;
Uri photoUri = Uri.fromFile(new File(mFilePath));
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);//保存到指定的Uri中
startActivityForResult(intent,REQ_2);
}
//自定义相机
public void CustomCamera(View view){
Intent intent = new Intent(MainActivity.this, CustomCameraActivity.class);
// 注意:使用的是 android.net.Uri;
Uri photoUri = Uri.fromFile(new File(mFilePath));
intent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);//保存到指定的Uri中
startActivityForResult(intent,REQ_2);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK){
if(requestCode == REQ_1){
Bundle bundle = data.getExtras();
Bitmap bitmap = (Bitmap) bundle.get("data");
mInageView.setImageBitmap(bitmap);
}else if(requestCode == REQ_2){
FileInputStream fis = null;
try {
fis = new FileInputStream(mFilePath);
Bitmap bitmap = BitmapFactory.decodeStream(fis);
mInageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
try {
fis.close();
} catch (IOException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
}
}
自定义相机布局:
<LinearLayout 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"
android:orientation="vertical"
tools:context="com.example.mytest.CustomCameraActivity">
<Button
android:id="@+id/button4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Capture"
android:onClick="capture"/>
<SurfaceView
android:id="@+id/preview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
CustomCameraActivity代码:
public class CustomCameraActivity extends Activity implements SurfaceHolder.Callback{
private Camera mCamera;
private SurfaceView mPreview;
private SurfaceHolder mHolder;
//实现回调方法
private Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
// 参数data存放的是完整的图片数据,不是缩略图
File tempFile = new File("/sdcard/temp.png");
try {
FileOutputStream fos = new FileOutputStream(tempFile);
fos.write(data);
fos.close();
//实行页面跳转,展示拍照结果
Intent intent = new Intent(CustomCameraActivity.this, Result.class);
intent.putExtra("picPath",tempFile.getAbsolutePath());
startActivity(intent);
CustomCameraActivity.this.finish();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_camera);
mPreview = (SurfaceView) findViewById(R.id.preview);
mHolder = mPreview.getHolder();
mHolder.addCallback(this);
//点击SurfaceView自动对焦
mPreview.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCamera.autoFocus(null);
}
});
}
public void capture(View view) {
//设置拍照参数
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPictureFormat(ImageFormat.JPEG);
parameters.setPreviewSize(800, 400);//预览大小
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);//自动对焦
mCamera.autoFocus(new Camera.AutoFocusCallback() { //获取对清晰的对焦照片
@Override
public void onAutoFocus(boolean success, Camera camera) {
if(success){ //如果对焦成功
Toast.makeText(getApplicationContext(),"对焦成功",Toast.LENGTH_SHORT).show();
mCamera.takePicture(null, null, mPictureCallback);
}else{
Toast.makeText(getApplicationContext(),"对焦失败",Toast.LENGTH_SHORT).show();
}
}
});
}
/**
* 第一步:创建三个方法
*/
//获取Camera对象,注意Camera包不要导错
private Camera getCamera() {
//由于是自定义相机,不是系统i相机,需要添加相机权限
Camera camera;
try {
camera = Camera.open();
} catch (Exception e) {
camera = null;
e.printStackTrace();
}
return camera;
}
//开始预览相机内容(将相机与SurfaceView进行绑定)
private void setStartPreview(Camera camera, SurfaceHolder holder) {
try {
camera.setPreviewDisplay(holder);
//将系统Camera预览角度进行调整
camera.setDisplayOrientation(90);
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
//释放相机资源 并且将 相机 与 SurfaceView 解除绑定
private void releaseCamera() {
if(mCamera != null){
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();;
mCamera = null;
}
}
/**
* 第二步:将这三个方法与Activity的生命周期绑定
*/
@Override
protected void onResume() {
super.onResume();
if(mCamera == null){
mCamera = getCamera();
if(mHolder != null){
setStartPreview(mCamera,mHolder);
}
}
}
@Override
protected void onPause() {
super.onPause();
releaseCamera();
}
/**
* 第三步:实现 implements SurfaceHolder.Callback 的3个方法
*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
setStartPreview(mCamera,mHolder);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mCamera.stopPreview();
setStartPreview(mCamera, mHolder);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
releaseCamera();
}
}
展示结果的布局界面:
<LinearLayout 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"
android:orientation="vertical"
tools:context="com.example.mytest.Result">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Capture Result"
android:textSize="30sp"/>
<ImageView
android:id="@+id/pic"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="center"
app:srcCompat="@mipmap/ic_launcher" />
</LinearLayout>
Result代码
public class Result extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_result);
String path = getIntent().getStringExtra("picPath");
ImageView imageView = (ImageView) findViewById(R.id.pic);
try {
FileInputStream fis = new FileInputStream(path);
Bitmap bitmap = BitmapFactory.decodeStream(fis);
Matrix matrix = new Matrix();//定义一个矩阵
matrix.setRotate(90);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
// Bitmap bitmap = BitmapFactory.decodeFile(path);
// imageView.setImageBitmap(bitmap);
}
由于是自定义的相机,需要添加权限
manifest.xml添加权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />