2021SC@SDUSC
前言
上几篇文章已经分析完了飞花令的项目,从这一篇开始分析camera的项目。开发人员的设计中,以手机相机为依托的camera项目不仅需要有基础的拍照功能,并且还需要对拍摄的照?进??系列处理,包括但不仅限于图?抗扭曲,曝光度,聚焦等。具体可以整理为以下功能: 1. 相机预览功能 2. 拍照的偏好设置,如闪光灯,聚焦,曝光补偿 3. 相机可随设备旋转,拍摄横屏和竖屏的照? 4. 拍照后保存在?机的pictures?件夹 5. 可以预览拍摄的照? 6. 图?抗扭曲处理 这篇将继续分析相机的偏好设置和拍照的功能。
一、项目环境
android studio版本 4.1.2
sdk版本 Compile SDK version:30
Build Tools Version 30.0.3
gradle版本 6.8.3
二、代码分析
条目value变化时立即应用设置
用户调整偏好设置之后,SettingsFragment需要监听条目value变化,给SettingsFragment添加监听事件,一旦出现变化,就根据其key立即应用新的value到相机。
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
switch (key) {//key中存储变化的偏好设置
case KEY_PREF_FOCUS_MODE:
setFocusMode(sharedPreferences.getString(key, ""));
break;
case KEY_PREF_FLASH_MODE:
setFlashMode(sharedPreferences.getString(key, ""));
break;
case KEY_PREF_EXPOS_COMP:
setExposComp(sharedPreferences.getString(key, ""));
break;
}
mCamera.stopPreview();
mCamera.setParameters(mParameters);
mCamera.startPreview();
}
onSharedPreferenceChanged()为监听事件回调。onResume()和onPause()是Android推荐写法,防止由于Fragment的不断调用导致事件监听失效。 onResume():onResume()是当该activity与用户能进行交互时被执行,用户可以获得activity的焦点,能够与用户交互。此时的活动一定位于返回栈的栈顶,并且处于运行状态。 onPause():onPause()意味着你的activity仍然处于部分可见的状态,但正在进入其他的activity,当时大多数时候,那意味着用户正在离开这个activity并马上会进入Stopped state. Activity必需离开Activity栈的栈顶 onStop():当你的activity调用onStop()方法, activity不再可见,并且应该释放那些不再需要的所有资源。一旦你的activity停止了,系统会在不再需要这个activity时摧毁它的实例。在极端情况下,系统会直接杀死你的app进程,并且不执行activity的onDestroy()回调方法, 因此你需要使用onStop()来释放资源,从而避免内存泄漏。 onDestory(): onDestory()作用是在一个Activity对象被销毁之前,Android系统会调用该方法,用于释放此Activity之前所占用的资源。 三种调用的场景: 一个Activity启动另一个Activity: onPause()->onStop(),再返回:onRestart()->onStart()->onResume() 程序按back 退出: onPause()->onStop()->onDestory(),再进入:onCreate()->onStart()->onResume(); 程序按home 退出: onPause()->onStop(),再进入:onRestart()->onStart()->onResume();
设置菜单中显示ListPreference的当前值
PreferenceGroup是直接继承于Preference,起到的是一个容器作用,他的子类有 PreferenceCategory 和PreferenceScreen,这两个直接继承PreferenceGroup所以在开发中起的作用也是容器,用于”安置“其他子Preference的容器。
如果pref时PreferenceGroup的实例,那pref中将pref强转为PreferenceGroup类,利用PreferenceGroup中的getPreference()方法获取到容器内Preference的数量,并且利用getPreference来得到参数,这是一个嵌套函数,如果已经得到了具体的函数,就调用updateSummary方法, 利用getEntry()方法用于在指定参数的帮助下获取此实例的 参数值。
private static void initSummary(Preference pref) {
if (pref instanceof PreferenceGroup) {
PreferenceGroup prefGroup = (PreferenceGroup) pref;
for (int i = 0; i < prefGroup.getPreferenceCount(); i++) {
initSummary(prefGroup.getPreference(i));
}
} else {
updatePrefSummary(pref);
}
}
private static void updatePrefSummary(Preference pref) {
if (pref instanceof ListPreference) {
pref.setSummary(((ListPreference) pref).getEntry());
}
}
以下是界面效果:
照片文件命名:生成文件名
文件名首先标记文件类型,然后是时间,如IMG_20160503_153218.jpg,在CameraPreview中添加:
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
private Uri outputMediaFileUri;
private String outputMediaFileType ="0";
external storage就是SD卡,利用了Environment.getExternalStoragePubicDirectory( Environment.DIRECTORY_PICTURES)获得到文件存储目录,用以进一步存储照片,getExternalStoragePubicDirectory()是一个更加方便的访问Android给我们提供好的一些公共目录的方法 File.separator 的作用相当于 ’ \ ',起到一个分隔符的作用,用于指定新文件的路径 URI,统一资源标志符(Uniform Resource Identifier, URI),表示的是每一种可用的资源,如 图像、视频片段、程序等都由一个URI进行标识的。
private File getOutputMediaFile(int type) {
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), TAG);
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.d(TAG, "failed to create directory");
return null;
}//创建目录,失败返回false
}
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());//获取当前时间,并且定义格式
File mediaFile;
if (type == MEDIA_TYPE_IMAGE) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_" + timeStamp + ".jpg");
outputMediaFileType = "image/*";
} else if (type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_" + timeStamp + ".mp4");
outputMediaFileType = "video/*";
} else {
return null;
}
outputMediaFileUri = Uri.fromFile(mediaFile);
return mediaFile;
}
public Uri getOutputMediaFileUri() {
return outputMediaFileUri;
}
public String getOutputMediaFileType() {
return outputMediaFileType;
}
三、总结
这次分析完成了相机预览和偏好设置的代码,并且开始了关于拍照处理的代码,首先分析了关于拍照片文件命名和存储的代码,下一篇将开始分析如何实现拍照
|