配色: 字号:
Android Camera开发
2016-10-17 | 阅:  转:  |  分享 
  
AndroidCamera开发

Camera的基本调用与实现拍照功能以及获取拍照图片加载大图片

一.Camera的启动方式



1.调用系统方式

2.自定义相机

二.调用系统相机



喜闻乐见,调用系统相机是十分的简单的,我们这里演示的话,还是新建一个工程吧,这里就直接用Eclipse开发了,这里我们新建一个项目——SystemCamera



activity_main.xml



这里直接一个button就够了


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

android:layout_width="match_parent"

android:layout_height="match_parent">




android:id="@+id/on_camera"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="打开相机"/>





MainActivity



packagecom.lgl.camera;



importandroid.app.Activity;

importandroid.content.Intent;

importandroid.os.Bundle;

importandroid.provider.MediaStore;

importandroid.view.View;

importandroid.view.View.OnClickListener;

importandroid.widget.Button;



publicclassMainActivityextendsActivity{



privateButtonon_camera;



@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);



on_camera=(Button)findViewById(R.id.on_camera);

on_camera.setOnClickListener(newOnClickListener(){



@Override

publicvoidonClick(Viewv){

/

我们使用Intent的方式打开系统相机

1.直接跳转相机包名,前提是你知道这个应用的包名

2.就是使用隐式Intent了,在这里我们就使用隐式intent

/

Intentintent=newIntent(MediaStore.ACTION_IMAGE_CAPTURE);//指定拍照

startActivity(intent);

}

});

}

}



三.获取拍照图片



说到获取图片,大家应该就立马想到了startActivityForResult,没错,我们就是这样直接拿到传递回来的data,然后通过Bundle转换二进制流的方式获得一个bitmap,好的,这样的话,我们就要新增加一个imageview了

activity_main.xml




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

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">




android:id="@+id/on_camera"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="打开相机"/>




android:id="@+id/iv_photo"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>







MainActivity



packagecom.lgl.camera;



importandroid.app.Activity;

importandroid.content.Intent;

importandroid.graphics.Bitmap;

importandroid.os.Bundle;

importandroid.provider.MediaStore;

importandroid.view.View;

importandroid.view.View.OnClickListener;

importandroid.widget.Button;

importandroid.widget.ImageView;



publicclassMainActivityextendsActivity{



privateButtonon_camera;

privateImageViewiv_photo;



//返回码

privatestaticfinalintCODE=1;



@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);



iv_photo=(ImageView)findViewById(R.id.iv_photo);

on_camera=(Button)findViewById(R.id.on_camera);

on_camera.setOnClickListener(newOnClickListener(){



@Override

publicvoidonClick(Viewv){

/

我们使用Intent的方式打开系统相机

1.直接跳转相机包名,前提是你知道这个应用的包名

2.就是使用隐式Intent了,在这里我们就使用隐式intent

/

Intentintent=newIntent(MediaStore.ACTION_IMAGE_CAPTURE);//指定拍照\

//拍照返回图片

startActivityForResult(intent,CODE);

}

});

}



@Override

protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){

//TODOAuto-generatedmethodstub

super.onActivityResult(requestCode,resultCode,data);

//判断是否返回值

if(resultCode==RESULT_OK){

//判断返回值是否正确

if(requestCode==CODE){

//获取图片

Bundlebundle=data.getExtras();

//转换图片的二进制流

Bitmapbitmap=(Bitmap)bundle.get("data");

//设置图片

iv_photo.setImageBitmap(bitmap);

}

}

}

}



好,我们继续运行一下



加载大图片



这里我们要知道一个概念,就是我们返回结果是从data中取出来的,但是这个data不可能存储太多的东西,比如你拍的4K照片,动辄几十M,那不就直接挂了嘛,google是这样设定的,data返回的只是有一个缩略图,但是我们实际开发当中怎么可以使用缩略图,别急,是有办法的

我们再增加一个button和一个imageview为了显示真实大小的图片,这里就直接上完整代码了,思路十分的顺,但是我们所用到的方式是要写sd卡的,我们新增加一个权限

接着我们就可以在他返回请求的时候请求另一个返回码了

activity_main.xml




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

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">




android:id="@+id/on_camera"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="打开相机"/>




android:id="@+id/on_camera_big"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="大图片"/>




android:id="@+id/iv_photo"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>






android:id="@+id/iv_photo_big"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>







MainActivity



packagecom.lgl.camera;



importjava.io.File;

importjava.io.FileInputStream;

importjava.io.FileNotFoundException;

importjava.io.IOException;



importandroid.app.Activity;

importandroid.content.Intent;

importandroid.graphics.Bitmap;

importandroid.graphics.BitmapFactory;

importandroid.net.Uri;

importandroid.os.Bundle;

importandroid.os.Environment;

importandroid.provider.MediaStore;

