package com.zjw.mymultimedia2;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
//8.3.1 p294 调用摄像头拍照
//布局里面一个Button调用摄像头,一个Image显示拍到的图片
//FileProvider要在清单文件注册
/*
代码如下
<provider
android:authorities="com.zjw.mymultimedia2.fileprovider"
android:name="android.support.v4.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_path"/>
</provider>
其中
name属性值是固定的
authorities属性值要和getUriForFile()参数二里设置的唯一字符串相同
<meta-data/>标签用来指定Uri的共享路径,引用了file_path.xml资源
*/
/*
创建file_path.xml资源
res下新建xml文件夹,里面创建file_path.xml文件
代码如下
<?xml version="1.0" encoding="utf-8"?>
<Paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="my_images"
path=""/>
</Paths>
其中
external-path用来指定Uri共享
name属性可以随便填
path属性表示共享的具体路径,设置为空就是将整个SD卡进行共享
*/
/*
Android 4.0系统以前,访问SD卡应用关联目录需要声明权限,4.0后不用,做兼容还需声明
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
*/
public class CallCamera extends AppCompatActivity {
private Uri mImageUri;
private static final int TAKE_PHOTO = 646;
private Button mBtnTakePhoto;
private ImageView mIvPicture;
private static final String TAG = "zjw";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_call_camera);
//找到控件
mBtnTakePhoto = (Button) findViewById(R.id.btn_take_photo);
mIvPicture = (ImageView) findViewById(R.id.iv_picture);
//点击事件
mBtnTakePhoto.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//存储拍照后图片
//将它存放在手机SD卡的应用关联缓存目录下
//应用关联缓存目录:SD卡中专门用来存放当前应用缓存数据的位置
//getExternalCacheDir():/sdcard/Android/data/<package name>/cache
//从Android6.0开始,读写SD卡被列为高危权限,只you使用应用关联目录可以跳过运行时权限处理
File outputImage = new File(getExternalCacheDir(), "output_image.jpg");
Log.d(TAG, "onClick: " + "1_" + getExternalCacheDir().getAbsolutePath());
try {
if (outputImage.exists()) {
outputImage.delete();
}
outputImage.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
//Android7.0开始,直接使用本地这是路径Uri被认为是不safe的,会报FileUriExposedException异常
if (Build.VERSION.SDK_INT >= 24) {
//FileProvider一种特殊的内容提供器,可以选择性的将封装过得Uri共享给外部
//getUriForFile()将File对象转换为一个封装过的Uri
//参数一:Context
//参数二:任意唯一字符串
//参数三刚刚创建的File对象
mImageUri = FileProvider.getUriForFile(
CallCamera.this, "com.zjw.mymultimedia2.fileprovider", outputImage);
} else {//版本低于Android7.0,这个Uri标识这张图片本地zhen实路径
mImageUri = Uri.fromFile(outputImage);
Log.d(TAG, "onClick: " + "2_" + mImageUri);
}
//调用相机
//MediaStore.ACTION_IMAGE_CAPTURE
//android.media.action.IMAGE_CAPTURE
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
startActivityForResult(intent, TAKE_PHOTO);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case TAKE_PHOTO:
if (resultCode == RESULT_OK) {
//将照片显示出来
try {
// InputStream is = getContentResolver().openInputStream(mImageUri);
// Bitmap bitmap = BitmapFactory.decodeStream(is);
// System.out.println(bitmap.getByteCount()+"czb");
//加载大图
InputStream is = getContentResolver().openInputStream(mImageUri);
BitmapFactory.Options opts = new BitmapFactory.Options();
// 不读取像素数组到内存中,仅读取图片的信息
opts.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is, null, opts);
// 从Options中获取图片的分辨率
int imageHeight = opts.outHeight;
int imageWidth = opts.outWidth;
// 获取Android屏幕的服务
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
// 获取屏幕的分辨率,getHeight()、getWidth已经被废弃掉了
// 应该使用getSize(),但是这里为了向下兼容所以依然使用它们
int windowHeight = wm.getDefaultDisplay().getHeight();
int windowWidth = wm.getDefaultDisplay().getWidth();
// 计算采样率
int scaleX = imageWidth / windowWidth;
int scaleY = imageHeight / windowHeight;
int scale = 1;
// 采样率依照最大的方向为准
if (scaleX > scaleY && scaleY >= 1) {
scale = scaleX;
}
if (scaleX < scaleY && scaleX >= 1) {
scale = scaleY;
}
// 采样率
opts.inSampleSize = scale;
// false表示读取图片像素数组到内存中,依照设定的采样率
opts.inJustDecodeBounds = false;
is = getContentResolver().openInputStream(mImageUri);
Bitmap bitmap = BitmapFactory.decodeStream(is, null, opts);
Log.d(TAG, "onActivityResult: " + "3_" + bitmap.toString());
mIvPicture.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
break;
default:
break;
}
}
private Toast mToast;
public void showToast(String msg) {
if (mToast == null) {
mToast = Toast.makeText(this, "", Toast.LENGTH_SHORT);
}
mToast.setText(msg);
mToast.show();
}
}
转载于:https://my.oschina.net/u/3620480/blog/1477315
本文详细介绍在Android应用中实现调用摄像头拍照并显示图片的过程。包括使用FileProvider安全地处理图片路径,兼容不同Android版本,以及如何调整图片大小以适应屏幕。
648

被折叠的 条评论
为什么被折叠?



