1. 程式人生 > >Android呼叫系統相機、相簿功能,適配6.0許可權獲取以及7.0以後獲取URI(相容多版本)

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

  Android中呼叫系統相機來拍攝照片的程式碼,如下:

1、首先設定Uri獲取判斷以及相機請求Code

  1. publicfinalint TYPE_TAKE_PHOTO = 1;//Uri獲取型別判斷
  2. publicfinalint CODE_TAKE_PHOTO = 1;//相機RequestCode

 2、調起系統相機

  1. Intent takeIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);  
  2. Uri photoUri = getMediaFileUri(TYPE_TAKE_PHOTO);  
  3. takeIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);  
  4. startActivityForResult(takeIntent, CODE_TAKE_PHOTO);  
3、封裝獲取Uri程式碼
  1. public Uri getMediaFileUri(int type){  
  2.     File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "相簿名字");  
  3.     if (!mediaStorageDir.exists()) {  
  4.         if (!mediaStorageDir.mkdirs()) {  
  5.             returnnull;  
  6.         }  
  7.     }  
  8.     //建立Media File
  9.     String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());  
  10.     File mediaFile;  
  11.     if (type == TYPE_TAKE_PHOTO) {  
  12.         mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg"
    );  
  13.     } else {  
  14.         returnnull;  
  15.     }  
  16.     return Uri.fromFile(mediaFile);  
  17. }  

4、相機拍照完畢後獲取返回資料,並在頁面顯示照片

  1. @Override
  2.     protectedvoid onActivityResult(int requestCode, int resultCode, Intent data) {  
  3.         super.onActivityResult(requestCode, resultCode, data);  
  4.         switch (requestCode) {  
  5.             case CODE_TAKE_PHOTO:  
  6.                 if (resultCode == RESULT_OK) {  
  7.                     if (data != null) {  
  8.                         if (data.hasExtra("data")) {  
  9.                             Log.i("URI""data is not null");  
  10.                             Bitmap bitmap = data.getParcelableExtra("data");  
  11.                             imageView.setImageBitmap(bitmap);//imageView即為當前頁面需要展示照片的控制元件,可替換
  12.                         }  
  13.                     } else {  
  14.                         Log.i("URI""Data is null");  
  15.                         Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath());  
  16.                         imageView.setImageBitmap(bitmap);//imageView即為當前頁面需要展示照片的控制元件,可替換
  17.                     }  
  18.                 }  
  19.                 break;  
  20.         }  
  21.     }  
  特殊:

 一般情況,以上程式碼在Android7.0以下,也就是api<24時,執行是沒有任何問題的。可是當targetSdkVersion變成24及其以上並且在android7.0(及以上版本)系統執行時,會丟擲異常:FileUriExposedException。

  許可權:

由於已經寫過一篇文章對android6.0後許可權設定和6.0以前許可權設定進行過講述,在此就不再贅述如何配置許可權了,對於6.0後許可權設定不瞭解的,可以看看:通俗易懂,手把手教會你android 6.0後(相容6.0之前版本)申請危險許可權的方法

  Android7.0及以上版本呼叫系統相機

1、為什麼會報FileUriExposedException異常

android N以後收回了訪問檔案的許可權,按照android N的要求,若在應用間共享檔案,需要傳送Content://Uri,而不再是File://Uri,並且需要對此Uri進行臨時訪問授權。

2、解決辦法:

  使用FileProvider,FileProvider是V4包下的類,繼承自ContentProvider。

3、使用步驟:

  ①、首先在清單檔案中進行FileProvider註冊(與activity同級,四大元件沒啥說的):

  1. <provider
  2.             android:name="android.support.v4.content.FileProvider"
  3.             android:authorities="專案包名.fileprovider"
  4.             android:exported="false"
  5.             android:grantUriPermissions="true">
  6.             <meta-data
  7.                 android:name="android.support.FILE_PROVIDER_PATHS"
  8.                 android:resource="@xml/provider_path"/>
  9.         </provider>
  補充:android:exported="false"  表示對其他應用不可用
        android:grantUriPermissions="true"  授予臨時許可權

  ②、在res目錄下新建xml資料夾,即res/xml,在xml中新建一個provider_path檔案,如下:

  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <pathsxmlns:android="http://schemas.android.com/apk/res/android">
  3.     <external-pathname="external_files"path=""/>
  4. </paths>
補充:<paths>下一般常用以下子節點:

