1. 程式人生 > >給Android原始碼增加一個專案

給Android原始碼增加一個專案

所謂增加一個專案的意思是,增加一個子專案,以便於Android原始碼遍以後,編譯目標中能夠包含該專案。比如:可以增加一個C/C++工具程式,從而可以在目標系統的shell命令列下使用該工具。再比如,可增加一個apk程式,從而在該裝置出廠時就自帶該程式。

      從編譯中樞的角度來講,增加專案就是告訴編譯中樞一些資訊,這些資訊包括:

  • 這個專案的target名稱是什麼?
  • 這個專案的輸出型別是什麼?比如:apk、jar包等
  • 這個專案對應的variant是什麼?

有了這些資訊後,編譯中樞就知道如何編譯該專案,並將輸出的目標打包到不同的variant產品分類中。

一、給Android原始碼增加一個C專案

下面說明如何增加一個C專案。

首先,需要選擇一個目錄,本例可以選擇external目錄。

接著,需要給該專案定義一個target名稱,這個target名稱必須是全域性唯一的,這裡可以定義為helloMake。該工程很簡單,只包含一個main.c檔案,其內容如下:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "hello.h"
  4. int main()  
  5. {  
  6.     makePrintf("helloMake");  
  7.     return 0 ;  
  8. }  
hello.h檔案內容如下:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #ifndef _HELLO_H
  4. #define _HELLO_H
  5. void makePrintf(char* str)  
  6. {  
  7.     printf("%s" , str);  
  8. }  
  9. #endif
