Android4.4下MediaProvider無法向外置SD卡中文件寫數(shù)據(jù)的解決方法
本文實(shí)例講述了Android4.4下MediaProvider無法向外置SD卡中文件寫數(shù)據(jù)的解決方法。分享給大家供大家參考,具體如下:
Android4.4平臺(tái)限制應(yīng)用對(duì)外置SD卡的讀寫權(quán)限。MediaProvider通過 checkAccess方法 限制對(duì)外置SD卡的讀寫。
private void checkAccess(Uri uri, File file, int modeBits) throws FileNotFoundException {
final boolean isWrite = (modeBits & MODE_WRITE_ONLY) != 0;
final String path;
try {
path = file.getCanonicalPath();
} catch (IOException e) {
throw new IllegalArgumentException("Unable to resolve canonical path for " + file, e);
}
Context c = getContext();
boolean readGranted =
(c.checkCallingOrSelfUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
== PackageManager.PERMISSION_GRANTED);
if (path.startsWith(sExternalPath) || path.startsWith(sLegacyPath)) {
if (!readGranted) {
c.enforceCallingOrSelfPermission(
READ_EXTERNAL_STORAGE, "External path: " + path);
}
if (isWrite) {
if (c.checkCallingOrSelfUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
!= PackageManager.PERMISSION_GRANTED) {
c.enforceCallingOrSelfPermission(
WRITE_EXTERNAL_STORAGE, "External path: " + path);
}
}
} else if (path.startsWith(sCachePath)) {
if (!readGranted) {
c.enforceCallingOrSelfPermission(
ACCESS_CACHE_FILESYSTEM, "Cache path: " + path);
}
//外置SD卡,isWrite = true
} else if (isWrite) {
// don't write to non-cache, non-sdcard files.
throw new FileNotFoundException("Can't access " + file);
} else if (isSecondaryExternalPath(path)) {
// read access is OK with the appropriate permission
if (!readGranted) {
c.enforceCallingOrSelfPermission(
READ_EXTERNAL_STORAGE, "External path: " + path);
}
} else {
checkWorldReadAccess(path);
}
}
從以上代碼我們看出,如果sExternalPath 沒有指向外置SD卡并且path 是外置SD卡的文件路徑,那么該方法 就會(huì)拋出FileNotFoundException,sExternalPath 一般都是指向內(nèi)部存儲(chǔ)
在應(yīng)用中 我們通常 通過contentresolver.openOutputStream(uri) 來打開存儲(chǔ)卡上媒體文件的文件流,如果媒體文件在外置SD卡上,那么我們就無法打開對(duì)應(yīng)的文件流,自然肯定無法向其中寫數(shù)據(jù)。
為了解決該問題,我們只能改變Android4.4平臺(tái)下Mediaprovider 對(duì)向SD卡寫數(shù)據(jù)的限制,具體修改方式如下
private void checkAccess(Uri uri, File file, int modeBits) throws FileNotFoundException {
final boolean isWrite = (modeBits & MODE_WRITE_ONLY) != 0;
final String path;
try {
path = file.getCanonicalPath();
} catch (IOException e) {
throw new IllegalArgumentException("Unable to resolve canonical path for " + file, e);
}
Context c = getContext();
boolean readGranted =
(c.checkCallingOrSelfUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
== PackageManager.PERMISSION_GRANTED);
if (path.startsWith(sExternalPath) || path.startsWith(sLegacyPath) || isSecondaryExternalPath(path)) {
if (!readGranted) {
c.enforceCallingOrSelfPermission(
READ_EXTERNAL_STORAGE, "External path: " + path);
}
if (isWrite) {
if (c.checkCallingOrSelfUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
!= PackageManager.PERMISSION_GRANTED) {
c.enforceCallingOrSelfPermission(
WRITE_EXTERNAL_STORAGE, "External path: " + path);
}
}
} else if (path.startsWith(sCachePath)) {
if (!readGranted) {
c.enforceCallingOrSelfPermission(
ACCESS_CACHE_FILESYSTEM, "Cache path: " + path);
}
//外置SD卡,isWrite = true
} else if (isWrite) {
// don't write to non-cache, non-sdcard files.
throw new FileNotFoundException("Can't access " + file);
} else {
checkWorldReadAccess(path);
}
},
對(duì)于滿足isSecondaryExternalPath(path) 的文件路徑,我們都可以進(jìn)行讀寫,對(duì)于外置SD卡的文件而言 isSecondaryExternalPath(path) 肯定為true
希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。
相關(guān)文章
Android 通過騰訊TBS實(shí)現(xiàn)文件預(yù)覽功能
這篇文章主要介紹了Android 通過騰訊TBS實(shí)現(xiàn)文件預(yù)覽功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
android12?SD如何動(dòng)態(tài)申請(qǐng)讀寫權(quán)限
這篇文章主要給大家介紹了關(guān)于android12?SD如何動(dòng)態(tài)申請(qǐng)讀寫權(quán)限的相關(guān)資料,從Android?6.0開始,權(quán)限不再是在manifest?件中粘貼?下即可,這時(shí)候權(quán)限也正式?進(jìn)?家的視野,需要的朋友可以參考下2023-07-07
Android實(shí)現(xiàn)屏幕各尺寸的獲取的示例
本篇文章主要介紹了Android實(shí)現(xiàn)屏幕各尺寸的獲取的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09
Android封裝對(duì)原生Log進(jìn)行封裝的操作
這篇文章主要介紹了Android封裝對(duì)原生Log進(jìn)行封裝的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-08-08
Android自定義ViewPagerIndicator實(shí)現(xiàn)炫酷導(dǎo)航欄指示器(ViewPager+Fragment)
這篇文章主要為大家詳細(xì)介紹了Android自定義ViewPagerIndicator實(shí)現(xiàn)炫酷導(dǎo)航欄指示器,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02
Java程序員轉(zhuǎn)Android開發(fā)必讀經(jīng)驗(yàn)一份
小編最近幾日偷偷的發(fā)現(xiàn)部分Java程序員想轉(zhuǎn)安卓開發(fā),故此加緊補(bǔ)充知識(shí),為大家搜集資料,積極整理前人的經(jīng)驗(yàn),希望可以給正處于困惑中的你,帶來些許的幫助。2017-11-11
Android編程實(shí)現(xiàn)列表側(cè)滑刪除的方法詳解
這篇文章主要介紹了Android編程實(shí)現(xiàn)列表側(cè)滑刪除的方法,結(jié)合實(shí)例形式詳細(xì)分析了Android列表側(cè)滑刪除功能的原理與具體實(shí)現(xiàn)技巧,注釋中包含詳盡的說明,需要的朋友可以參考下2018-01-01
非常實(shí)用的側(cè)滑刪除控件SwipeLayout
這篇文章主要為大家詳細(xì)介紹了非常實(shí)用的側(cè)滑刪除控件SwipeLayout,類似于QQ側(cè)滑點(diǎn)擊刪除效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-08-08
Android測(cè)試中Appium的一些錯(cuò)誤解決技巧
今天小編就為大家分享一篇關(guān)于Android測(cè)試中Appium的一些錯(cuò)誤解決技巧的文章,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-10-10

