Android自定义照相机实现

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

创建一个项目:FingerTakePicture

首先来搞一下界面:

xmlns:tools="http://schemas.android.com/tools"

android:id="@+id/FrameLayout1"

android:layout_width="match_parent"

android:layout_height="match_parent" >

android:id="@+id/surfaceView"

android:layout_width="match_parent"

android:layout_height="match_parent"

/>

android:id="@+id/buttonLayout"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:visibility="gone"

>

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"

/>

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"

/>

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

权限设置少不了:

package="com.wwj.finger"

android:versionCode="1"

android:versionName="1.0" >

android:minSdkVersion="4"

android:targetSdkVersion="15" />

android:icon="@drawable/ic_launcher"

android:label="@string/app_name"

android:theme="@style/AppTheme" >

android:name=".MainActivity"

android:label="@string/title_activity_main"

>

android:name=".ShowPicActivity"

android:label="@string/app_name"

android:theme="@style/AppTheme"

android:configChanges="orientation|keyboardHidden"

>

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

}

}

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

安android自定义照相机,Android自定义照相机的实例相关推荐

  1. android 画布叠加,Android自定义图形,图形的拼接、叠加、相容

    直接上Xfermode子类: AvoidXfermode  指定了一个颜色和容差,强制Paint避免在它上面绘图(或者只在它上面绘图). PixelXorXfermode  当覆盖已有的颜色时,应用一 ...

  2. android 自定义控件 焦点,Android 自定义Button按钮显示样式(正常、按下、获取焦点)...

    现在的用户对APP的外观看得很重要,如果APP内所有元件都用Android默认样式写,估计下面评论里就有一堆在骂UI丑的.今天学习自定义Button按钮样式.Button样式修改的是Button的背景 ...

  3. android炫酷的自定义view,Android自定义View实现炫酷进度条

    本文实例为大家分享了Android实现炫酷进度条的具体代码,供大家参考,具体内容如下 下面我们来实现如下效果: 第一步:创建attrs文件夹,自定义属性: 第二步:自定义View: /** * Cre ...

  4. android单线字体,Android自定义字体

    在main文件夹下,新建assets/fonts文件,添加.otf文件 image.png 字体工具类 import android.app.Application; import android.g ...

  5. android 自定义命名空间,Android自定义ActionBar实例

    本文实例讲述了android自定义actionbar的实现方法.分享给大家供大家参考.具体实现方法如下: android 3.0及以上已经有了actionbar的api,可以通过引入support p ...

  6. android 自定义图片容器,Android应用开发中自定义ViewGroup视图容器的教程

    一.概述在写代码之前,我必须得问几个问题: 1.ViewGroup的职责是啥?ViewGroup相当于一个放置View的容器,并且我们在写布局xml的时候,会告诉容器(凡是以layout为开头的属性, ...

  7. android sqlite自定义函数,Android中自定义一个View的方法详解

    本文实例讲述了Android中自定义一个View的方法.分享给大家供大家参考,具体如下: Android中自定义View的实现比较简单,无非就是继承父类,然后重载方法,即便如此,在实际编码中难免会遇到 ...

  8. Android Paint应用之自定义View实现进度条控件

    在上一篇文章<Android神笔之Paint>学习了Paint的基本用法,但是具体的应用我们还没有实践过.从标题中可知,本文是带领读者使用Paint,自定义一个进度条控件. 上图就是本文要 ...

  9. android 自定义图形,Android自定义View之图形图像(模仿360的刷新球自定

    概述: 360安全卫士的那个刷新球(姑且叫它刷新球,因为真的不知道叫什么好,不是dota里的刷新球!!),里面像住了水一样,生动可爱,看似简单,写起来不太简单,本例程只是实现了它的部分功能而已,说实话 ...

最新文章

  1. 电脑画画软件_手绘、板绘、还有用pad画画都有啥区别?
  2. 嵌入式系统学习笔记之五-uboot常用命令之补充
  3. 视频和音频播放的演示最简单的例子9:SDL2广播PCM
  4. 15分钟在阿里云Kubernetes服务上快速建立Jenkins X Platform并运用GitOps管理应用发布...
  5. Android IOC模块,利用了Java反射和Java注解
  6. 027_jdbc-mysql几个常用的日期类型
  7. Sklearn(v3)——朴素贝叶斯(1)
  8. 本周学习总结JAVA
  9. xshell最多支持4个_中集拉钢卷专用挂车来了!自重5吨,最多能装4个钢卷
  10. Java的class文件批量反编译成Java文件
  11. 短线买股赚钱的概率有多大?python带你来分析
  12. Evaluate the Malignancy of Pulmonary Nodules Using the 3D Deep Leaky Noisy-or Network 论文阅读
  13. 解决使用adprep升级windows2003/win2008/win2012域时遇到的问题
  14. Spring3中的mvc:interceptors标签配置拦截器
  15. 【渝粤教育】电大中专药物分析技术基础 (2)_1作业 题库
  16. 高盛也上GitHub了!让交易员赚取10亿美元的神秘“利器” 即将开源
  17. Codeforces Round #612 (Div. 2) A~E2
  18. MATLAB求前N个数的阶乘和(通俗易懂)
  19. apng java,免费的APNG、WebP格式转换工具-iSparta
  20. 塞格Np7280游戏笔记本概述

热门文章

  1. java-使用ffemg插件截取rtsp视频流实现视频录制(海康相机)
  2. 为什么我们需要去中心化存储?
  3. 圣何塞Hadoop Summit 2014看点
  4. Vue项目的数据获取到渲染操作
  5. SQL在现实时间增加天数
  6. 关于qt执行带有中文参数的DOS命令执行不成功
  7. 重庆市建筑物矢量数据(Shp格式+带高度)
  8. IEC61400-6 2020 塔架及基础设计要求 翻译 第7章 混凝土塔架和基础
  9. 【共享农场】共享农场土地租赁,智慧农业众筹,家禽认养小程序都有什么功能?
  10. 软件工具:ubuntu adb shell无法识别设备