<files-path>:Context.getFilesDir()——指向內部儲存要共享的目錄 

        <cache-path>:Context.getCacheDir()——指向快取要共享的目錄

  <external-path>:Environment.getExternalStorageDirectory()——指向外部儲存要共享的目錄 

        <root-path>:尚未發現官方對其的說明,知道的童鞋歡迎補充。根據字面理解,為整個儲存的根路徑,針對諸如查詢不到照片地址的Bug。

name為自定義的名字,path為目錄,path=""指的是全部目錄|path="."即為當前的根目錄

  ③、只用更改上面貼出來的getMediaFileUri()方法,因為牽涉多版本呼叫相機,所以再封裝一個適用於7.0以上獲取Uri的方法get24MediaFileUri(),程式碼如下:

  1. /** 
  2.      * 版本24以上 
  3.      */
  4.     public Uri get24MediaFileUri(int type) {  
  5.         File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "相簿名字");  
  6.         if (!mediaStorageDir.exists()) {  
  7.             if (!mediaStorageDir.mkdirs()) {  
  8.                 returnnull;  
  9.             }  
  10.         }  
  11.         //建立Media File
  12.         String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());  
  13.         File mediaFile;  
  14.         if (type == TYPE_TAKE_PHOTO) {  
  15.             mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");  
  16.         } else {  
  17.             returnnull;  
  18.         }  
  19.         return FileProvider.getUriForFile(this, getPackageName()+".fileprovider", mediaFile);  
  20.     }  

  注意:get24MediaFileUri()與getMediaFileUri()唯一的不同為:api24以下,使用的是Uri.fromFile(File)獲取的Uri,api24及以上必須使用FileProvider,呼叫FileProvider.getUriForFile(this, getPackageName()+".fileprovider", File)來獲取Uri。

④、7.0以上呼叫系統相機,如下:

  1. Intent takeIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);  
  2. Uri photoUri = get24MediaFileUri(TYPE_TAKE_PHOTO);  
  3. takeIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);  
  4. startActivityForResult(takeIntent, CODE_TAKE_PHOTO);  

  只是將Uri獲取的途徑由getMediaFileUri()改為了get24MediaFileUri()。

  ⑤、多版本適配

