資料與檔案儲存空間總覽
如果您自己的 app 內有不希望與其他 app 共用的資料檔案,又不要這些私用檔案被編譯進二進位 apk,可將檔案存放在 assets(assets 的用途及用法請另行拜大神)。
但存放在 assets 的檔案是唯讀的,若您需要這些檔案可更新修改,又不希望分享給其他 app,或是不想公開,則需將檔案複製到裝置的內部儲存空間(從内部儲存空間訪問不需要任何權限)。
下面程式搭配了 AsyncTask 使用。
public class MainActivity extends Activity
{
private static final String TAG = "MainActivity";
ProgressDialog progdlg;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 檢查內部儲存空間是否已存在該檔案
File file = getBaseContext().getFileStreamPath("test.zip");
if(file.exists())
Toast.makeText(this, "檔案已存在", Toast.LENGTH_LONG).show();
else
{
// 檔案不存在, 執行 AsyncTask 將檔案自 assets 複製到內部儲存空間
// Toast.makeText(this, "no file", Toast.LENGTH_LONG).show();
new CopyFileTask().execute();
}
//
}
private class CopyFileTask extends AsyncTask<Void, Void, Void>
{
protected void onPreExecute ()
{
progdlg = ProgressDialog.show(MainActivity.this, "複製檔案練習", "檔案複製中...", true, true);
}
@Override
protected Void doInBackground(Void...params)
{
Log.d(TAG, "CopyFileTask begin...");
AssetManager manager = getAssets();
String FILENAME = "test.zip";
try
{
FileOutputStream out = openFileOutput("test.zip", Context.MODE_PRIVATE);
InputStream in = getAssets().open("test.zip");
byte[] buffer = new byte[1024];
int read = in.read(buffer);
while (read != -1)
{
out.write(buffer, 0, read);
read = in.read(buffer);
}
out.close();
in.close();
Log.d(TAG, "CopyFileTask end...");
}
catch(IOException e)
{
e.printStackTrace();
}
return null;
}
protected void onProgressUpdate(Void... args)
{}
protected void onPostExecute(Void args)
{
progdlg.dismiss();
}
}
}
檔案在裝置內的位置為
/data/data/完整 package name/files/
開啟 device monitor 看看模擬器
改接實際的裝置,發現是看不到的,第一層的 /data 就無法往下展開。
在 Acer B1-760HD(Android 5.0.1, API21),執行的結果,複製 1.01 MB (1,067,006 位元組) 的檔案雖然沒花多少時間,但 Google 仍強烈建議 檔案存取 之類的動作不要在主執行緒進行。
相關筆記 ----
AsyncTask - Thread 外的另一選擇


