系统相机调用_第1页
系统相机调用_第2页
系统相机调用_第3页
系统相机调用_第4页
系统相机调用_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

android手机有自带的照相机和图库,我们做的项目中有时用到上传图片到服务器,今天做了一个项目用到这个功能,所以把我的代码记录下来和大家分享,第一次写博客希望各位大神多多批评。

首先上一段调用android相册和相机的代码:

代码如下:

Intentintent=newIntent(MediaStore.ACTION_IMAGE_CAPTURE);//调用android自带的照相机

photoUri=MediaStore.Images.Media.EXTERNAL_CONTENT_URI;

startActivityForResult(intent,1);

代码如下:

Intenti=newIntent(Intent.ACTION_PICK,

vider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);//调用android的图库

startActivityForResult(i,2);

代码如下:

@Override

protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){

//完成照相后回调用此方法

super.onActivityResult(requestCode,resultCode,data);

case1:

switch(resultCode){

caseActivity.RESULT_OK://照相完成点击确定

StringsdStatus=Environment.getExternalStorageState();

if(!sdStatus.equals(Environment.MEDIA_MOUNTED)){//检测sd是否可用

Log.v("TestFile","SDcardisnotavaiable/writeablerightnow.");

return;}

Bundlebundle=data.getExtras();

Bitmapbitmap=(Bitmap)bundle.get("data");//获取相机返回的数据,并转换为Bitmap图片格式

FileOutputStreamb=null;

Filefile=newFile("/sdcard/pk4fun/");

file.mkdirs();//创建文件夹,名称为pk4fun//照片的命名,目标文件夹下,以当前时间数字串为名称,即可确保每张照片名称不相同。网上流传的其他Demo这里的照片名称都写死了,则会发生无论拍照多少张,后一张总会把前一张照片覆盖。细心的同学还可以设置这个字符串,比如加上“IMG”字样等;然后就会发现sd卡中myimage这个文件夹下,会保存刚刚调用相机拍出来的照片,照片名称不会重复。

Stringstr=null;

Datedate=null;

SimpleDateFormatformat=newSimpleDateFormat("yyyyMMddHHmmss");//获取当前时间,进一步转化为字符串

date=newDate(resultCode);

str=format.format(date);

StringfileName="/sdcard/myImage/"+str+".jpg";

sendBroadcast(fileName);

try{

b=newFileOutputStream(fileName);

press(Bitmap.CompressFormat.JPEG,100,b);//把数据写入文件

}catch(FileNotFoundExceptione){

e.printStackTrace();

}finally{

try{

b.flush();

b.close();

}catch(IOExceptione){

e.printStackTrace();

}

}break;

caseActivity.RESULT_CANCELED://取消

break;

}

break;

case2:

switch(resultCode){

caseActivity.RESULT_OK:{

Uriuri=data.getData();

Cursorcursor=mActivity.getContentResolver().query(uri,null,

null,null,null);

cursor.moveToFirst();

StringimgNo=cursor.getString(0);//图片编号

StringimgPath=cursor.getString(1);//图片文件路径

StringimgSize=cursor.getString(2);//图片大小

StringimgName=cursor.getString(3);//图片文件名

cursor.close();

//Optionsoptions=newBitmapFactory.Options();

//options.inJustDecodeBounds=false;

//options.inSampleSize=10;

//Bitmapbitmap=BitmapFactory.decodeFile(imgPath,options);

}

break;

caseActivity.RESULT_CANCELED://取消

break;

}

break;

}

最后记得加权限

<uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<uses-permissionandroid:name="android.permission.CAMERA"/>

<uses-permissionandroid:name="android.permission.RECORD_AUDIO"/>

<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>Android调用系统相机和自定义相机实例

本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显示出来,该例子也会涉及到Android加载大图片时候的处理(避免OOM),还有简要提一下有些人SurfaceView出现黑屏的原因。

Android应用拍照的两种方式,下面为两种形式的Demo展示出来的效果。

知识点:一、调用系统自带的相机应用二、自定义我们自己的拍照界面三、关于计算机解析图片原理(如何正确加载图片到Android应用中)

所需权限:

?123456<uses-permissionandroid:name="android.permission.CAMERA"/>

<uses-featureandroid:name="android.hardware.camera"/>

<uses-featureandroid:name="android.hardware.camera.autofocus"/><uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

一、调用系统照相机程序拍照(方式一)

1.定义所需要的权限

2.我们需要定义调用系统相机App的Intent,当然是通过设定IntentFilter中的Action来打开我们想要的activity了。

