自定义Camera综述(一般步骤、注意事项、遇到的难题<【内存溢出问题】>、像素参考)
一般步骤:
1. 检查和访问Camera:创建代码来检查Camera和所申请访问的存在性;
2. 创建一个预览类:继承SurfaceView来创建一个Camera的预览类,并实现SurfaceHolder接口。这个类用来预览来自Camera的实时图像。
3. 构建一个预览布局:一旦有了Camera预览类,就可以把这个预览类和你想要的用户界面控制结合在一起来创建一个视图布局。
4. 针对采集建立监听:把监听器与响应用户动作(如按下按钮)的界面控制连接到一起来启动图像或视频的采集。
5. 采集和保存文件:针对真正采集的图片或视频,以及输出的保存来编写代码。
6. 释放Camera:使用Camera之后,你的应用程序必须释放Camera,以便其他应用程序能够使用。
注意事项:
Camera硬件是一个必须要认真管理的共享资源,因此你的应用程序在使用它时,不能跟其他应用程序发生冲突。(以后会讨论如何检查Camera硬件、如何申请对Camera的访问,如何采集图片和视频,以及在应用使用完成后如何释放Camera。)
警告:在应用程序使用完Camera时,要记住通过调用Camera.release()方法来释放Camera对象。如果你的应用程序没有正确的释放Camera,所有的后续的视图对Camera的访问,包括你自己的应用程序,都会失败,并可能到你的或其他的应用程序关闭。
遇到的难题:
1、Activity之间切换出现短暂黑屏。
在默认情况下,Android应用程序启动时,会有一个黑屏的时期。同样,使用startActivity(intent)方法从一个Activity进入到新的Activity时,这个过程中也会出现短暂的黑屏。原因是,首个activity会加载一些数据,比如初始化列表数据、向服务器发送请求获取数据等等。这个问题的存在是由Android应用框架决定的,但的确很影响用户体验。下面就动手来解决这个黑屏问题!
第一步:自定义Theme(主题)——使目标Activity透明
在your_project/res/values/styles.xml中加入自定义Activity的Theme,如下所示:
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- Activity主题 --> <style name="activityTheme" parent="@android:style/Theme"> <item name="android:windowIsTranslucent">true</item> </style> </resources>
其中<item name="android:windowIsTranslucent">true</item>的意思是设置目标Activity(要启动的那个Activity)是透明的。很容易理解,两个Activity,A和B;在A中启动B,因为B是透明的,看到的背景仍是A,这样就解决了这个短暂的黑屏问题。
第二步:修改Manifest,将Theme应用到目标Activity上
定义好Theme后,就该为对应的Activity绑定Theme了。这个代码主要在Manifest中实现,在Activity中加上以下属性:
<activity android:name=".activity.PlacingOrderStep1Activity" android:theme="@style/activityTheme" />
到此问题解决!
2、图片处理出现内存溢出问题。
原因:
- 大量使用createBitmap、setImageBitmap、setImageResource、BitmapFactory.decodeResource来设置一张大图;因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。
- 对处理完的Bitmap未进行显式的回收操作。if(bitmapObject.isRecycled()==false) //如果没有回收 { bitmapObject.recycle(); }
解决方法:
- 在左右旋转图片时采用:
通过BitmapFactory.decodeStream方法,创建bitmap,再将其设为ImageView的 source;decodeStream最大的秘密在于其直接调用JNI>>nativeDecodeAsset()来完成decode,无需再使用java层的createBitmap,从而节省了java层的空间。BitmapOrgLeft = BitmapFactory.decodeStream(new FileInputStream(MatrixLeftFile), null, RotateOptions);
采用压缩转档方法:BitmapOrgLeft.compress(Bitmap.CompressFormat.JPEG, 100, bos);
- 在其他特效处理时采用:
通过【线程】处理图片,将Bitmap转换为Drawable来处理,进而使用setImageDrawable(BitmapDrawable)来显示图片。
Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { Drawable targetBitmapDrawable = new BitmapDrawable((Bitmap) msg.obj);// 将Bitmap转换为Drawable is.setImageDrawable(targetBitmapDrawable); } };
每次线程处理完图片,都进行线程的回收。
thread.start();
thread = null;
到此问题【部分】解决,最终只能做到最大5M的图片处理!
像素参考:
800万 3264x1836 8M
500万 2592x1944 5 M(目前已实现的)
300万 2048x1536 3.2M
UXGA 1600x1200 1920x1088 2M
XGA 1024x768 0.8M SVGA 800x600
VGA 640x480 0.3M