2、在許可權獲取後,判斷SDK版本,然後進行相應操作,如下:

  1. if (Build.VERSION.SDK_INT >= 24) {  
  2.         Intent takeIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);  
  3.         Uri photoUri = get24MediaFileUri(TYPE_TAKE_PHOTO);  
  4.         takeIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);  
  5.         startActivityForResult(takeIntent, CODE_TAKE_PHOTO);  
  6.     } else {  
  7.         Intent takeIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);  
  8.         Uri photoUri = getMediaFileUri(TYPE_TAKE_PHOTO);  
  9.         takeIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);  
  10.         startActivityForResult(takeIntent, CODE_TAKE_PHOTO);  
  11.     }  

  ⑥、拍照完畢後,獲取返回資料顯示照片,api24以後,需要轉換輸入流來獲取Bitmap,而輸入流的獲取需要通過getContentResolvrer.openInputStream()來獲取,具體程式碼如下:

  1. @Override
  2.     protectedvoid onActivityResult(int requestCode, int resultCode, Intent data) {  
  3.         super.onActivityResult(requestCode, resultCode, data);  
  4.         switch (requestCode) {  
  5.             case CODE_TAKE_PHOTO:  
  6.                 if (resultCode == RESULT_OK) {  
  7.                     if (data != null) {  
  8.                         if (data.hasExtra("data")) {  
  9. 相關推薦

    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.

    Android完美呼叫系統相機相簿以及裁剪功能

    在 Android應用中,很多時候我們需要實現上傳圖片,或者直接呼叫手機上的拍照功能拍照處理然後直接顯示並上傳功能,下面將講述呼叫相機拍照處理圖片然後顯示和呼叫手機相簿中的圖片處理然後顯示的功能,要想實現上傳功能,一般都是上傳到資料庫中,將imageView中的

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

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

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

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

    Android呼叫系統相機相簿

    拍照和相簿的功能在實際開發中是最常見的功能,這裡記錄下。 準備工作 許可權 1234 <!-- 往SDCard寫入資料許可權 --> <uses-permission android:name="android.permission.WRIT

    Android呼叫系統相機自定義相機處理大圖片

    Android呼叫系統相機和自定義相機例項 本博文主要是介紹了android上使用相機進行拍照並顯示的兩種方式,並且由於涉及到要把拍到 的照片顯示出來,該例子也會涉及到Android載入大圖片時候的處理(避免OOM),還有簡要提一下有些人SurfaceView出現黑屏的原因。 An

    android呼叫系統相機實現拍照功能

    在實現拍照的功能時遇到了很多問題,搜尋了很多資料,嘗試了很多辦法,終於解決了,下面簡要的描述下在開發過程中遇到的問題。 雖然之前看過android開發的書,但是沒有做過東西,這次也是臨時決定讓我做一個android採集系統的演示程式。拍照是其中一個功能,讓網搜尋了下拍照有兩

    android呼叫系統相機相簿上傳頭像

    話說昨天的冰碴下得真心大,騎車回來的路上臉被打的生疼啊!清明小長假第一天,借這個時間把前兩天想記錄的一點內容補充上吧。這篇文章主要記錄呼叫系統相機或者從系統相簿中選取照片然後上傳頭像,這是一個很平常的需求,網上的例子也很多,但是,(注意:前方高能預警!!!)我遇到了一個坑,選

    呼叫系統相機相簿並選擇圖片

    相信很多學習android的朋友,都和我一樣連一個簡單的獲取手機圖片的無從知曉,於是藉助於百度尋求幫助,於是乎有感寫,這篇部落格不僅僅是鞏固自身的基礎知識,希望能幫助到其他人。 Uri mPhotoUri; private static fin

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

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

    Android呼叫系統相機拍照相簿中選擇照片呼叫系統攝像機錄影

    最近在Android Studio上折騰程式碼,昨天編譯器又很不給面子的報錯了: Error type 3 Error: Activity class {com.example.myapplication/com.example.myapplication

    Android 呼叫系統相機拍照並且顯示在相簿以及中間可能會遇到的一些問題的解決

    主要思路是在使用照相機拍照,然後為拍得的照片在SD卡新開一個儲存照片的檔案 程式碼:因為要呼叫照相機和SD卡所以需要新增以下許可權: 在manifests中新增 <uses-permission android:name="android.permission.CAM

    Android 呼叫系統相機拍照並上傳圖片所注意的一些問題

    其實android拍照這個地方還是有很多注意事項的,我在上個專案中就遇到一些坑,因此我想把它記錄下來,希望能幫助一些跟我遇到的同樣的問題的人 如果你在專案中遇到以下問題: 通過系統路徑,拍出來的圖片不清楚 在某些情況下,onActivityResult

    呼叫系統相機相簿並且裁剪成圓形圖片(解決6.07.08.0版本問題)

    之前寫過一篇部落格,那篇部落格對7.0手機裁剪圖片的問題沒有進行解決,現在對之前的那篇部落格進行補充,解決了Android6.0,7.0,8.0版本問題,不僅可以呼叫相簿,相機,還可以將圖片儲存到本地,並且裁剪成圓形圖片 必要的許可權: <uses-permissi

    android 呼叫系統相機拍照返回的data為null

    最近做專案,需要拍照功能,於是就想簡單的呼叫系統相機來完成這一需求(當然,如果想要個性化一點的,也可以自定義camera去實現,這裡暫時不做)。 if(Environment.getExternalStorageState().equals(Environ

    android之 h5呼叫系統相機相簿並顯示

    先上html介面的程式碼,放在assets裡面就可以了,我也不太會html,所以隨便寫了點 <!doctype html> <html lang="en"> <head> <meta charset="UT

    (複習)android 呼叫系統相機 相簿 裁剪-圖片上傳-客服端-伺服器

    效果: 客服端程式碼: package com.cn.lxz.zhaopian; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat;

    解決Android呼叫系統相機拍照後相片無法在相簿中顯示問題

    目前自己使用傳送廣播實現了效果public void photo() { Intent openCameraIntent = new Intent(android.provider.MediaSt

    Android 呼叫系統相機拍照 . 選取本地相簿

    專案中,基本都有使用者自定義頭像或自定義背景的功能,實現方法一般都是呼叫系統相機–拍照,或者系統相簿–選擇照片,然後進行剪裁,最終設為頭像或背景。 我直接貼上使用的程式碼吧! 這次偷懶了,沒有做效果圖,不過這是我試過的程式碼,可以,只不過不能選取原圖,因為