MediaStore.ACTION_IMAGE_CAPTURE-这个Action将打开拍照的系统相机。返回一个Image

MediaStore.ACTION_VIDEO_CAPTURE-这个Action将打开录像的系统相机。返回一个Video

在MediaStore.ACTION_IMAGE_CAPTURE中,我们可以看到这段话:

【ThecallermaypassanextraEXTRA_OUTPUTtocontrolwherethisimagewillbe

written.IftheEXTRA_OUTPUTisnotpresent,thenasmallsizedimageisreturned

asaBitmapobjectintheextrafield.Thisisusefulforapplicationsthatonly

needasmallimage.IftheEXTRA_OUTPUTispresent,thenthefull-sizedimagewill

bewrittentotheUrivalueofEXTRA_OUTPUT.】

3.API规定我们传入拍照得到图片的存储位置的Uri。否则Bimmap将以一个压缩后的形式返回到我们当前Activity.

intent.putExtra(MediaStore.EXTRA_OUTPUT,fileUri);//settheimagefilename则会把拍照的图片存储到我们传入的Uri对应的File里面。

4.我们调用startActivityForResult(intent)来启动这样一个系统相机app之后,然后在当前应用Activity的onActivityResult()中接受到返回拍照成功或者失败的消息,做相应处理。

5.“压缩处理”(Android应用中加载大图片),并显示到ImageView中。

二、自定义照相机1.检查相机是否存在,并获取相机Camera。2.创建一个相机图像预览类:extendsSurfaceView并implementsSurfaceHolder(我定义:MySurfaceView)

3.把这个预览类放入一个自定义布局layout里面,并且可以在layout里添加自己的其他按钮

4.设置对应的拍照按钮然后听事件

5.捕获照片和保存图片6.释放掉我们使用的相机Camera,不然之后其他应用将无法使用它。三、计算机解析图片的方式和Android中大图片Bitmap的压缩显示处理这个问题有点老生长谈了,平时我们经常遇到一些图片资源,我们把它加载到内存发现抛出内存不够用的异常,即OOM,当然加载图片时出现的OOM情况有很多种,比如单张图片没有做压缩,导致图片占用内存过大而发生内存溢出,也有多张图片一次性加载进来,导致的内存溢出。通常单张大图,我们加载进来往往会经过一个图片的压缩处理的过程,而如果多张图片加载,我们可能就需要一些缓存机制,再加上一些算法来保证程序不出现OOM。我们这里想要讲的知识点跟单张大图比较有关系首先,我们知道一个图片,它是由很多像素点来表示的,而像素点的个数只跟图片的分辨率有关,而跟图片所占的内存空间大小无关。比如我们的桌面壁纸:1280*768的分辨率,那么它就有1280*768=983040个像素点,这意味着什么呢?我们知道我们要表示一个像素点的颜色,最经常我们需要RGB三种颜色来表示,而R:0~255,相当于两个FF的位置,就是8位,这样的话RGB合起来,一个像素点的表示就需要24位(这就是我们平衡听到的24位图),而加上透明度的8位,就是平时说的32位图。那么一张图片,它加载到内存中的话,它会占用多大的空间呢?计算方法:(像素点*一个像素所占用的byte数)/1024/1024(MB)

以1280*768的分辨率,32位图为例:所占内存大小:((1280*768*(32/8))/1024)/1024=3.75(MB)说了这么多,那么我们再来说下Android系统的规定吧,Android系统严格规定了每个应用所能分配的最大的内存为多少,我们知道有一个VM值(在我们创建模拟器的时候),这个VM值里面便是我们所说的堆空间(HeapSize),当你的应用占用的空间已经超出我们定义的堆空间大小,那么不好意思,OOM这样的话,我们明白了图片的大小占据原理,还有尽量不要超出这个堆空间,那么OK,现在问题变得简单了。如果我们有一种方式可以在图片加载进来之前,知道图片的大小,然后改变它的长、宽,这样的话,分辨率便变小了,这样出来的乘积也就变小了。比如:我们的屏幕只有320*240,这时候你加载大分辨的图片进来最多也只能显示成这样,所以我们常采用的是对图片进行压缩处理。这里有个概念叫压缩比:长:1024/320=3.2

约等于3宽:768/240=3.2

那这样我们如果把图片压缩成这样大小的,最后的图片加载进来的大小便是((320

*240

*(32/8))/1024)/1024=0.29(MB)希望我这样讲完,大家都能听懂了,我这里先把照相机实例中出现的关于如果处理这块图片的代码先粘出来?12345678910111213141516171819202122232425//-----------------------Android大图的处理方式---------------------------

