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

具體實(shí)現(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();
}
}
- Android中文件讀寫(xiě)(輸入流和輸出流)操作小結(jié)
- Android手機(jī)內(nèi)存中文件的讀寫(xiě)方法小結(jié)
- Android應(yīng)用程序中讀寫(xiě)txt文本文件的基本方法講解
- Android編程之文件的讀寫(xiě)實(shí)例詳解
- Android 讀寫(xiě)文件方法匯總
- android開(kāi)發(fā)之Json文件的讀寫(xiě)的示例代碼
- Android如何讀寫(xiě)CSV文件方法示例
- android 開(kāi)發(fā) 文件讀寫(xiě)應(yīng)用案例分析
- Android讀寫(xiě)文件工具類(lèi)詳解
- Android日志文件的讀寫(xiě)工具類(lèi)
相關(guān)文章
Android之RecyclerView實(shí)現(xiàn)時(shí)光軸效果示例
本篇文章主要介紹了Android之RecyclerView實(shí)現(xiàn)時(shí)光軸效果,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02
Android自定義對(duì)話框Dialog的簡(jiǎn)單實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了Android自定義對(duì)話框Dialog的簡(jiǎn)單實(shí)現(xiàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08
Android 文件夾顯示紅色嘆號(hào)的解決方法(必看)
下面小編就為大家?guī)?lái)一篇Android 文件夾顯示紅色嘆號(hào)的解決方法(必看)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04
Flutter 中的PageStorage小部件使用及最佳實(shí)踐
在Flutter中,PageStorage小部件提供了一種方法來(lái)保存和恢復(fù)頁(yè)面間的信息,這對(duì)于具有多個(gè)頁(yè)面且需要在這些頁(yè)面之間共享狀態(tài)的應(yīng)用程序非常有用,本文將詳細(xì)介紹PageStorage的用途、如何使用它以及一些最佳實(shí)踐,感興趣的朋友跟隨小編一起看看吧2024-05-05
Android 游戲開(kāi)發(fā)中繪制游戲觸摸軌跡的曲線圖
本文主要介紹 Android 繪制游戲觸摸軌跡的曲線圖的簡(jiǎn)單示例,這里詳細(xì)說(shuō)明使用方法,并附示例代碼,有需要的小伙伴可以參考下2016-08-08
Android入門(mén)之日歷選擇與時(shí)間選擇組件的使用
這篇文章主要為大家詳細(xì)介紹了Android中TimePicker時(shí)間選擇與DatePicker日期選擇組件的使用方法,文中的示例代碼講解詳細(xì),需要的朋友可以參考下2022-11-11
Android使用lottie加載json動(dòng)畫(huà)的示例代碼
本篇文章主要介紹了Android使用lottie加載json動(dòng)畫(huà)的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
Android學(xué)習(xí)之AppWidget筆記分享
這篇文章主要為大家詳細(xì)介紹了Android學(xué)習(xí)筆記之AppWidget的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-08-08
Android中Handler與Message的簡(jiǎn)單實(shí)例
這篇文章主要介紹了Android中Handler與Message的簡(jiǎn)單實(shí)例的相關(guān)資料,這里提供實(shí)例來(lái)說(shuō)明線程Handler與message 的結(jié)合使用,需要的朋友可以參考下2017-08-08
Android中的sqlite查詢(xún)數(shù)據(jù)時(shí)去掉重復(fù)值的方法實(shí)例
今天小編就為大家分享一篇關(guān)于Android中的sqlite查詢(xún)數(shù)據(jù)時(shí)去掉重復(fù)值的方法實(shí)例,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-01-01

