Android 7.0調(diào)用系統(tǒng)相機(jī)適配-bo

版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。

目錄(?)[+]

對(duì)于Android N以下,文件直接Uri.fromFile(file)就可以直接使用,Audroid N 即編譯app的版本 compileSdkVersion 24時(shí),此時(shí)會(huì)報(bào)出FileUriExposedException異常,解釋如下:

對(duì)于面向AndroidN 的應(yīng)用,Android框架執(zhí)行的 StrictMode,API 禁止向您的應(yīng)用外公開 file://URI。

如果一項(xiàng)包含文件 URI 的 Intent 離開您的應(yīng)用,應(yīng)用失敗,并出現(xiàn) FileUriExposedException異常。

若要在應(yīng)用間共享文件,您應(yīng)發(fā)送一項(xiàng) content://URI,并授予 URI 臨時(shí)訪問權(quán)限。

進(jìn)行此授權(quán)的最簡(jiǎn)單方式是使用 FileProvider類。

@Overridepublic voidonTakePhoto() {if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.N) {//7.0及其以后版本使用升級(jí)后的代碼處理Intent takePictureIntent =newIntent(MediaStore.ACTION_IMAGE_CAPTURE);if(takePictureIntent.resolveActivity(getPackageManager()) !=null) {//判斷是否有相機(jī)應(yīng)用picName= DateUtil.format(newDate(),"yyyyMMddHHmmss") +".jpg";File imagePath =newFile(Files.photoPath,picName);Uri photoURI =getUriForFile(this,"xxx.xxx.xxx",imagePath);takePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加這一句表示對(duì)目標(biāo)應(yīng)用臨時(shí)授權(quán)該Uri所代表的文件takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,photoURI);startActivityForResult(takePictureIntent,PHOTO_REQUEST_TAKEPHOTO);}? ? }else{//7.0之前還保持原來方案進(jìn)行處理即可Intent cameraintent =newIntent(MediaStore.ACTION_IMAGE_CAPTURE);picName= DateUtil.format(newDate(),"yyyyMMddHHmmss") +".jpg";File f =newFile(Files.photoPath,picName);cameraintent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(f));PrefTool.setBooleanSave(this,Prefs.PRE_NOT_TO_BACKGROUD, true);startActivityForResult(cameraintent,PHOTO_REQUEST_TAKEPHOTO);}}

現(xiàn)在,需要配置FileProvider。在應(yīng)用程序的清單,提供者添加到您的應(yīng)用程序,authorities=”applicationId.fileprovider”,使用時(shí)

file-path

表示你應(yīng)用內(nèi)部存儲(chǔ)區(qū)域的文件的子目錄。這個(gè)子目錄和getFilesDir()的返回值一樣。external-path

表示你應(yīng)用外部存儲(chǔ)區(qū)域的文件的子目錄。這個(gè)子目錄和getExternalFilesDir()的返回值一樣。cache-path

表示你應(yīng)用內(nèi)部存儲(chǔ)區(qū)域的緩存子目錄。這個(gè)子目錄的根目錄和getCacheDir()的返回值一樣。(如果你修改了provider和paths中的值,需要把應(yīng)用卸載重裝或者開關(guān)機(jī)一下才能看到變化。)

@Overrideprotected voidonActivityResult(intrequestCode, intresultCode,Intent data) {super.onActivityResult(requestCode,resultCode,data);switch(requestCode) {casePHOTO_REQUEST_TAKEPHOTO:// 當(dāng)選擇拍照時(shí)調(diào)用if(resultCode ==RESULT_CANCELED) {return;}else if(resultCode !=RESULT_OK) {? ? ? ? ? ? ? ? showMsg("Take photo failed.");}else{? ? ? ? ? ? ? //處理返回?cái)?shù)據(jù)}break;

}

}

關(guān)于FileProvider

FileProvider 是 ContentProvider 的一個(gè)特殊的子類,它有利于安全地分享應(yīng)用相關(guān)的文件,通過對(duì)一個(gè)文件創(chuàng)建content:// Uri而不是file:/// Uri。

由于FileProvider的默認(rèn)功能包括文件的content URI的生成,你并不需要在代碼中定義一個(gè)子類。相反,你可以在你的應(yīng)用中包含一個(gè)FileProvider通過在XML文件中指定它。對(duì)于指定FileProvider,添加一個(gè)元素在你應(yīng)用的清單文件中。設(shè)置android:name屬性為android.support.v4.content.FileProvider。根據(jù)你控制的域名設(shè)置android:authorities屬性為一個(gè)URI authority(authorities可以隨意填寫,但是要保證使用時(shí)與authority保持一致,推薦applicationId.fileprovider,以免定義重復(fù))。設(shè)置android:exported屬性為false;FileProvider不需要公開。設(shè)置android:grantUriPermissions屬性為true,為了允許你進(jìn)行臨時(shí)訪問文件的授權(quán)。

一個(gè)FileProvider只能生成一個(gè)content

URI

對(duì)應(yīng)你事先指定目錄下的文件。對(duì)于指定一個(gè)目錄,使用元素的子元素,在XML中指定它的存儲(chǔ)區(qū)域和路徑。例如,下面的paths元素告訴FileProvider你打算請(qǐng)求你的私有文件區(qū)域的

images/ 子目錄的content URIs

以下摘自Androiddeveloper 文檔:

虛擬文件

在較早的 Android 版本中,您的應(yīng)用可以使用存儲(chǔ)訪問框架來允許用戶從他們的云存儲(chǔ)帳戶中選擇文件,如 Google Drive。但是,不能表示沒有直接字節(jié)碼表示的文件;每個(gè)文件都必須提供一個(gè)輸入流。

Android 7.0 在存儲(chǔ)訪問框架中添加了虛擬文件的概念。虛擬文件功能可以讓您的DocumentsProvider返回可與ACTION_VIEWintent

使用的文件 URI,即使它們沒有直接字節(jié)碼表示。Android 7.0 還允許您為用戶文件(虛擬或其他類)提供備用格式。

為獲得您的應(yīng)用中的虛擬文件的 URI,首先您應(yīng)創(chuàng)建一個(gè)Intent以打開文件選擇器 UI。由于應(yīng)用不能使用openInputStream()方法來直接打開一個(gè)虛擬文件,因此如果您包括了CATEGORY_OPENABLE類別,您的應(yīng)用不會(huì)收到任何虛擬文件。

在用戶選擇之后,系統(tǒng)調(diào)用onActivityResult()方法。您的應(yīng)用可以檢索虛擬文件的 URI,并得到一個(gè)輸入流,這表現(xiàn)在以下片段中的代碼。

// Other Activity code ...finalstaticprivateintREQUEST_CODE=64;// We listen to the OnActivityResult event to respond to the user's selection.@OverridepublicvoidonActivityResult(intrequestCode,intresultCode,IntentresultData){try{if(requestCode==REQUEST_CODE&&resultCode==Activity.RESULT_OK){Uriuri=null;if(resultData!=null){uri=resultData.getData();ContentResolverresolver=getContentResolver();// Before attempting to coerce a file into a MIME type,// check to see what alternative MIME types are available to// coerce this file into.String[]streamTypes=resolver.getStreamTypes(uri,"*/*");AssetFileDescriptordescriptor=resolver.openTypedAssetFileDescriptor(uri,streamTypes[0],null);// Retrieve a stream to the virtual file.InputStreaminputStream=descriptor.createInputStream();}}}catch(Exceptionex){Log.e("EXCEPTION","ERROR: ",ex);}}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,117評(píng)論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,860評(píng)論 3 423
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,128評(píng)論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,291評(píng)論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,025評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,421評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,477評(píng)論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,642評(píng)論 0 289
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,177評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,970評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,157評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,717評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,410評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,821評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,053評(píng)論 1 289
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,896評(píng)論 3 395
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,157評(píng)論 2 375

推薦閱讀更多精彩內(nèi)容