privatevoidsetPicToImageView(ImageViewimageView,FileimageFile){

intimageViewWidth=imageView.getWidth();

intimageViewHeight=imageView.getHeight();

BitmapFactory.Optionsopts=

newOptions();

//设置这个,只得到Bitmap的属性信息放入opts,而不把Bitmap加载到内存中

opts.inJustDecodeBounds=

true;

BitmapFactory.decodeFile(imageFile.getPath(),opts);

intbitmapWidth=opts.outWidth;

intbitmapHeight=opts.outHeight;

//取最大的比例,保证整个图片的长或者宽必定在该屏幕中可以显示得下

intscale=Math.max(imageViewWidth/bitmapWidth,imageViewHeight/bitmapHeight);

//缩放的比例

opts.inSampleSize=scale;

//内存不足时可被回收

opts.inPurgeable=

true;

//设置为false,表示不仅Bitmap的属性,也要加载bitmap

opts.inJustDecodeBounds=

false;

Bitmapbitmap=BitmapFactory.decodeFile(imageFile.getPath(),opts);

imageView.setImageBitmap(bitmap);

}关于堆空间:堆(HEAP)是VM中占用内存最多的部分,通常是动态分配的。堆的大小不是一成不变的,通常有一个分配机制来控制它的大小。比如初始的HEAP是4M大,当4M的空间被占用超过75%的时候,重新分配堆为8M大;当8M被占用超过75%,分配堆为16M大。倒过来,当16M的堆利用不足30%的时候,缩减它的大小为8M大。重新设置堆的大小,尤其是压缩,一般会涉及到内存的拷贝,所以变更堆的大小对效率有不良影响。

废话少说下面就看代码咯~~为了大家看起来方便点,代码的结构可能不是很规范!源码下载地址:/detail/u011133213/7844683

代码部分:

一、用系统的相机按钮点击之后开启系统相机Activity?1234567891011findViewById(R.id.system_camera_btn).setOnClickListener(newOnClickListener(){

@Override

publicvoidonClick(Viewv){

Intentintent=

newIntent();

intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);

imageFileUri=getOutFileUri(TYPE_FILE_IMAGE);//得到一个FileUri

intent.putExtra(MediaStore.EXTRA_OUTPUT,imageFileUri);

startActivityForResult(intent,SYSTEM_CAMERA_REQUESTCODE);

}

});生成File文件,并得到Uri?123456789101112131415161718192021222324252627282930313233343536373839404142434445//-----------------------生成Uri---------------------------------------

//得到输出文件的URI

privateUrigetOutFileUri(intfileType){

returnUri.fromFile(getOutFile(fileType));

}

//生成输出文件

privateFilegetOutFile(intfileType){

StringstorageState=Environment.getExternalStorageState();

if(Environment.MEDIA_REMOVED.equals(storageState)){

Toast.makeText(getApplicationContext(),

"oh,no,SD卡不存在",Toast.LENGTH_SHORT).show();

returnnull;

}

FilemediaStorageDir=

newFile(Environment

.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)

,"MyPictures");

if(!mediaStorageDir.exists()){

if(!mediaStorageDir.mkdirs()){

Log.i("MyPictures",

"创建图片存储路径目录失败");

Log.i("MyPictures",

"mediaStorageDir:"+mediaStorageDir.getPath());

returnnull;

}

}

Filefile=

newFile(getFilePath(mediaStorageDir,fileType));

returnfile;

}

//生成输出文件路径

privateStringgetFilePath(FilemediaStorageDir,

intfileType){

StringtimeStamp=newSimpleDateFormat("yyyyMMdd_HHmmss")

.format(newDate());

StringfilePath=mediaStorageDir.getPath()+File.separator;

if(fileType==TYPE_FILE_IMAGE){

filePath+=("IMG_"+timeStamp+

".jpg");

}elseif(fileType==TYPE_FILE_VEDIO){

filePath+=("VIDEO_"+timeStamp+

".mp4");

}else{

returnnull;

}

returnfilePath;

}

二、用自定义的相机检测相机设备是否存在:?12345678/*检测相机是否存在*/

privatebooleancheckCameraHardWare(Contextcontext){

PackageManagerpackageManager=context.getPackageManager();

if(packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)){

returntrue;

}

returnfalse;

}

按钮按下之后的判断:?12345678910111213findViewById(R.id.myapp_camera_btn).setOnClickListener(newOnClickListener(){

@Override

publicvoidonClick(Viewv){

if(checkCameraHardWare(getApplicationContext())){

Intentintent=

newIntent(getApplicationContext(),MyCameraActivity.class);

startActivity(intent);

}else{

Toast.makeText(getApplicationContext(),

"没有相机存在",Toast.LENGTH_SHORT).show();

}

}

});

自定义的SurfaceView类:?123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172packagecn.panghu.camera;

importandroid.content.Context;importandroid.graphics.Canvas;importandroid.graphics.Rect;importandroid.hardware.Camera;importandroid.util.AttributeSet;importandroid.view.Surface;importandroid.view.SurfaceHolder;importandroid.view.SurfaceView;

publicclassMySurfaceView

extendsSurfaceView

implementsSurfaceHolder.Callback{

privateCameracamera=

null;

privateSurfaceHoldersurfaceHolder=

null;

publicMySurfaceView(Contextcontext,Cameracamera){

super(context);

this.camera=camera;

surfaceHolder=getHolder();

surfaceHolder.addCallback(this);

surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

}

publicMySurfaceView(Contextcontext){

super(context);

//TODOAuto-generatedconstructorstub

}

@Override

publicvoidsurfaceCreated(SurfaceHolderholder){

try{

camera.setPreviewDisplay(surfaceHolder);

camera.startPreview();

}catch(Exceptione){

e.printStackTrace();

}

}

@Override

publicvoidsurfaceChanged(SurfaceHolderholder,

intformat,

intwidth,

intheight){

//根本没有可处理的SurfaceView

if(surfaceHolder.getSurface()==

null){

return;

}

//先停止Camera的预览

try{

camera.stopPreview();

}catch(Exceptione){

e.printStackTrace();

}

//这里可以做一些我们要做的变换。

//重新开启Camera的预览功能

try{

camera.setPreviewDisplay(surfaceHolder);

camera.startPreview();

}catch(Exceptione){

e.printStackTrace();

}

}

@Override

publicvoidsurfaceDestroyed(SurfaceHolderholder){

}

}自定义相机Activity类:(为了避免当用户按下Home键,之后再回到我们App中,SurfaceView变黑屏,我们需要将SurfaceView加载到FrameLayout中的代码写在onResume中)?123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200packagecn.panghu.camera;

importjava.io.File;importjava.io.FileNotFoundException;importjava.io.FileOutputStream;importjava.io.IOException;importjava.text.SimpleDateFormat;importjava.util.Date;

importandroid.app.Activity;importandroid.hardware.Camera;importandroid.hardware.Camera.PictureCallback;import.Uri;importandroid.os.Bundle;importandroid.os.Environment;importandroid.util.Log;importandroid.view.View;importandroid.view.View.OnClickListener;importandroid.widget.Button;importandroid.widget.FrameLayout;importandroid.widget.Toast;

importcom.example.camerademoapp.R;

publicclassMyCameraActivity

