一、配置文件:
需要引入摄像头权限,sdcard读写权限。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.takepicture"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" /> <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" > <!-- screenOrientation设置activity在屏幕上显示方式:横向 -->
<activity
android:name="com.example.takepicture.MainActivity"
android:label="@string/app_name"
android:screenOrientation="landscape" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<!-- 摄像头权限 -->
<uses-permission android:name="android.permission.CAMERA" />
<!-- 在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> </manifest>
布局文件,当activity启动时在屏幕上横向显示,手指触摸屏幕时,出现拍照和对焦两个按钮,采用相对布局。
<RelativeLayout 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"
tools:context=".MainActivity" > <SurfaceView
android:id="@+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent" /> <RelativeLayout
android:id="@+id/buttonlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone" > <Button
android:id="@+id/autofouce"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_alignTop="@+id/takePicture"
android:layout_marginRight="5dp"
android:layout_toLeftOf="@+id/takePicture"
android:onClick="takePicture"
android:text="@string/autofouce" /> <Button
android:id="@+id/takePicture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginRight="59dp"
android:onClick="takePicture"
android:text="@string/takepicture" />
</RelativeLayout> </RelativeLayout>
二、代码实现:
package com.example.takepicture; import java.io.File;
import java.io.FileOutputStream; import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager; public class MainActivity extends Activity { private View layout;
private static final String TAG = "TakePicture";
private SurfaceView surfaceView;
private Camera camera;
private boolean preview; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//设置窗口没有标题
requestWindowFeature(Window.FEATURE_NO_TITLE);
//全屏显示
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN); //getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//高亮 setContentView(R.layout.activity_main);
layout= this.findViewById(R.id.buttonlayout);
//确定surfaceView什么时候被时间
surfaceView = (SurfaceView) this.findViewById(R.id.surfaceView);
surfaceView.getHolder().addCallback(new SufaceListener());
/*下面设置Surface不维护自己的缓冲区,而是等待屏幕的渲染引擎将内容推送到用户面前*/
surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceView.getHolder().setFixedSize(176, 144); //设置分辨率
surfaceView.getHolder().setKeepScreenOn(true);//设置高亮
} //触摸事件
public boolean onTouchEvent(MotionEvent event) {
//手指按下屏幕
if(event.getAction()==MotionEvent.ACTION_DOWN){
layout.setVisibility(ViewGroup.VISIBLE);//显示布局
return true;
}
return super.onTouchEvent(event);
} private final class SufaceListener implements SurfaceHolder.Callback{
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
Log.i(TAG, "surfaceCreated .... ");
camera = Camera.open();//打开摄像头
Camera.Parameters parameters = camera.getParameters();
Log.i(TAG, parameters.flatten());//打印参数
//WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
//Display display = wm.getDefaultDisplay();
//图片大小的设置要符合手机上图片大小,否则会出现参数设置错误
//parameters.setPreviewSize(display.getWidth(), display.getHeight());//设置预览照片的大小
parameters.setPreviewFrameRate(3);//每秒3帧
parameters.setPictureFormat(PixelFormat.JPEG);//设置照片的输出格式
parameters.set("jpeg-quality", 85);//照片质量
//parameters.setPictureSize(display.getWidth(), display.getHeight());//设置照片的大小
camera.setParameters(parameters);
camera.setPreviewDisplay(surfaceView.getHolder());//通过SurfaceView显示取景画面
camera.startPreview();
preview = true;
Log.i(TAG, "surfaceCreated .. end .. ");
} catch (Exception e) {
Log.e(TAG, e.toString());
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//是否摄像头
if(camera!=null){
if(preview) camera.stopPreview();
camera.release();
camera = null;
}
}
} public void takePicture(View v){
if (camera!=null) {
switch (v.getId()) {
case R.id.takePicture:
Log.i(TAG, " start take picture ... ");
//内部采用异步操作照片
camera.takePicture(null, null, new PictureCallbackListener());
Log.i(TAG, " end take picture ... ");
break;
case R.id.autofouce:
camera.autoFocus(null);//自动对焦
break;
}
}
}
/*
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(camera!=null && event.getRepeatCount()==0){
switch (keyCode) {
case KeyEvent.KEYCODE_SEARCH:
camera.autoFocus(null);//自动对焦
break;
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_CAMERA:
//拍照
//camera.takePicture(null, null, new PictureCallbackListener());
break;
}
}
return true;
}
*/
private final class PictureCallbackListener implements Camera.PictureCallback{
/**
* data:所拍摄图片数据
*/
@Override
public void onPictureTaken(byte[] data, Camera camera) {
try {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
// File file = new File(Environment.getExternalStorageDirectory(), "my.jpg");
File file=new File("/storage/sdcard0/360/",System.currentTimeMillis()+".jpg");
FileOutputStream outStream = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 100, outStream);
outStream.close();
//重新浏览,否则画面就不动
camera.stopPreview();
camera.startPreview();
preview = true;
} catch (Exception e) {
Log.e(TAG, e.toString());
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
} }
三、出现异常:
设置摄像头参数时,尤其是图片大小要符合手机匹配图片大小,否则会出现设置参数错误。