1.现象
在项目中调用相机拍照和录像的时候,android4.x,Android5.x,Android6.x均没有问题,在Android7.x下面直接闪退
2.原因分析
Android升级到7.0后对权限又做了一个更新即不允许出现以file://的形式调用隐式APP,需要用共享文件的形式:content:// URI
3.解决方案
下面是打开系统相机的方法,做了
android各个版本的兼容:
import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import com.qhcloud.filetransfer.TransferApp;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Function:相机工具类
* 调用相机拍照
* 调用相机录像并保存到目录
* Created by xuzhuyun on 2017/3/2.
*/
public class CameraUtil {
public static File tempFile;
public static final int PHOTO_REQUEST_CAREMA = 1;// 拍照
public static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 2;// 拍摄视频
/**
* 打开相机拍照
*
* @param activity
*/
public static void openCamera(Activity activity) {
//獲取系統版本
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
// 激活相机
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// 判断存储卡是否可以用,可用进行存储
if (hasSdcard()) {
SimpleDateFormat timeStampFormat = new SimpleDateFormat(
"yyyy_MM_dd_HH_mm_ss");
String filename = timeStampFormat.format(new Date());
tempFile = new File(Environment.getExternalStorageDirectory(),
filename + ".jpg");
if (currentapiVersion < 24) {
// 从文件中创建uri
Uri uri = Uri.fromFile(tempFile);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
} else {
//兼容android7.0 使用共享文件的形式
ContentValues contentValues = new ContentValues(1);
contentValues.put(MediaStore.Images.Media.DATA, tempFile.getAbsolutePath());
Uri uri = TransferApp.getApplication().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
}
}
// 开启一个带有返回值的Activity,请求码为PHOTO_REQUEST_CAREMA
activity.startActivityForResult(intent, PHOTO_REQUEST_CAREMA);
}
/**
* 打开相机录像
*/
public static void startToVideo(Activity activity) {
//獲取系統版本
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
Uri fileUri = null;
File file = null;
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
try {
file = createMediaFile();
if (file.exists()) {
fileUri = Uri.fromFile(file); // create a file to save the video
}
} catch (IOException e) {
e.printStackTrace();
}
if (currentapiVersion < 24) {
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); // set the video image quality to high
} else {
//兼容android7.0
ContentValues contentValues = new ContentValues(1);
contentValues.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());
Uri uri = activity.getApplication().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
}
// start the Video Capture Intent
activity.startActivityForResult(intent, CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE);
}
/*
* 判断sdcard是否被挂载
*/
public static boolean hasSdcard() {
return Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED);
}
/**
* 创建保存录制得到的视频文件
*
* @return
* @throws IOException
*/
public static File createMediaFile() throws IOException {
if (hasSdcard()) {
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_MOVIES), "CameraVideos");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
return null;
}
}
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "VID_" + timeStamp;
String suffix = ".mp4";
File mediaFile = new File(mediaStorageDir + File.separator + imageFileName + suffix);
return mediaFile;
}
return null;
}
}
以上是做了android7.0兼容处理的工具类,录像时保存到了指定目录。