android 自定义相机源码,Android 自定义相机及分析源码

Android 自定义相机及分析源码

使用Android 系统相机的方法:

要想让应用有相机的action,咱们就必须在清单文件中做一些声明,好让系统知道,如下

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();

}

}

}

}

//记得最后一定要关闭相关的流操作。否则会引起相关的异常的。

开发自定义的相机

由于开发自定义的相机要进行相关的权限的生命,所以一定不要忘记在清单文件中做相关的处理,如下

然后有以下几个步骤:

创建Camera,并完成初始化Camera,开始预览,释放资源三个方法

与Activity的SurfaceView进行绑定。

在系统的onPause(),onResume()方法中进行相关状态设置

对Camera进行参数设置,作用就是对照片类型和状态进行相关的设置

将拍得的照片进行展示,一般会新开一个Activity,用ImageView进行承载,我们还可以在此Activity上添加TextView,实现水印效果等其他的美化操作

另外,如果想加入自动聚焦的功能,就可以在SurfaceView上添加onClickListener(),对屏幕进行侦听,调用myCamera.autoFocus(null);方法即可

以上就是整个思路

接下来就是使用系统Camera的代码展示

(可以直接copy相关代码块,添加到你的应用中去,实现Camera这一功能。)

首先是MainActivity

布局

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" >

android:id="@+id/startCarema"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_margin="6dp"

android:text="StartCarema"

android:onClick="onStartCarema"

/>

android:id="@+id/startCarema2"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_margin="6dp"

android:text="StartCarema2"

android:onClick="onStartCarema2"

/>

android:id="@+id/customCarema"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_margin="6dp"

android:text="CustomCarema"

android:onClick="onCustomCarema"

/>

android:id="@+id/imageview"

android:layout_width="match_parent"

android:layout_height="match_parent"

/>

代码

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();

}

}

}

}

}

}

接下来是自定义相机的代码

主界面布局

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical" >

android:id="@+id/capture"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_margin="6dp"

android:text="Capture"

android:onClick="onCapture"

/>

android:id="@+id/preview"

android:layout_width="match_parent"

android:layout_height="match_parent"

/>

ResultActivity的布局

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical" >

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="Capture Result"

android:textSize="28dp"

android:textColor="#BFAACD"

android:gravity="center"

/>

android:id="@+id/picture"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:scaleType="center"

/>

代码

首先是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();

}

}

}

以上代码中已经做了下关的代码注释

总结:

安卓6.0以上版本记得加动态权限,不然会报空指针哦,还有点击拍照事件那里  别忘了加进去,不然拍照没反应

以上就是Android 自定义相机的实例详解,如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值