讀寫Android中assets目錄下的文件的方法詳解
Android資源文件大致可以分為兩種:
第一種是res目錄下存放的可編譯的資源文件:
這種資源文件系統(tǒng)會在R.java里面自動生成該資源文件的ID,所以訪問這種資源文件比較簡單,通過R.XXX.ID即可;
第二種是assets目錄下存放的原生資源文件:
因為系統(tǒng)在編譯的時候不會編譯assets下的資源文件,所以我們不能通過R.XXX.ID的方式訪問它們。那我么能不能通過該資源的絕對路徑去訪問它們呢?因為apk安裝之后會放在/data/app/**.apk目錄下,以apk形式存在,asset/res和被綁定在apk里,并不會解壓到/data/data/YourApp目錄下去,所以我們無法直接獲取到assets的絕對路徑,因為它們根本就沒有。
還好Android系統(tǒng)為我們提供了一個AssetManager工具類。
查看官方API可知,AssetManager提供對應用程序的原始資源文件進行訪問;這個類提供了一個低級別的API,它允許你以簡單的字節(jié)流的形式打開和讀取和應用程序綁定在一起的原始資源文件。
Android除了提供/res目錄存放資源文件外,在/assets目錄也會提供存放資源文件,在/assets目錄下面不會在R.java里面自動生成ID,所以讀取assets目錄下面的資源文件需要提供路徑,我們可以通過AssetManager類來訪問這些文件。
作者需要實現(xiàn)從 A.apk( 資源apk ,把所有的資源如:so、apk、可執(zhí)行文件等放到assets目錄下面,apk沒有實現(xiàn)邏輯代碼)拷貝資源到指定目錄下,所以作者創(chuàng)建了一個實現(xiàn)資源拷貝邏輯的 B.apk( 一個Service,也可用Activity實現(xiàn)),由于拷貝路徑一般情況下是不可訪問或者創(chuàng)建的(每個apk安裝之后只能訪問/data/data/自己包名/下面的私有空間),作者需要這個apk能夠獲取系統(tǒng)權(quán)限(System權(quán)限),則必須在AndroidManifest.xml聲明shareduserid,具體如何操作下一節(jié)進行記錄。
一、AssetManager讀取文件常用的幾個API
1.文件讀取方式
AssetManager.open(String filename),返回的是一個InputSteam類型的字節(jié)流,這里的filename必須是文件,而不能是文件夾,AssetManager打開資源文件的open方法是一個重載方法,可以添加一個打開方式的int參數(shù),根據(jù)參數(shù)不同可做相應操作。具體請看官方文檔http://web.mit.edu/clio/MacData/afs/sipb/project/android/docs/reference/android/content/res/AssetManager.html
2.資源文件是可以存在文件夾以及子目錄
public final String[]list(String path),返回當前目錄下面的所有文件以及子目錄的名稱??梢酝ㄟ^遞歸遍歷整個文件目錄,實現(xiàn)所有資源文件的訪問。String[] Array of strings, one for each asset. These file names are relative to 'path'. You can open the file by concatenating 'path' and a name in the returned string (via File) and passing that to open().
二、相關(guān)實現(xiàn)代碼
資源APK(A.apk)

具體實現(xiàn)代碼片段,由于使用系統(tǒng)權(quán)限,生成的路徑可以自己改一下B.apk
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
ctxDealFile = this.createPackageContext("com.zlc.ipanel",
Context.CONTEXT_IGNORE_SECURITY);
} catch (NameNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
btn3.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
try {
String uiFileName = "ipanelJoin";
deepFile(ctxDealFile, uiFileName);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
textView.setText("file is wrong");
}
}
});
//
}
public void deepFile(Context ctxDealFile, String path) {
try {
String str[] = ctxDealFile.getAssets().list(path);
if (str.length > 0) {//如果是目錄
File file = new File("/data/" + path);
file.mkdirs();
for (String string : str) {
path = path + "/" + string;
System.out.println("zhoulc:\t" + path);
// textView.setText(textView.getText()+"\t"+path+"\t");
deepFile(ctxDealFile, path);
path = path.substring(0, path.lastIndexOf('/'));
}
} else {//如果是文件
InputStream is = ctxDealFile.getAssets().open(path);
FileOutputStream fos = new FileOutputStream(new File("/data/"
+ path));
byte[] buffer = new byte[1024];
int count = 0;
while (true) {
count++;
int len = is.read(buffer);
if (len == -1) {
break;
}
fos.write(buffer, 0, len);
}
is.close();
fos.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
相關(guān)文章
Android之RecyclerView實現(xiàn)時光軸效果示例
本篇文章主要介紹了Android之RecyclerView實現(xiàn)時光軸效果,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02
Android自定義對話框Dialog的簡單實現(xiàn)
這篇文章主要為大家詳細介紹了Android自定義對話框Dialog的簡單實現(xiàn),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08
Flutter 中的PageStorage小部件使用及最佳實踐
在Flutter中,PageStorage小部件提供了一種方法來保存和恢復頁面間的信息,這對于具有多個頁面且需要在這些頁面之間共享狀態(tài)的應用程序非常有用,本文將詳細介紹PageStorage的用途、如何使用它以及一些最佳實踐,感興趣的朋友跟隨小編一起看看吧2024-05-05
Android中的sqlite查詢數(shù)據(jù)時去掉重復值的方法實例
今天小編就為大家分享一篇關(guān)于Android中的sqlite查詢數(shù)據(jù)時去掉重復值的方法實例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-01-01

