安卓系統(tǒng)的資源編譯_第1頁(yè)
安卓系統(tǒng)的資源編譯_第2頁(yè)
安卓系統(tǒng)的資源編譯_第3頁(yè)
安卓系統(tǒng)的資源編譯_第4頁(yè)
安卓系統(tǒng)的資源編譯_第5頁(yè)
已閱讀5頁(yè),還剩175頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(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ì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論