新增這2個檔案後,需要編寫一個Android.mk檔案,其內容如下:
  1. LOCAL_PATH := $(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_SRC_FILES := \  
  4.     main.c  
  5. LOCAL_C_INCLUDES += $(LOCAL_PATH)  
  6. LOCAL_MODULE := helloMake  
  7. LOCAL_MODULE_TAGS := eng  
  8. include $(BUILD_EXECUTABLE)  
該mk檔案中需要注意以下幾點:

1、所有的C/C++原檔案必須手動新增,因為編譯中樞並沒有提供一個能夠自動從當前目錄下尋找所有C/C++檔案列表的函式。

2、由於C語言中會使用到include命令,因此,必須在mk檔案中指定標頭檔案的路徑,僅需指定專案中包含的特別路徑,而不需要指定系統標頭檔案路徑。因為系統標頭檔案路徑在編譯中樞中已經設定好了,具體是在config.mk檔案中設定的,如以下程式碼所示。如果要新增一些特別的系統路徑,可以更該build/core/config.mk檔案中SRC_HEADERS的值。


3、該專案使用的TAG值為eng,因此,僅當用戶指定的產品類別是eng時才會包含該專案。如果要讓所有類別的產品都包含該專案,可以將TAG值設定為optional,並在相應的product的配置檔案中的PRODUCT_PACKAGES變數中包含該專案即可。./vendor/xxxx/build/product/xxxx_sdk.mk

4、然後就可以編譯SDK,完成後,將新的system.img耍人裝置,啟動./adb shell,在命令列下,直接呼叫helloMake,程式將輸出helloMake。

二、給Android原始碼增加一個apk專案

      新增一個apk專案可能是很多應用工程師經常遇到的問題,下面來介紹如何新增一個apk專案,該過程的原理和新增C專案相同,只是apk專案中相關的編譯變數名稱和C專案稍有不同。

      首先,假設已經在Eclipse下新建了一個名稱為HelloAPK的Android應用專案,下面要做的就是要把這個專案移植進Android原始碼中。前面曾經說過,編譯中樞會搜尋Android根目錄下除out目錄外的所有子目錄,並找出Android.mk檔案作為一個子專案。因此理論上可以將HelloAPK專案放在任何目錄下,只不過為了目錄的清晰,廠商一般習慣於將自己定義的專案放到vendor下的相應目錄中。

      然後,刪除HelloApk目錄下的bin和gen目錄,因為這2個目錄是Eclipse編譯的輸出目錄,而其對Android編譯系統而言是多餘的,它甚至會認為這是2個原始碼目錄。從這點上看,編譯中樞似乎需要改進一下,它應該能夠自動排除APK專案下的bin和gen目錄。

      接下來,就需要新建一個Android.mk檔案,並將其放到HelloAPK目錄下,該Android.mk的內容如以下程式碼所示。

  1. LOCAL_PATH:= $(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_MODULE_TAGS := optional  
  4. LOCAL_SRC_FILES := $(call all-java-files-under, src)  
  5. #LOCAL_SDK_VERSION := current  
  6. LOCAL_PACKAGE_NAME := bright-yinjk  
  7. LOCAL_CERTIFICATE := platform  
  8. include $(BUILD_PACKAGE)  
  9. include $(call all-makefiles-under,$(LOCAL_PATH))  
以上.mk檔案說明如下:

LOCAL_MODAL_TAGS 用於指定該專案的標籤值,對於應用類子專案而言,只能指定為3種情況,分別為:optional、tests、eng,這與C專案是相同的,本例中使用的是optional。因此,對於實體裝置必須在devices/haiii/k/k.mk檔案中包含該專案,否則K產品將不會包含該,如以下程式碼所示,

  1. PRODUCT_PACKAGES := \  
  2.         heoolMake \  
  3.         HelloAPK  
對於模擬器需要在vendor/hisxxx/build/product/hitv_sdk.mk檔案中增加如下程式碼:
  1. # thirdparty packages for device  
  2. PRODUCT_PACKAGES += \  
  3.     com.tencent.qqpinyin \  
  4.     bright-yinjk  
LOCAL_SRC_FILE用於指定該專案中的JAVA原始碼,編譯中樞提供了一個函式,可以直接遍歷指定目錄下的所有JAVA檔案,從而不必手工列出所有的JAVA原檔案,而C專案中沒有類似功能的指令碼函式。

LOCAL_PACKAGE_NAME:用於描述APK專案的名稱,而C專案中用的是LOCAL_MODULE_NAME,注意區分。

LOCAL_SDK_VERSION:用於指定該APK專案所需的SDK版本,current代表了當前Android原始碼的版本。

LOCAL_CERTIFICATE:用於指定該APK專案將使用何種簽名檔案簽名最後生成的apk檔案。系統中一共包含4種簽名檔案,分別如下:

  • platform      FrameWork原始碼最後將生成一個Jar包,該Jar包預設使用該型別簽名
  • shared        一些系統應用程式使用該型別簽名,比如Contacts等
  • user             一些私有專案使用該簽名
  • tests             除錯過程中使用該簽名

至於使用何種簽名取決於專案的需要,一般當需要和特定的程式共享資料庫資源時,兩個專案必須擁有相同的簽名。

最後,使用include包含BUILD_PACKAGE命令巨集告訴編譯中樞該專案的目標是一個apk程式。

以上介紹的是以原始碼的方式新增一個專案,有些時候可能還需要以一個apk檔案的方式新增一個專案,在這種情況下,本質上新增的不是一個專案,而僅僅是一個檔案。前面講過,一個product中包含的專案分為3種,其中最後一種就是私有的專案或者檔案,而這種方式實際上就是私有的檔案。因此,需要在product相關的腳步檔案中宣告該product中包含apk檔案。本例中就應該在k.mk檔案中新增以下程式碼,其中賦值的源路徑是主機系統上的路徑,而目標路徑是裝置上的路徑,兩者使用冒號分割,如下:

  1. PRODUCT_COPY_FILES := \  
  2.       vendor/haiii/k/helloapk/helloapk.apk:/system/app  
        該段程式碼僅僅是將HelloApk.apk複製到最終裝置的/system/app目錄下,如果想給apk進行簽名怎麼辦?對不起,編譯中樞沒有單獨提供這個功能,也就是說,再包HelloApk.apk複製到原始碼中前,應該事先給apk進行簽名。如果開發中真的有這種需求,可以嘗試增加一個BUILD_PACKAGE_WITHAPK的命令巨集,就像BUILD_PACKAGE一樣。使用者可以在Android.mk檔案中使用include命令包含該巨集,然後在該命令巨集的定義中手工實現對apk的簽名。