目錄
- Android 應用檔案存盤目錄
- 1.內部存盤空間中的應用私有目錄
- 2.外部存盤空間中的應用私有目錄
- 3.外部存盤空間中的公共目錄
- 將圖片存盤到應用私有目錄
- 讀取私有目錄下的圖片
- FileProvider將Uri傳遞給其他app
- 1.在AndroidManifest.xml 中宣告
- 2. 指定可分享的檔案路徑
- 3.將 file:// 轉為 content://
- 4.將簡單的資料發送給其他應用
- 5.從其他應用接收簡單的資料
- 參考文章
Android 應用檔案存盤目錄
1.內部存盤空間中的應用私有目錄
每安裝一個 App 系統都會在內部存盤空間的 data/data 目錄下以應用包名為名字自動創建與之對應的檔案夾,這個檔案夾用于持久化 App 中的 WebView 快取頁面資訊、SharedPreferences、SQLiteDatabase等應用相關資料,當用戶卸載 App 時,系統自動洗掉 data/data 目錄下對應包名的檔案夾及其內容,
Android SDK 提供 獲取并操作內部存盤空間中的應用私有目錄的方法如下:
- context.getFilesDir(): /data/user/0/packagename/files
- context.getCacheDir():/data/user/0/packagename/cache
- context.deleteFile():洗掉檔案
- context.fileList():遍歷當前目錄下所有子檔案夾
- Environment.getDataDirectory():/data
2.外部存盤空間中的應用私有目錄
考慮到普通用戶無法訪問應用的內部存盤空間,比如用戶想從應用里面保存一張圖片,那么這張圖片應該存盤在外部存盤空間,用戶才能訪問的到,外部存盤空間路徑為:/storage/emulated/0/Android/data/<包名>
默認情況下,系統并不會自動創建外部存盤空間的應用私有目錄,只有在應用需要的時候,開發人員通過 SDK 提供的 API 創建該目錄檔案夾和操作檔案夾內容,
當用戶卸載 App 時,系統也會自動洗掉外部存盤空間下的對應 App 私有目錄檔案夾及其內容,
Android SDK 中提供給開發人員直接操作外部存盤空間下的應用私有目錄的方法如下:
- context.getExternalFilesDir():/storage/emulated/0/Android/data/packagename/files
- context.getExternalCacheDir():/storage/emulated/0/Android/data/packagename/cache
- Environment.getExternalStorageDirectory():/storage/emulated/0
3.外部存盤空間中的公共目錄
外部存盤空間中的公共目錄用來存放當應用被卸載時,仍然可以保存在設備中的資訊,如:拍照類應用的圖片檔案,用戶是使用瀏覽器手動下載的檔案等,
外部存盤空間已經為用戶默認分類出一些公共目錄,開發人員可以通過 Environment 類提供的方法直接獲取相應目錄的絕對路徑,傳遞不同的 type 引數型別即可:
Environment.getExternalStoragePublicDirectory(String type);
Envinonment 類提供諸多 type 引數的常量,比如:
- DIRECTORY_MUSIC:/storage/emulated/0/Music
- DIRECTORY_MOVIES:/storage/emulated/0/Movies
- DIRECTORY_PICTURES:/storage/emulated/0/Pictures
- DIRECTORY_DOWNLOADS:/storage/emulated/0/Download
下面是一個本人自己寫的一個例子:
廢話不多說 直接上代碼:
將圖片存盤到應用私有目錄
public void btn(View v){
String filename = "123456.jpg";
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.second);
img = findViewById(R.id.sharted);
FileOutputStream outputStream;
try {
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, outputStream);
outputStream.flush();
outputStream.close();
} catch (Exception e) {
Log.i("sadjlk","@"+e.toString());
e.printStackTrace();
}
}
openFileOutput()默認目錄是context.getFilesDir(): /data/user/0/packagename/files
宣告:本人使用的是Andorid 7.0的虛擬機 請看程式運行效果圖

