通过appt获取apk文件的基本信息

1.主要过程

1.1 解析AndroidManifest.xml文件,获取E: application节点下的android:icon信息

./aapt dump xmltree /Users/mac123/Desktop/携程旅行.apk --file AndroidManifest.xml

部分输出结果如下:

E: application (line=128)A: http://schemas.android.com/apk/res/android:theme(0x01010000)=@0x7f0c01c5A: http://schemas.android.com/apk/res/android:label(0x01010001)="携程旅行" (Raw: "携程旅行")A: http://schemas.android.com/apk/res/android:icon(0x01010002)=@0x7f030000A: http://schemas.android.com/apk/res/android:name(0x01010003)="ctrip.base.component.CtripBaseApplication" (Raw: "ctrip.base.component.CtripBaseApplication")A: http://schemas.android.com/apk/res/android:allowBackup(0x01010280)=falseA: http://schemas.android.com/apk/res/android:largeHeap(0x0101035a)=trueA: http://schemas.android.com/apk/res/android:supportsRtl(0x010103af)=falseA: http://schemas.android.com/apk/res/android:resizeableActivity(0x010104f6)=falseA: http://schemas.android.com/apk/res/android:networkSecurityConfig(0x01010527)=@0x7f070006

上述结果中0x7f030000就是我们需要的Id信息,根据此Id在resource资源文件总获取缩略图。

1.2 打印apk文件的resource table内容

Print the contents of the resource table from the APK.

./aapt dump resources /Users/mac123/Desktop/携程旅行.apk

部分输出结果如下:

type mipmap id=03 entryCount=3resource 0x7f030000 mipmap/common_ic_launcher(ldpi-v4) (file) res/mipmap-ldpi-v4/common_ic_launcher.png type=PNG(mdpi-v4) (file) res/mipmap-mdpi-v4/common_ic_launcher.png type=PNG(hdpi-v4) (file) res/mipmap-hdpi-v4/common_ic_launcher.png type=PNG(xhdpi-v4) (file) res/mipmap-xhdpi-v4/common_ic_launcher.png type=PNG(xxhdpi-v4) (file) res/mipmap-xxhdpi-v4/common_ic_launcher.png type=PNG(anydpi-v26) (file) res/mipmap-anydpi-v26/common_ic_launcher.xml type=XMLresource 0x7f030001 mipmap/ic_launcher(mdpi-v4) (file) res/mipmap-mdpi-v4/ic_launcher.png type=PNG(hdpi-v4) (file) res/mipmap-hdpi-v4/ic_launcher.png type=PNG(xhdpi-v4) (file) res/mipmap-xhdpi-v4/ic_launcher.png type=PNG(xxhdpi-v4) (file) res/mipmap-xxhdpi-v4/ic_launcher.png type=PNG(xxxhdpi-v4) (file) res/mipmap-xxxhdpi-v4/ic_launcher.png type=PNGresource 0x7f030002 mipmap/leak_canary_icon(mdpi-v4) (file) res/mipmap-mdpi-v4/leak_canary_icon.png type=PNG(hdpi-v4) (file) res/mipmap-hdpi-v4/leak_canary_icon.png type=PNG(xhdpi-v4) (file) res/mipmap-xhdpi-v4/leak_canary_icon.png type=PNG(xxhdpi-v4) (file) res/mipmap-xxhdpi-v4/leak_canary_icon.png type=PNG(xxxhdpi-v4) (file) res/mipmap-xxxhdpi-v4/leak_canary_icon.png type=PNG(anydpi-v26) (file) res/mipmap-anydpi-v26/leak_canary_icon.xml type=XML

我们需要的信息就在type mipmap 或者type drawable中,一般情况下,上述输出结果中只有其一,因此代码中需要分支判断,单独处理。

根据Id信息,定位到resource 0x7f030000之后,解析其内部信息,即可得到各个分辨率的缩略图路径。

