第十六章 使用intent拍照
- 声明: 应用需要使用相机
<uses-feature
android:name="android.hardware.camera"
android:required="false" /> <!--对该应用的请求并不是必须的,若为真,则无法下载该app-->
- 声明
FileProvider
- 填写路径描述(新建xml文件)
<paths>
<files-path
name="crime_photos"
path="."/><!--将私有储存的路径映射为crime_photos-->
</paths>
- 关联使用路径描述资源
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.bignerdranch.android.criminalintent.fileprovider"
android:exported="false"
android:grantUriPermissions="true"><!--给其他应用授权,允许他们向指定位置存储-->
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/files" />
</provider>
允许其他应用写入
mPhotoButton = v.findViewById(R.id.crime_camera);
final Intent captureImage = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
boolean canTakePhoto = mPhotoFile != null &&
captureImage.resolveActivity(packageManager) != null;
mPhotoButton.setEnabled(canTakePhoto);
mPhotoButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//把本地文件路径转化成相机能够看到的uri形式,有路径以及输出的格式
Uri uri = FileProvider.getUriForFile(getActivity(),
"com.bignerdranch.android.criminalintent.fileprovider",
mPhotoFile);
captureImage.putExtra(MediaStore.EXTRA_OUTPUT, uri);
List<ResolveInfo> cameraActivities = getActivity()//查询所有符合该Intent的应用
.getPackageManager().queryIntentActivities(captureImage,
PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo activity : cameraActivities) { //给他们在uri处写入照片的授权
getActivity().grantUriPermission(activity.activityInfo.packageName,
uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}
startActivityForResult(captureImage, REQUEST_PHOTO);
}
});
缩放和显示位图
public class PictureUtils {
/** 对位图进行缩放处理
* @param path 传入文件路径
* @param destWidth 视图的宽度
* @param destHeight 视图的高度
* @return 将文件路径解码为位图并返回
*/
public static Bitmap getScaledBitmap(String path, int destWidth, int destHeight) {
// Read in the dimensions of the image on disk
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; //设置为真,则返回空值
// 将文件路径解码为位图,若指定的路径为空或无法解码位图,则函数返回空值。此处应为初始化。
BitmapFactory.decodeFile(path, options);
float srcWidth = options.outWidth;//位图的结果宽度
float srcHeight = options.outHeight;
//压缩
int inSampleSize = 1;
if (srcHeight > destHeight || srcWidth > destWidth) {
float heightScale = srcHeight / destHeight; //高度的缩放比
float widthScale = srcWidth / destWidth; //宽度的缩放比
inSampleSize = Math.round(heightScale > widthScale ? heightScale :
widthScale);//取出两者中较大的那个值并四舍五入
}
options = new BitmapFactory.Options();
// 如果设置为大于1的值,则要求解码器对原始图像进行次采样,返回较小的图像以节省内存。
// 例如,insampleSize==4返回的图像是原始图像的宽度/高度的1/4,以及像素数的1/16。且任何值<=1都被视为1。
options.inSampleSize = inSampleSize;
//创建位图对象
return BitmapFactory.decodeFile(path, options);
}
/** 获取屏幕视图的状态大小
* @param path 传入文件路径
* @param activity 当前activity
* @return 调用getScaledBitmap(...)处理图片缩放的方法
*/
public static Bitmap getScaledBitmap(String path, Activity activity) {
Point size = new Point();
activity.getWindowManager().getDefaultDisplay()
.getSize(size); //确定屏幕尺寸
return getScaledBitmap(path, size.x, size.y);
}
}
挑战练习
- 放大版照片显示
- 利用DialogFragment来展示
mPhotoView = v.findViewById(R.id.crime_photo);
mPhotoView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mPhotoFile == null || !mPhotoFile.exists()){
mPhotoView.setImageDrawable(null);
}else {
FragmentManager manager = getFragmentManager();
ShowPhotosFragment dialog = ShowPhotosFragment.newInstance(mPhotoFile);
dialog.setTargetFragment(CrimeFragment.this, REQUEST_PHOTO);
dialog.show(manager, SHOW_PHOTO);
}
}
});
- 优化缩略图加载
我可能存在理解性的问题,如果有,请不吝指教,谢谢。