1. 程式人生 > >Android7.0呼叫照相、相簿總結

Android7.0呼叫照相、相簿總結

前言

前段時間寫了一個呼叫Camera拍照,並從相簿中選取圖片的小程式,但是當它在7.0的系統上執行時,直接崩潰,根本不能使用。
原來Android5.0、6.0、7.0增加了很多特性,我並沒有對此進行適配,從而導致了很多錯誤。

異常錯誤:

android.os.FileUriExposedException: file:///storage/emulated/0/camera/1513393885728.jgp
exposed beyond app through ClipData.Item.getUri()

java.lang.SecurityException: Permission Denial: reading android.support.v4.content.FileProvider uri content://com.zxl.test_picture_camera/camera_gallery/camera/1514101205911.jgp from pid=5847, uid=10048 requires the provider be exported, or grantUriPermission()
java.lang.SecurityException: Permission Denial: writing android.support.v4.content.FileProvider uri content://com.zxl.test_picture_camera/camera_gallery/camera/1514101317846.jgp from pid=8336, uid=10048 requires the provider be exported, or grantUriPermission()

功能點:

-許可權校驗
-許可權申請
-賦予第三方應用Uri許可權
-開啟照相機
-開啟相簿


-裁剪圖片

1.許可權校驗

public static boolean checkPermission(Context context, String permissionStr){
    boolean result = true;
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
        result = context.checkSelfPermission(permissionStr) == PackageManager.PERMISSION_GRANTED;
    }else{
        result = PermissionChecker.checkSelfPermission(context,permissionStr) == PackageManager.PERMISSION_GRANTED;
    }
    return result;
}

1.1 Camera許可權校驗

Manifest.permission.CAMERA

public static boolean checkCameraPermission(Context context){
    return  checkPermission(context, Manifest.permission.CAMERA);
}

1.2 外部儲存目錄許可權校驗

Manifest.permission.READ_EXTERNAL_STORAGE
Manifest.permission.WRITE_EXTERNAL_STORAGE

public static boolean checkSDCardPermission(Context context){
    return  checkPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) && checkPermission(context,Manifest.permission.WRITE_EXTERNAL_STORAGE);
}

2.許可權申請

AndroidManifest.xml新增許可權:
android.permission.CAMERA
android.permission.READ_EXTERNAL_STORAGE
android.permission.WRITE_EXTERNAL_STORAGE

在Android6.0以後有的許可權需要主動去申請
requestPermissions

@RequiresApi(api = Build.VERSION_CODES.M)
public static void requestPermission(Activity activity, String[] permissionStrs, int requestCode){					      
	activity.requestPermissions(permissionStrs,requestCode);
}

2.1 Camera許可權申請

requestPermissions Manifest.permission.CAMERA

@RequiresApi(api = Build.VERSION_CODES.M)
public static void requestCameraPermission(Activity activity, int requestCode){
    requestPermission(activity,new String[]{Manifest.permission.CAMERA},requestCode);
}

2.2 外部儲存目錄許可權申請

requestPermissions Manifest.permission.READ_EXTERNAL_STORAGE
Manifest.permission.WRITE_EXTERNAL_STORAGE

@RequiresApi(api = Build.VERSION_CODES.M)
public static void requestSDCardPermission(Activity activity, int requestCode){
    requestPermission(activity,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE},requestCode);
}

2.3 許可權申請結果回撥

通過Activity回撥介面獲取結果
onRequestPermissionsResult

@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
	super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

2.4 許可權申請結果校驗

PackageManager.PERMISSION_GRANTED

public static boolean checkRequestPermissionsResult(int[] grantResults){
    if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
        return true;
    }
    return false;
}

3.賦予第三方應用Uri許可權

當獲取到圖片後,需要進行裁剪,這需要將原圖片、裁剪後到圖片的儲存路徑都要給裁剪應用,並且要封裝成Uri通過Intent傳遞,在Android7.0增加了第三方應用讀取Uri的許可權校驗

3.1 配置共享檔案目錄資原始檔

在res/xml下新建資原始檔file_path.xml
files-path與Context.getFilesDir()相同的目錄
external-path與Environment.getExternalStorageDirectory()相同的目錄
cache-path與getCacheDir()相同的目錄
name為別名
path為表示對應型別的根目錄

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <paths>
        <files-path
            name="camera_gallery"
            path=""/>
        <external-path
            name="camera_gallery"
            path=""/>
        <cache-path
            name="camera_gallery"
            path=""/>
    </paths> 
</resources>

3.2 配置provider

AndroidManifest.xml新增provider

<provider
android:authorities="com.zxl.test_picture_camera"
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>

3.3 生成Uri

FileProvider.getUriForFile

private static Uri getFileUri(Context context,String filePath){
    Uri mUri = null;
    File mFile = new File(filePath);
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
        mUri = FileProvider.getUriForFile(context,"com.zxl.test_picture_camera",mFile);
    }else{
        mUri = Uri.fromFile(mFile);
    }
    return mUri;
}

3.4 賦予Uri讀取許可權