importandroid.view.View;

importandroid.view.View.OnClickListener;

importandroid.widget.Button;

importandroid.widget.ImageView;



publicclassMainActivityextendsActivity{



privateButtonon_camera;

privateImageViewiv_photo;

privateButtonon_camera_big;

privateImageViewiv_photo_big;



//返回码

privatestaticfinalintCODE=1;

privatestaticfinalintCODEBIG=2;



//记录文件保存位置

privateStringmFilePath;

privateFileInputStreamis=null;



@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);



//获取SD卡路径

mFilePath=Environment.getExternalStorageDirectory().getPath();

//文件名

mFilePath=mFilePath+"/"+"photo.png";



iv_photo=(ImageView)findViewById(R.id.iv_photo);

iv_photo_big=(ImageView)findViewById(R.id.iv_photo_big);

on_camera=(Button)findViewById(R.id.on_camera);

on_camera.setOnClickListener(newOnClickListener(){



@Override

publicvoidonClick(Viewv){

/

我们使用Intent的方式打开系统相机

1.直接跳转相机包名,前提是你知道这个应用的包名

2.就是使用隐式Intent了,在这里我们就使用隐式intent

/

Intentintent=newIntent(MediaStore.ACTION_IMAGE_CAPTURE);//指定拍照

//拍照返回图片

startActivityForResult(intent,CODE);

}

});

on_camera_big=(Button)findViewById(R.id.on_camera_big);

on_camera_big.setOnClickListener(newOnClickListener(){



@Override

publicvoidonClick(Viewv){

//指定拍照

Intentintent=newIntent(MediaStore.ACTION_IMAGE_CAPTURE);

//加载路径

Uriuri=Uri.fromFile(newFile(mFilePath));

//指定存储路径,这样就可以保存原图了

intent.putExtra(MediaStore.EXTRA_OUTPUT,uri);

//拍照返回图片

startActivityForResult(intent,CODEBIG);



}

});

}



@Override

protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){

//TODOAuto-generatedmethodstub

super.onActivityResult(requestCode,resultCode,data);

//判断是否返回值

if(resultCode==RESULT_OK){

//判断返回值是否正确

if(requestCode==CODE){

//获取图片

Bundlebundle=data.getExtras();

//转换图片的二进制流

Bitmapbitmap=(Bitmap)bundle.get("data");

//设置图片

iv_photo.setImageBitmap(bitmap);

//加载原图

}elseif(requestCode==CODEBIG){

try{

//获取输入流

is=newFileInputStream(mFilePath);

//把流解析成bitmap

Bitmapbitmap=BitmapFactory.decodeStream(is);

//设置图片

iv_photo_big.setImageBitmap(bitmap);

}catch(FileNotFoundExceptione){

//TODOAuto-generatedcatchblock

e.printStackTrace();

}finally{

//关闭流

try{

is.close();

}catch(IOExceptione){

//TODOAuto-generatedcatchblock

e.printStackTrace();

}

}

}

}

}

}



好的,最后运行一遍



这是基本的系统相机调用,我们下篇就开始来写自定义相机的API和回调方法

自定义Camera实现拍照查看图片等功能

我们还是在原来的demo上修改,新增一个button,点击跳转到CameraActivity,我们在CameraActivity内实现我们的自定义相机,这里值得注意的是,我们拍照时要一直捕捉拍照的过程,普通的view肯定不行,google给我们提供了一个view叫做



一.获取相机



这里有个前提,记得添加权限





我们新增一个方法来获取系统的相机实例

/

获取系统相机



@return

/

privateCameragetcCamera(){

Cameracamera=null;

try{

camera=Camera.open();

}catch(Exceptione){

camera=null;

}

returncamera;

}



这里值得注意的是,camera是废弃的对象,那是因为google新给出来一个新的api



但是其实新出的api只是作为高级使用的时候才会用,一般来讲,我们还是用回以前的api

二.SurfaceView预览



要使用SurfaceView还是要

implementsSurfaceHolder.Callback



activity_camera.xml






android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">




android:id="@+id/sv"

android:layout_width="match_parent"

android:layout_height="0dp"

android:layout_weight="1"/>




android:id="@+id/btn_camera"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="拍照"/>







预览图像



/

与SurfaceView传播图像

/

privatevoidshowViews(Cameracamera,SurfaceHolderholder){

//预览相机,绑定

try{

camera.setPreviewDisplay(holder);

//系统相机默认是横屏的,我们要旋转90°

camera.setDisplayOrientation(90);

//开始预览

camera.startPreview();



}catch(IOExceptione){

//TODOAuto-generatedcatchblock

e.printStackTrace();

}

}



释放占用内存



/

释放相机的内存

/

privatevoidclearCamera(){



//释放hold资源

if(mCamera!=null){

//停止预览

mCamera.stopPreview();

mCamera.setPreviewCallback(null);

//释放相机资源

mCamera.release();

mCamera=null;

}

}



绑定生命周期



@Override

protectedvoidonResume(){

//TODOAuto-generatedmethodstub

super.onResume();

//在activity运行时绑定

if(mCamera==null){

mCamera=getcCamera();

if(sh!=null){

showViews(mCamera,sh);

}

}

}



@Override

protectedvoidonPause(){

//TODOAuto-generatedmethodstub

super.onPause();

//activity暂停时我们释放相机内存

clearCamera();



}



SurfaceView回调并同步预览



@Override

publicvoidsurfaceCreated(SurfaceHolderholder){

//开始预览

showViews(mCamera,sh);



}



@Override

publicvoidsurfaceChanged(SurfaceHolderholder,intformat,intwidth,

inthwww.shanxiwang.neteight){

//重启功能

mCamera.stopPreview();

showViews(mCamera,sh);



}



@Override

publicvoidsurfaceDestroyed(SurfaceHolderholder){

//释放

clearCamera();

}



写到这里,基本上我们的可以预览了,我们来运行一下



这里因为是模拟器,他只有前置摄像头,本应该旋转270°的,我们只要知道通过以上的方法可以同步预览影像就可以了

拍照保存图片



我们设置拍照这个button的点击事件

btn_camera=(Button)findViewById(R.id.btn_camera);

btn_camera.setOnClickListener(newOnClickListener(){



@Override

publicvoidonClick(Viewv){

//获取当前相机参数

Camera.Parametersparameters=mCamera.getParameters();

//设置相片格式

parameters.setPictureFormat(ImageFormat.JPEG);

//设置预览大小

parameters.setPreviewSize(800,480);

//设置对焦方式,这里设置自动对焦

parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);

mCamera.autoFocus(newAutoFocusCallback(){



@Override

publicvoidonAutoFocus(booleansuccess,Cameracamera){

//判断是否对焦成功

if(success){

//拍照第三个参数为拍照回调

mCamera.takePicture(null,null,pc);

}

}

});



}

});



这里的pc是一个回调方法,我们重写

privatePictureCallbackpc=newPictureCallback(){



@Overridwww.sm136.come

publicvoidonPictureTaken(byte[]data,Cameracamera){

//data为完整数据

Filefile=newFile("/sdcard/photo.png");

//使用流进行读写

try{

FileOutputStreamfos=newFileOutputStream(file);

try{

fos.write(data);

//关闭流

fos.close();

//查看图片

Intentintent=newIntent(CameraActivity.this,

PhotoActivity.class);

//传递路径

intent.putExtra("path",file.getAbsolutePath());

startActivity(intent);

finish();

}catch(IOExceptione){

//TODOAuto-generatedcatchblock

e.printStackTrace();

}

}catch(FileNotFoundExceptione){

//TODOAuto-generatedcatchblock

e.printStackTrace();

}

}

};



查看图片



我们拍完照片然后就跳转到PhotoActivity查看图片

activity_photo.xml






android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical">




android:id="@+id/tv_path"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>




android:id="@+id/iv_photo"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>







PhotoActivity



packagecom.lgl.camera;



importjava.io.FileInputStream;

importjava.io.FileNotFoundException;



importandroid.app.Activity;

importandroid.graphics.Bitmap;

importandroid.graphics.BitmapFactory;

importandroid.graphics.Matrix;

importandroid.os.Bundle;

importandroid.widget.ImageView;

importandroid.widget.TextView;



publicclassPhotoActivityextendsActivity{



privateTextViewtv_path;

privateImageViewiv_photo;



@Override

protectedvoidonCreate(BundlesavedInstanceState){

//TODOAuto-generatedmethodstub

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_photo);



Stringpath=getIntent().getStringExtra("path");

tv_path=(TextView)findViewById(R.id.tv_path);

//显示路径

tv_path.setText(path);

iv_photo=(ImageView)findViewById(R.id.iv_photo);



//调整角度

try{

FileInputStreamfis=newFileInputStream(path);

Bitmapbitmap=BitmapFactory.decodeStream(fis);

//矩阵

Matrixmatrix=newMatrix();

matrix.setRotate(90);

bitmap=Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),

bitmap.getHeight(),matrix,true);

iv_photo.setImageBitmap(bitmap);

}catch(FileNotFoundExceptione){

//TODOAuto-generatedcatchblock

e.printStackTrace();

}

}

}



我们运行一下

拍完之后跳转到PhotoActivity界面



但是相机是一个大坑,各种不兼容,而且还有前后置摄像头之分哟,上面代码病没有提及前置,前置需要翻转270°,并且我们之前就应该判断是否是前置,再进行旋转,这个只是初学的示例代码。

献花(0)
+1
(本文系网络学习天...首藏)