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

下载本文档

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

文档简介

1、android手机有自带的照相机和图库,我们做的项目中有时用到上传图片到服务器,今天做了一个项目用到这个功能,所以把我的代码记录下来和大家分享,第一次写博客希望各位大神多多批评。首先上一段调用android相册和相机的代码:代码如下 :Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);/调用 android自带的照相机startActivityForResult(intent, 1);代码如下 :Intent i = new Intent(Intent.ACTION_PICK,调用android的图库startActivit

2、yForResult(i, 2);代码如下 :Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) 完成照相后回调用此方法super.onActivityResult(requestCode, resultCode, data);case 1:switch (resultCode) case Activity.RESULT_OK:/照相完成点击确定String sdStatus = Environment.getExternalStorageState();if (!sdSta

3、tus.equals(Environment.MEDIA_MOUNTED) /检测 sd 是否可用Log.v(TestFile, SD card is not avaiable/writeable right now.);return; Bundle bundle = data.getExtras();Bitmap bitmap = (Bitmap) bundle.get(data);/获取相机返回的数据,并转换为Bitmap图片格式FileOutputStream b = null;File file = new File(/sdcard/pk4fun/);file.mkdirs();/创建

4、文件夹,名称为pk4fun /照片的命名,目标文件夹下,以当前时间数字串为名称,即可确保每张照片名称不相同。网上流传的其他Demo这里的照片名称都写死了, 则会发生无论拍照多少张,后一张总会把前一张照片覆盖。细心的同学还可以设置这个字符串, 比如加上 “” 字样等;然后就会发现sd 卡中 myimage这个文件夹下,会保存刚刚调用相机拍出来的照片,照片名称不会重复。String str = null;Date date = null;SimpleDateFormat format = new SimpleDateFormat(yyyyMMddHHmmss);/获取当前时间,进一步转化为字符串d

5、ate = new Date(resultCode);str = format.format(date);String fileName = /sdcard/myImage/ + str + .jpg;sendBroadcast(fileName);try b = new FileOutputStream(fileName);把数据写入文件 catch (FileNotFoundException e) e.printStackTrace(); finally try b.flush();b.close(); catch (IOException e) e.printStackTrace();

6、 break;case Activity.RESULT_CANCELED:/break;break;case 2:取消switch (resultCode) case Activity.RESULT_OK: Uri uri = data.getData();Cursor cursor = mActivity.getContentResolver().query(uri, null,null, null, null);cursor.moveToFirst();String imgNo = cursor.getString(0); /图片编号String imgPath = cursor.getS

7、tring(1); /图片文件路径String imgSize = cursor.getString(2); /图片大小String imgName = cursor.getString(3); /图片文件名cursor.close();Options options = new BitmapFactory.Options();options.inJustDecodeBounds = false;options.inSampleSize = 10;Bitmap bitmap = BitmapFactory.decodeFile(imgPath, options);break;case Acti

8、vity.RESULT_CANCELED:/break;break;取消最后记得加权限uses-permissionuses-permissionuses-permissionAndroid 调用系统相机和自定义相机实例本博文主要是介绍了android 上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显示出来,该例子也会涉及到 Android 加载大图片时候的处理 (避免 OOM),还有简要提一下有些人 SurfaceView 出现黑屏的原因。Android 应用拍照的两种方式, 下面为两种形式的Demo展示出来的效果。知识点:一、调用系统自带的相机应用二、自定义我们自己的拍照

9、界面三、关于计算机解析图片原理(如何正确加载图片到Android 应用中)所需权限:?1 23 45 6 一、调用系统照相机程序拍照(方式一)1.定义所需要的权限2.我们需要定义调用系统相机App 的 Intent, 当然是通过设定 IntentFilter中的 Action来打开我 们想要的 activity了。MediaStore.ACTION_IMAGE_CAPTURE 这-个 Action 将打开拍照的系统相机。返回一个ImageMediaStore.ACTION_VIDEO_CAPTURE -这个 Action 将打开录像的系统相机。返回一个Video在 MediaStore.ACT

10、ION_IMAGE_CAPTURE中,我们可以看到这段话 :【The callermay pass an extraEXTRA_OUTPUTto controlwhere thisimage will bewritten. If the EXTRA_OUTPUT is not present, then a small sized image is returnedas a Bitmap object in the extra field. This is useful forapplications that onlyneed a small image. If the EXTRA_OUTP

11、UT is present, then the full-sized image willbe written to the Uri value of EXTRA_OUTPUT.】3.API 规定我们传入拍照得到图片的存储位置的Uri 。否则 Bimmap将以一个压缩后的形式返回到我们当前Aent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); / set theimage file name则会把拍照的图片存储到我们传入的Uri 对应的 File里面。4. 我们调用 startActivityForResult(intent)来启动这样一个系统相机 a

