Android自定义照相机实现(拍照 保存到SD卡,利用Bundle在Acitivity交换数据)

               

Android自定义照相机实现

近期小巫在学校有一个创新项目,也不是最近,是一个拖了很久的项目,之前一直没有去搞,最近因为要中期检查,搞得我跟小组成员一阵忙活,其实开发一款照相机软件并不太难,下面就是通过自定义的方式来实现手机照相的功能。

创建一个项目:FingerTakePicture


首先来搞一下界面:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/FrameLayout1"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <!-- 显示预览图形 --> <SurfaceView      android:id="@+id/surfaceView"     android:layout_width="match_parent"     android:layout_height="match_parent"     /> <!-- 相对布局,放置两个按钮 -->   <RelativeLayout      android:id="@+id/buttonLayout"      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:visibility="gone"     >     <!-- 拍照按钮 -->     <Button          android:id="@+id/takepicture"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:layout_alignParentRight="true"         android:layout_alignParentBottom="true"         android:background="@drawable/btn_tabkepicture_selector"         android:onClick="btnOnclick"         />     <ImageView          android:id="@+id/scalePic"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:layout_alignParentLeft="true"         android:layout_alignParentBottom="true"         android:layout_marginLeft="5dp"         android:background="@drawable/img_showpic_selector"         android:onClick="imageClick"         /> </RelativeLayout></FrameLayout>

界面效果(无法把预览给截屏下来滴):

Android自定义照相机实现(拍照 保存到SD卡,利用Bundle在Acitivity交换数据)



权限设置少不了:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.wwj.finger"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk        android:minSdkVersion="4"        android:targetSdkVersion="15" />    <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" /><application        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <activity            android:name=".MainActivity"            android:label="@string/title_activity_main"             >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>        <activity             android:name=".ShowPicActivity"            android:label="@string/app_name"            android:theme="@style/AppTheme"            android:configChanges="orientation|keyboardHidden"            ></activity>    </application></manifest>

主Activity:

package com.wwj.finger;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.Date;import android.app.Activity;import android.content.Intent;import android.graphics.PixelFormat;import android.hardware.Camera;import android.hardware.Camera.PictureCallback;import android.os.Bundle;import android.os.Environment;import android.view.KeyEvent;import android.view.MotionEvent;import android.view.Surface;import android.view.SurfaceHolder;import android.view.SurfaceHolder.Callback;import android.view.SurfaceView;import android.view.View;import android.view.ViewGroup;import android.widget.Toast;/** * Android手指拍照 *  * @author wwj * @date 2013/4/29 */public class MainActivity extends Activity private View layout; private Camera camera; private Camera.Parameters parameters = null; Bundle bundle = null; // 声明一个Bundle对象,用来存储数据 @Override public void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  // 显示界面  setContentView(R.layout.activity_main);  layout = this.findViewById(R.id.buttonLayout);  SurfaceView surfaceView = (SurfaceView) this    .findViewById(R.id.surfaceView);  surfaceView.getHolder()    .setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);  surfaceView.getHolder().setFixedSize(176, 144); //设置Surface分辨率  surfaceView.getHolder().setKeepScreenOn(true);// 屏幕常亮  surfaceView.getHolder().addCallback(new SurfaceCallback());//为SurfaceView的句柄添加一个回调函数 } /**  * 按钮被点击触发的事件  *   * @param v  */ public void btnOnclick(View v) {  if (camera != null) {   switch (v.getId()) {   case R.id.takepicture:    // 拍照    camera.takePicture(null, null, new MyPictureCallback());    break;   }  } } /**  * 图片被点击触发的时间  *   * @param v  */ public void imageClick(View v) {  if (v.getId() == R.id.scalePic) {   if (bundle == null) {    Toast.makeText(getApplicationContext(), R.string.takephoto,      Toast.LENGTH_SHORT).show();   } else {    Intent intent = new Intent(this, ShowPicActivity.class);    intent.putExtras(bundle);    startActivity(intent);   }  } } private final class MyPictureCallback implements PictureCallback {  @Override  public void onPictureTaken(byte[] data, Camera camera) {   try {    bundle = new Bundle();    bundle.putByteArray("bytes", data); //将图片字节数据保存在bundle当中,实现数据交换    saveToSDCard(data); // 保存图片到sd卡中    Toast.makeText(getApplicationContext(), R.string.success,      Toast.LENGTH_SHORT).show();    camera.startPreview(); // 拍完照后,重新开始预览   } catch (Exception e) {    e.printStackTrace();   }  } } /**  * 将拍下来的照片存放在SD卡中  * @param data   * @throws IOException  */ public static void saveToSDCard(byte[] data) throws IOException {  Date date = new Date();  SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); // 格式化时间  String filename = format.format(date) + ".jpg";  File fileFolder = new File(Environment.getExternalStorageDirectory()    + "/finger/");  if (!fileFolder.exists()) { // 如果目录不存在,则创建一个名为"finger"的目录   fileFolder.mkdir();  }  File jpgFile = new File(fileFolder, filename);  FileOutputStream outputStream = new FileOutputStream(jpgFile); // 文件输出流  outputStream.write(data); // 写入sd卡中  outputStream.close(); // 关闭输出流 } private final class SurfaceCallback implements Callback {  // 拍照状态变化时调用该方法  @Override  public void surfaceChanged(SurfaceHolder holder, int format, int width,    int height) {   parameters = camera.getParameters(); // 获取各项参数   parameters.setPictureFormat(PixelFormat.JPEG); // 设置图片格式   parameters.setPreviewSize(width, height); // 设置预览大小   parameters.setPreviewFrameRate(5); //设置每秒显示4帧   parameters.setPictureSize(width, height); // 设置保存的图片尺寸   parameters.setJpegQuality(80); // 设置照片质量  }  // 开始拍照时调用该方法  @Override  public void surfaceCreated(SurfaceHolder holder) {   try {    camera = Camera.open(); // 打开摄像头    camera.setPreviewDisplay(holder); // 设置用于显示拍照影像的SurfaceHolder对象    camera.setDisplayOrientation(getPreviewDegree(MainActivity.this));    camera.startPreview(); // 开始预览   } catch (Exception e) {    e.printStackTrace();   }  }  // 停止拍照时调用该方法  @Override  public void surfaceDestroyed(SurfaceHolder holder) {   if (camera != null) {    camera.release(); // 释放照相机    camera = null;   }  } } /**  * 点击手机屏幕是,显示两个按钮  */ @Override public boolean onTouchEvent(MotionEvent event) {  switch (event.getAction()) {  case MotionEvent.ACTION_DOWN:   layout.setVisibility(ViewGroup.VISIBLE); // 设置视图可见   break;  }  return true; }  @Override public boolean onKeyDown(int keyCode, KeyEvent event) {  switch (keyCode) {  case KeyEvent.KEYCODE_CAMERA: // 按下拍照按钮   if (camera != null && event.getRepeatCount() == 0) {    // 拍照    //注:调用takePicture()方法进行拍照是传入了一个PictureCallback对象——当程序获取了拍照所得的图片数据之后    //,PictureCallback对象将会被回调,该对象可以负责对相片进行保存或传入网络    camera.takePicture(null, null, new MyPictureCallback());   }  }  return super.onKeyDown(keyCode, event); } // 提供一个静态方法,用于根据手机方向获得相机预览画面旋转的角度 public static int getPreviewDegree(Activity activity) {  // 获得手机的方向  int rotation = activity.getWindowManager().getDefaultDisplay()    .getRotation();  int degree = 0;  // 根据手机的方向计算相机预览画面应该选择的角度  switch (rotation) {  case Surface.ROTATION_0:   degree = 90;   break;  case Surface.ROTATION_90:   degree = 0;   break;  case Surface.ROTATION_180:   degree = 270;   break;  case Surface.ROTATION_270:   degree = 180;   break;  }  return degree; }}


用来显示图片的Activity:

package com.wwj.finger;import android.app.Activity;import android.content.Intent;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Matrix;import android.os.Bundle;import android.widget.ImageView;public class ShowPicActivity extends Activity private ImageView ivPic = null; // 显示图片控件 /**  * Activity在创建的时候回调的函数 主要用来初始化一些变量  */ @Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.showpic);  ivPic = (ImageView) findViewById(R.id.ivPic);  setImageBitmap(getImageFormBundle()); } /**  * 将MainActivity传过来的图片显示在界面当中  *   * @param bytes  */ public void setImageBitmap(byte[] bytes) {  Bitmap cameraBitmap = byte2Bitmap();  // 根据拍摄的方向旋转图像(纵向拍摄时要需要将图像选择90度)  Matrix matrix = new Matrix();  matrix.setRotate(MainActivity.getPreviewDegree(this));  cameraBitmap = Bitmap    .createBitmap(cameraBitmap, 0, 0, cameraBitmap.getWidth(),      cameraBitmap.getHeight(), matrix, true);  ivPic.setImageBitmap(cameraBitmap); } /**  * 从Bundle对象中获取数据  *   * @return  */ public byte[] getImageFormBundle() {  Intent intent = getIntent();  Bundle data = intent.getExtras();  byte[] bytes = data.getByteArray("bytes");  return bytes; } /**  * 将字节数组的图形数据转换为Bitmap  *   * @return  */ private Bitmap byte2Bitmap() {  byte[] data = getImageFormBundle();  // 将byte数组转换成Bitmap对象  Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);  return bitmap; }}



这是小巫那个创新项目的一小部分,已经完美实现简单的照相机功能了,保存图片不会像有些网友提供的代码给定一个特定的文件名,不能保存多张图片,还特定把一些方法封装了一下,有需要的朋友好好看看吧。


           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow