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>
界面效果(无法把预览给截屏下来滴):
权限设置少不了:
<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;
}
}
这是小巫那个创新项目的一小部分,已经完美实现简单的照相机功能了,保存图片不会像有些网友提供的代码给定一个特定的文件名,不能保存多张图片,还特定把一些方法封装了一下,有需要的朋友好好看看吧。
# Android自定义照相机
# Android照相机
# Android仿最新微信相机功能
# android 7自定义相机预览及拍照功能
# Android开源库自定义相机模块
# Android调用系统照相机拍照与摄像的方法
# Android如何调用系统相机拍照
# Android 照相机的实例应用
# Android 自定义相机及分析源码
# Android 用 camera2 API 自定义相机
# Android相机启动加速详解
# 回调
# 自定义
# 创建一个
# 是一个
# 这是
# 放在
# 小巫
# 将会
# 句柄
# 很久
# 不存在
# 我跟
# 按下
# 一直没有
# 搞得
# 提供一个
# 看看吧
# 转换成
# 时要
# 来实现
相关文章:
如何通过老薛主机一键快速建站?
小视频制作网站有哪些,有什么看国内小视频的网站,求推荐?
微网站制作教程,我微信里的网站怎么才能复制到浏览器里?
安云自助建站系统如何快速提升SEO排名?
公司网站制作需要多少钱,找人做公司网站需要多少钱?
广州网站制作的公司,现在专门做网站的公司有没有哪几家是比较好的,性价比高,模板也多的?
盐城做公司网站,江苏电子版退休证办理流程?
全景视频制作网站有哪些,全景图怎么做成网页?
网站制作哪家好,cc、.co、.cm哪个域名更适合做网站?
移民网站制作流程,怎么看加拿大移民官网?
佛山网站制作系统,佛山企业变更地址网上办理步骤?
网站制作话术技巧,网站推广做的好怎么话术?
青浦网站制作公司有哪些,苹果官网发货地是哪里?
如何在建站之星网店版论坛获取技术支持?
家族网站制作贴纸教程视频,用豆子做粘帖画怎么制作?
网站制作难吗安全吗,做一个网站需要多久时间?
如何在阿里云ECS服务器部署织梦CMS网站?
如何高效利用200m空间完成建站?
定制建站流程步骤详解:一站式方案设计与开发指南
高防网站服务器:DDoS防御与BGP线路的AI智能防护方案
制作国外网站的软件,国外有哪些比较优质的网站推荐?
如何在Golang中处理模块冲突_解决依赖版本不兼容问题
如何在建站之星绑定自定义域名?
如何在万网开始建站?分步指南解析
怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?
学校为何禁止电信移动建设网站?
C++中的Pimpl idiom是什么,有什么好处?(隐藏实现)
已有域名建站全流程解析:网站搭建步骤与建站工具选择
如何通过FTP服务器快速搭建网站?
小建面朝正北,A点实际方位是否存在偏差?
如何通过WDCP绑定主域名及创建子域名站点?
如何在IIS管理器中快速创建并配置网站?
图册素材网站设计制作软件,图册的导出方式有几种?
如何通过虚拟主机空间快速建站?
Swift开发中switch语句值绑定模式
利用JavaScript实现拖拽改变元素大小
如何破解联通资金短缺导致的基站建设难题?
免费的流程图制作网站有哪些,2025年教师初级职称申报网上流程?
建站之星代理如何优化在线客服效率?
如何快速搭建高效WAP手机网站吸引移动用户?
百度网页制作网站有哪些,谁能告诉我百度网站是怎么联系?
如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?
大连网站制作费用,大连新青年网站,五年四班里的视频怎样下载啊?
建站主机是否等同于虚拟主机?
简单实现Android文件上传
广州营销型建站服务商推荐:技术优势与SEO优化解析
如何在宝塔面板中修改默认建站目录?
教程网站设计制作软件,怎么创建自己的一个网站?
如何解决VPS建站LNMP环境配置常见问题?
自助网站制作软件,个人如何自助建网站?
*请认真填写需求信息,我们会在24小时内与您取得联系。