12、pp 之后,然后在当前应用Activity的 onActivityResult()中接受到返回拍照成功或者失败的消息,做相应处理。5. “压缩处理” (Android应用中加载大图片 ), 并显示到 ImageView 中。二、自定义照相机1.检查相机是否存在,并获取相机 Camera。2.创建一个相机图像预览类: extends SurfaceView并 implementsSurfaceHolder (我定义: MySurfaceView )把这个预览类放入一个自定义布局 layout 里面,并且可以在 layout里添加自己的其他按钮设置对应的拍照按钮然后听事件捕获照片和保存图片释放掉我

13、们使用的相机 Camera,不然之后其他应用将无法使用它。三、计算机解析图片的方式和Android 中大图片 Bitmap 的压缩显示处理这个问题有点老生长谈了,平时我们经常遇到一些图片资源, 我们把它加载到内存发现抛出内存不够用的异常,即 OOM,当然加载图片时出现的 OOM情况有很多种,比如单张图片没有做压缩, 导致图片占用内存过大而发生内存溢出,也有多张图片一次性加载进来,导致的内存溢出。通常单张大图,我们加载进来往往会经过一个图片的压缩处理的过程,而如果多张图片加载,我们可能就需要一些缓存机制, 再加上一些算法来保证程序不出现 OOM。我们这里想要讲的知识点跟单张大图比较有关系首先,我

14、们知道一个图片,它是由很多像素点来表示的,而像素点的个数只跟图片的分辨率有关,而跟图片所占的内存空间大小无关。比如我们的桌面壁纸: 1280 * 768 的分辨率, 那么它就有 1280 * 768 = 983040 个像素点,这意味着什么呢?我们知道我们要表示一个像素点的颜色,最经常我们需要 RGB三种颜色来表示,而 R:0255,相当于两个 FF 的位置,就是 8 位,这样的话 RGB合起来,一个像素点的表示就需要 24 位(这就是我们平衡听到的 24 位图),而加上透明度的 8 位,就是平时说的 32 位图。那么一张图片,它加载到内存中的话,它会占用多大的空间呢?计算方法:( 像素点 *

15、一个像素所占用的byte 数) / 1024 / 1024 (MB)以 1280 * 768 的分辨率, 32 位图为例:所占内存大小:(1280* 768* (32 / 8)) / 1024)/1024=3.75(MB)说了这么多,那么我们再来说下Android 系统的规定吧, Android 系统严格规定了每个应用所能分配的最大的内存为多少,我们知道有一个VM值(在我们创建模拟器的时候),这个VM值里面便是我们所说的堆空间(Heap Size), 当你的应用占用的空间已经超出我们定义的堆空间大小,那么不好意思, OOM这样的话,我们明白了图片的大小占据原理,还有尽量不要超出这个堆空间,那么

16、 OK,现在问题变得简单了。 如果我们有一种方式可以在图片加载进来之前,知道图片的大小,然后改变它的长、宽,这样的话,分辨率便变小了,这样出来的乘积也就变小了。比如:我们的屏幕只有320240, 这时候你加载大分辨的图片进来最多也只能显示成这样,所以我们常采用的是对图片进行压缩处理。这里有个概念叫压缩比:长: 1024 / 320 = 3.2约等于 3宽: 768 / 240 = 3.2那这样我们如果把图片压缩成这样大小的, 最后的图片加载进来的大小便是(320* 240* (32 / 8) ) / 1024)/1024=0.29(MB)希望我这样讲完, 大家都能听懂了,我这里先把照相机实例中