res/mipmap-ldpi-v4/common_ic_launcher.png
res/mipmap-mdpi-v4/common_ic_launcher.png
res/mipmap-hdpi-v4/common_ic_launcher.png
res/mipmap-xhdpi-v4/common_ic_launcher.png
res/mipmap-xxhdpi-v4/common_ic_launcher.png

1.3 通过命令从.apk文件中解压出icon

由于考虑性能及效率,只拉取分辨率最高的一张(xxhdpi-v4),然后通过命令从.apk文件中解压出即可。

解压命令如下:

unzip -j /Users/mac123/Desktop/携程旅行.apk "res/mipmap-xxhdpi-v4/common_ic_launcher.png" -d /Users/mac123/Desktop/getAppIconDecode

2. 其他命令

//获取bundleID
./aapt dump packagename  蘑菇街.apk//获取版本号:
./aapt dump badging my.apk | grep “VersionName” | sed -n "s/.*versionName='\([^']*\).*/\1/p"//获取versionCode
./aapt dump badging /path/test.apk | grep -o ‘versionCode=[^,]*’ | cut -d’=’ -f 2 | cut -d ‘ ‘ -f 1 | tr -d "'"//获取icon
./aapt dump badging /Users/mac123/Desktop/美团.apk | sed -n "/^application: /s/.*icon='\([^']*\).*/\1/p"

3. Objective-C代码

