版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、安卓的資源編譯過(guò)程一APK的結(jié)構(gòu)以及生成APK是Android Package的縮寫(xiě),即Android application package文件或Android安裝包。每個(gè)要安裝到Android平臺(tái)的應(yīng)用都要被編譯打包為一個(gè)單獨(dú)的文件,擴(kuò)展名為 .apk。APK文件是用編譯器編譯生成的文件包,其中包含了應(yīng)用的二進(jìn)制代碼、資源、配置文件等。通過(guò)將APK文件直接傳到Android手機(jī)中執(zhí)行即可安裝。APK文件其實(shí)就是zip格式,但其擴(kuò)展名被改為apk。在這里我們?yōu)榱嗽敿?xì)講述Android應(yīng)用程序我們將創(chuàng)建一個(gè)永恒的話題, 它就是HelloWorl
2、d程序,在這里我們創(chuàng)建的Android的HelloWorld程序的目錄結(jié)構(gòu)如下所示:一個(gè)典型的APK文件通常由下列內(nèi)容組成: AndroidManifest.xml 程序全局配置文件 classes.dex Dalvik字節(jié)碼
3、;resources.arsc 資源索引表, 解壓縮resources.ap_就能看到 res 該目錄存放資源文件(圖片,文本,xml布局)
4、 assets 該目錄可以存放一些配置文件 src
5、160; java源碼文件 libs 存放應(yīng)用程序所依賴的庫(kù) gen
6、 編譯器根據(jù)資源文件生成的java文件 bin 由編譯器生成的apk文件和各種依賴的資源 META-INF
7、; 該目錄下存放的是簽名信息首先來(lái)看一下使用Java語(yǔ)言編寫(xiě)的Android應(yīng)用程序從源碼到安裝包的整個(gè)過(guò)程,示意圖如下,其中包含編譯、鏈接和簽名等:(1). 使用aapt工具將資源文件生成R.java文件, resources.arsc和打包資源文件(2). 使用aidl工具將.aidl文件編譯成.java文件(3). 使用javac工具將.java文件編譯成.class文件(4). 使用dx腳本將眾多.class文件轉(zhuǎn)換成一個(gè).dex文件(5). 使
8、用apkbuilder腳本將資源文件和.dex文件生成未簽名的apk安裝文件(6). 使用jdk中的jarsigner對(duì)apk安裝文件進(jìn)行簽名上述工具都保存在android-sdk-linux中的tools/和platform-tools文件夾下面.范例:src/com.example.helloworldactivity:package com.example.helloworldactivity;import android.app.Activity;import android.os.Bundle;import android.view.
9、View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;public class MainActivity extends Activity private final static String TAG = "MainActivity"
10、; private TextView mTextView = null; Override protected void onCreate(Bundle savedInstanceState) super.onCreate(savedInstanceState);
11、; setContentView(R.layout.activity_main); mTextView = (TextView)findViewById(R.id.text_view); Button showButton = (Button)findViewById(R.id.button
12、); showButton.setOnClickListener(new OnClickListener() public void onClick(View v)
13、160; mTextView.setText(R.string.hello_world); ); res/layout/activity_main.xml:<LinearLayout xmlns:android="
14、60; xmlns:tools=" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" > <Button
15、160; android:id="+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:te
16、xt="string/show" /> <TextView android:id="+id/text_view" android:layout_width="match_parent" an
17、droid:layout_height="wrap_content" android:text="" /></LinearLayout>res/values/strings.xml:<?xml version="1.0" encoding="utf-8"?><resources> <string
18、60;name="app_name">HelloWorldActivity</string> <string name="action_settings">Settings</string> <string name="show">Show</string> <string name="h
19、ello_world">Hello world!</string></resources>AndroidManifest.xml:<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android=" package="com.example.helloworldactivity"
20、android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="
21、17" /> <application android:allowBackup="true" android:icon="drawable/ic_launcher" android:label=&qu
22、ot;string/app_name" android:theme="style/AppTheme" > <activity android:name="com.example.helloworldactiv
23、ity.MainActivity" android:label="string/app_name" > <intent-filter>
24、160; <action android:name="ent.action.MAIN" /> <category android:name="ent.category.LAUNCHER" />
25、 </intent-filter> </activity> </application></manifest>我們前面創(chuàng)建的HelloWorldActivity應(yīng)用程序資源目錄結(jié)構(gòu)如下所示:project 接下來(lái),我們?cè)贖elloWor
26、ldActivity工程目錄下可以使用aapt命令:aapt p -f -m -J mygen/ -S res/ -I /tool/android-sdk-linux/platforms/android-17/android.jar -A assets/ -M AndroidManifest.xml -F helloworldresources.apk在mygen目錄下生成一個(gè)資源ID文件R.java和在當(dāng)前目錄下生成一個(gè)名為hell
27、oworldresources.apk的資源包,解壓縮里面內(nèi)容如下所示: 被打包的APK資源文件中包含有:資源索引表文件resources.arsc, AndroidManifest.xml二進(jìn)制文件和res目錄下的應(yīng)用程序圖片資源及l(fā)ayout目錄下的二進(jìn)制activity_main.xml文件, res目錄下信息如下所示: 注意:res/values目錄下的字符串信息被編譯進(jìn)了resources.arsc資源索引文件中,而在R.java文件中僅僅保存了資源ID信息. R.java信息如下所示:package
28、;com.example.helloworldactivity;public final class R public static final class attr public static final class dimen
29、 public static final int activity_horizontal_margin=0x7f040000; public static final int activity_vertical_margin=0x7f040001; public static final c
30、lass drawable public static final int ic_launcher=0x7f020000; public static final class id public
31、;static final int button=0x7f070000; public static final int text_view=0x7f070001; public static final class layout
32、 public static final int activity_main=0x7f030000; public static final class string public static final int action_settings
33、=0x7f050001; public static final int app_name=0x7f050000; public static final int hello_world=0x7f050003; public s
34、tatic final int show=0x7f050002; public static final class style public static final int AppBaseT
35、heme=0x7f060000; public static final int AppTheme=0x7f060001; 下面我們根據(jù)分析appt的源碼詳細(xì)講述命令:aapt p -f -m -J mygen/ -S res/ -
36、I /tool/android-sdk-linux/platforms/android-17/android.jar -A assets/ -M AndroidManifest.xml -F helloworldresources.apk是如何將上述應(yīng)用程序資源編譯生成一個(gè)R.java文件, 資源索引表文件resources.arsc, AndroidManifest.xml二進(jìn)制文件和res目錄下的應(yīng)用程序圖片資源及l(fā)ayout目錄下的二進(jìn)制activity_main.xml文件的.appt入口函數(shù)ma
37、in具體實(shí)現(xiàn)如下所示:路徑:frameworks/base/tools/aapt/Main.cppint main(int argc, char* const argv) char *prog = argv0; Bundle bundle; / 定義一個(gè)Bundle類存儲(chǔ)appt命令的各種編譯選項(xiàng) bool
38、0;wantUsage = false; int result = 1; / pessimistically assume an error. int tolerance = 0;/* default to compression * 設(shè)置默認(rèn)的壓縮標(biāo)準(zhǔn)*/
39、; bundle.setCompressionMethod(ZipEntry:kCompressDeflated); if (argc < 2) wantUsage = true; goto bail;
40、160; if (argv10 = 'v') bundle.setCommand(kCommandVersion); . else if (argv10 = 'p') / 命令行選項(xiàng)p表示我們要打包資源
41、0; bundle.setCommand(kCommandPackage);. argc -= 2; argv += 2; /* * Pull out flags. We support "-fv" and "-f
42、60;-v". * 一下while循環(huán)將各種aapt編譯選項(xiàng)提取出來(lái)存放到bundle中 */ while (argc && argv00 = '-') /* flag(s) found */
43、0; const char* cp = argv0 +1; while (*cp != '0') switch (*cp)
44、60; . case 'f': / 如果編譯出來(lái)的文件已經(jīng)存在,強(qiáng)制覆蓋 bundle.setForce(true); /
45、0;bundle.mForce(bool) break; . case 'm':
46、0;/ 使生成的包的目錄存放在-J參數(shù)指定的目錄 bundle.setMakePackageDirs(true); / bundle.mMakePackageDirs(bool) break
47、; . case 'A': / assert文件夾路徑 argc-;
48、 argv+; if (!argc)
49、60; fprintf(stderr, "ERROR: No argument supplied for '-A' optionn"); wantUsage = true;
50、60; goto bail;
51、 convertPath(argv0); / 裝換為指定OS的路徑 bundle.setAssetSourceDir(argv0); / mAssetSourceDir(const char*)
52、 break; . case 'I': / 某個(gè)版本平臺(tái)的android.jar的路徑
53、60; argc-; argv+; if (!argc)
54、 fprintf(stderr, "ERROR: No argument supplied for '-I' optionn");
55、60; wantUsage = true; goto bail;
56、60; convertPath(argv0);/ mPackageIncludes.add(file); android:Vector<const char*> bundle.addPack
57、ageInclude(argv0); break; case 'F': / 具體指定APK文件的輸出 &
58、#160; argc-; argv+; if (!argc)
59、0; fprintf(stderr, "ERROR: No argument supplied for '-F' optionn"); &
60、#160; wantUsage = true; goto bail; &
61、#160; convertPath(argv0);/ mOutputAPKFile(const char*) bundle.setOutputAPKFile(argv0);
62、160; break; case 'J': / 指定生成的R.java 的輸出目錄
63、; argc-; argv+; if (!argc)
64、160; fprintf(stderr, "ERROR: No argument supplied for '-J' optionn"); wantUsage
65、160;= true; goto bail;
66、; convertPath(argv0); bundle.setRClassDir(argv0); / mRClassDir(const char*)
67、160; break; case 'M': / 指定AndroidManifest.xml文件路徑 argc-;
68、160; argv+; if (!argc)
69、; fprintf(stderr, "ERROR: No argument supplied for '-M' optionn"); wantUsage = true;
70、; goto bail; co
71、nvertPath(argv0);/ mAndroidMainifestFile(const char*) bundle.setAndroidManifestFile(argv0); br
72、eak; . case 'S': / res文件夾路徑 argc-;
73、 argv+; if (!argc)
74、60; fprintf(stderr, "ERROR: No argument supplied for '-S' optionn"); wantUsage = tr
75、ue; goto bail;
76、 convertPath(argv0);/ android:Vector<const char*> mResourceSourceDirs;/ mResourceSourceDirs.insertAt(dir,0); bundle.addResourceSourceDir(argv0);
77、 break; . default:
78、60; fprintf(stderr, "ERROR: Unknown flag '-%c'n", *cp); wantUsage = true;
79、160; goto bail; cp+; &
80、#160; argc-; argv+; /* * We're past the flags. The rest all goes straight in.
81、;* 設(shè)置Bundle的成員變量mArgv和mArgc分別為argv, argc */ bundle.setFileSpec(argv, argc); /* 通過(guò)handleCommand函數(shù)來(lái)處理指定命令 */ result = handleCommand(&bundle);bail: if (wantUsage)
82、 usage(); result = 2; /printf("-> returning %dn", result); return result;處理完aapt的編譯選項(xiàng)之后
83、,接著調(diào)用handleCommand函數(shù)來(lái)處理對(duì)應(yīng)的功能:路徑:frameworks/base/tools/aapt/Main.cppint handleCommand(Bundle* bundle). switch (bundle->getCommand() . case kCommandPackage: return doPackage(bundle);.
84、;default: fprintf(stderr, "%s: requested command not yet supportedn", gProgName); return 1; 最終打包APK的工作由函數(shù)doPackage完成,而打包一個(gè)應(yīng)用程序資源的過(guò)程非常
85、復(fù)雜,我們分如下模塊一一講解:一. 收錄一個(gè)應(yīng)用程序所有資源文件路徑:frameworks/base/tools/aapt/Command.cpp/* * Package up an asset directory and associated application files. * 打包應(yīng)用程序中的資源文件 */int doPackage(Bundle* bundle) const
86、60;char* outputAPKFile; int retVal = 1; status_t err; sp<AaptAssets> assets; int N; FILE* fp; String8 dependenc
87、yFile;./ 檢查aapt打包時(shí)的參數(shù)是否都存在 N = bundle->getFileSpecCount();if (N < 1 && bundle->getResourceSourceDirs().size() = 0 && bundle->getJarFiles().size() = 0
88、 && bundle->getAndroidManifestFile() = NULL && bundle->getAssetSourceDir() = NULL) fprintf(stderr, "ERROR: no input filesn");
89、 goto bail; / 得到最終將資源打包輸出到的APK名稱outputAPKFile = bundle->getOutputAPKFile();/ Make sure the filenames provided exist and are of the app
90、ropriate type./ 檢查該文件是否存在不存在則創(chuàng)建,并確定其實(shí)常規(guī)文件 if (outputAPKFile) FileType type; type = getFileType(outputAPKFile); &
91、#160; if (type != kFileTypeNonexistent && type != kFileTypeRegular) fprintf(stderr,
92、160;"ERROR: output file '%s' exists but is not regular filen", outputAPKFile);
93、0; goto bail; / Load the assets./ 創(chuàng)建一個(gè)AaptAssets對(duì)象 assets = new AaptAssets(); ./* 1.調(diào)用AaptAssets類的成員函數(shù)slurpFromArgs將AndroidManifest.x
94、ml文件,* 目錄assets和res下的資源目錄和資源文件收錄起來(lái)保存到AaptAssets中的* 成員變量中 */ err = assets->slurpFromArgs(bundle); if (err < 0) goto bail;
95、 .AaptAssets的slurpFromArgs函數(shù)的具體實(shí)現(xiàn)如下所示:路徑:frameworks/base/tools/aapt/AaptAssets.cppssize_t AaptAssets:slurpFromArgs(Bundle* bundle) int count; int totalCount = 0;FileType type;/ 獲取res目錄的路徑
96、0; const Vector<const char *>& resDirs = bundle->getResourceSourceDirs(); const size_t dirCount =resDirs.size(); sp<AaptAssets> current = this;/ 獲取bundle內(nèi)所保存的a
97、apt的命令選項(xiàng)個(gè)數(shù),即要完成的功能個(gè)數(shù) const int N = bundle->getFileSpecCount(); /* * If a package manifest was specified, include that first. *
98、160;如果bundle中指定了AndroidManifest.xml文件,則首先包含它 */ if (bundle->getAndroidManifestFile() != NULL) / place at root of zip. String8
99、0;srcFile(bundle->getAndroidManifestFile();/* 每向AaptAssets的對(duì)象中添加一個(gè)資源文件或者一個(gè)資源目錄都要新建一個(gè)* 類型AaptGroupEntry的空對(duì)象并將其添加到一個(gè)類型為SortedVector的* AaptAssets的成員變量mGroupEntries中, 在這里調(diào)用addFile函數(shù)是* 將AndroidManifest.xml文件添加到成員變量mFiles中去.*/ addF
100、ile(srcFile.getPathLeaf(), AaptGroupEntry(), srcFile.getPathDir(), NULL, String8();/* 每添加一個(gè)資源就加1統(tǒng)計(jì)一次 */ totalCount+;
101、; /* * If a directory of custom assets was supplied, slurp 'em up. * 判斷是否指定了assets文件夾,如果指定則解析它 */ if (bundle->get
102、AssetSourceDir() const char* assetDir = bundle->getAssetSourceDir(); / 獲取目錄名稱 FileType type = getFileType(assetDir); / 獲取目錄類型
103、; if (type = kFileTypeNonexistent) fprintf(stderr, "ERROR: asset directory '%s' does not existn", assetDir); &
104、#160; return UNKNOWN_ERROR; if (type != kFileTypeDirectory) &
105、#160; fprintf(stderr, "ERROR: '%s' is not a directoryn", assetDir); return UNKNOWN_ERROR;
106、; String8 assetRoot(assetDir);/* 創(chuàng)建一個(gè)名為”assets”的AaptDir對(duì)象 */ sp<AaptDir> assetAaptDir = makeDir(String8(kAssetDir); AaptGroupEntry group;/* 調(diào)用A
107、aptDir的成員函數(shù)slurpFullTree收錄目錄“assets”下的資源文件,* 并返回資源文件個(gè)數(shù) */ count = assetAaptDir->slurpFullTree(bundle, assetRoot, group,
108、; String8(), mFullAssetPaths); if (count < 0)
109、 totalCount = count; goto bail; if (count > 0)
110、160; mGroupEntries.add(group); /* 統(tǒng)計(jì)資源文件總個(gè)數(shù) */ totalCount += count;
111、if (bundle->getVerbose() printf("Found %d custom asset file%s in %sn",
112、60;count, (count=1) ? "" : "s", assetDir); /* * If a directory of resource-specific assets was supplied, slurp 'em
113、up. * 收錄指定的res資源目錄下的資源文件 */ for (size_t i=0; i<dirCount; i+) const char *res = resDirsi; if
114、0;(res) type = getFileType(res); / 獲取文件類型 if (type = kFileTypeNonexistent) &
115、#160; fprintf(stderr, "ERROR: resource directory '%s' does not existn", res); return
116、0;UNKNOWN_ERROR; if (type = kFileTypeDirectory) / 如果指定了多個(gè)res資源目錄文件, 則為其創(chuàng)建多個(gè)AaptAssets/ 類來(lái)分別收錄這些目錄中的信息,并將其設(shè)置賦值給當(dāng)前/ Aap
117、tAssets對(duì)象的成員變量mOverlay if (i>0) sp<AaptAssets> nextOver
118、lay = new AaptAssets(); current->setOverlay(nextOverlay);
119、0; current = nextOverlay; current->setFullResPaths(mFullResPaths); &
120、#160;/ 調(diào)用成員函數(shù)slurpResourceTree來(lái)收錄res目錄下的資源文件 count = current->slurpResourceTree(bundle, String8(res);
121、60; if (count < 0) totalCount = count;
122、160; goto bail; totalCount += count; / 統(tǒng)計(jì)資源文件個(gè)數(shù)
123、160; else fprintf(stderr, "ERROR: '%s' is not
124、160;a directoryn", res); return UNKNOWN_ERROR; &
125、#160; /* * Now do any additional raw files. * 接著收錄剩余的指定的資源文件 */ for (int arg=0; arg<N;
126、0;arg+) const char* assetDir = bundle->getFileSpecEntry(arg); FileType type = getFileType(assetDir); if (type&
127、#160;= kFileTypeNonexistent) fprintf(stderr, "ERROR: input directory '%s' does not existn", assetDir);
128、0; return UNKNOWN_ERROR; if (type != kFileTypeDirectory) fprintf(stderr, "ERROR: &
129、#39;%s' is not a directoryn", assetDir); return UNKNOWN_ERROR; String8 assetRoot(assetDir)
130、; if (bundle->getVerbose() printf("Processing raw dir '%s'n", (const char*) assetDir);
131、0; /* * Do a recursive traversal of subdir tree. We don't make any * guarantees about ordering, so
132、we're okay with an inorder search * using whatever order the OS happens to hand back to us. */
133、0; count = slurpFullTree(bundle, assetRoot, AaptGroupEntry(), String8(), mFullAssetPaths); if (count < 0)
134、; /* failure; report error and remove archive */ totalCount = count; goto bail;
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度法人代表臨時(shí)任職及解任合同
- 2025年度車輛借出免責(zé)及保險(xiǎn)責(zé)任合同
- 2025年度快遞驛站經(jīng)營(yíng)權(quán)轉(zhuǎn)讓合同模板
- 二零二五年度外國(guó)留學(xué)生實(shí)習(xí)項(xiàng)目聘用及支持合同
- 2025年房屋檢測(cè)評(píng)估合同樣本
- 2025年抵押權(quán)義務(wù)債權(quán)借款合同
- 2020-2025年中國(guó)水地源熱泵行業(yè)發(fā)展趨勢(shì)預(yù)測(cè)及投資戰(zhàn)略咨詢報(bào)告
- 2024-2030年中國(guó)筆記本行業(yè)發(fā)展監(jiān)測(cè)及投資戰(zhàn)略研究報(bào)告
- 2025年中國(guó)金華市服裝行業(yè)發(fā)展監(jiān)測(cè)及市場(chǎng)發(fā)展?jié)摿︻A(yù)測(cè)報(bào)告
- 2025年復(fù)合鋼管項(xiàng)目可行性研究報(bào)告
- 洛奇化石復(fù)原腳本
- 人教版三年級(jí)上冊(cè)豎式計(jì)算練習(xí)300題及答案
- 【“凡爾賽”網(wǎng)絡(luò)流行語(yǔ)的形成及傳播研究11000字(論文)】
- 建筑工程施工安全管理思路及措施
- 麻痹性腸梗阻學(xué)習(xí)課件
- 領(lǐng)導(dǎo)干部的情緒管理教學(xué)課件
- 初中英語(yǔ)-Unit2 My dream job(writing)教學(xué)課件設(shè)計(jì)
- 供貨方案及時(shí)間計(jì)劃安排
- 唐山動(dòng)物園景觀規(guī)劃設(shè)計(jì)方案
- 中國(guó)版梅尼埃病診斷指南解讀
- 創(chuàng)業(yè)投資管理知到章節(jié)答案智慧樹(shù)2023年武漢科技大學(xué)
評(píng)論
0/150
提交評(píng)論