Android实现自定义的相机
使用系统相机
android中使用系统相机是很方便的,单这仅仅是简单的使用而已,并不能获得什么特殊的效果。
要想让应用有相机的action,咱们就必须在清单文件中做一些声明,好让系统知道,如下
<intent-filter>
<action android:name="android.intent.action.IMAGE_CAPTURE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
action的作用就是声明action的类型,便于Intent的使用,category的作用就是注册,没有它。相关操作将不起作用。
一种方式是简单粗暴的实现,如下
Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, REQ_1);
//然后在 onActivityResult方法中实现数据的获取,此处是展示在了一个ImageView上
if(resultCode==RESULT_OK){
if(requestCode==REQ_1){
Bundle bundle=data.getExtras();
Bitmap bitmap=(Bitmap) bundle.get("data");
imageView.setImageBitmap(bitmap);
}
小总结:这样的好处是简单快捷,但是在现在的android智能机中,好多相片都是很大的,这里获得的仅仅是一个缩略图罢了
另外一种方式是稍微温婉一点了,而且效果也更好一点,好处就在于它是先将照片信息存储到本地一个临时文件中,然后让ImageView去相关路径下进行读取,这样就可以获得清晰度很高的图片了。如下
/*
* 此方法的存在意义就是不在onActivityResult方法的data中获取我们拍照的缩略图,而是从我们的文件输出目录下直接查看原图
* 这样的好处就是可以对大容量的照片进行便捷的准确的操作
*/
public void onStartCarema2(View view){
Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//见你给你路径传递回需要的处理方法中
Uri uri=Uri.fromFile(new File(myFilePath));
//设置文件的输出路径
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, REQ_2);
}
//然后在onActivityResult方法中进行相关的处理就可以了
else if(requestCode==REQ_2){
FileInputStream fis=null;
try {
fis=new FileInputStream(myFilePath);
Bitmap bitmap=BitmapFactory.decodeStream(fis);
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
//记得最后一定要关闭相关的流操作。否则会引起相关的异常的。
开发自定义的相机
由于开发自定义的相机要进行相关的权限的生命,所以一定不要忘记在清单文件中做相关的处理,如下
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA"/>
然后有以下几个步骤:
- 创建Camera,并完成初始化Camera,开始预览,释放资源三个方法
- 与Activity的SurfaceView进行绑定。
- 在系统的onPause(),onResume()方法中进行相关状态设置
- 对Camera进行参数设置,作用就是对照片类型和状态进行相关的设置
- 将拍得的照片进行展示,一般会新开一个Activity,用ImageView进行承载,我们还可以在此Activity上添加TextView,实现水印效果等其他的美化操作
- 另外,如果想加入自动聚焦的功能,就可以在SurfaceView上添加onClickListener(),对屏幕进行侦听,调用myCamera.autoFocus(null);方法即可
以上就是整个思路
接下来就是使用系统Camera的代码展示
(可以直接copy相关代码块,添加到你的应用中去,实现Camera这一功能。)
首先是MainActivity
- 布局
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity" >
<Button
android:id="@+id/startCarema"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="6dp"
android:text="StartCarema"
android:onClick="onStartCarema"
/>
<Button
android:id="@+id/startCarema2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="6dp"
android:text="StartCarema2"
android:onClick="onStartCarema2"
/>
<Button
android:id="@+id/customCarema"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="6dp"
android:text="CustomCarema"
android:onClick="onCustomCarema"
/>
<ImageView
android:id="@+id/imageview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
- 代码
package com.example.camerademo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
public class MainActivity extends Activity {
//为下面的获取请求所用
private static int REQ_1=1;
private static int REQ_2=2;
Button btn_startCareme,btn_startCarema2,btn_customCarema;
ImageView imageView;
//定义照片存储的路径
private String myFilePath;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_startCareme=(Button) findViewById(R.id.startCarema);
btn_startCarema2=(Button) findViewById(R.id.startCarema2);
btn_customCarema=(Button) findViewById(R.id.customCarema);
imageView=(ImageView) findViewById(R.id.imageview);
//初始化不同手机的SD卡的路径
myFilePath=Environment.getExternalStorageDirectory().getPath();
myFilePath=myFilePath+"/"+"temperature.png";
}
public void onCustomCarema(View view){
Intent intent=new Intent(this,CustomCarema.class);
startActivity(intent);
}
public void onStartCarema(View view){
Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, REQ_1);
}
/*
* 此方法的存在意义就是不在onActivityResult方法的data中获取我们拍照的缩略图,而是从我们的文件输出目录下直接查看原图
* 这样的好处就是可以对大容量的照片进行便捷的准确的操作
*/
public void onStartCarema2(View view){
Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//见你给你路径传递回需要的处理方法中
Uri uri=Uri.fromFile(new File(myFilePath));
//设置文件的输出路径
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, REQ_2);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if(resultCode==RESULT_OK){
if(requestCode==REQ_1){
Bundle bundle=data.getExtras();
Bitmap bitmap=(Bitmap) bundle.get("data");
imageView.setImageBitmap(bitmap);
}else if(requestCode==REQ_2){
FileInputStream fis=null;
try {
fis=new FileInputStream(myFilePath);
Bitmap bitmap=BitmapFactory.decodeStream(fis);
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
接下来是自定义相机的代码
- 主界面布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/capture"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="6dp"
android:text="Capture"
android:onClick="onCapture"
/>
<SurfaceView
android:id="@+id/preview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
- ResultActivity的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Capture Result"
android:textSize="28dp"
android:textColor="#BFAACD"
android:gravity="center"
/>
<ImageView
android:id="@+id/picture"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="center"
/>
</LinearLayout>
- 代码
首先是CustomCamera类,
package com.example.camerademo;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.content.Intent;
import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
@SuppressWarnings("unused")
public class CustomCarema extends Activity implements SurfaceHolder.Callback{
private Camera myCamera;
private SurfaceView preview;
private SurfaceHolder myHolder; //myHolder勇于展现surfaceView的图像
private Camera.PictureCallback myPictureCallBack=new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera arg1) {
//将拍照得到的数据信息存储到本地
File tempFile=new File("/sdcard/temp.png");
try {
FileOutputStream fos=new FileOutputStream(tempFile);
fos.write(data);
fos.close();
//然后将这个照片的数据信息传送给要进行展示的Activity即可
Intent intent=new Intent(CustomCarema.this,ResultActivity.class);
intent.putExtra("PicturePath", tempFile.getAbsolutePath());
startActivity(intent);
//拍照结束之后销毁当前的Activity,进入到图片展示界面
CustomCarema.this.finish();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.customcarema);
preview=(SurfaceView) findViewById(R.id.preview);
myHolder=preview.getHolder();
myHolder.addCallback(this);
//实现点击屏幕自动聚焦的功能,此处并不需要拍照,故只是聚焦
preview.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
myCamera.autoFocus(null);
}
});
}
@Override
protected void onResume() {
super.onResume();
if(myCamera==null){
myCamera=getCamera();
if(myHolder != null ){
setStartPreview(myCamera, myHolder);
}
}
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
releaseCamera();
}
/**
* 释放相机的资源
*/
private void releaseCamera(){
if(myCamera !=null ){
myCamera.setPreviewCallback(null);
myCamera.stopPreview();
myCamera.release();
myCamera=null;
}
}
/**
* 拍照的一些参数设置,点击此按钮之后会触发拍照的会掉,进而实现拍照的效果
* @param view
*/
public void onCapture(View view){
Camera.Parameters parameters=myCamera.getParameters();
//设置照片的类型
parameters.setPictureFormat(ImageFormat.JPEG);
parameters.setPictureSize(800, 600);
//设置为自动聚焦
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
//设置为自动聚焦是不够的,因为我们先得到的是最为清晰的图片,所以要在聚焦成功的时候才进行拍照
myCamera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
// TODO Auto-generated method stub
if(success){
myCamera.takePicture(null, null, myPictureCallBack);
}
}
});
}
/**
* 获取系统的一个Camera对象
*/
private Camera getCamera(){
Camera camera=null;
try{
camera=Camera.open();
}catch(Exception e){
e.printStackTrace();
}
return camera;
}
/**
* 开始预览相机的内容,其实就是讲surfaceHolder与之绑定
*/
private void setStartPreview(Camera camera,SurfaceHolder holder){
//直接调用系统方式绑定预览
try {
camera.setPreviewDisplay(holder);
//由于系统默认使用横屏预览,,所以要进行设置
camera.setDisplayOrientation(90);
camera.startPreview();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
myCamera.stopPreview();
setStartPreview(myCamera, myHolder);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
setStartPreview(myCamera, myHolder);
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
releaseCamera();
}
}
然后是结果界面代码:
package com.example.camerademo;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.os.Bundle;
import android.widget.ImageView;
public class ResultActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.resultactivity);
String path=getIntent().getStringExtra("PicturePath");
ImageView imageview=(ImageView) findViewById(R.id.picture);
//由于这样稚嫩获得横屏,所以我们要使用流的形式来转换
// Bitmap bitmap=BitmapFactory.decodeFile(path);
// imageview.setImageBitmap(bitmap);
FileInputStream fis;
try {
fis = new FileInputStream(path);
Bitmap bitmap=BitmapFactory.decodeStream(fis);
Matrix matrix=new Matrix();
matrix.setRotate(90);
bitmap=Bitmap.createBitmap(bitmap, 0,0, bitmap.getWidth()
,bitmap.getHeight(),matrix,true);
imageview.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
以上代码中已经做了下关的代码注释
总结:
//写这篇博客的目的一方面是为了今后复习时方便一点,毕竟思路在此刻是清晰的,过几天就有可能忘记了。另一方面若能帮到在这方面有欠缺的小伙伴们的话,那是更好的了。最后尤其要感谢的是Imooc中eclipse_xu 老师,我就是看着他的视频来敲得代码。
Android实现自定义的相机的更多相关文章
- Android之运行时相机权限和联系人权限获取
原文:Android之运行时相机权限和联系人权限获取 本文链接:http://blog.csdn.net/qq_16628781/article/details/61623502 Android之运行 ...
- Android RatingBar 自定义样式
Android RatingBar 自定义样式 1.先定义Style: <style name="RadingStyle" parent="@android:sty ...
- Android实现自定义带文字和图片的Button
Android实现自定义带文字和图片的Button 在Android开发中经常会需要用到带文字和图片的button,下面来讲解一下常用的实现办法. 一.用系统自带的Button实现 最简单的一种办法就 ...
- Android Studio 自定义debug签名文件keystore
Android Studio 自定义debug签名文件keystore
- Android读取自定义View属性
Android读取自定义View属性 attrs.xml : <?xml version="1.0" encoding="utf-8"?> < ...
- Android之自定义画图文字动画
结构: BaseView: package com.caiduping.canvas; import android.content.Context; import android.graphics. ...
- Android 三档自定义滑动开关,禁止点击功能的实现,用默认的seekbar组件实现
android三档自定义滑动开关,禁止点击功能的实现,普通开关网上有很多例子,三档滑动开关的则找了整天都没有相关例子,开始用普通开关的源码修改了自己实现了一个类,但效果不如人意,各种边界情况的算法很难 ...
- Android 自定义View修炼-【2014年最后的分享啦】Android实现自定义刮刮卡效果View
一.简介: 今天是2014年最后一天啦,首先在这里,我祝福大家在新的2015年都一个个的新健康,新收入,新顺利,新如意!!! 上一偏,我介绍了用Xfermode实现自定义圆角和椭圆图片view的博文& ...
- Android Toast 自定义
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...
随机推荐
- tomcat7+jdk的keytool生成证书 配置https
目前只会使用jdk的keytool来生成证书.本文仅介绍这种方法. 1Windows下: 1.1 生成keystore文件及导出证书 打开控制台: 运行: %JAVA_HOME%\bin\keytoo ...
- 网站用户身份识别俩大招之cookie
导航: 原理介绍 代码实现 过程分析 追踪Cookie 原理介绍 众所周知,http协议是无状态的协议,简单理解是用户的前一步操作和后一步操作之间没有关系,互相不知道,不干扰.而在很多场景下,浏览网页 ...
- salesforce lightning零基础学习(三) 表达式的!(绑定表达式)与 #(非绑定表达式)
在salesforce的classic中,我们使用{!expresion}在前台页面展示信息,在lightning中,上一篇我们也提及了,如果展示attribute的值,可以使用{!v.expresi ...
- Oracle中的行转列例子详解
--场景1: A B a a a b b 希望实现如下效果: a ,, b , create table tmp as B from dual union all B from dual union ...
- java绘图原理------在窗口界面(或面板上)画出一张或多张图片问题解决方法
/** *@author blovedr * 功能: java绘图原理------在窗口界面(或面板上)画出一张或多张图片问题解决方法 * 日期: 2018年4月28日 16:20 * 注释: ...
- Java面试06|项目相关介绍
1.明确你的项目到底是做什么的,有哪些功能 广告投放机:项目主要是为移动端有针对性的进行广告展示. 媒体管理平台SSP:为媒体端实现多种变现途径 (1)广告投放机中关于广告检索与排序的功能 1.广告检 ...
- Objective-C的继承与组合
Objective-C的继承与组合 Objective-C与Java继承上的区别 区别 Objective-C Java 成员变量 Objective-C继承不允许子类和父类拥有相同名称的成员变量 J ...
- CentOS 7 下使用虚拟环境Virtualenv安装Tensorflow cpu版记录
1.首先安装pip-install 在使用centos7的软件包管理程序yum安装python-pip的时候会报一下错误: No package python-pip available. Error ...
- Android简易实战教程--第三十七话《NotifiCation》
通知的使用,无疑是Android系统的亮点之一:就连IOS在5.0开始也引入了类似通知的技巧.可见它的实用性. 今天这个小案例,就学习一下通知的基本使用,API是使用最新的API,4.3以前创建通知的 ...
- 深度学习与计算机视觉系列(2)_图像分类与KNN
作者: 寒小阳 &&龙心尘 时间:2015年11月. 出处: http://blog.csdn.net/han_xiaoyang/article/details/49949535 ht ...