Intent.FLAG_GRANT_READ_URI_PERMISSION

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
	mIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}

3.5 賦予Uri寫許可權

通過Intent找到符合的要開啟的Activity
activity.grantUriPermission
Intent.FLAG_GRANT_WRITE_URI_PERMISSION

List resInfoList = queryActivityByIntent(activity,mIntent);
if (resInfoList.size() == 0) {
    showMsg(activity, "沒有合適的應用程式");
    return;
}
Iterator resInfoIterator = resInfoList.iterator();
while (resInfoIterator.hasNext()) {
    ResolveInfo resolveInfo = (ResolveInfo) resInfoIterator.next();
    String packageName = resolveInfo.activityInfo.packageName;
    activity.grantUriPermission(packageName, desUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}

private static List<ResolveInfo> queryActivityByIntent(Activity activity, Intent intent){
	List resInfoList = activity.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
	return resInfoList;
}

4.開啟照相機

public static void startCamera(Activity activity,int requestCode,String filePath){
    if(hasSdcard()){
        Intent mOpenCameraIntent = new Intent();
        mOpenCameraIntent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);

        Uri desUri = getFileUri(activity,filePath);

        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
            //已申請camera許可權
            //mOpenCameraIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }

        mOpenCameraIntent.putExtra(MediaStore.EXTRA_OUTPUT,desUri);
        activity.startActivityForResult(mOpenCameraIntent,requestCode);
    }else{
        showMsg(activity,"裝置沒有SD卡!");
    }
}

5.開啟相簿

public static void startGallery(Activity activity,int requestCode){
    if(hasSdcard()){
        Intent mOpenGalleryIntent = new Intent(Intent.ACTION_GET_CONTENT);
        mOpenGalleryIntent.setType("image/*");
        activity.startActivityForResult(mOpenGalleryIntent,requestCode);
    }else{
        showMsg(activity,"裝置沒有SD卡!");
    }
}

6.裁剪圖片

public static void startCropImage(Activity activity, Uri originUri, Uri desUri, int aspectX, int aspectY, int outputX, int outputY, int requestCode){
    Intent mIntent = new Intent();
    mIntent.setAction("com.android.camera.action.CROP");
    mIntent.setDataAndType(originUri,"image/*");

    List resInfoList = queryActivityByIntent(activity,mIntent);
    if (resInfoList.size() == 0) {
        showMsg(activity, "沒有合適的應用程式");
        return;
    }
    Iterator resInfoIterator = resInfoList.iterator();
    while (resInfoIterator.hasNext()) {
        ResolveInfo resolveInfo = (ResolveInfo) resInfoIterator.next();
        String packageName = resolveInfo.activityInfo.packageName;
        activity.grantUriPermission(packageName, desUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    }


    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
        mIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }


    mIntent.putExtra("crop","true");
    mIntent.putExtra("aspectX",aspectX);
    mIntent.putExtra("aspectY",aspectY);
    mIntent.putExtra("outputX",outputX);
    mIntent.putExtra("outputY",outputY);
    mIntent.putExtra("scale",true);

    mIntent.putExtra(MediaStore.EXTRA_OUTPUT, desUri);
    mIntent.putExtra("return-data",false);
    mIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
    mIntent.putExtra("noFaceDetection",true);

    activity.startActivityForResult(mIntent,requestCode);
}

相關推薦

Android7.0呼叫照相相簿總結

前言 前段時間寫了一個呼叫Camera拍照,並從相簿中選取圖片的小程式,但是當它在7.0的系統上執行時,直接崩潰,根本不能使用。 原來Android5.0、6.0、7.0增加了很多特性,我並沒有對此進

android 提示“無法返回該圖片”有些機型比如:sony 手機resultCode = 0或者照相相簿裁剪時候onActivityResult的Intent返回null

這個弄了一下的時間糊里糊塗解決的。 問題就是不管怎麼呼叫相簿還是相機都是返回 “無法返回該圖片”,debug到startActivityForResult都有資料,但在onActivityResult接收資料的時候resultCode = 0了,,本該返回-1怎麼就變成0了,,一直想不明白,

Android7.0呼叫系統相機拍照訪問相簿問題。

關於Android7.0呼叫系統相機拍照、訪問相簿的一些問題: 在Android6.0中Google提出了動態申請許可權的Api,呼叫相機拍照,訪問SDcard等操作都需要先申請對應的許可權如下: <uses-permission android:name="and

Android7.0呼叫系統拍照系統相簿(圖片壓縮檢視原圖許可權處理)

效果以及需求 檢視原圖可點選放大,可兩指放大等 1.PopupWindow的簡單使用 PopupWindow最基本的三個條件是一定要設定的:View contentView

Android7.0呼叫系統相機拍照訪問相簿問題上傳到伺服器

//model層 package zhaochuang.bawei.com.myapplication.model; import java.util.Map; import okhttp3.RequestBody; import zhaochuang.bawei.com

