資料與檔案儲存空間總覽
如果您自己的 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 外的另一選擇