//获取apk文件的信息
- (NSDictionary *)getApkBaseInfoWithPath:(NSString *)apkPath {NSMutableDictionary *baseInfoDic = [[NSMutableDictionary alloc] init];//获取包名NSArray *packageNameArgArr = @[@"dump", @"packagename", apkPath];NSString *packageName = [self runAAPTCommondWithArguments:packageNameArgArr];if (packageName != nil && packageName.length > 0) {packageName = [[packageName componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] componentsJoinedByString:@""];[baseInfoDic setValue:packageName forKey:@"name"];}NSArray *allPropertyArr = [NSArray arrayWithObjects:@"dump",@"badging",apkPath, nil];NSString *allProperty = [self runAAPTCommondWithArguments:allPropertyArr];NSArray *outputArr = [allProperty componentsSeparatedByString:@"\n"];//获取版本号NSArray *packageArr = [outputArr filteredArrayUsingPredicate: [NSPredicate predicateWithFormat: @"SELF contains[c] 'versionName'"]];NSArray *packageStrArr = [[packageArr firstObject] componentsSeparatedByString:@" "];for (NSString *propertyStr in packageStrArr) {if ([propertyStr rangeOfString:@"="].location == NSNotFound) {continue;}NSArray *inlineArr = [propertyStr componentsSeparatedByString:@"="];NSString *keyName = [inlineArr firstObject];NSString *value = [inlineArr lastObject];value = [value stringByReplacingOccurrencesOfString:@"'" withString:@""];if (keyName.length > 0 && value.length > 0) {[baseInfoDic setValue:value forKey:keyName];}}//缩略图路径NSArray *containsApplicationArr = [outputArr filteredArrayUsingPredicate: [NSPredicate predicateWithFormat: @"SELF contains[c] 'application'"]];NSArray *applicationArr = [[containsApplicationArr lastObject] componentsSeparatedByString:@" "];for (NSString *propertyStr in applicationArr) {if ([propertyStr rangeOfString:@"="].location == NSNotFound) {continue;}NSArray *inlineArr = [propertyStr componentsSeparatedByString:@"="];NSString *keyName = [inlineArr firstObject];NSString *value = [inlineArr lastObject];value = [value stringByReplacingOccurrencesOfString:@"'" withString:@""];if (keyName.length > 0 && value.length > 0) {if ([keyName isEqualToString:@"icon"]) {if ([Help isImageType:value.pathExtension]) {[baseInfoDic setValue:value forKey:keyName];}else {NSString *iconPath = [self getApkIconFromMinmapFileWithApkPath:apkPath];[baseInfoDic setValue:iconPath forKey:keyName];}}else {[baseInfoDic setValue:value forKey:keyName];}}}NSLog(@"app baseInfoDic = %@", baseInfoDic);return baseInfoDic;
}//从minmap文件中获取apk缩略图路径
- (NSString *)getApkIconFromMinmapFileWithApkPath:(NSString *)apkPath {NSString *resultString = @"";NSArray *manifesetXMLParams = [NSArray arrayWithObjects:@"dump", @"xmltree", apkPath, @"--file", @"AndroidManifest.xml", nil];NSString *manifestAll = [self runAAPTCommondWithArguments:manifesetXMLParams];NSArray *outputArr = [manifestAll componentsSeparatedByString:@"\n"];NSArray *applicationArr = [outputArr filteredArrayUsingPredicate: [NSPredicate predicateWithFormat: @"SELF contains[c] 'E: application'"]];NSInteger applicationIndex = [outputArr indexOfObject:[applicationArr firstObject]];outputArr = [outputArr subarrayWithRange:NSMakeRange(applicationIndex+1, 10)];NSArray *containIconArr = [outputArr filteredArrayUsingPredicate: [NSPredicate predicateWithFormat: @"SELF contains[c] 'android:icon'"]];if (containIconArr.count > 0) {NSString *propertyStr = containIconArr.firstObject;if ([propertyStr rangeOfString:@"="].location != NSNotFound) {NSArray *inlineArr = [propertyStr componentsSeparatedByString:@"="];NSString *value = [inlineArr lastObject];value = [value stringByReplacingOccurrencesOfString:@"'" withString:@""];value = [value stringByReplacingOccurrencesOfString:@"@" withString:@""];if (value.length > 0) {resultString = [[self getAppIconPathsArrWithId:value apkPath:apkPath] lastObject];}}}return resultString;
}//根据id查找appicon,从mimap或者drawable中截取路径
- (NSArray *)getAppIconPathsArrWithId:(NSString *)IdStr apkPath:(NSString *)apkPath {NSMutableArray *resultArr = [[NSMutableArray alloc] init];NSArray *minmapParams = [NSArray arrayWithObjects:@"dump", @"resources", apkPath, nil];NSString *resourcesArr = [self runAAPTCommondWithArguments:minmapParams];NSArray *outputArr = [resourcesArr componentsSeparatedByString:@"\n"];NSPredicate *mipmapPredicate = [NSPredicate predicateWithFormat: @"SELF contains[c] 'type mipmap'"];NSPredicate *drawablePredicate = [NSPredicate predicateWithFormat: @"SELF contains[c] 'type drawable'"];if ([outputArr filteredArrayUsingPredicate:mipmapPredicate].count > 0) {NSArray * containMipmapArr = [outputArr filteredArrayUsingPredicate:mipmapPredicate];NSString *typeOfMinmap = [containMipmapArr firstObject];NSInteger index = [outputArr indexOfObject:typeOfMinmap];if (index != NSNotFound) {NSArray *minmapNodeArr = [outputArr subarrayWithRange:NSMakeRange(index+1, 50)];NSArray *iconsArr = [minmapNodeArr filteredArrayUsingPredicate: [NSPredicate predicateWithFormat: @"SELF contains[c] %@", IdStr]];if (iconsArr.count > 0) {NSInteger iconArrIndex = [minmapNodeArr indexOfObject:[iconsArr firstObject]];if (iconArrIndex != NSNotFound) {NSArray *images = [minmapNodeArr subarrayWithRange:NSMakeRange(iconArrIndex+1, 10)];for (NSString *subStr in images) {if ([subStr rangeOfString:@"resource"].location != NSNotFound) {break;}NSArray *allIconsArr = [subStr componentsSeparatedByString:@" "];if([subStr rangeOfString:@"type="].location != NSNotFound) {NSString *iconPath = [allIconsArr objectAtIndex:allIconsArr.count-2];iconPath = [iconPath stringByReplacingOccurrencesOfString:@"\"" withString:@""];iconPath = [[iconPath componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] componentsJoinedByString:@""];if ([Help isImageType:iconPath.pathExtension]) {[resultArr addObject:iconPath];}}else {NSString *iconPath = [allIconsArr lastObject];iconPath = [iconPath stringByReplacingOccurrencesOfString:@"\"" withString:@""];iconPath = [[iconPath componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] componentsJoinedByString:@""];if ([Help isImageType:iconPath.pathExtension]) {[resultArr addObject:iconPath];}}}}}}}else if([outputArr filteredArrayUsingPredicate:drawablePredicate].count > 0) {NSArray * containDrawableArr = [outputArr filteredArrayUsingPredicate:drawablePredicate];NSString *typeOfDrawble = [containDrawableArr firstObject];NSInteger index = [outputArr indexOfObject:typeOfDrawble];if (index != NSNotFound) {NSArray *drawableNodeArr = [outputArr subarrayWithRange:NSMakeRange(index+1, 50)];NSArray *iconsArr = [drawableNodeArr filteredArrayUsingPredicate: [NSPredicate predicateWithFormat: @"SELF contains[c] %@", IdStr]];if (iconsArr.count > 0) {NSInteger iconArrIndex = [drawableNodeArr indexOfObject:[iconsArr firstObject]];if (iconArrIndex != NSNotFound) {NSArray *images = [drawableNodeArr subarrayWithRange:NSMakeRange(iconArrIndex+1, 10)];for (NSString *subStr in images) {if ([subStr rangeOfString:@"resource"].location != NSNotFound) {break;}NSArray *tempStrArr = [subStr componentsSeparatedByString:@" "];NSString *typeStr = [tempStrArr lastObject];NSArray *typeArr = [typeStr componentsSeparatedByString:@"="];if (typeArr.count != 2 || ![typeArr.firstObject isEqualToString:@"type"]) {continue;}if (![Help isImageType:[typeArr lastObject]]) {continue;}NSString *iconPath = [tempStrArr objectAtIndex:tempStrArr.count - 2];iconPath = [iconPath stringByReplacingOccurrencesOfString:@"\"" withString:@""];iconPath = [[iconPath componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] componentsJoinedByString:@""];if ([Help isImageType:iconPath.pathExtension]) {[resultArr addObject:iconPath];}}}}}}return resultArr;
}//运行appt
- (NSString *)runAAPTCommondWithArguments:(NSArray *)arguments {NSTask *zipTask = [[NSTask alloc] init];NSString *launchPath = [[NSBundle mainBundle] pathForResource:@"aapt" ofType:@""];if (![[DMFileManager defaultManager] fileExistsAtPath:launchPath]) {return nil;}zipTask.launchPath = launchPath;zipTask.arguments = arguments;NSPipe *pipe;pipe = [NSPipe pipe];[zipTask setStandardOutput: pipe];NSFileHandle *file;file = [pipe fileHandleForReading];[zipTask launch];NSData *data;data = [file readDataToEndOfFile];NSString *output;output = [[NSString alloc] initWithData: dataencoding: NSUTF8StringEncoding];[file closeFile];[zipTask waitUntilExit];//    NSLog(@"output = %@", output);if (output.length <= 0) {return nil;}return output;
}

