Android 獲取建立各種儲存路徑工具類(內建許可權獲取)
前言
最近工作比較輕,從專案中總結抽象出一些工具類,利人利己,歡迎交流完善~
概念介紹
1、內部儲存 Internal Storage:
注意內部儲存不是記憶體。內部儲存位於系統中很特殊的一個位置,如果你想將檔案儲存於內部儲存中,那麼檔案預設只能被你的應用訪問到,且一個應用所建立的所有檔案都在和應用包名相同的目錄下。也就是說應用創建於內部儲存的檔案,與這個應用是關聯起來的。當一個應用解除安裝之後,內部儲存中的這些檔案也被刪除。從技術上來講如果你在建立內部儲存檔案的時候將檔案屬性設定成可讀,其他app能夠訪問自己應用的資料,前提是他知道你這個應用的包名,如果一個檔案的屬性是私有(private),那麼即使知道包名其他應用也無法訪問。 內部儲存空間十分有限,因而顯得可貴,另外,它也是系統本身和系統應用程式主要的資料儲存所在地,一旦內部儲存空間耗盡,手機也就無法使用了。所以對於內部儲存空間,我們要儘量避免使用。Shared Preferences和SQLite資料庫都是儲存在內部儲存空間上的
getFilesDir()獲取你app的內部儲存空間,相當於你的應用在內部儲存上的根目錄。
2、外部儲存 External Storage
所有的安卓裝置都有外部儲存和內部儲存,這兩個名稱來源於安卓的早期裝置,那個時候的裝置內部儲存確實是固定的,而外部儲存確實是可以像U盤一樣移動的。但是在後來的裝置中,很多中高階機器都將自己的機身儲存擴充套件到了8G以上,他們將儲存在概念上分成了”內部internal” 和”外部external” 兩部分,但其實都在手機內部。所以不管安卓手機是否有可移動的sdcard,他們總是有外部儲存和內部儲存。最關鍵的是,我們都是通過相同的api來訪問可移動的sdcard或者手機自帶的儲存(外部儲存)。最重要的是,無論手機機身儲存多大,都會被API看做為外部的儲存,只有少部分空間被分為內部儲存
用法
核心用法如下,獲取所需要的path,注意建立資料夾時注意判斷是否存在和用try/catch包裹。
Log.i(TAG, "getCacheDirectory: "+ StorageUtils.getCacheDirectory(this));
Log.i(TAG, "getCacheDirectory true: "+ StorageUtils.getCacheDirectory(this,true));
Log.i(TAG, "getCacheDirectory false: "+ StorageUtils.getCacheDirectory (this,false));
Log.i(TAG, "getIndividualCacheDirectory:"+StorageUtils.getIndividualCacheDirectory(this));
Log.i(TAG, "getOwnCacheDirectory:"+StorageUtils.getOwnCacheDirectory(this,"/JayGoo"));
String path=StorageUtils.getCacheDirectory(this).toString();
File fileDir=new File(path);
if(!fileDir.exists()){
try {
fileDir.mkdirs();
}catch (Exception e){
e.printStackTrace();
}
}
執行結果:
08-18 17:08:41.333 25041-25041/? I/jinjie: getCacheDirectory: /storage/emulated/0/Android/data/com.example.google_acmer.asimplecachedemo/cache
08-18 17:08:41.343 25041-25041/? I/jinjie: getCacheDirectory true: /storage/emulated/0/Android/data/com.example.google_acmer.asimplecachedemo/cache
08-18 17:08:41.343 25041-25041/? I/jinjie: getCacheDirectory false: /data/user/0/com.example.google_acmer.asimplecachedemo/cache
08-18 17:08:41.353 25041-25041/? I/jinjie: getIndividualCacheDirectory:/storage/emulated/0/Android/data/com.example.google_acmer.asimplecachedemo/cache/uil-images
08-18 17:08:41.363 25041-25041/? I/jinjie: getOwnCacheDirectory:/storage/emulated/0/JayGoo
原始碼
package com.example.google_acmer.asimplecachedemo.Utils;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.util.Log;
import java.io.File;
import java.io.IOException;
import static android.os.Environment.MEDIA_MOUNTED;
/**
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
* @created : JayGoo
* @Description: Provides application storage paths
*
* Methods get storage path samples:
*
* getCacheDirectory: /storage/emulated/0/Android/data/com.example.google_acmer.asimplecachedemo/cache
* getCacheDirectory true: /storage/emulated/0/Android/data/com.example.google_acmer.asimplecachedemo/cache
* getCacheDirectory false: /data/user/0/com.example.google_acmer.asimplecachedemo/cache
* getIndividualCacheDirectory:/storage/emulated/0/Android/data/com.example.google_acmer.asimplecachedemo/cache/uil-images
* getOwnCacheDirectory:/storage/emulated/0/JayGoo
*/
public final class StorageUtils {
private static final String EXTERNAL_STORAGE_PERMISSION = "android.permission.WRITE_EXTERNAL_STORAGE";
private static final String INDIVIDUAL_DIR_NAME = "uil-images";
private static final String TAG = "StorageUtils";
private StorageUtils() {
}
/**
* Returns application cache directory. Cache directory will be created on SD card
* <i>("/Android/data/[app_package_name]/cache")</i> if card is mounted and app has appropriate permission. Else -
* Android defines cache directory on device's file system.
*
* @param context Application context
* @return Cache {@link File directory}.<br />
* <b>NOTE:</b> Can be null in some unpredictable cases (if SD card is unmounted and
* {@link android.content.Context#getCacheDir() Context.getCacheDir()} returns null).
*/
public static File getCacheDirectory(Context context) {
return getCacheDirectory(context, true);
}
/**
* Returns application cache directory. Cache directory will be created on SD card
* <i>("/Android/data/[app_package_name]/cache")</i> (if card is mounted and app has appropriate permission) or
* on device's file system depending incoming parameters.
*
* @param context Application context
* @param preferExternal Whether prefer external location for cache
* @return Cache {@link File directory}.<br />
* <b>NOTE:</b> Can be null in some unpredictable cases (if SD card is unmounted and
* {@link android.content.Context#getCacheDir() Context.getCacheDir()} returns null).
*/
public static File getCacheDirectory(Context context, boolean preferExternal) {
File appCacheDir = null;
String externalStorageState;
try {
externalStorageState = Environment.getExternalStorageState();
} catch (NullPointerException e) { // (sh)it happens (Issue #660)
externalStorageState = "";
}
if (preferExternal && MEDIA_MOUNTED.equals(externalStorageState) && hasExternalStoragePermission(context)) {
appCacheDir = getExternalCacheDir(context);
}
if (appCacheDir == null) {
appCacheDir = context.getCacheDir();
}
if (appCacheDir == null) {
String cacheDirPath = "/data/data/" + context.getPackageName() + "/cache/";
Log.d(TAG, "Can't define system cache directory! " + cacheDirPath + " will be used.");
appCacheDir = new File(cacheDirPath);
}
return appCacheDir;
}
/**
* Returns individual application cache directory (for only image caching from ImageLoader). Cache directory will be
* created on SD card <i>("/Android/data/[app_package_name]/cache/uil-images")</i> if card is mounted and app has
* appropriate permission. Else - Android defines cache directory on device's file system.
*
* @param context Application context
* @return Cache {@link File directory}
*/
public static File getIndividualCacheDirectory(Context context) {
File cacheDir = getCacheDirectory(context);
File individualCacheDir = new File(cacheDir, INDIVIDUAL_DIR_NAME);
if (!individualCacheDir.exists()) {
if (!individualCacheDir.mkdir()) {
individualCacheDir = cacheDir;
}
}
return individualCacheDir;
}
/**
* Returns specified application cache directory. Cache directory will be created on SD card by defined path if card
* is mounted and app has appropriate permission. Else - Android defines cache directory on device's file system.
*
* @param context Application context
* @param cacheDir Cache directory path (e.g.: "AppCacheDir", "AppDir/cache/images")
* @return Cache {@link File directory}
*/
public static File getOwnCacheDirectory(Context context, String cacheDir) {
File appCacheDir = null;
if (MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) && hasExternalStoragePermission(context)) {
appCacheDir = new File(Environment.getExternalStorageDirectory(), cacheDir);
}
if (appCacheDir == null || (!appCacheDir.exists() && !appCacheDir.mkdirs())) {
appCacheDir = context.getCacheDir();
}
return appCacheDir;
}
private static File getExternalCacheDir(Context context) {
File dataDir = new File(new File(Environment.getExternalStorageDirectory(), "Android"), "data");
File appCacheDir = new File(new File(dataDir, context.getPackageName()), "cache");
if (!appCacheDir.exists()) {
if (!appCacheDir.mkdirs()) {
Log.d(TAG, "Unable to create external cache directory");
return null;
}
try {
new File(appCacheDir, ".nomedia").createNewFile();
} catch (IOException e) {
Log.d(TAG, "Can't create \".nomedia\" file in application external cache directory");
}
}
return appCacheDir;
}
private static boolean hasExternalStoragePermission(Context context) {
int perm = context.checkCallingOrSelfPermission(EXTERNAL_STORAGE_PERMISSION);
return perm == PackageManager.PERMISSION_GRANTED;
}
}