@@ -45,6 +45,12 @@ extension on String {
4545 return (matches.isNotEmpty) ? matches.first.group (group)! : null ;
4646 }
4747
48+ Map <K , V > foldToMap <K ,V >(String regexp, K Function (RegExpMatch match) key, V Function (RegExpMatch match, V ? prev) value) {
49+ Map <K ,V > map = {};
50+ for (var m in RegExp (regexp).allMatches (this )) map.update (key (m), (v) => value (m, v), ifAbsent: () => value (m, null ));
51+ return map;
52+ }
53+
4854 Map <K , V > toMap <K ,V >(String regexp, K Function (RegExpMatch match) key, V Function (RegExpMatch match) value) {
4955 return {for (var m in RegExp (regexp).allMatches (this )) key (m) : value (m)};
5056 }
@@ -100,7 +106,7 @@ class ApkReader {
100106 //I just put '&& true' there so I could conveniently switch it off
101107 static bool DEBUG = ! kReleaseMode && true ;
102108 static String TEST_FILE = /*r'C:\Users\Alex\Downloads\com.atono.dropticket.apk'*/ '' ;
103- static late Future <String > resourceDump;
109+ static late Future <Map < String , Resource > > resourceDump;
104110 static late Future <Map <int , String >> stringDump;
105111 static late Future <Archive > apkArchive;
106112
@@ -137,24 +143,18 @@ class ApkReader {
137143 .replaceAllMapped (RegExp ('([cC]olor=[\' "])(type([0-9])+/([0-9]*))' ), (m) => m.group (1 )! + '#' + (int .parse (m.group (4 )! ).toRadixString (16 ).padLeft (8 , '0' )) )
138144 .replaceAllMapped (RegExp ('([\\ s\\ n]android:fillType=[\' "])([0-9]*)' ), (m) => m.group (1 )! + (fillType[m.group (2 )! ] ?? "winding" ) );
139145 }
140-
141- //TODO use a map to avoid searching for values twice
146+
142147 static Future <Resource ?> getResources (String resId) async {
143- String resources = await resourceDump;
144- ResType ? type;
148+ Map <String , Resource > resources = await resourceDump;
145149 if (DEBUG ) log ("checking RES-ID: $resId " );
146- Iterable <dynamic >? resCodes = resources.findAllAnd ('(^|\\ s|\\ n)*$resId [\\ s]+.*\\ st=0x0*([^\\ s\\ n]*).*\\ sd=0x0*([^\\ s\\ n]*)[\\ s|\\ n]' , (m) =>
147- ((type ?? = getResType (m.group (2 )! )) == ResType .FILE ) ? int .parse (m.group (3 )! , radix: 16 ) : m.group (3 )! );
148- if (resCodes.isNotEmpty) {
149- if (DEBUG ) log ("found RES-VALUES: $resCodes of RES-TYPE: $type for RES-ID: $resId " );
150- //Fix 'type' not resolved in release mode because of the lazy nature of the 'map' function
151- resCodes.first;
152- if (type == ResType .COLOR ) return Resource (resCodes.map ((e)=> e), type! );
153- //resCodes as Iterable<int>;
150+ var resource = resources[resId];
151+ if (resource != null ) {
152+ if (DEBUG ) log ("found RES-VALUES: ${resource .values } of RES-TYPE: ${resource .type } for RES-ID: $resId " );
153+ if (resource.type == ResType .COLOR ) return resource;
154154 Map <int , String > strings = await stringDump;
155- Iterable <String > files = strings.getAll (resCodes. map ((e) => e ));
156- if (DEBUG ) log ("found RES-FILES: $files of RES-TYPE: $type for RES-ID: $resId " );
157- return files.isNotEmpty ? Resource (files, type! ) : null ;
155+ Iterable <String > files = strings.getAll (resource.values. map ((e) => int . parse (e, radix : 16 ) ));
156+ if (DEBUG ) log ("found RES-FILES: $files of RES-TYPE: ${ resource . type } for RES-ID: $resId " );
157+ return files.isNotEmpty ? Resource (files, resource. type) : null ;
158158 }
159159 else return null ;
160160 }
@@ -242,9 +242,12 @@ class ApkReader {
242242 data = pData;
243243 TEST_FILE = data.fileName;
244244 //resourceDump = Process.run('${Env.TOOLS_DIR}\\aapt.exe', ['dump', 'resources', TEST_FILE]).then<String>((p) => p.stdout.toString());
245- resourceDump = Process .run ('${Env .TOOLS_DIR }\\ aapt.exe' , ['dump' , 'resources' , TEST_FILE ]).then <String >((p) => p.stdout.toString ());
245+ resourceDump = Process .run ('${Env .TOOLS_DIR }\\ aapt.exe' , ['dump' , 'resources' , TEST_FILE ]).then ((p) =>
246+ p.stdout.toString ().foldToMap (r'(^|\n)\s*resource (0x[0-9a-zA-Z]*)[\s]+.*\st=0x0*([^\s\n]*).*\sd=0x0*([^\s\n]*)[\s|\n]' , (m) => m.group (2 )! ,
247+ (m,old) => Resource ((old != null ) ? ((old.values as ListQueue <String >)..addAll ([m.group (4 )! ])) : ListQueue <String >.from ([m.group (4 )! ]), old? .type ?? getResType (m.group (3 )! )) )
248+ );
246249 //strings.findAll('(^|\\n|\\s)*String\\s+#(${resCodes.join("|")})\\s*:\\s*([^\\s\\n]*)', 3);
247- stringDump = Process .run ('${Env .TOOLS_DIR }\\ aapt.exe' , ['dump' , 'strings' , TEST_FILE ]).then < Map < int , String >> ((p) =>
250+ stringDump = Process .run ('${Env .TOOLS_DIR }\\ aapt.exe' , ['dump' , 'strings' , TEST_FILE ]).then ((p) =>
248251 p.stdout.toString ().toMap (r'(^|\n|\s)*String\s+#([0-9]*)\s*:\s*([^\s\n]*)' , (m) => int .parse (m.group (2 )! ), (m) => m.group (3 )! )
249252 );
250253 initArchive ();
0 commit comments