Мне хотелось получить информацию об APK-файлах (включая разделенные APK-файлы), даже если они находятся внутри сжатых zip-файлов (без их распаковки). В моем случае это включает в себя различные вещи, такие как имя пакета, код версии, имя версии, метка приложения, значок приложения, а также то, является ли это разделенным APK-файлом или нет.
Обратите внимание, что я хочу сделать все это внутри приложения Android, а не с помощью ПК, поэтому некоторые инструменты могут быть недоступны для использования.
Проблема
Это означает, что я не могу используйте функцию getPackageArchiveInfo, так как для этой функции требуется путь к APK-файлу, и она работает только с файлами без разделения apk.
Короче говоря, для этого не существует встроенной функции, поэтому мне нужно найти способ сделать это, перейдя в заархивированный файл, используя входной поток в качестве входных данных для его анализа в функции.
В Интернете есть различные решения, в том числе за пределами Android, но я не знаю ни одного стабильного и работающего во всех случаях. Многие из них могут быть хороши даже для Android (пример здесь), но при синтаксическом анализе может произойти сбой, и вместо Uri/InputStream может потребоваться путь к файлу.
Что я нашел и попробовал
Я нашел это на StackOverflow, но, к сожалению, согласно моим тестам, он всегда генерирует контент, но в некоторых редких случаях это недопустимый XML content.
На данный момент я обнаружил имена пакетов этих приложений и коды их версий, которые анализатору не удалось проанализировать, поскольку выходной XML-контент недействителен:
- com.farproc.wifi.analyzer 139
- com.teslacoilsw.launcherclientproxy 2
- com.hotornot.app 3072
- android 29 (это само системное приложение «Android System»)
- com.google.android.videos 41300042
- com.facebook.katana 201518851
- com.keramidas.TitaniumBackupPro 10
- com.google.android.apps.tachyon 2985033
- com.google.android.apps.photos 3594753
- Для #1, #2 я получил очень странный контент, начиная с
return decompressXML(zipInputStream.readBytes())
// }
}
}
}
return null
}
/**
* Binary XML doc ending Tag
*/
private var endDocTag = 0x00100101
/**
* Binary XML start Tag
*/
private var startTag = 0x00100102
/**
* Binary XML end Tag
*/
private var endTag = 0x00100103
/**
* Reference var for spacing
* Used in prtIndent()
*/
private var spaces = " "
/**
* Parse the 'compressed' binary form of Android XML docs
* such as for AndroidManifest.xml in .apk files
* Source: http://stackoverflow.com/questions/2097 ... 89#4761689
*
* @param xml Encoded XML content to decompress
*/
private fun decompressXML(xml: ByteArray): String {
val resultXml = StringBuilder()
// Compressed XML file/bytes starts with 24x bytes of data,
// 9 32 bit words in little endian order (LSB first):
// 0th word is 03 00 08 00
// 3rd word SEEMS TO BE: Offset at then of StringTable
// 4th word is: Number of strings in string table
// WARNING: Sometime I indiscriminently display or refer to word in
// little endian storage format, or in integer format (ie MSB first).
val numbStrings = lew(xml, 4 * 4)
// StringIndexTable starts at offset 24x, an array of 32 bit LE offsets
// of the length/string data in the StringTable.
val sitOff = 0x24 // Offset of start of StringIndexTable
// StringTable, each string is represented with a 16 bit little endian
// character count, followed by that number of 16 bit (LE) (Unicode) chars.
val stOff = sitOff + numbStrings * 4 // StringTable follows StrIndexTable
// XMLTags, The XML tag tree starts after some unknown content after the
// StringTable. There is some unknown data after the StringTable, scan
// forward from this point to the flag for the start of an XML start tag.
var xmlTagOff = lew(xml, 3 * 4) // Start from the offset in the 3rd word.
// Scan forward until we find the bytes: 0x02011000(x00100102 in normal int)
run {
var ii = xmlTagOff
while (ii < xml.size - 4) {
if (lew(xml, ii) == startTag) {
xmlTagOff = ii
break
}
ii += 4
}
} // end of hack, scanning for start of first start tag
// XML tags and attributes:
// Every XML start and end tag consists of 6 32 bit words:
// 0th word: 02011000 for startTag and 03011000 for endTag
// 1st word: a flag?, like 38000000
// 2nd word: Line of where this tag appeared in the original source file
// 3rd word: FFFFFFFF ??
// 4th word: StringIndex of NameSpace name, or FFFFFFFF for default NS
// 5th word: StringIndex of Element Name
// (Note: 01011000 in 0th word means end of XML document, endDocTag)
// Start tags (not end tags) contain 3 more words:
// 6th word: 14001400 meaning??
// 7th word: Number of Attributes that follow this tag(follow word 8th)
// 8th word: 00000000 meaning??
// Attributes consist of 5 words:
// 0th word: StringIndex of Attribute Name's Namespace, or FFFFFFFF
// 1st word: StringIndex of Attribute Name
// 2nd word: StringIndex of Attribute Value, or FFFFFFF if ResourceId used
// 3rd word: Flags?
// 4th word: str ind of attr value again, or ResourceId of value
// TMP, dump string table to tr for debugging
//tr.addSelect("strings", null);
//for (int ii=0; ii