只简述我发现问题的根源,有些是适配了7.0,会报权限失败问题,那是由于没有动态授权导致,接下来我一步一步给大家实现7.0适配,使用的是Kotlin语言
1.在mainfest标签里加入以下该权限
<uses-permissionandroid:name="android.permission.CAMERA" />
<uses-permissionandroid:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
2.在application下加入该
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.wocus.myapplication.fileprovider" //这里写自己的包名,后面固定
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
<provider>
提供filepaths源码,在res目录下创建xml文件夹,在里面新建filepaths.xml文件
<resources>
<paths>
<external-pathpath=""name="sdcard_files"/>
<external-files-pathpath=""name="camera_has_sdcard"/>
<files-pathpath=""name="camera_no_sdcard"/>
<paths/>
<resources/>
3.实现拍照和选择相册裁剪的代码
a.新建3个file对象用于存储读取出来的图片
varcamerafile:File?=null//照相机File对象
vargalleryfile:File?=null//相册的File对象
varcropfile:File?=null//照相机的File对象
b.首先在开始调用拍照或者选择图片的时候要动态验证权限
@SuppressLint("NewApi")
fun requestReadExternalPermission(){
if(checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
if(shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) {
}else{
requestPermissions(arrayOf(Manifest.permission.CAMERA,Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE),0)
}
}
}
//权限回调方法
override funonRequestPermissionsResult(requestCode: Int,permissions: Array,grantResults: IntArray) {
when(requestCode){
0->{
if(grantResults.size>0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
}else{
Toasty.error(baseContext,"授权失败").show()
}
}
}
super.onRequestPermissionsResult(requestCode,permissions,grantResults)
}
c.拍照的代码
/**
* 选择照相机拍照
*/
fungetCamera(){
varintent:Intent= Intent(MediaStore.ACTION_IMAGE_CAPTURE)
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
img_paths=SimpleDateFormat("yyyyMMddHHmmss").format(Date())+".jpg"
varpath:File= getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
camerafile= File(path,img_paths)
if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.N) {//7.0及以上
intent.putExtra(MediaStore.EXTRA_OUTPUT,FileProvider.getUriForFile(this,"com.wocus.myapplication.fileprovider",camerafile))
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
}else{
intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(camerafile))
}
startActivityForResult(intent,100)
}else{
Toasty.error(this,"存储卡不可用!").show()
}
}
d.从相册选择图片的代码
/**
* 从相册选择照片
*/
fungetGallery(){
img_paths=SimpleDateFormat("yyyyMMddHHmmss").format(Date())+".jpg"
varpath:File= getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
galleryfile= File(path,img_paths)
varintent:Intent= Intent(Intent.ACTION_GET_CONTENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.setType("image/*")
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N){
intent.putExtra(MediaStore.EXTRA_OUTPUT,FileProvider.getUriForFile(baseContext,"com.wocus.myapplication.fileprovider",galleryfile))
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
startActivityForResult(intent,200)
}else{
startActivityForResult(intent,200)
}
}
e.回传方法的代码
override funonActivityResult(requestCode: Int,resultCode: Int,data: Intent?) {
super.onActivityResult(requestCode,resultCode,data)
if(requestCode==100&& resultCode== Activity.RESULT_OK){//拍照回传
img_paths=SimpleDateFormat("yyyyMMddHHmmss").format(Date())+".jpg"
varpath:File= getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
cropfile= File(path,img_paths)
if(Build.VERSION.SDK_INT>=24){
varinputUri:Uri=FileProvider.getUriForFile(baseContext,"com.wocus.myapplication.fileprovider",camerafile)
startPhotoZoom(inputUri)
}else{
varinputUri:Uri=Uri.fromFile(camerafile)
startPhotoZoom(inputUri)
}
}else if(requestCode==200&& resultCode== Activity.RESULT_OK){//选择照片回传
img_paths=SimpleDateFormat("yyyyMMddHHmmss").format(Date())+".jpg"
varpath:File= getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
cropfile= File(path,img_paths)
if(Build.VERSION.SDK_INT>=24){
varimgUri:File= File(GetImagePath.getPath(baseContext,data!!.data))
vardataUri:Uri=FileProvider.getUriForFile(baseContext,"com.wocus.myapplication.fileprovider",imgUri)
startPhotoZoom(dataUri)
}else{
startPhotoZoom(data!!.data)
}
}else{//裁剪回传
varbm:Bitmap=BitmapFactory.decodeFile(cropfile!!.absolutePath)
img_up_photo.setImageBitmap(bm)
}
}
f.裁剪代码
/**
* 图片剪裁
*/
funstartPhotoZoom(inputUri:Uri){
if(inputUri==null)return
varintent:Intent= Intent("com.android.camera.action.CROP")
//sdk>=24
if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.N) {
varoutPutUri:Uri = Uri.fromFile(cropfile)
intent.setDataAndType(inputUri,"image/*")
intent.putExtra(MediaStore.EXTRA_OUTPUT,outPutUri)
intent.putExtra("noFaceDetection", false);//去除默认的人脸识别,否则和剪裁匡重叠
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
}else{
varoutPutUri:Uri = Uri.fromFile(cropfile)
if(Build.VERSION.SDK_INT>= android.os.Build.VERSION_CODES.KITKAT) {
varurl = GetImagePath.getPath(this,inputUri)//这个方法是处理4.4以上图片返回的Uri对象不同的处理方法
intent.setDataAndType(Uri.fromFile(File(url)),"image/*")
}else{
intent.setDataAndType(inputUri,"image/*")
}
intent.putExtra(MediaStore.EXTRA_OUTPUT,outPutUri)
}
// 设置裁剪
intent.putExtra("crop","true")
// aspectX aspectY 是宽高的比例
intent.putExtra("aspectX",1)
intent.putExtra("aspectY",1)
// outputX outputY 是裁剪图片宽高
intent.putExtra("outputX",200)
intent.putExtra("outputY",200)
intent.putExtra("return-data", false)
intent.putExtra("outputFormat",Bitmap.CompressFormat.JPEG.toString())// 图片格式
startActivityForResult(intent,300)//这里就将裁剪后的图片的Uri返回了
}
g.分享一个图片相关工具类,网上很多人用的是这个
packagecom.wocus.myapplication.util;
importandroid.annotation.SuppressLint;
importandroid.content.ContentUris;
importandroid.content.Context;
importandroid.database.Cursor;
importandroid.net.Uri;
importandroid.os.Build;
importandroid.os.Environment;
importandroid.provider.DocumentsContract;
importandroid.provider.MediaStore;
public classGetImagePath {
// 4.4以上 content://com.android.providers.media.documents/document/image:3952
// 4.4以下 content://media/external/images/media/3951
@SuppressLint("NewApi")
public staticStringgetPath(finalContext context, finalUri uri) {
final booleanisKitKat = Build.VERSION.SDK_INT>= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if(isKitKat && DocumentsContract.isDocumentUri(context,uri)) {
// ExternalStorageProvider
if(isExternalStorageDocument(uri)) {
finalString docId = DocumentsContract.getDocumentId(uri);
finalString[] split = docId.split(":");
finalString type = split[0];
if("primary".equalsIgnoreCase(type)) {
returnEnvironment.getExternalStorageDirectory() +"/"+ split[1];
}
}
// DownloadsProvider
else if(isDownloadsDocument(uri)) {
finalString id = DocumentsContract.getDocumentId(uri);
finalUri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"),Long.valueOf(id));
returngetDataColumn(context,contentUri, null, null);
}
// MediaProvider
else if(isMediaDocument(uri)) {
finalString docId = DocumentsContract.getDocumentId(uri);
finalString[] split = docId.split(":");
finalString type = split[0];
Uri contentUri =null;
if("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
}else if("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
}else if("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
finalString selection ="_id=?";
finalString[] selectionArgs =newString[]{
split[1]
};
returngetDataColumn(context,contentUri,selection,selectionArgs);
}
}
// MediaStore (and general)
else if("content".equalsIgnoreCase(uri.getScheme())) {
// Return the remote address
if(isGooglePhotosUri(uri))
returnuri.getLastPathSegment();
returngetDataColumn(context,uri, null, null);
}
// File
else if("file".equalsIgnoreCase(uri.getScheme())) {
returnuri.getPath();
}
return null;
}
//Android 4.4以下版本自动使用该方法
public staticStringgetDataColumn(Context context,Uri uri,String selection,
String[] selectionArgs) {
Cursor cursor =null;
finalString column ="_data";
finalString[] projection = {
column
};
try{
cursor = context.getContentResolver().query(uri,projection,selection,selectionArgs,
null);
if(cursor !=null&& cursor.moveToFirst()) {
final intindex = cursor.getColumnIndexOrThrow(column);
returncursor.getString(index);
}
}finally{
if(cursor !=null)
cursor.close();
}
return null;
}
/**
*@paramuriThe Uri to check.
*@returnWhether the Uri authority is ExternalStorageProvider.
*/
public static booleanisExternalStorageDocument(Uri uri) {
return"com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
*@paramuriThe Uri to check.
*@returnWhether the Uri authority is DownloadsProvider.
*/
public static booleanisDownloadsDocument(Uri uri) {
return"com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
*@paramuriThe Uri to check.
*@returnWhether the Uri authority is MediaProvider.
*/
public static booleanisMediaDocument(Uri uri) {
return"com.android.providers.media.documents".equals(uri.getAuthority());
}
/**
*@paramuriThe Uri to check.
*@returnWhether the Uri authority is Google Photos.
*/
public static booleanisGooglePhotosUri(Uri uri) {
return"com.google.android.apps.photos.content".equals(uri.getAuthority());
}
}
就到这里就OK了,关于为什么会出现问题可以度娘,我这里提供相关解决方案,如大家有任何疑问,我的QQ752422962,联系我