欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android自定义照相机的实例

程序员文章站 2022-10-10 12:28:16
android自定义照相机实现 近期小巫在学校有一个创新项目,也不是最近,是一个拖了很久的项目,之前一直没有去搞,最近因为要中期检查,搞得我跟小组成员一阵忙活,其实开...

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自定义照相机的实例

权限设置少不了:

<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; 
  } 
} 

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