只簡述我發(fā)現(xiàn)問題的根源腻脏,有些是適配了7.0,會報權(quán)限失敗問題银锻,那是由于沒有動態(tài)授權(quán)導(dǎo)致永品,接下來我一步一步給大家實(shí)現(xiàn)7.0適配,使用的是Kotlin語言
1.在mainfest標(biāo)簽里加入以下該權(quán)限
<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目錄下創(chuàng)建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.實(shí)現(xiàn)拍照和選擇相冊裁剪的代碼
a.新建3個file對象用于存儲讀取出來的圖片
varcamerafile:File?=null//照相機(jī)File對象
vargalleryfile:File?=null//相冊的File對象
varcropfile:File?=null//照相機(jī)的File對象
b.首先在開始調(diào)用拍照或者選擇圖片的時候要動態(tài)驗(yàn)證權(quán)限
@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)
}
}
}
//權(quán)限回調(diào)方法
override funonRequestPermissionsResult(requestCode: Int,permissions: Array,grantResults: IntArray) {
when(requestCode){
0->{
if(grantResults.size>0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
}else{
Toasty.error(baseContext,"授權(quán)失敗").show()
}
}
}
super.onRequestPermissionsResult(requestCode,permissions,grantResults)
}
c.拍照的代碼
/**
* 選擇照相機(jī)拍照
*/
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);//去除默認(rèn)的人臉識別炕桨,否則和剪裁匡重疊
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)
}
// 設(shè)置裁剪
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.分享一個圖片相關(guān)工具類,網(wǎng)上很多人用的是這個
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了殃饿,關(guān)于為什么會出現(xiàn)問題可以度娘谋作,我這里提供相關(guān)解決方案,如大家有任何疑問乎芳,我的QQ752422962遵蚜,聯(lián)系我