Android中使用系统相机是很方便的,单这仅仅是简单的使用而已,并不能获得什么特殊的效果。
要想让应用有相机的action,咱们就必须在清单文件中做一些声明,好让系统知道,如下
<intent-filter> <action android:name="android.intent.action.IMAGE_CAPTURE" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> 12345 12345action的作用就是声明action的类型,便于Intent的使用,category的作用就是注册,没有它。相关操作将不起作用。 一种方式是简单粗暴的实现,如下
Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intent, REQ_1); //然后在 onActivityResult方法中实现数据的获取,此处是展示在了一个ImageView上 if(resultCode==RESULT_OK){ if(requestCode==REQ_1){ Bundle bundle=data.getExtras(); Bitmap bitmap=(Bitmap) bundle.get("data"); imageView.setImageBitmap(bitmap); } 123456789 123456789小总结:这样的好处是简单快捷,但是在现在的android智能机中,好多相片都是很大的,这里获得的仅仅是一个缩略图罢了
另外一种方式是稍微温婉一点了,而且效果也更好一点,好处就在于它是先将照片信息存储到本地一个临时文件中,然后让ImageView去相关路径下进行读取,这样就可以获得清晰度很高的图片了。如下
/* * 此方法的存在意义就是不在onActivityResult方法的data中获取我们拍照的缩略图,而是从我们的文件输出目录下直接查看原图 * 这样的好处就是可以对大容量的照片进行便捷的准确的操作 */ public void onStartCarema2(View view){ Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //见你给你路径传递回需要的处理方法中 Uri uri=Uri.fromFile(new File(myFilePath)); //设置文件的输出路径 intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(intent, REQ_2); } //然后在onActivityResult方法中进行相关的处理就可以了 else if(requestCode==REQ_2){ FileInputStream fis=null; try { fis=new FileInputStream(myFilePath); Bitmap bitmap=BitmapFactory.decodeStream(fis); imageView.setImageBitmap(bitmap); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { fis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } //记得最后一定要关闭相关的流操作。否则会引起相关的异常的。 123456789101112131415161718192021222324252627282930313233 123456789101112131415161718192021222324252627282930313233由于开发自定义的相机要进行相关的权限的生命,所以一定不要忘记在清单文件中做相关的处理,如下
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.CAMERA"/> 12 12然后有以下几个步骤:
创建Camera,并完成初始化Camera,开始预览,释放资源三个方法与Activity的SurfaceView进行绑定。在系统的onPause(),onResume()方法中进行相关状态设置对Camera进行参数设置,作用就是对照片类型和状态进行相关的设置将拍得的照片进行展示,一般会新开一个Activity,用ImageView进行承载,我们还可以在此Activity上添加TextView,实现水印效果等其他的美化操作另外,如果想加入自动聚焦的功能,就可以在SurfaceView上添加onClickListener(),对屏幕进行侦听,调用myCamera.autoFocus(null);方法即可以上就是整个思路
接下来就是使用系统Camera的代码展示
(可以直接copy相关代码块,添加到你的应用中去,实现Camera这一功能。)
首先是MainActivity
布局 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context=".MainActivity" > <Button android:id="@+id/startCarema" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="6dp" android:text="StartCarema" android:onClick="onStartCarema" /> <Button android:id="@+id/startCarema2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="6dp" android:text="StartCarema2" android:onClick="onStartCarema2" /> <Button android:id="@+id/customCarema" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="6dp" android:text="CustomCarema" android:onClick="onCustomCarema" /> <ImageView android:id="@+id/imageview" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> 123456789101112131415161718192021222324252627282930313233343536373839404142434445 123456789101112131415161718192021222324252627282930313233343536373839404142434445 代码 package com.example.camerademo; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; import android.view.View; import android.widget.Button; import android.widget.ImageView; public class MainActivity extends Activity { //为下面的获取请求所用 private static int REQ_1=1; private static int REQ_2=2; Button btn_startCareme,btn_startCarema2,btn_customCarema; ImageView imageView; //定义照片存储的路径 private String myFilePath; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn_startCareme=(Button) findViewById(R.id.startCarema); btn_startCarema2=(Button) findViewById(R.id.startCarema2); btn_customCarema=(Button) findViewById(R.id.customCarema); imageView=(ImageView) findViewById(R.id.imageview); //初始化不同手机的SD卡的路径 myFilePath=Environment.getExternalStorageDirectory().getPath(); myFilePath=myFilePath+"/"+"temperature.png"; } public void onCustomCarema(View view){ Intent intent=new Intent(this,CustomCarema.class); startActivity(intent); } public void onStartCarema(View view){ Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE); startActivityForResult(intent, REQ_1); } /* * 此方法的存在意义就是不在onActivityResult方法的data中获取我们拍照的缩略图,而是从我们的文件输出目录下直接查看原图 * 这样的好处就是可以对大容量的照片进行便捷的准确的操作 */ public void onStartCarema2(View view){ Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //见你给你路径传递回需要的处理方法中 Uri uri=Uri.fromFile(new File(myFilePath)); //设置文件的输出路径 intent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(intent, REQ_2); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // TODO Auto-generated method stub super.onActivityResult(requestCode, resultCode, data); if(resultCode==RESULT_OK){ if(requestCode==REQ_1){ Bundle bundle=data.getExtras(); Bitmap bitmap=(Bitmap) bundle.get("data"); imageView.setImageBitmap(bitmap); }else if(requestCode==REQ_2){ FileInputStream fis=null; try { fis=new FileInputStream(myFilePath); Bitmap bitmap=BitmapFactory.decodeStream(fis); imageView.setImageBitmap(bitmap); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { fis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } } 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899接下来是自定义相机的代码
主界面布局 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/capture" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="6dp" android:text="Capture" android:onClick="onCapture" /> <SurfaceView android:id="@+id/preview" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> 1234567891011121314151617181920212223242526 1234567891011121314151617181920212223242526 ResultActivity的布局 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Capture Result" android:textSize="28dp" android:textColor="#BFAACD" android:gravity="center" /> <ImageView android:id="@+id/picture" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="center" /> </LinearLayout> 12345678910111213141516171819202122 12345678910111213141516171819202122 代码 首先是CustomCamera类, package com.example.camerademo; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import android.app.Activity; import android.content.Intent; import android.graphics.ImageFormat; import android.hardware.Camera; import android.os.Bundle; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; @SuppressWarnings("unused") public class CustomCarema extends Activity implements SurfaceHolder.Callback{ private Camera myCamera; private SurfaceView preview; private SurfaceHolder myHolder; //myHolder勇于展现surfaceView的图像 private Camera.PictureCallback myPictureCallBack=new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera arg1) { //将拍照得到的数据信息存储到本地 File tempFile=new File("/sdcard/temp.png"); try { FileOutputStream fos=new FileOutputStream(tempFile); fos.write(data); fos.close(); //然后将这个照片的数据信息传送给要进行展示的Activity即可 Intent intent=new Intent(CustomCarema.this,ResultActivity.class); intent.putExtra("PicturePath", tempFile.getAbsolutePath()); startActivity(intent); //拍照结束之后销毁当前的Activity,进入到图片展示界面 CustomCarema.this.finish(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.customcarema); preview=(SurfaceView) findViewById(R.id.preview); myHolder=preview.getHolder(); myHolder.addCallback(this); //实现点击屏幕自动聚焦的功能,此处并不需要拍照,故只是聚焦 preview.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { // TODO Auto-generated method stub myCamera.autoFocus(null); } }); } @Override protected void onResume() { super.onResume(); if(myCamera==null){ myCamera=getCamera(); if(myHolder != null ){ setStartPreview(myCamera, myHolder); } } } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); releaseCamera(); } /** * 释放相机的资源 */ private void releaseCamera(){ if(myCamera !=null ){ myCamera.setPreviewCallback(null); myCamera.stopPreview(); myCamera.release(); myCamera=null; } } /** * 拍照的一些参数设置,点击此按钮之后会触发拍照的会掉,进而实现拍照的效果 * @param view */ public void onCapture(View view){ Camera.Parameters parameters=myCamera.getParameters(); //设置照片的类型 parameters.setPictureFormat(ImageFormat.JPEG); parameters.setPictureSize(800, 600); //设置为自动聚焦 parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); //设置为自动聚焦是不够的,因为我们先得到的是最为清晰的图片,所以要在聚焦成功的时候才进行拍照 myCamera.autoFocus(new Camera.AutoFocusCallback() { @Override public void onAutoFocus(boolean success, Camera camera) { // TODO Auto-generated method stub if(success){ myCamera.takePicture(null, null, myPictureCallBack); } } }); } /** * 获取系统的一个Camera对象 */ private Camera getCamera(){ Camera camera=null; try{ camera=Camera.open(); }catch(Exception e){ e.printStackTrace(); } return camera; } /** * 开始预览相机的内容,其实就是讲surfaceHolder与之绑定 */ private void setStartPreview(Camera camera,SurfaceHolder holder){ //直接调用系统方式绑定预览 try { camera.setPreviewDisplay(holder); //由于系统默认使用横屏预览,,所以要进行设置 camera.setDisplayOrientation(90); camera.startPreview(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder holder, int arg1, int arg2, int arg3) { // TODO Auto-generated method stub myCamera.stopPreview(); setStartPreview(myCamera, myHolder); } @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub setStartPreview(myCamera, myHolder); } @Override public void surfaceDestroyed(SurfaceHolder arg0) { // TODO Auto-generated method stub releaseCamera(); } } 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187然后是结果界面代码:
package com.example.camerademo; import java.io.FileInputStream; import java.io.FileNotFoundException; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.os.Bundle; import android.widget.ImageView; public class ResultActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.resultactivity); String path=getIntent().getStringExtra("PicturePath"); ImageView imageview=(ImageView) findViewById(R.id.picture); //由于这样稚嫩获得横屏,所以我们要使用流的形式来转换 // Bitmap bitmap=BitmapFactory.decodeFile(path); // imageview.setImageBitmap(bitmap); FileInputStream fis; try { 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) { // TODO Auto-generated catch block e.printStackTrace(); } } } 123456789101112131415161718192021222324252627282930313233343536373839404142 123456789101112131415161718192021222324252627282930313233343536373839404142总结:
安卓6.0以上版本记得加动态权限,不然会报空指针哦,还有点击拍照事件那里 别忘了加进去,不然拍照没反应
//写这篇博客的目的一方面是为了今后复习时方便一点,毕竟思路在此刻是清晰的,过几天就有可能忘记了。另一方面若能帮到在这方面有欠缺的小伙伴们的话,那是更好的了。最后尤其要感谢的是Imooc中eclipse_xu 老师,我就是看着他的视频