Mac通过aapt获取apk文件的基本信息相关推荐

  1. 【Android 安全】DEX 加密 ( 代理 Application 开发 | multiple-dex-core 依赖库开发 | 配置元数据 | 获取 apk 文件并准备相关目录 )

    文章目录 一.multiple-dex-core 依赖库作用 二.配置目录元数据 三.multiple-dex-core 代理 Application 四.获取 apk 文件并准备相关目录 五.相关代 ...

  2. python解析apk文件_Python获取apk文件URL地址实例

    Python获取apk文件URL地址实例 更新时间:2013年11月01日 10:22:39   作者:   我要评论 需要提取apk文件的特定URL地址的朋友可以看一下这个代码实例. 工作中经常需要 ...

  3. python示例apk_Python获取apk文件URL地址实例

    工作中经常需要提取apk文件的特定URL地址,如是想到用Python脚本进行自动处理. 需要用到的Python基础知识如下: os.walk() 函数声明:os.walk(top,topdown=Tr ...

  4. java调用aapt_java使用android aapt获取APK信息

    /** * 获取APK的基本信息 * @param apkPath * @return * @throws java.io.IOException */ String osName = System. ...

  5. Android O 获取APK文件权限 Demo案例

    1. 通过 aapt 工具查看 APK权限 C:\Users\zh>adb pull /system/priv-app/Settings . /system/priv-app/Settings/ ...

  6. 获取Google Play Store中的apk文件

    背景: 直接从Google play store中下载应用程序时,应用程序是直接安装在手机上.作为手机用户并无法获得当前应用程序的apk文件. 在某些需要apk测试的情况下,我们就需要单纯的获得某些应 ...

  7. 【Android 安全】DEX 加密 ( Java 工具开发 | apk 文件签名 )

    文章目录 一.生成 jks 文件 二.签名命令 三.执行结果 四.处理 Unsupported major.minor version 52.0 错误 参考博客 : [Android 安全]DEX 加 ...

  8. 【Android 安全】DEX 加密 ( Java 工具开发 | apk 文件对齐 )

    文章目录 一.apk 对齐操作 二.apk 对齐命令 三.apk 对齐操作代码示例 四.apk 对齐执行结果 参考博客 : [Android 安全]DEX 加密 ( 常用 Android 反编译工具 ...

  9. 【Android 安全】DEX 加密 ( Java 工具开发 | 解压 apk 文件 | 加密生成 dex 文件 | 打包未签名 apk 文件 | 文件解压缩相关代码 )

    文章目录 一.解压 apk 文件 二.加密生成 dex 文件 三.打包未签名 apk 文件 四.完整代码示例 五.文件解压缩相关代码 六.执行结果 参考博客 : [Android 安全]DEX 加密 ...

最新文章

  1. Oracle的使用和Oracle安装过程
  2. 机器人时代的资本主义:21世纪的工作,收入和财富
  3. php面向对象mysqli,php+mysqli使用面向对象方式更新数据库实例
  4. MIT与TI研究人员已打造出新型防黑RFID芯片
  5. Umi 4 RC 发布
  6. c++ long 转 short_C精品编程之——C语言的数据类型、运算符、表达式,精品课程...
  7. c# mysql 插入 和 查询_C#对数据库的操作(增删改查)
  8. 广播(有序)跨应用发送简单举例
  9. 【转载】产品经理如何行之有效的提高执行力
  10. flutter的路由工具类
  11. linux拷贝依赖库到指定目录,Linux 批量依赖库拷贝(ldd)
  12. sql统计表中各类型金额_各类型模具设计中“脱料结构”种类、使用范围揭秘,值得收藏...
  13. 如何控制局域网网速_水星无线路由器怎么设置网速限制【设置方法】
  14. 李笑来《自学是门手艺》
  15. 文本相似度计算(中英文)详解实战
  16. 机器学习平台基础知识
  17. 电商类-仿美团页面demo
  18. Glide加载网络图片出现模糊问题
  19. c语言中常量有何作用,正确的C语言常量是什么?
  20. 不要在翻译中迷失:如何进行网站本地化-20150105早读课

热门文章

  1. spring clud config分布式配置中心的简单使用
  2. A bean with that name has already been defined in class path resource [.] and overriding is disabled
  3. 设备树下的 platform 驱动开发框架
  4. 第110章 Caché 函数大全 $ZLCHAR 函数
  5. 面渣逆袭:Spring三十五问,四万字+五十图详解
  6. 我的世界java1.14刷铁机_我的世界1.14版刷铁机怎么做?
  7. 小孢子的神奇之旅——如何阅读MindSpore报错信息系列(1)
  8. 信息孤岛影响_国内企业的痛点,“企业信息孤岛”怎么破?
  9. java和大行自行车哪个好_大行自行车P8和D8哪个好?
  10. 关于RouterOS 国内DDNS服务