#! /usr/bin/env python3import sysfrom zipfile import ZipFileclass ApkDiff:# resources.arsc is ignored due to https://issuetracker.google.com/issues/110237303# May be fixed in Android Gradle Plugin 3.4IGNORE_FILES = ["META-INF/MANIFEST.MF", "META-INF/SIGNAL_S.RSA", "META-INF/SIGNAL_S.SF", "resources.arsc"]def compare(self, sourceApk, destinationApk):sourceZip = ZipFile(sourceApk, 'r')destinationZip = ZipFile(destinationApk, 'r')if self.compareManifests(sourceZip, destinationZip) and self.compareEntries(sourceZip, destinationZip) == True:print("APKs match!")else:print("APKs don't match!")def compareManifests(self, sourceZip, destinationZip):sourceEntrySortedList = sorted(sourceZip.namelist())destinationEntrySortedList = sorted(destinationZip.namelist())for ignoreFile in self.IGNORE_FILES:while ignoreFile in sourceEntrySortedList: sourceEntrySortedList.remove(ignoreFile)while ignoreFile in destinationEntrySortedList: destinationEntrySortedList.remove(ignoreFile)if len(sourceEntrySortedList) != len(destinationEntrySortedList):print("Manifest lengths differ!")for (sourceEntryName, destinationEntryName) in zip(sourceEntrySortedList, destinationEntrySortedList):if sourceEntryName != destinationEntryName:print("Sorted manifests don't match, %s vs %s" % (sourceEntryName, destinationEntryName))return Falsereturn Truedef compareEntries(self, sourceZip, destinationZip):sourceInfoList = list(filter(lambda sourceInfo: sourceInfo.filename not in self.IGNORE_FILES, sourceZip.infolist()))destinationInfoList = list(filter(lambda destinationInfo: destinationInfo.filename not in self.IGNORE_FILES, destinationZip.infolist()))if len(sourceInfoList) != len(destinationInfoList):print("APK info lists of different length!")return Falsefor sourceEntryInfo in sourceInfoList:for destinationEntryInfo in list(destinationInfoList):if sourceEntryInfo.filename == destinationEntryInfo.filename:sourceEntry = sourceZip.open(sourceEntryInfo, 'r')destinationEntry = destinationZip.open(destinationEntryInfo, 'r')if self.compareFiles(sourceEntry, destinationEntry) != True:print("APK entry %s does not match %s!" % (sourceEntryInfo.filename, destinationEntryInfo.filename))return FalsedestinationInfoList.remove(destinationEntryInfo)breakreturn Truedef compareFiles(self, sourceFile, destinationFile):sourceChunk = sourceFile.read(1024)destinationChunk = destinationFile.read(1024)while sourceChunk != b"" or destinationChunk != b"":if sourceChunk != destinationChunk:return FalsesourceChunk = sourceFile.read(1024)destinationChunk = destinationFile.read(1024)return Trueif __name__ == '__main__':if len(sys.argv) != 3:print("Usage: apkdiff <pathToFirstApk> <pathToSecondApk>")sys.exit(1)ApkDiff().compare(sys.argv[1], sys.argv[2])
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。