android外部存儲路徑
『壹』 Android - 文件系統與Android11 分區存儲
Android文件系統分為 內部存儲(internal storage) 和 外部存儲(external storage)
1.1 用一個表格來直觀對比一下兩者:
1.2 應用的私有路徑
應用在安裝之後,系統會自動在內部存儲和外部存儲,分別建立應用的私有存儲區域。
內部存儲 : data/user/0/packageName
外部存儲 : storage/emulated/0/android/data/packageName
當應用卸載或者清除數據後,該區域文件會被刪除。
1.3 內外部存儲圖解
Android 10版本中,Google推出 分區存儲 (scoped storage)的功能。
背景 :
分區存儲功能是針對內置的外部存儲來說的,很多應用喜歡在外部存儲的根目錄創建自己的文件夾,比如:storage/emulated/0/***
這樣做的好處:1. 當不斷向該目錄存儲時,應用自己的容量不會變化; 2. 當應用卸載時,該目錄下文件不會被刪除,可用於保存一些可持久性的文件。
但是也有壞處: 1. 對用戶來說,會有很多垃圾文件存在於手機中;2. 只要獲取到Read 和 Write許可權,就可以隨意訪問外部存儲的任何目錄,信息安全存在隱患。
分區存儲 :
除了應用的私有目錄和公共目錄,其他位置都稱為 舊版存儲位置 ,我們需要將舊版存儲位置的數據遷移到能兼容分區存儲的位置。
『貳』 Android數據存儲之File總結
在使用File存儲App數據時,我們需要了解Android系統的存儲系統。Android的存儲分為內部存儲和外部存儲。
由於Android系統的廠商比較多,對於外部存儲目錄的定義有所不同,可能在根目錄下的mnt,sdcard和storage下。以storage為例,打開emulated/0目錄,外部存儲目錄就出現了。雖然可以通過多種路徑打開外部存儲文件,但是最終他們的路徑是相同的:
mnt:
storage:
sdcard:
外部存儲目錄下包含兩大類:公有目錄和私有目錄
私有目錄:
對比下來External有以下幾點優點:
缺點:
內部存儲與外部存儲許可權申請對比如下:
首先我們要獲取外部存儲目標文件的路徑:
然後確定自己需要創建的文件名,結合上面的到的路徑,創建一個File對象:
Android系統默認數據清理的路徑是,內部存儲目錄中相應的cache文件夾中的文件和外部存儲中相應的cache文件夾中的文件。
你的app的internal storage 目錄是以你的app的包名作為標識存放在Android文件系統的特定目錄下[data/data/com.example.xx]。 從技術上講,如果你設置文件為可讀的,那麼其他app就可以讀取你的internal文件。然而,其他app需要知道你的包名與文件名。若是你沒有設置為可讀或者可寫,其他app是沒有辦法讀寫的。因此只要你使用MODE_PRIVATE ,那麼這些文件就不可能被其他app所訪問。
另外記住一點,內部存儲在你的APP卸載的時候,會一塊被刪除,因此,我們可以在cache目錄裡面放置我們的圖片緩存,而且cache與files的差別在於,如果手機的內部存儲空間不夠了,會自行選擇cache目錄進行刪除,因此,不要把重要的文件放在cache文件裡面,可以放置在files裡面,因為這個文件只有在APP被卸載的時候才會被刪除。還有要注意的一點是,如果應用程序是更新操作,內部存儲不會被刪除,區別於被用戶手動卸載。
不管你是使用 () 來存儲可以共享的文件,還是使用 getExternalFilesDir() 來儲存那些對於你的app來說是私有的文件,有一點很重要,那就是你要使用那些類似DIRECTORY_PICTURES 的API的常量。那些目錄類型參數可以確保那些文件被系統正確的對待。例如,那些以DIRECTORY_RINGTONES 類型保存的文件就會被系統的media scanner認為是ringtone而不是音樂。
在開發中,不建議往內部存儲中寫太多的數據,畢竟空間有限。外部存儲在使用的時候最好能夠將文件存放在私有目錄下,這樣有利於系統維護,也避免用戶的反感。
徹底理解android中的內部存儲與外部存儲
Android存儲挖坑記
緩存文件可以放在哪裡?它們各自的特點是什麼
『叄』 xamarin怎樣獲取android外卡路徑
xamarin怎樣獲取android外卡路徑
一部分手機將eMMC存儲掛載到 /mnt/external_sd 、/mnt/sdcard2 等節點,而將外置的SD卡掛載到 Environment.getExternalStorageDirectory()這個結點。
此時,調用Environment.getExternalStorageDirectory(),則返回外置的SD的路徑。
android 怎樣動態的獲取sd卡路徑
鏈接電腦USB調試情況下,在電腦上有新的磁碟顯示,一個SD的,一個手機的,打開SD的就可以找各文件夾路徑
Android怎樣獲取外部存儲器路徑
讀寫sdcard上的文件
其中讀寫步驟按如下進行:
1、調用Environment的getExternalStorageState()方法判斷手機上是否插了sd卡,且應用程序具有讀寫SD卡的許可權,如下代碼將返回true
Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)
2、調用Environment.getExternalStorageDirectory()方法來獲取外部存儲器,也就是SD卡的目錄,或者使用"/mnt/sdcard/"目錄
3、使用IO流操作SD卡上的文件
注意點:手機應該已插入SD卡,對於模擬器而言,可通過mksdcard命令來創建虛擬存儲卡
必須在AndroidManifest.xml上配置讀寫SD卡的許可權
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
我怎樣才能獲得外部SD卡路徑為Android 4.0 +
1. 我想你需要這個外部SD卡:
new File("/mnt/external_sd/")
或
new File("/mnt/extSdCard/")
你的情況......
在更換Environment.getExternalStorageDirectory()您的作品,應在MNT目錄優先和工作在那裡檢查什麼..
你鍵入選擇哪個SD卡
File storageDir = new File("/mnt/");
if(storageDir.isDirectory()){
String[] dirList = storageDir.list();
TODO some type of selecton method?
}
怎樣獲取class路徑
- importjava.io.File;
-
publicclassFileTest{
-
publicstaticvoidmain(String[]args)throwsException{
-
System.out.println(Thread.currentThread().getContextClassLoader()
-
.getResource(""));
-
System.out.println(FileTest.class.getClassLoader().getResource(""));
-
System.out.println(ClassLoader.getSystemResource(""));
-
System.out.println(FileTest.class.getResource(""));
-
System.out.println(FileTest.class.getResource("/"));
-
Class文件所在路徑
-
System.out.println(newFile("/").getAbsolutePath());
-
System.out.println(System.getProperty("user.dir"));
-
System.out.println(System.getProperty("file.encoding"));
-
}
-
}
android 怎麼獲取相冊路徑
android手機4.2版本之前是一個方法,大於4.2版本又是一個方法。
注意:現在手機市場android版本2015面上半年平均4.4,現在是平均5.0了。
-
before
你網路一下,都能查到,很簡單.
-
after
private void startPickPhotoActivity() {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.setType("image/*"); Or 'image/ jpeg '
startActivityForResult(intent, RESULT_PICK_PHOTO_NORMAL);
}
獲得圖片返回的路徑
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (requestCode == RESULT_PICK_PHOTO_NORMAL) {
if (resultCode == RESULT_OK && data != null) {
選中圖片路徑
mFileName = MainActivity.getPath(getApplicationContext(),
data.getData());
if ("".equals(mFileName)) {
return;
}
Intent intent = new Intent(this, EditActivity.class);
intent.putExtra("pathName", mFileName);
startActivity(intent);
}
}
}
@TargetApi(Build.VERSION_CODES.KITKAT)
public static String getPath(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
ExternalStorageProvider
if (UriUtils.isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/"
+ split[1];
}
}
DownloadsProvider
else if (UriUtils.isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content:downloads/public_downloads"),
Long.valueOf(id));
return UriUtils.getDataColumn(context, contentUri, null, null);
}
MediaProvider
else if (UriUtils.isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String 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;
}
final String selection = MediaColumns._ID + "=?";
final String[] selectionArgs = new String[] { split[1] };
return UriUtils.getDataColumn(context, contentUri, selection,
selectionArgs);
}
}
MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
Return the remote address
if (UriUtils.isGooglePhotosUri(uri))
return uri.getLastPathSegment();
return UriUtils.getDataColumn(context, uri, null, null);
}
File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
如何獲取android sdcard路徑
Environment.getExternalStorageDirectory()
android怎麼獲取U盤路徑
用Re管理器進入/mnt/目錄一個一個找
android怎麼獲取分區路徑
我們可以在adb中使用df 來查看分區情況。
1、跨分區不能用 MV命令來拷貝。但是可以用CP命令。如PWD,當前目錄為:/data/local/tmp 。
此目錄下有個busybox和1.txt文件。則利用CP命令拷貝如下:./busybox cp1.txt /system.
2、Android的用戶組有 System, root, shell
3、怎麼樣才能操作分區。
分區操作是需要許可權的。一般來說System分區的許可權限製得比較嚴,Data分區限制比較嚴,用戶可以操作的目錄有local,app目錄。比如/data/local/tmp.
data分區常用目錄:app , system , data ,local,misc 其中system,local可以進入並使用ls等命令。data,app可以進入,但不能用ls命令。
data/data目錄:存放的是所有APK程序數據的目錄,每個APK對就一個自己的Data目錄,就是在data/data/目錄下,會產生一個跟Package一樣的目錄。如有一個APK,它的包名叫.test.hello則,在data/data/目錄下會有一個.test.hello的目錄,這個APK只能操作此目錄,不能操作其它APK的目錄.這個在LINUX下叫做用戶進程只能操作自己的進程目錄.
data/app目錄:用戶安裝的APK放在這里。我們如果把APK放入這個文件夾下面的話,就算安裝好了。這就叫靜默安裝。不用管APK文件裡面的lib目錄下的庫文件,系統會自動幫我們放入調用庫的。
data/system目錄下面有packages.xml ,packages.list,appwidgets.xml, 等等一些記錄手機安裝的軟體,Widget等信息。
data/misc目錄:保存WIFI帳號,VPN設置信息等。如保存了一個WIFI連接帳號,則此目錄下的WIFI目錄下面可以查看到。
system分區常用目錄: app , lib, xbin, bin , media,framework.
system/app目錄:存放系統自帶的APK。沒有測試過是否將APK放入到System/app目錄下,也是靜默安裝APK。?
system/lib目錄:存放APK程序用到的庫文件。
system/bin目錄和system/xbin目錄:存放的是shell命令。
system/framework目錄:啟用Android系統所用到框架,如一些jar文件。
4 Android下面的目錄都是有許可權的,要操作目錄都需要有此許可權才能操作,如果沒有,則使用chomd777來修改.如果是分區根目錄,如/data分區, /system分區.都沒有許可權,則需要重新掛載. 使用 mount -oremount XX
『肆』 Android外部存儲ExternalStorage
內存(emory)
內部存儲(ternalStorage)
1)storage或者mnt文件夾下
2) 通過:
Environment.getExternalStorageDirectory()
可以看到外部存儲的位置
3) 公有目錄(DCIM、DOWNLOAD等),要使用需要申請許可權。
4) 私有目錄(Android/data/應用包名),只能被當前應用訪問。
String path= Environment.getExternalStorageDirectory().getAbsolutePath() +"/Mytest.txt";
try {
if (!file.exists()) {
file.createNewFile();
}
}catch (IOException e) {
e.printStackTrace();
}
try {
if (!file.exists()) {
file.createNewFile();
}
FileOutputStream fos=new FileOutputStream(path,true);
String str=infoEdt.getText().toString();
fos.write(str.getBytes());//以位元組流的方式寫入
}catch (IOException e) {
e.printStackTrace();
}
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
其中第二條許可權可能會報錯,這時候解決辦法是:
在報錯的地方添加
tools:ignore="ProtectedPermissions"
同時在manifest標簽里添加;
xmlns:tools="http://schemas.android.com/tools"
FileInputStream fis =new FileInputStream(path);
byte[] b =new byte[1024];
int len = fis.read(b);//讀取fis位元組流,將其存儲在位元組數組b中,並返回數組的長度(位元組的個數)
String str2=new String(b,0,len);
txt.setText(str2);
注意:1、從外部存儲讀取文件不需要許可權
2、Android6.0以上對外部存儲(內存卡)共有目錄的讀寫需要運行時許可權(允許訪問內存卡),這個許可權需要用戶手動開啟,只在AndroidManifest.xml中申請是沒用的。
int permissionContextCompet.checkSelfPermission(context,permission) 檢查是否具有許可權
第一個參數,環境上下文(this),第二個參數,許可權名,Manifest.permission.WRITE_EXTERNAL_STORAGE,返回的是一個int類型的變數,將其與PackageManger.PERMISSION_GRANTED比較,等於則說明有許可權,不等於的話則要動態申請許可權:
if(permission!= PackageManager.PERMISSION_GRANTED){
//沒有許可權,則要申請許可權
}
ActivityCompet.reaquestPermissions(activity,permission,code) 請求許可權,第一個參數:activity 第二個參數:String類型的數組,裡面裝了各種許可權, 當有多項許可權需要申請的時候可以一起申請,第三個參數:一個int類型的請求碼,動態申請許可權的時候會觸發onRequestPermissionsResult()方法,如果在申請的過程中有什麼需要做的操作可以定義在該方法中,第三個參數請求嗎可以幫助知道是那個許可權的申請觸發了這個方法
int permission=ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if(permission!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode==1){
//當前沒有什麼要處理的
}
}
通過:Environment.getExternalStorageDirectory()獲取到的是根目錄,通過在後面拼接目錄名稱,可以訪問到公有目錄
要獲取外部存儲目錄的私有目錄,可以通過:
1)Context.getExternalFilesDir(String type)獲取到SDCard/Android/data/包名/files/目錄,這個目錄下一般存放一些需要長時間保存的數據。這個參數是用於指定文件夾類型的(圖片,音樂,視頻...)。
2)Context。getExternalCacheDir()獲取到SDCard/Android/data/包名/cache/目錄,這個目錄下面一般存放一些臨時的緩存性的數據。
『伍』 Android 內部存儲/外部存儲 及 讀寫許可權
Android 使用 VFS (Virtual File System) 虛擬文件系統。VFS提供了供存儲設備掛載的節點,同一存儲設備經過分區後,不同的分區可以掛載到不同的節點上,如手機的內置存儲卡。
內置存儲卡 / 外置SD卡
內部存儲 / 外部存儲
VFS 的目錄以 / 為根節點,根節點下面又有不同的節點。物理存儲設備就是掛載到這些節點上。
內部存儲卡/外置SD卡 ≠ 內部存儲/外部存儲
首先明確, 內置存儲卡/外置SD卡 是在 物理層面 相對於 手機大眾用戶 來說的。
外置SD卡:可手動插拔的SD卡。
內置存儲卡:焊接在手機內部不可拆卸的存儲卡。
而, 內部存 /外部存儲 是在 文件系統邏輯層面 相對於 開發者 來說的,指具體的路徑。
一般針對某個應用而言的,屬於該應用的存儲路徑叫內部存儲,反之為外部存儲。
路徑: /data/data/package_name
/data/data/ 下都是已安裝應用的目錄,該目錄下包含的文件都是以包名作為文件名的目錄,例如 /data/data/com.sankuai.meituan
獲取內部存儲的方式如下:
其中,參數 mode 指創建模式,一種 4 種
注意: Android 7.0 以上 android.os.Build.VERSION.SDK_INT>=Build.VERSION_CODES.N 使用3/4 常量時,將會導致SecurityException,這意味著 不能通過名稱共享私有文件 。
嘗試共享 file://URI URI將會導致FileUriExposedException,StrictMode API政策禁止在您的應用外部公開file://URL。如果您的應用需要與其他應用共享私有文件,則可以使用 FileProvider 與 FLAG_GRANT_READ_URI_PERMISSION 配合使用。 Android 7.0 行為變更 通過FileProvider在應用間共享文件吧
外部存儲,可以是 外置SD卡 或 內置存儲卡的部分分區。
外部存儲,分為 公共目錄 和 私有目錄
獲取方式
檢查可用性的方法:
Android 4.3 以下,只能通過 Context#getExternalFilesDir(type) 來獲取外部存儲在內置存儲卡分區的私有目錄,無法獲取外置SD卡。
Android 4.3 開始,可以通過 Context#getExternalFilesDirs(type) 獲取一個File數組,包含了內置存儲卡分區和外置SD的私有目錄地址。
可以使用兼容庫的靜態方法 ContextCompate.getExternalFilesDirs() 兼容 4.3。
感謝以下文章作者
解析Android內部存儲、外部存儲的區別
『陸』 Android存儲及路徑
分為:內部存儲和外部存儲
如何區分內部存儲和外部存儲:可以從物理和邏輯區分
從物理的角度區分,內部存儲就是手機自帶存儲空間,外部存儲就是外部接入的存儲空間例如SD卡
從邏輯意義上區分,data,system 目錄就是手機的內部存儲,而 mnt 或者 storage目錄下的sdcard0指向的sdcard目錄就是外部存儲。如果是手機自帶的外部存儲被稱為機身外部存儲,外置的SD卡則稱之為外部存儲。當然兩者都稱為外部存儲也沒關系。這里描述的內部存儲和機身外部存儲都屬於機身存儲;
邏輯區分是從4.4以上版本開始的;
獲取內部存儲路徑和api對應關系
1,通過Environment
2,通過上下文Context
Build.VERSION_CODES.LOLLIPOP及以上版本新增的API
Build.VERSION_CODES.N及以上版本新增的API
特點:
1、內部存儲路徑中的文件是分類存儲的,我們無法干涉,除了cache目錄,別的目錄系統不會自動創建
2、除了files目錄,別的目錄我們幾乎都是無法手動操作的
3、別的App幾乎無法訪問內部存儲中的數據,除了用非法手段或者我們主動暴露
4、內部存儲目錄下的文件夾及文件會隨著app的卸載而被系統自動刪除
外部存儲又可分為共有目錄和私有目錄;
私有目錄
私有目錄:不需要訪問許可權
Android 在外部存儲空間中也提供了特殊目錄供App存放私有文件,該路徑為:/storage/emulated/0/Android/data/包名/
注意:應用安裝之後/storage/emulated/0/Android/data/是沒有對應的應用文件夾的,需要手動調用對應的API創建;
獲取私有目錄路徑
共有目錄
共有目錄:需要申請許可權才能訪問
許可權:6.0以上需要動態申請
獲取共有目錄的API 29中已過時: