android模块,android模块化和组件化
如何学习android框架,框架分为哪些模块
其实主要是看你的工作中会用到什么,感觉还是先把Android的基础学好,毕竟框架也是在Android的基础上面进行开发的,你说的这几个框架我没怎么用过,大概看过一点,比如xutils和ThinkAndroid,他们都有一些自己的模块如view,http,bitmap相关的模块,这些模块把一些常用的操作都进行了封装,直接拿过来使用就可以了,这样确实减少了开发的工作,也会减少工作中可能会犯的一些错误,比如如果bitmap处理不好就很容易造成内存的问题。网上对这些框架有比较详细的介绍和每个框架里面实现的模块以及各个模块支持的功能。对比一下哪个是你工作中最需要的,然后学习一下即可,学会了一种那么其他的框架在看的时候就可以做到举一反三了。不过在学习框架的同时还是要把android的基础多学习一下的。
专业领域包括成都网站建设、网站制作、商城网站定制开发、微信营销、系统平台开发, 与其他网站设计及系统开发公司不同,创新互联的整合解决方案结合了帮做网络品牌建设经验和互联网整合营销的理念,并将策略和执行紧密结合,为客户提供全网互联网整合方案。
Android硬件抽象层模块编写规范
硬件抽象层模块编写规范
硬件抽象层最终都会生成.so文件,放到系统对应的目录中。在系统使用的时候,系统会去对应目录下加载so文件,实现硬件抽象层的功能。因此硬件抽象层的加载过程就是我们使用so的一个接口。先了解加载过程从源头了解抽象层模块儿的编写规范。
1、硬件抽象层加载过程
系统在加载so的过程中,会去两个目录下查找对应id的so文件。这两个目录分别是/system/lib/hw和/vendor/lib/hw。
so文件的名字分为两个部分例如id.prop.so,第一部分是模块id。第二部分是系统prop的值,获取顺序为“ro.hardware”、“ro.producat.board”、“ro.board.platform”、“ro.arch”,如果prop都找不到的话,就用default。(不是找不到prop的值,是找不到prop值对应的so文件)。
负责加载硬件抽象层模块的函数是hw_get_module,所在的文件是/hardware/libhardware/hardware.c如下:
/** Base path of the hal modules */
#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 modules. The form of the filename
* is ".variant.so" so for the led module the Dream variants
* of base "ro.product.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.product.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_module_t **pHmi)
{
int status;
void *handle;
struct hw_module_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: module=%s\n%s", path, err_str?err_str:"unknown");
status = -EINVAL;
goto done;
}
/* Get the address of the struct hal_module_info. */
const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
hmi = (struct hw_module_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_module_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_module_by_class(const char *class_id, const char *inst,
const struct hw_module_t **module)
{
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 copy 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_module_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
/* Loop through the configuration variants looking for a module */
for (i=0 ; iHAL_VARIANT_KEYS_COUNT; i++) {
if (property_get(variant_keys[i], prop, NULL) == 0) {
continue;
}
if (hw_module_exists(path, sizeof(path), name, prop) == 0) {
goto found;
}
}
/* Nothing found, try the default */
if (hw_module_exists(path, sizeof(path), name, "default") == 0) {
goto found;
}
return -ENOENT;
found:
/* load the module, if this fails, we're doomed, and we should not try
* to load a different variant. */
return load(class_id, path, module);
}
int hw_get_module(const char *id, const struct hw_module_t **module)
{
return hw_get_module_by_class(id, NULL, module);
}
找到so文件之后,调用方法load方法去加载对应的so文件,并返回hw_module_t结构体。load方法源码在上面程序中。
load方法首先调用dlopen加载对应的so文件到内存中。然后用dlsym方法找到变量HAL_MODULE_INFO_SYM_AS_STR符号对应的地址,这个地址也就是一个hw_module_t结构体,然后从这个结构体中拿出id比对load方法出入的id是否一致,如果是的话表示打开成功。加载过程完成。
HAL_MODULE_INFO_SYM_AS_STR这个符号值为HMI,也就是必须要保证这个符号之后是一个hw_module_t。接下来的规范中有这个要求。
到此,模块加载完成
2、硬件抽象层模块编写规范
硬件抽象层有两个结构体,一个是hw_module_t和hw_device_t,定义在hardware.h中。
首先说一下hw_module_t的编写规范。
1、必须要有一个“自定义硬件抽象层结构体”,且结构体第一个变量类型要为hw_module_t。
2、必须存在一个HARDWARE_MODULE_INFO_TAG的符号,且指向“自定义硬件抽象层结构体”。在加载的时候根据这个符号找到地址,并把地址的转变为hw_module_t,这也是为什么第一条中hw_module_t必须要在第一个的原因。
3、hw_module_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模块化之MicroModule(微信Pins工程)
相信你看过微信关于模块化的分享 《微信Android模块化架构重构实践》 ,也注意到里面提到的pins工程结构。
作者是这样描述的 ------“pins工程能在module之内再次构建完整的多子工程结构,通过project.properties来指定编译依赖关系。通过依赖关系在编译时找到所有的资源和源码路径。”
仔细推敲这句话的意思,应该能知道它实现的基本原理------通过设置sourceSets指定多个java、res等路径.
有关sourceSets的介绍:
但是,有一个问题需要要知道的是,一个module只能指定一个AndroidManifest文件,pins工程中包含了多个AndroidManifest,它是怎么做到的?
研究过 com.android.tools.build:gradle ,会留意到它使用到一个子库 com.android.tools.build:manifest-merger ,官方通过这个库来合并多个AndroidManifest文件,或许pins工程也是用了这方式。
接下来,再它的基础上,我做的一些改动,取了另一个名字叫 MicroModule ,先来看一下工程结构:
与pins工程的结构大致不变,增加了 androidTest 和 test ,以及将 project.properties 替换为 build.gradle 。
基本原理是不变的,与微信pins工程一样配置 sourceSets 。AndroidManifest合并用了 com.android.tools.build:manifest-merger 。
在根项目的build.gradle中添加插件依赖:
在模块的build.gradle中引用插件并配置 MicroModule:
MicroModule中的build.gradle:
为了使用上的更加方便,专门写了Android Studio的插件,能快速的创建一个MicroMoudle.
插件安装步骤 :
插件详解 :
插件项目地址 :
MicroModule已经上传至Github,欢迎star交流。
Android核心模块结构层次有哪些呢
Android作为一个移动设备的平台,其软件层次结构包括了一个操作系统(OS),中间件(MiddleWare)和应用程序(Application)。
根据Android的软件框图,其Android核心模块结构自下而上分为以下几个层次:
第一、操作系统层(OS)
第二、各种库(Libraries)和Android 运行环境(RunTime)
第三、应用程序框架(Application Framework)
第四、应用程序(Application)
什么是android应用模块开发
android应用模块开发:
在android的项目开发中,都会遇到后期功能拓展增强与主程序代码变更的现实矛盾,也就是程序的灵活度。
由于linux平台的安全机制,再加上dalvik的特殊机制,各种权限壁垒,使得开发一个灵活多变的程序,变得比较困难,不像pc平台下那么容易。
瞅瞅elipse的插件,瞅瞅360的插件,在android下,我们一开始很难写好一个主程序,然后通过插件机制来应对以后的功能拓展,于是程序变得不那么灵活多变了。
比如一款android下的安全软件,新版本增加了一个功能,如短信拦截,往往会因为一个模块的增加,而重新编译一个apk包,这样周而复始,哪怕只增加50kb的功能代码,用户也需要升级一个完整的apk,往往是5~6M的体积。
分享文章:android模块,android模块化和组件化
浏览路径:http://azwzsj.com/article/dsdphej.html