Android 呼叫相機相簿(適配6.0

又好久沒有寫部落格了,好習慣不能斷,該寫點就得寫點,今天帶來的筆記是關於Android 專案呼叫系統相機 與呼叫系統相簿的之後拿到照片的基本操作,我感覺好多人還是不太熟悉的哈。專案相容 Android 5.0裝置、Android 6.0裝置、Android 7.0、Android 8.0

Android7.0及以上相機相簿呼叫閃退處理封裝,向下相容

上一篇博文其實解決過這個問題,但是,博主更希望能夠一行程式碼調起相機和相簿,並且回撥拿到相應的bitmap,於是,在上一篇博文的基礎上,博主又進行了相關優化,並且將相機相簿的呼叫封裝成了一個jar包,讓和博主一樣希望更簡單寫程式碼的諸位能夠更輕鬆的使用相機相簿。註明:該ja

android7.0呼叫相機時候,FileProvider報NullPointerException的解決方法

      今天在做專案的時候,用到了呼叫相機的功能。但是這次忽然FileProvider報了空指標的錯誤      定位錯誤的時候,找到了FileProvider,是獲取地址的一個方法      在這裡報空指標的話,我覺得應該是地址為空所造成的,在檢查完所寫方法後,

android7.0呼叫相機拍照的問題解決方案

最近在應用中開發呼叫系統相機拍照的時候,遇到一個問題,就是在安卓7.0及以上機型使用,按照往常寫法Uri.fromFile(imgFile)回丟擲異常FileUriExposedException導致程

h5呼叫相機相簿攝像頭拍照錄影並壓縮預覽

1、使用h5中的input標籤  <!--相機--> <input id="fileBtn" type="file" onchange="upload('#fileBtn');" accept="image/*" capture='camera' styl

Android7.0新特性新功能

前言: 總想寫點自己的東西,因為很多Android知識網上大部分都有教程,這樣寫的話總是忍不住借鑑別人寫的東西,再加入點自己的一些元素,我只好對網上的各種知識,我認為很多知識可以總結到一起的把它們總結

android照相相簿獲取圖片剪裁部分手機異常的解決方法

解決辦法 可以定義一個Uri物件來儲存剪下後的圖片 File file = new File(Environment.getExternalStorageDirectory(),BitmapUtil.generateFileName()); corpUri = U

Android7.0呼叫系統相機和裁剪

最近將專案的targetSdkVersion升級到了26,發現呼叫系統相機的時候報了下面這個錯誤: android.os.FileUriExposedException: file:///storage/emulated/0/Android/data/b

Android7.0 頭像 拍照照片裁剪

首先,好規則,看看自己的實現效果: 當然,這個github 各種開源庫,這裡只講 Android 自帶的功能。 其實這個也不難,關鍵點無非就2個: 7.0 之後相機的 uri 獲取裁剪時的 uri 獲取這裡可以放一下底部 popupwindow 的佈局,另外可以看我的 popupwindow封裝: 拒

呼叫系統相機相簿剪裁圖片並上傳(常用於上傳頭像,相容Android7.0

轉載請註明出處文章地址 本文轉自Hansion的部落格 由於在Android 7.0 採用了StrictMode API政策禁,其中有一條限制就是對目錄訪問的限制。 這項變更意味著我們無法通過File API訪問手機儲存上的資料,也就是說,給其他應用傳

解決Android7.0系統 呼叫系統相機系統播放器播放視訊切圖相容問題,報異常android.os.FileUriExposedException

Android7.0以前獲取本地檔案uri用的Uri.fromFile(new File(filePath)); 後會得到一個file://,這種方式呢7.0及以後的系統版本就用不了,且會報一個異常:

Android呼叫系統相機相簿功能,適配6.0許可權獲取以及7.0以後獲取URI(相容多版本)

  Android中呼叫系統相機來拍攝照片的程式碼,如下:1、首先設定Uri獲取判斷以及相機請求Codepublicfinalint TYPE_TAKE_PHOTO = 1;//Uri獲取型別判斷publicfinalint CODE_TAKE_PHOTO = 1;//相機R

Android呼叫系統相機相簿裁剪圖片並壓縮上傳(適配7.0

作者:八怪不姓醜 連結:http://www.jianshu.com/p/e11a34e2ea4f 著作權歸作者所有,本文經作者授權推送。 一、前言 最近在開發中遇到了一個比較棘手的問題 由於在之前使用的版本-targetSdkVersion小於24也就是小於7.

Android7.0調用系統相機拍照讀取系統相冊照片+CropImageView剪裁照片

alpha pri process 點擊事件 self tps 而在 center ase Android手機拍照、剪裁,並非那麽簡單 簡書地址:[我的簡書–T9的第三個三角] 前言 項目中,基本都有用戶自定義頭像或自定義背景的功能,實現方法一般都是調用

SimplePhotoPicker:呼叫系統相機相簿的輕量框架

SimplePhotoPicker 一個進入相簿,呼叫相機的可高度定製化的框架,持續維護中… 效果圖 那些你所擔心但是已經幫你解決的問題 1.Android6.0**隱私許可權**請求問題—>已判斷並處理 2.Android7.0 Fi