這樣我們就成功將一個存在我們專案本地的一個圖片轉存到我們當前app的私有目錄下了,只能我們的應用可以訪問這個圖片 (后期看個人需求選擇合適的存放位置)
讀取私有目錄下的圖片
這里我寫了三種方式都可以獲取到應用私有目錄下的圖片
第一種方式:
public void query(View view){
querySignImageBox(getFilesDir(),"123456.jpg");
}
//先指定哪個檔案夾,再指定名稱
public Bitmap querySignImageBox(File environmentType, String fileName) {
if (TextUtils.isEmpty(fileName)) return null;
Bitmap bitmap = null;
try {
if (environmentType != null && environmentType.exists() && environmentType.isDirectory()) {
File[] files = environmentType.listFiles();
if (files != null) {
//遍歷當前目錄下的所有
for (File file : files) {
Log.i("paonbul","@"+file.getPath());
bitmap = BitmapFactory.decodeFile(file.getPath());
img.setImageBitmap(bitmap);
}
}
}
} catch (Exception e) {
}
return bitmap;
}
列印出來的file.getPath()的路徑如下:/data/user/0/com.example.materialdesigndemo/files/123456.jpg
第二種方法:
String path = getFilesDir().getPath()+"/"+"123456.jpg";
Bitmap a = BitmapFactory.decodeFile(path);
img.setImageBitmap(a);
這一種就比較簡單了,直接拿我們已知的全路徑就可以了和第一種大差不差
第三種方法:
try {
InputStream fileInputStream = openFileInput("123456.jpg");
Log.i("wochouch","@"+fileInputStream);
Bitmap bitmap = BitmapFactory.decodeStream(fileInputStream);
img.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
這里直接使用openFileInput(String name) 的方式就直接拿到了
三種的效果圖一樣 如下:

當然到這里還沒有完,如何將我們的私有目錄下的檔案提供給第三方app才是我們今天的硬菜
FileProvider將Uri傳遞給其他app
1.在AndroidManifest.xml 中宣告
在Manifest.xml的application標簽中
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="packagename.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
- name :配置當前 FileProvider 的實作類
- authorities:配置一個 FileProvider 的名字,它在當前系統內需要是唯一值,
- exported:表示該 FileProvider 是否需要公開出去,傳 false 表示不公開,
- granUriPermissions:是否允許授權檔案的臨時訪問權限,傳 true 表示需要 ,
2. 指定可分享的檔案路徑
file_paths.xml內容如下:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="aliluya" path="." />
</paths>
這里看一眼Google給出的提示:

通俗來講這里的name 和 path的意思是什么呢?
- name:是一個檔案別名,對外可見路徑的一部分,隱藏真實檔案目錄 ;
- path:是一個相對目錄,相對于當前標簽的根目錄,path值為點符號(".")時,該根目錄下所有的檔案夾都可以臨時授權訪問
例子:
<!-- Context.getCacheDir() + "/path/" -->
<cache-path
name="my_cache"
path="mazaiting/"/>
這個的意思就是共享 Context.getCacheDir()目錄下的mazaiting目錄下的檔案
- root-path:表示根目錄,“/”,
- files-path:表示 content.getFileDir() 獲取到的目錄
- cache-path:表示 content.getCacheDir() 獲取到的目錄
- external-path:表示Environment.getExternalStorageDirectory() 指向的目錄
- external-files-path:表示 ContextCompat.getExternalFilesDirs() 獲取到的目錄
- external-cache-path:表示 ContextCompat.getExternalCacheDirs() 獲取到的目錄
3.將 file:// 轉為 content://
File imagePath = new File(getFilesDir(), "123456.jpg");
Uri contentUri = getUriForFile(this, "com.example.materialdesigndemo.fileProvider", imagePath);
主要通過getUriForFile()將file檔案轉為uri
4.將簡單的資料發送給其他應用
File imagePath = new File(getFilesDir(), "123456.jpg");
Uri contentUri = getUriForFile(this, "com.example.materialdesigndemo.fileProvider", imagePath);
Log.i("wjdsajdsa","@"+contentUri);
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
shareIntent.setType("image/jpg");
startActivity(Intent.createChooser(shareIntent, "請選擇您的心動女生:"));
5.從其他應用接收簡單的資料
這里新建一個project 然后再Manifest中進行配置
<activity android:name=".receive.ReceiverActivity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
ReceiveActivity中的代碼如下:
public class ReceiverActivity extends AppCompatActivity {
private ImageView img;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_receiver);
img = findViewById(R.id.img);
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
if(type.startsWith("image/")){
handleSendImage(intent);
}
}
}
private void handleSendImage(Intent intent) {
Uri imageUri = intent.getParcelableExtra(Intent.EXTRA_STREAM);
if (imageUri != null) {
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
Log.i("chjocucu","@"+bitmap);
img.setImageBitmap(bitmap);
} catch (IOException e) {
Log.i("chjocucuee","@"+e.toString());
e.printStackTrace();
}
}
}
}
來看最終效果:

歐克,最終結果就是這個樣子
參考文章
參考文章:
鏈接: Android FileProvider 踩坑指北
這里作者對于每一個詳細的知識點的描述很仔細 推薦大家查看喲
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/76440.html
標籤:其他