17、出现的关于如果处理这块图片的代码先粘出来?1 /-Android大图的处理方式2 -3privatevoid setPicToImageView(ImageViewimageView, File imageFile)4intimageViewWidth = imageView.getWidth();5intimageViewHeight = imageView.getHeight();6BitmapFactory.Options opts =new Options();78/设置这个,只得到 Bitmap的属性信息放入opts ,而不把 Bitmap加载到内存中10opts.inJustDec

18、odeBounds =true ;11BitmapFactory.decodeFile(imageFile.getPath(), opts);1213intbitmapWidth = opts.outWidth;14intbitmapHeight = opts.outHeight;15/ 取最大的比例,保证整个图片的长或者宽必定在该屏幕中可以显示得下16intscale = Math.max(imageViewWidth / bitmapWidth,17 imageViewHeight / bitmapHeight);1819/ 缩放的比例20opts.inSampleSize = scale

19、;21/ 内存不足时可被回收22opts.inPurgeable =true ;23/ 设置为 false,表示不仅 Bitmap 的属性,也要加载 bitmap24opts.inJustDecodeBounds =false ;25Bitmap bitmap = BitmapFactory.decodeFile(imageFile.getPath(),opts);imageView.setImageBitmap(bitmap);关于堆空间:堆( HEAP)是 VM中占用内存最多的部分,通常是动态分配的。堆的大小不是一成不变的, 通常有一个分配机制来控制它的大小。 比如初始的HEAP是 4M大

20、,当 4M的空间被占用超过 75%的时候,重新分配堆为 8M 大;当 8M被占用超过 75%,分配堆为 16M大。倒过来,当 16M的堆利用不足 30%的时候,缩减它的大小为 8M大。重新设置堆的大小, 尤其是压缩,一般会涉及到内存的拷贝,所以变更堆的大小对效率有不良影响。废话少说下面就看代码咯 为了大家看起来方便点, 代码的结构可能不是很规范!源码下载地址:代码部分:一、用系统的相机按钮点击之后开启系统相机Activity?new2 OnClickListener() 34Override5public void onClick(View v) 6Intent intent =new Int

21、ent();7intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);8imageFileUri = getOutFileUri(TYPE_FILE_IMAGE);/ 得到一9 个 File Uri10intent.putExtra(MediaStore.EXTRA_OUTPUT,11 imageFileUri);startActivityForResult(intent,SYSTEM_CAMERA_REQUESTCODE););生成 File文件,并得到 Uri?1 -生成/2Uri-/ 得到输出文件的 URI4privateUri getOutF

22、ileUri(intfileType) 5returnUri.fromFile(getOutFile(fileType);/ 生成输出文件9privateFile getOutFile(int fileType) 10String storageState = Environment.getExternalStorageState();1if(Environment.MEDIA_REMOVED.equals(storageState)1Toast.makeText(getApplicationContext(),oh,no, SD卡不存在1 , Toast.LENGTH_SHORT).show

23、();2returnnull;131File mediaStorageDir =newFile (Environment4.getExternalStoragePublicDirectory(Environment.DIRECTO1RY_PICTURES)5, MyPictures);1if(!mediaStorageDir.exists()6if(!mediaStorageDir.mkdirs()1Log.i(MyPictures, 创建图片存储路径目录失败 );7Log.i(MyPictures,mediaStorageDir : +1mediaStorageDir.getPath();8

24、returnnull;1920File file =new File(getFilePath(mediaStorageDir,fileType);21returnfile;2/ 生成输出文件路径2privateString getFilePath(File mediaStorageDir,int fileType)3String timeStamp =new SimpleDateFormat(yyyyMMdd_HHmmss )2.format(new Date();4String filePath = mediaStorageDir.getPath() + File.separator;2if

25、 (fileType = TYPE_FILE_IMAGE)5filePath += (IMG_ + timeStamp +.jpg );2 elseif(fileType = TYPE_FILE_VEDIO)6filePath += (VIDEO_+ timeStamp +.mp4 );2 else7returnnull;28returnfilePath;2930313233343536373839404142434445二、用自定义的相机检测相机设备是否存在:?/* 检测相机是否存在 */2privateboolean checkCameraHardWare(Context context)

26、3PackageManager packageManager = context.getPackageManager();4if5 (packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)6returntrue ;78returnfalse;按钮按下之后的判断:?1 findViewById(R.id.myapp_camera_btn).setOnClickListener(new2 OnClickListener() 34Override5publicvoidonClick(View v) 6if(checkCameraH

27、ardWare(getApplicationContext()7Intentintent= new Intent(getApplicationContext(),8 MyCameraActivity.class );9startActivity(intent);10 else 11Toast.makeText(getApplicationContext(), 没有相机12存在 , Toast.LENGTH_SHORT).show();13);自定义的 SurfaceView 类:?1 package23 import4 import5 import6 import7 import8 impor

28、t9 import1 import01 publicclassMySurfaceViewextendsSurfaceViewimplementsSurfaceHolder.Callback1privateCamera camera =null;3privateSurfaceHolder surfaceHolder =null ;14publicMySurfaceView(Context context, Camera camera) 1super (context);5this.camera = camera;1surfaceHolder = getHolder();6surfaceHolde

29、r.addCallback(this);1surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS7 );18publicMySurfaceView(Context context) 1super (context);9/ TODO Auto-generated constructor stub2Override1publicvoidsurfaceCreated(SurfaceHolder holder) 2try2camera.setPreviewDisplay(surfaceHolder);2camera.startPrev

30、iew();3 catch(Exception e)2e.printStackTrace();42Override6publicvoidsurfaceChanged(SurfaceHolder holder,int format,int2 width,7intheight) 2/ 根本没有可处理的 SurfaceView8if(surfaceHolder.getSurface() =null)2return;930/ 先停止 Camera 的预览3try 1camera.stopPreview();3 catch(Exception e)2e.printStackTrace();333/ 这里

31、可以做一些我们要做的变换。43/重新开启 Camera 的预览功能5try3camera.setPreviewDisplay(surfaceHolder);6camera.startPreview();3 catch (Exception e)7e.printStackTrace();3Override4publicvoid surfaceDestroyed(SurfaceHolder holder) 034445464748495051525354555657585960616263646566676869707172自定义相机 Activity 类: ( 为了避免当用户按下 Home键,之

32、后再回到我们 App 中, SurfaceView 变黑屏,我们需要将 SurfaceView 加载到 FrameLayout 中的代码写在 onResume中)?1 package23 import4 import5 importjava.io.FileOutputStream;6 importjava.io.IOException;7 importjava.text.SimpleDateFormat;8 importjava.util.Date;910 importandroid.app.Activity;11 importandroid.hardware.Camera;12 import

33、android.hardware.Camera.PictureCallback;13 .Uri;14 importandroid.os.Bundle;15 importandroid.os.Environment;16 importandroid.util.Log;17 importandroid.view.View;18 importandroid.view.View.OnClickListener;19 importandroid.widget.Button;20 importandroid.widget.FrameLayout;21 importandroid.widget.Toast;

34、2223 importcom.example.camerademoapp.R;2425 publicclassMyCameraActivityextends Activity 26privateButton btn_camera_capture =null;27privateButton btn_camera_cancel =null;28privateButton btn_camera_ok =null;2930privateCamera camera =null;31privateMySurfaceView mySurfaceView =null ;3233privatebyte buff

35、er =null;3435privatefinalintTYPE_FILE_IMAGE =1;36privatefinalintTYPE_FILE_VEDIO =2;3738privatePictureCallback pictureCallback =new PictureCallback() 3940Override41publicvoid onPictureTaken(byte data, Camera camera) 42if(data =null)43Log.i(MyPicture, picture taken data: null);44 else45Log.i(MyPicture

36、, picture taken data: +46 data.length);474849buffer =new byte data.length;50buffer = data.clone();51;Override54protectedvoidonCreate(Bundle savedInstanceState) 55/ TODO Auto-generated method stub56super.onCreate(savedInstanceState);57setContentView(R.layout.mycamera_layout);5859btn_camera_capture =

37、(Button)60 findViewById(R.id.camera_capture);61btn_camera_ok = (Button) findViewById(R.id.camera_ok);62btn_camera_cancel = (Button) findViewById(R.id.camera_cancel);636465btn_camera_capture.setOnClickListener(new OnClickListener() 66Override67publicvoidonClick(View v) 6869camera.takePicture(null ,nu

38、ll, pictureCallback);7071btn_camera_capture.setVisibility(View.INVISIBLE);72btn_camera_ok.setVisibility(View.VISIBLE);73btn_camera_cancel.setVisibility(View.VISIBLE);7475);76btn_camera_ok.setOnClickListener(newOnClickListener() 7778Override79publicvoidonClick(View v) 80/保存图片81saveImageToFile();8283c

39、amera.startPreview();84btn_camera_capture.setVisibility(View.VISIBLE);85btn_camera_ok.setVisibility(View.INVISIBLE);86btn_camera_cancel.setVisibility(View.INVISIBLE);8788);89btn_camera_cancel.setOnClickListener(new OnClickListener() 9091Override92publicvoidonClick(View v) 9394camera.startPreview();9

40、5btn_camera_capture.setVisibility(View.VISIBLE);96btn_camera_ok.setVisibility(View.INVISIBLE);97btn_camera_cancel.setVisibility(View.INVISIBLE);989910);010Override1protectedvoidonPause() 10/ TODO Auto-generated method stub2super.onPause();103camera.release();10camera =null;4105Override10protectedvoi

41、donResume() 6/ TODO Auto-generated method stub10super.onResume();7if (camera =null )10camera = getCameraInstance();810/ 必须放在 onResume 中,不然会出现Home 键之后,再回到该APP,黑屏9mySurfaceView =new MySurfaceView(getApplicationContext(),11camera);0FrameLayout preview = (FrameLayout)11findViewById(R.id.camera_preview);

42、1preview.addView(mySurfaceView);2/* 得到一相机对象 */3privateCamera getCameraInstance()11Camera camera =null ;4try11camera = camera.open();5 catch(Exception e)11e.printStackTrace();611returncamera;11811/-保存图片9-12privatevoid saveImageToFile()0File file = getOutFile(TYPE_FILE_IMAGE);12if(file =null )1Toast.m

43、akeText(getApplicationContext(), 文件创建失败 , 请检12查 SD 卡读写权限 , Toast.LENGTH_SHORT).show();2return;123Log.i(MyPicture, 自定义相机图片路径: + file.getPath();12Toast.makeText(getApplicationContext(), 图片保存路径: +4 file.getPath(), Toast.LENGTH_SHORT).show();12if(buffer =null)5Log.i(MyPicture, 自定义相机 Buffer: null);12 els

44、e 6try12FileOutputStream fos =newFileOutputStream(file);7fos.write(buffer);12fos.close();8 catch(IOException e)12e.printStackTrace();9130131/-生成13Uri-/ 得到输出文件的 URI13privateUri getOutFileUri(intfileType) 3returnUri.fromFile(getOutFile(fileType);4/ 生成输出文件5privateFile getOutFile(int fileType) 136String

45、 storageState = Environment.getExternalStorageState();13if(Environment.MEDIA_REMOVED.equals(storageState)7Toast.makeText(getApplicationContext(),oh,no, SD 卡不存在13 , Toast.LENGTH_SHORT).show();8returnnull ;13914File mediaStorageDir =new File (Environment0.getExternalStoragePublicDirectory(Environment.DIRECT14ORY_PIC

温馨提示

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

评论

0/150

提交评论