windows下android打包工具
这是我的第一篇博客,以前总想写点什么,但总是迟迟不见行动,会有各种借口来放弃,最近反思自己,这样真的好吗,呵呵,改变从现在开始。
首先我来说下为什么我要写windows下android打包工具,我们的android4.2项目开发是在windows上的,大家用的是eclipse,各自写好的APK最后交于一人,由他来合成最后的system.img.ext4,然后发于客户升级,合成环境也是在windows上,一开始,我们找到了“ROM助手”这款软件,用来打包apk,以及so,用用还可以,但随着客户的增多,以及其他类型的文件需要打包,这款软件开始出现其弊端,因为需要手工去点击操作,而不是批量化生成,效率比较低而且容易出错,鉴于此我打算写一款工具,用来满足我们的工作需求。
想过几种方案,最简单的莫过于在Ubuntu上写个脚本,直接用现成的make_ext4fs工具来生成,但我们要求在winddows上,所以排除了,至于为什么不用Ubuntu,那理由很low,就不说了。
后来想到了cygwin下能编译Linux上的软件,所以将make_ext4fs的源代码拷出,放于cygwin上编译,编译通过,哈哈,竟然能在windows上生成system.img.ext4了,开心了会,但又发现了问题,权限不对,全部变为0755了,而且不支持链接文件,这不符合我们的要求啊,而且要求系统工程师提供的原始system.img.ext4文件已经全部解压开来,汗。发现了问题,那就要解决问题。
现在需要解决的问题有:
1.system.img.ext4在windows下解压开来,要求记录链接文件以及权限,uid等信息。
2. 修改make_ext4fs程序,使之支持读取我们记录下来的权限等信息。
对于第一个问题,我们知道system.img.ext4其实不是ext4格式的,具体叫什么格式,我也不知道,呵呵,只知道Linux下有个simg2img 工具,可以将system.img.ext4转化为裸的ext4格式的image,暂且就叫system.img.ext4为simg格式吧,这种格式其实就是用一个个的chunk,有CHUNK_TYPE_RAW,CHUNK_TYPE_DONT_CARE类型,CHUNK_TYPE_RAW记录实际的文件数据,CHUNK_TYPE_DONT_CARE记录的是image中的0块,这样就可以实现文件的精简,原理其实和wince的xip格式也差不多,都是为了跳过大块的0区域。
simg2img 工具的实现可以按照实现make_ext4fs在cygwin实现的方式一样。但我自己又实现了一种简单的转化函数,效果一样,看源码:
// 转化函数
bool simg2ext4(char *srcPath, char *desPath)
{
// 打开文件
HANDLE hFile =CreateFile(srcPath, GENERIC_WRITE|GENERIC_READ,
FILE_SHARE_READ,NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if (hFile ==INVALID_HANDLE_VALUE)
{
printf("%snot exist \r\n", srcPath);
return false;
}
// 得到文件大小
int dwfileSize = GetFileSize(hFile,NULL);
printf("dwfileSize= %d \r\n", dwfileSize);
// 文件映射
HANDLE hFileMapping =CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (NULL ==hFileMapping)
{
printf("CreateFileMappingerror\r\n");
CloseHandle(hFile);
return false;
}
CloseHandle(hFile);
// 得到文件内存指针
unsigned char*lpbMapAddress = (unsigned char *)MapViewOfFile(hFileMapping, FILE_MAP_READ, 0,0, dwfileSize);
if (lpbMapAddress ==NULL)
{
printf("MapViewOfFileerror \r\n");
return false;
}
//--------------------- 解析文件-----------------------
unsigned intblock_size = 0;
unsigned int chunk_cnt= 0;
unsigned int filelen =dwfileSize;
unsigned char*pfileBuffer = NULL;
unsigned int datalen;
unsigned longu8WriteAddr = 0;
sparse_header_t*ptSparseHeader = NULL;
chunk_header_t *ptChunkHeader = NULL;
// 1. 获取sparse的头
ptSparseHeader =(sparse_header_t *)lpbMapAddress;
block_size =ptSparseHeader->blk_sz;
chunk_cnt =ptSparseHeader->total_chunks;
printf("ptSparseHeader->blk_sz = 0X%x\r\n", ptSparseHeader->blk_sz);
printf("ptSparseHeader->total_blks = 0X%x\r\n",ptSparseHeader->total_blks);
printf("ptSparseHeader->total_chunks = 0X%x\r\n",ptSparseHeader->total_chunks);
// 2. 内容开始出
pfileBuffer =lpbMapAddress + sizeof(sparse_header_t);
filelen -=sizeof(sparse_header_t);
// 3. 用0填充文件
HANDLE hFileWrite =CreateFile(desPath, GENERIC_WRITE|GENERIC_READ,
FILE_SHARE_READ,NULL, CREATE_ALWAYS, 0, 0);
void *buff =malloc(ptSparseHeader->blk_sz);
memset(buff, 0x00,ptSparseHeader->blk_sz);
unsigned longdwNumberOfBytesWritten;
for (unsigned int i=0;i<ptSparseHeader->total_blks; i++)
{
WriteFile(hFileWrite,buff, ptSparseHeader->blk_sz, &dwNumberOfBytesWritten, 0);
}
free(buff);
// 4. 将数据写入文件
while((chunk_cnt>0) && (filelen>0))
{
ptChunkHeader =(chunk_header_t *)pfileBuffer;
datalen =ptChunkHeader->chunk_sz * block_size;
printf("ptChunkHeader->chunk_type = %d\r\n",ptChunkHeader->chunk_type);
printf("ptChunkHeader->chunk_sz = 0X%x\r\n",ptChunkHeader->chunk_sz);
printf("datalen = 0X%x\r\n", datalen);
if(CHUNK_TYPE_RAW == ptChunkHeader->chunk_type)
{
pfileBuffer+= CHUNK_HEADER_LEN;
SetFilePointer(hFileWrite,u8WriteAddr, 0, FILE_BEGIN);
WriteFile(hFileWrite,pfileBuffer, datalen, &dwNumberOfBytesWritten, 0);
filelen-= ptChunkHeader->total_sz;
chunk_cnt--;
pfileBuffer&#