android模塊
❶ Android模塊化開發解耦需要注意的一些事項
模塊化開發的目的 - 解耦,所以我們的注意事項,都應該圍繞著解耦來做。
❷ Android硬體抽象層模塊編寫規范
硬體抽象層模塊編寫規范
硬體抽象層最終都會生成.so文件,放到系統對應的目錄中。在系統使用的時候,系統會去對應目錄下載入so文件,實現硬體抽象層的功能。因此硬體抽象層的載入過程就是我們使用so的一個介面。先了解載入過程從源頭了解抽象層模塊兒的編寫規范。
1、硬體抽象層載入過程
系統在載入so的過程中,會去兩個目錄下查找對應id的so文件。這兩個目錄分別是/system/lib/hw和/vendor/lib/hw。
so文件的名字分為兩個部分例如id.prop.so,第一部分是模塊id。第二部分是系統prop的值,獲取順序為「ro.hardware」、「ro.procat.board」、「ro.board.platform」、「ro.arch」,如果prop都找不到的話,就用default。(不是找不到prop的值,是找不到prop值對應的so文件)。
負責載入硬體抽象層模塊的函數是hw_get_mole,所在的文件是/hardware/libhardware/hardware.c如下:
/** Base path of the hal moles */
#if defined(__LP64__)
#define HAL_LIBRARY_PATH1 "/system/lib64/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib64/hw"
#else
#define HAL_LIBRARY_PATH1 "/system/lib/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"
#endif
/**
* There are a set of variant filename for moles. The form of the filename
* is ".variant.so" so for the led mole the Dream variants
* of base "ro.proct.board", "ro.board.platform" and "ro.arch" would be:
*
* led.trout.so
* led.msm7k.so
* led.ARMV6.so
* led.default.so
*/
static const char *variant_keys[] = {
"ro.hardware", /* This goes first so that it can pick up a different
file on the emulator. */
"ro.proct.board",
"ro.board.platform",
"ro.arch"
};
static const int HAL_VARIANT_KEYS_COUNT =
(sizeof(variant_keys)/sizeof(variant_keys[0]));
/**
* Load the file defined by the variant and if successful
* return the dlopen handle and the hmi.
* @return 0 = success, !0 = failure.
*/
static int load(const char *id,
const char *path,
const struct hw_mole_t **pHmi)
{
int status;
void *handle;
struct hw_mole_t *hmi;
/*
* load the symbols resolving undefined symbols before
* dlopen returns. Since RTLD_GLOBAL is not or'd in with
* RTLD_NOW the external symbols will not be global
*/
handle = dlopen(path, RTLD_NOW);
if (handle == NULL) {
char const *err_str = dlerror();
ALOGE("load: mole=%s\n%s", path, err_str?err_str:"unknown");
status = -EINVAL;
goto done;
}
/* Get the address of the struct hal_mole_info. */
const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
hmi = (struct hw_mole_t *)dlsym(handle, sym);
if (hmi == NULL) {
ALOGE("load: couldn't find symbol %s", sym);
status = -EINVAL;
goto done;
}
/* Check that the id matches */
if (strcmp(id, hmi->id) != 0) {
ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);
status = -EINVAL;
goto done;
}
hmi->dso = handle;
/* success */
status = 0;
done:
if (status != 0) {
hmi = NULL;
if (handle != NULL) {
dlclose(handle);
handle = NULL;
}
} else {
ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",
id, path, *pHmi, handle);
}
*pHmi = hmi;
return status;
}
/*
* Check if a HAL with given name and subname exists, if so return 0, otherwise
* otherwise return negative. On success path will contain the path to the HAL.
*/
static int hw_mole_exists(char *path, size_t path_len, const char *name,
const char *subname)
{
snprintf(path, path_len, "%s/%s.%s.so",
HAL_LIBRARY_PATH2, name, subname);
if (access(path, R_OK) == 0)
return 0;
snprintf(path, path_len, "%s/%s.%s.so",
HAL_LIBRARY_PATH1, name, subname);
if (access(path, R_OK) == 0)
return 0;
return -ENOENT;
}
int hw_get_mole_by_class(const char *class_id, const char *inst,
const struct hw_mole_t **mole)
{
int i;
char prop[PATH_MAX];
char path[PATH_MAX];
char name[PATH_MAX];
char prop_name[PATH_MAX];
if (inst)
snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
else
strlcpy(name, class_id, PATH_MAX);
/*
* Here we rely on the fact that calling dlopen multiple times on
* the same .so will simply increment a refcount (and not load
* a new of the library).
* We also assume that dlopen() is thread-safe.
*/
/* First try a property specific to the class and possibly instance */
snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name);
if (property_get(prop_name, prop, NULL) > 0) {
if (hw_mole_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
/* Loop through the configuration variants looking for a mole */
for (i=0 ; i<HAL_VARIANT_KEYS_COUNT; i++) {
if (property_get(variant_keys[i], prop, NULL) == 0) {
continue;
}
if (hw_mole_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
/* Nothing found, try the default */
if (hw_mole_exists(path, sizeof(path), name, "default") == 0) {
goto found;
}
return -ENOENT;
found:
/* load the mole, if this fails, we're doomed, and we should not try
* to load a different variant. */
return load(class_id, path, mole);
}
int hw_get_mole(const char *id, const struct hw_mole_t **mole)
{
return hw_get_mole_by_class(id, NULL, mole);
}
找到so文件之後,調用方法load方法去載入對應的so文件,並返回hw_mole_t結構體。load方法源碼在上面程序中。
load方法首先調用dlopen載入對應的so文件到內存中。然後用dlsym方法找到變數HAL_MODULE_INFO_SYM_AS_STR符號對應的地址,這個地址也就是一個hw_mole_t結構體,然後從這個結構體中拿出id比對load方法出入的id是否一致,如果是的話表示打開成功。載入過程完成。
HAL_MODULE_INFO_SYM_AS_STR這個符號值為HMI,也就是必須要保證這個符號之後是一個hw_mole_t。接下來的規范中有這個要求。
到此,模塊載入完成
2、硬體抽象層模塊編寫規范
硬體抽象層有兩個結構體,一個是hw_mole_t和hw_device_t,定義在hardware.h中。
首先說一下hw_mole_t的編寫規范。
1、必須要有一個「自定義硬體抽象層結構體」,且結構體第一個變數類型要為hw_mole_t。
2、必須存在一個HARDWARE_MODULE_INFO_TAG的符號,且指向「自定義硬體抽象層結構體」。在載入的時候根據這個符號找到地址,並把地址的轉變為hw_mole_t,這也是為什麼第一條中hw_mole_t必須要在第一個的原因。
3、hw_mole_t的tag必須為HARDWARE_MODULE_TAG
4、結構體中要有一個方法列表,其中要有一個open方法。用open方法獲得hw_device_t
接下來說一下hw_device_t的編寫規范
1、必須要有一個「自定義硬體設備結構體」,且結構體第一個變數類型要為hw_device_t。
2、hw_device_t的tag必須為HARDWARE_DEVICE_TAG
3、要有一個close函數指針,來關閉設備
按照上面規范編寫的硬體抽象層就可以由系統載入並正確獲取到device。具體的應用層邏輯在device中實現。
❸ Android 模塊之旅:ARoutrer框架使用教程
隨著公司項目越來越大,人員增多,項目會出現難維護、新人入職後,需要花費很多時間去熟悉項目。最重要的是,每次編譯時間真的太久了!!!為了解決這個問題,項目重構、模塊化需要提上日程。項目拆分成模塊之後,頁面的跳轉就不能直接startActivity 調用具體的activity了,因為這個Activity已經在另外一個模塊中,直接用顯示引用是提示不出來的,這時需要通過藉助路由庫來實現頁面的跳轉,當然通過反射的方式也是可以跳轉到對應頁面的。通過這樣的路由跳轉,而不是顯示引用,就達到了模塊之間解耦的目的,在不需要的時候,可以不需要引入這個模塊編譯,提高開發速度,發布的時候又能很方便的集成進來,功能不受影響,這就實現了模塊化的第一步。路由框架推薦使用阿里開源的ARouter路由框架,畢竟是大廠開源的框架,穩定性、可靠性也相對較高。
路由路徑,我們可以封裝一個 RouterManger 工具類放在 moudle_base 模塊中,統一管理整個項目的 Path 及路由框架的初始化操作, 示例如下:
我們經常需要在目標頁面中配置一些屬性,比方說"是否需要登陸"之類的
可以通過 Route 註解中的 extras 屬性進行擴展,這個屬性是一個 int值,換句話說,單個int有4位元組,也就是32位,可以配置32個開關
剩下的可以自行發揮,通過位元組操作可以標識32個開關,通過開關標記目標頁面的一些屬性,在攔截器中可以拿到這個標記進行業務邏輯判斷
ARouter更加詳細的使用教程可以前往官方GitHub查閱,上述為個人使用過程中覺得需要記錄下來東西,不足之處,敬請見諒
❹ 什麼是android應用模塊開發
android應用模塊開發:
在android的項目開發中,都會遇到後期功能拓展增強與主程序代碼變更的現實矛盾,也就是程序的靈活度。
由於linux平台的安全機制,再加上dalvik的特殊機制,各種許可權壁壘,使得開發一個靈活多變的程序,變得比較困難,不像pc平台下那麼容易。
瞅瞅elipse的插件,瞅瞅360的插件,在android下,我們一開始很難寫好一個主程序,然後通過插件機制來應對以後的功能拓展,於是程序變得不那麼靈活多變了。
比如一款android下的安全軟體,新版本增加了一個功能,如簡訊攔截,往往會因為一個模塊的增加,而重新編譯一個apk包,這樣周而復始,哪怕只增加50kb的功能代碼,用戶也需要升級一個完整的apk,往往是5~6M的體積。
❺ Android核心模塊結構層次有哪些呢
Android作為一個移動設備的平台,其軟體層次結構包括了一個操作系統(OS),中間件(MiddleWare)和應用程序(Application)。
根據Android的軟體框圖,其Android核心模塊結構自下而上分為以下幾個層次:
第一、操作系統層(OS)
第二、各種庫(Libraries)和Android 運行環境(RunTime)
第三、應用程序框架(Application Framework)
第四、應用程序(Application)
❻ MoleService-Android模塊之間解耦問題實現
模塊間解耦庫,解決mole之間的依賴問題,github地址: https://github.com/breaktian/MoleServiceDemo
項目大了之後,mole增多了,尤其是業務模塊之間的依賴關系變得復雜,而且gradle不允許雙向依賴,
比如說biz-a模塊依賴biz-b模塊,如果biz-b模塊想使用biz-a模塊的服務怎麼辦?biz-b再去依賴biz-a gradle編譯會出錯
demo項目的模塊:App、biz-login、biz-usercenter、shell。其中shell模塊是公共模塊,他們的依賴關系是App依賴biz-login、biz-usercenter、biz-shell,
biz-login依賴shell,biz-usercenter依賴shell。其實shell就是一個公共模塊。biz-login和biz-usercenter沒有依賴關系。
當然,任何模塊都可以提供服務,而且任何模塊都能使用協議中已經存在的服務。這樣之前繁雜冗餘的業務模塊之間的依賴就沒有了,還可以提高編譯的速度。
❼ androidstudio如何把模塊由app調用
androidstudio把模塊由app調用方法如下:
1、自己創建一個新的android項目,選擇EmptyActivity,一直選擇默認項file->new->importmole。
2、選擇模塊文件,點擊finish。
3、點擊file->projectStructure。
4、選中Moles下的app,注意這個app就是自己newproject的mole。
5、點擊+號,選中Moledependency。
6、選中之前導入的模塊,點擊ok。
❽ android 模塊化中打開其他模塊activity的方式
AndroidManifest.xml 中配置 meta-data
在Activity中,通過packageyManage獲取到activityInfo再獲取到該activity的meta-data
獲取到配置的meta-date value之後,再通過反射去創建一個需要的activity實例
這樣用的好處之一就是在模塊化APP中不同模塊可以通過包名去調用其他模塊的內容。
總結:
獲取meta-data的方法只是一種思路,通過packageManage獲取到meta-data的value值(需要跳轉到的activity包路徑)
實質上就是通過反射去創建一個activity實例,這樣的思路還可以用在其他地方,比如後端某一個表中新建一個action欄位等等...
❾ 如何學習android框架,框架分為哪些模塊
其實主要是看你的工作中會用到什麼,感覺還是先把Android的基礎學好,畢竟框架也是在Android的基礎上面進行開發的,你說的這幾個框架我沒怎麼用過,大概看過一點,比如xutils和ThinkAndroid,他們都有一些自己的模塊如view,http,bitmap相關的模塊,這些模塊把一些常用的操作都進行了封裝,直接拿過來使用就可以了,這樣確實減少了開發的工作,也會減少工作中可能會犯的一些錯誤,比如如果bitmap處理不好就很容易造成內存的問題。網上對這些框架有比較詳細的介紹和每個框架裡面實現的模塊以及各個模塊支持的功能。對比一下哪個是你工作中最需要的,然後學習一下即可,學會了一種那麼其他的框架在看的時候就可以做到舉一反三了。不過在學習框架的同時還是要把android的基礎多學習一下的。
❿ Android模塊化設計方案之使用代理模式解耦
Android模塊化設計方案系列文章:
1、 Android模塊化設計方案模型圖
2、 Android模塊化設計方案之介面API化
3、 Android模塊化設計方案之使用代理模式解耦
本篇是Android模塊化設計方案的第三篇,也是對 第一篇 中ThridLibs Proxy模塊進行說明。
很多人覺得對那些優秀的第三方依賴庫再次封裝是一件多餘的事情,因為這些庫可能出自大神/大廠,或有非常高的star並且使用起來十分穩定,可以在項目中直接拿來使用。當然每個開發者都有自己的態度,我也只是根據以往的經驗,表達一下自己的看法。
作為從了解四大組件就不愁找不到工作的互聯網大時代中一路走來的Android老鳥,經歷了網路請求框架從HttpConnection到Volley再到OkHttp,也經歷了圖片載入框架從UniversalImageLoader到Picasso再到Gilde,技術的迭代隨時都會發生。讓項目架構具有良好的擴展性是在設計之初就需要考慮的東西。
那麼接下來我用一個簡單的demo來演示一下如何使用代理模式對第三方框架進行解耦。
現在我們有一個名為 thirdlib 的模塊,為我們提供圖片載入功能。
第一步:我們創建了一個新的模塊 thridlibproxy ,並且該模塊依賴於 thirdlib ,我們在該模塊中創建包私有的介面ImageLoaderInterface,這個介面中把thirdlib模塊中提供的功能抽象為介面:
第二步:創建包私有的介面的實現類ImageLoaderOneImpl,類中圖片載入的業務邏輯是通過調用 thirdlib 中的ImageLoader類實現的:
第三步:我們提供一個供外部調用的ImageLoaderOneImpl介面代理類ImageLoaderProxy:
最後我們就可以通過ImageLoaderProxy中提供的loadImage方法進行圖片的載入了。
看到這里有些盆友就會問了,在第二步的時候,我們就完成了 thirdlib 的封裝工作,為什麼還要有第三步?還有我寫一個單例類直接對 thirdlib 進行封裝不就行了,為什麼還要抽象出介面?
原因很簡單,為的就是盡可能的滿足軟體設計七大原則中的第一個: 開閉原則 。
一個好的軟體設計,需要對拓展開放,對修改關閉。我們在設計之初就要想到,在更換圖片載入框架之後如何最大程度上滿足開閉原則。
如果直接對 thirdlib 進行封裝,是面向類的開發而不是面向介面。如果此時更換圖片載入類庫,那必然會對封裝出來的類進行大量的修改,把原來的實現替換為新的實現。
使用代理模式的好處就是,我新創建一個被代理的類ImageLoaderTwoImpl:
然後只需要對第三步中的被代理類進行替換就行了。
在想要達到相同效果的時候,最大程度的滿足了開閉原則。
我們業務層模塊也和第三方庫實現了完全的解耦,我不需要知道 thridlibproxy 是如何幫我完成圖片載入工作的,但是只要調用它提供的方法就完事兒的,這也符合軟體設計七大原則中的: 最少知道原則 。
關於為何以及怎麼通過代理調用第三方依賴庫,到這里就介紹完畢了,趕快動手試試吧~
我只想說: 原則是死的,人是活的😹
如果覺得有收獲的話,歡迎點贊評論以及關注~