extendsActivity{

privateButtonbtn_camera_capture=

null;

privateButtonbtn_camera_cancel=

null;

privateButtonbtn_camera_ok=

null;

privateCameracamera=

null;

privateMySurfaceViewmySurfaceView=

null;

privatebyte[]buffer=

null;

privatefinalintTYPE_FILE_IMAGE=

1;

privatefinalintTYPE_FILE_VEDIO=

2;

privatePictureCallbackpictureCallback=

newPictureCallback(){

@Override

publicvoidonPictureTaken(byte[]data,Cameracamera){

if(data==

null){

Log.i("MyPicture",

"picturetakendata:null");

}else{

Log.i("MyPicture",

"picturetakendata:"+data.length);

}

buffer=

newbyte[data.length];

buffer=data.clone();

}

};

@Override

protectedvoidonCreate(BundlesavedInstanceState){

//TODOAuto-generatedmethodstub

super.onCreate(savedInstanceState);

setContentView(R.layout.mycamera_layout);

btn_camera_capture=(Button)findViewById(R.id.camera_capture);

btn_camera_ok=(Button)findViewById(R.id.camera_ok);

btn_camera_cancel=(Button)findViewById(R.id.camera_cancel);

btn_camera_capture.setOnClickListener(newOnClickListener(){

@Override

publicvoidonClick(Viewv){

camera.takePicture(null,

null,pictureCallback);

btn_camera_capture.setVisibility(View.INVISIBLE);

btn_camera_ok.setVisibility(View.VISIBLE);

btn_camera_cancel.setVisibility(View.VISIBLE);

}

});

btn_camera_ok.setOnClickListener(newOnClickListener(){

@Override

publicvoidonClick(Viewv){

//保存图片

saveImageToFile();

camera.startPreview();

btn_camera_capture.setVisibility(View.VISIBLE);

btn_camera_ok.setVisibility(View.INVISIBLE);

btn_camera_cancel.setVisibility(View.INVISIBLE);

}

});

btn_camera_cancel.setOnClickListener(newOnClickListener(){

@Override

publicvoidonClick(Viewv){

camera.startPreview();

btn_camera_capture.setVisibility(View.VISIBLE);

btn_camera_ok.setVisibility(View.INVISIBLE);

btn_camera_cancel.setVisibility(View.INVISIBLE);

}

});

}

@Override

protectedvoidonPause(){

//TODOAuto-generatedmethodstub

super.onPause();

camera.release();

camera=

null;

}

@Override

protectedvoidonResume(){

//TODOAuto-generatedmethodstub

super.onResume();

if(camera==

null){

camera=getCameraInstance();

}

//必须放在onResume中,不然会出现Home键之后,再回到该APP,黑屏

mySurfaceView=

newMySurfaceView(getApplicationContext(),camera);

FrameLayoutpreview=(FrameLayout)findViewById(R.id.camera_preview);

preview.addView(mySurfaceView);

}

/*得到一相机对象*/

privateCameragetCameraInstance(){

Cameracamera=

null;

try{

camera=camera.open();

}catch(Exceptione){

e.printStackTrace();

}

returncamera;

}

//-----------------------保存图片---------------------------------------

privatevoidsaveImageToFile(){

Filefile=getOutFile(TYPE_FILE_IMAGE);

if(file==

null){

Toast.makeText(getApplicationContext(),

"文件创建失败,请检查SD卡读写权限",Toast.LENGTH_SHORT).show();

return;

}

Log.i("MyPicture",

"自定义相机图片路径:"+file.getPath());

Toast.makeText(getApplicationContext(),

"图片保存路径:"+file.getPath(),Toast.LENGTH_SHORT).show();

if(buffer==

null){

Log.i("MyPicture",

"自定义相机Buffer:null");

}else{

try{

FileOutputStreamfos=

newFileOutputStream(file);

fos.write(buffer);

fos.close();

}catch(IOExceptione){

e.printStackTrace();

}

}

}

//-----------------------生成Uri---------------------------------------

//得到输出文件的URI

privateUrigetOutFileUri(intfileType){

returnUri.fromFile(getOutFile(fileType));

}

//生成输出文件

privateFilegetOutFile(intfileType){

StringstorageState=Environment.getExternalStorageState();

if(Environment.MEDIA_REMOVED.equals(storageState)){

Toast.makeText(getApplicationContext(),

"oh,no,SD卡不存在",Toast.LENGTH_SHORT).show();

returnnull;

}

FilemediaStorageDir=

newFile(Environment

.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)

,"MyPictures");

if(!mediaStorageDir.exists()){

if(!mediaStorageDir.mkdirs()){

Log.i("MyPictures",

"创建图片存储路径目录失败");

Log.i("MyPictures",

"mediaStorageDir:"+mediaStorageDir.getPath());

returnnull;

}

}

Filefile=

newFile(getFilePath(mediaStorageDir,fileType));

returnfile;

}

//生成输出文件路径

privateStringgetFilePath(FilemediaStorageDir,

intfileType){

StringtimeStamp=newSimpleDateFormat("yyyyMMdd_HHmmss")

.format(newDate());

StringfilePath=mediaStorageDir.getPath()+File.separator;

if(fileType==TYPE_FILE_IMAGE){

filePath+=("IMG_"+timeStamp+

".jpg");

}elseif(fileType==TYPE_FILE_VEDIO){

filePath+=("VIDEO_"+timeStamp+

".mp4");

}else{

returnnull;

}

returnfilePath;

}

}2月12日北京OSC源创会——开源技术的年终盛典»

Intentintent=newIntent(MediaStore.ACTION_VIDEO_CAPTURE);

videopath=Environment.getExternalStorageDirectory().toString()+"/abc/";

Log.i("DareDream",videopath);

StringfileName=newSimpleDateFormat("yyyyMMddHHmmss").format(newDate())+".3gp";

Fileout=newFile(videopath);

if(!out.exists()){

out.mkdirs();

}

out=newFile(videopath,fileName);

videopath=videopath+fileName;

Uriuri=Uri.fromFile(out);

intent.putExtra(MediaStore.EXTRA_OUTPUT,uri);

intent.putExt

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论