123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650 |
- import xml.etree.ElementTree as ET
- import os.path
- namespaces = {'android' : 'http://schemas.android.com/apk/res/android'}
- encoding = 'UTF-8'
- def getPackageName(manifest):
- '''
- 获取包名
- '''
- tree = ET.parse(manifest)
- root = tree.getroot()
- return root.attrib['package']
- def changePackageName(manifest, packageName):
- '''
- 更改包名
- '''
- for key in namespaces:
- ET.register_namespace(key, namespaces[key])
- tree = ET.parse(manifest)
- root = tree.getroot()
- root.attrib['package'] = packageName
- tree.write(manifest, encoding)
- def removeLauncherActivity(manifest):
- '''
- 删除启动的activity
- '''
- for key in namespaces:
- ET.register_namespace(key, namespaces[key])
- tree = ET.parse(manifest)
- root = tree.getroot()
-
- attrName = getNamespacesFormat('android:name', namespaces)
- for node in root.findall('application/activity'):
- if len(node.getchildren()) <= 0:
- continue
- for sub in node.getchildren():
- if sub.tag != 'intent-filter':
- continue
- for sub2 in sub.getchildren():
- if not (sub2.tag == 'category' and sub2.attrib[attrName] == 'android.intent.category.LAUNCHER'):
- continue
- node.remove(sub)
- tree.write(manifest, encoding)
- return node.attrib[attrName]
- return 0
- def removeLauncherActivityByName(manifest,name):
- '''
- 删除启动的activity
- '''
- for key in namespaces:
- ET.register_namespace(key, namespaces[key])
- tree = ET.parse(manifest)
- root = tree.getroot()
- attrName = getNamespacesFormat('android:name', namespaces)
- for node in root.findall('application/activity'):
- print('node ----> ' + node.attrib[attrName])
- if node.attrib[attrName] != name:
- continue
- for sub in node.getchildren():
- if sub.tag != 'intent-filter':
- continue
- for sub2 in sub.getchildren():
- if not (sub2.tag == 'category' and sub2.attrib[attrName] == 'android.intent.category.LAUNCHER'):
- continue
- node.remove(sub)
- tree.write(manifest, encoding)
- return node.attrib[attrName]
- return 0
- def getScreenOrientation(manifest):
- '''
- 获取启动activity的方向
- '''
- for key in namespaces:
- ET.register_namespace(key, namespaces[key])
- tree = ET.parse(manifest)
- root = tree.getroot()
- attrName = getNamespacesFormat('android:name', namespaces)
- attrOrientation = getNamespacesFormat('android:screenOrientation', namespaces)
- for node in root.findall('application/activity'):
- if len(node.getchildren()) <= 0:
- continue
- for sub in node.getchildren():
- if sub.tag != 'intent-filter':
- continue
- for sub2 in sub.getchildren():
- if not (sub2.tag == 'category' and sub2.attrib[attrName] == 'android.intent.category.LAUNCHER'):
- continue
- return node.attrib[attrOrientation]
- return 0
- def addLauncherActivity(manifest, screenOrientation, activity):
- '''
- 添加启动的activity
- '''
- for key in namespaces:
- ET.register_namespace(key, namespaces[key])
- tree = ET.parse(manifest)
- root = tree.getroot()
-
- '''<activity android:name=".LauncherActivity"
- android:theme="@style/LauncherStyle">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>'''
- activity = ET.Element('activity', {'android:name' : activity,
- 'android:theme' : '@android:style/Theme.Holo.Light.NoActionBar.Fullscreen',
- 'android:launchMode' : 'singleTop',
- 'android:configChanges' : 'orientation|screenSize|keyboardHidden',
- 'android:screenOrientation' : screenOrientation})
- intent = ET.Element('intent-filter')
- action = ET.Element('action', {'android:name' : 'android.intent.action.MAIN'})
- category = ET.Element('category', {'android:name' : 'android.intent.category.LAUNCHER'})
- intent.append(action)
- intent.append(category)
- activity.append(intent)
-
- application = root.find('application')
- application.insert(0, activity)
- tree.write(manifest, encoding)
- def changeAppName(manifest, stringRes):
- '''
- 更改app名
- '''
-
- removeLauncherAttr(manifest, 'label')
- return changeApplicationAttr(manifest, 'label', stringRes)
- def getLauncherActivity(root):
- '''
- 获取启动的activity
- '''
- attrName = getNamespacesFormat('android:name', namespaces)
- for node in root.findall('application/activity'):
- if len(node.getchildren()) <= 0:
- continue
- for sub in node.getchildren():
- if sub.tag != 'intent-filter':
- continue
- for sub2 in sub.getchildren():
- if sub2.tag == 'category' and sub2.attrib[attrName] == 'android.intent.category.LAUNCHER':
- return node
- return None
- def getLauncherActivitys(manifest):
- '''
- 获取启动的activity
- '''
- attrName = getNamespacesFormat('android:name', namespaces)
- nodeList = []
- tree = ET.parse(manifest)
- root = tree.getroot()
- for node in root.findall('application/activity'):
- if len(node.getchildren()) <= 0:
- continue
- for sub in node.getchildren():
- if sub.tag != 'intent-filter':
- continue
- for sub2 in sub.getchildren():
- if sub2.tag == 'category' and sub2.attrib[attrName] == 'android.intent.category.LAUNCHER':
- nodeList.append(node)
- return nodeList
- def getLauncherActivityName(manifest):
- '''
- 获取启动的activity
- '''
- for key in namespaces:
- ET.register_namespace(key, namespaces[key])
- tree = ET.parse(manifest)
- root = tree.getroot()
- launcherActivity = getLauncherActivity(root)
- attrName = getNamespacesFormat('android:name', namespaces)
- activityName = launcherActivity.attrib[attrName]
- return activityName
- def addMoreIcon(manifest, icon, switchIcon):
- '''
- 添加多图标
- '''
- for key in namespaces:
- ET.register_namespace(key, namespaces[key])
- tree = ET.parse(manifest)
- root = tree.getroot()
- launcherActivity = getLauncherActivity(root)
- if launcherActivity is None:
- return 1
- attrName = getNamespacesFormat('android:name', namespaces)
- activityName = launcherActivity.attrib[attrName]
- activityAlias = ET.Element('activity-alias', {'android:name' : 'com.jmhy.sdk.icon.normal',
- 'android:enabled' : 'false',
- 'android:icon' : icon,
- 'android:targetActivity' : activityName})
- activityAlias2 = ET.Element('activity-alias', {'android:name' : 'com.jmhy.sdk.icon.switch',
- 'android:enabled' : 'false',
- 'android:icon' : switchIcon,
- 'android:targetActivity' : activityName})
- for item in launcherActivity.getchildren():
- activityAlias.append(item)
- activityAlias2.append(item)
- application = root.find('application')
- application.append(activityAlias)
- application.append(activityAlias2)
- tree.write(manifest, encoding)
- return 0
- def removeLauncherAttr(manifest, attrType):
- '''
- 移除启动的activity的label
- '''
- for key in namespaces:
- ET.register_namespace(key, namespaces[key])
- tree = ET.parse(manifest)
- root = tree.getroot()
- launcherActivity = getLauncherActivity(root)
- if launcherActivity is None:
- return 1
- attrName = getNamespacesFormat('android:%s' % attrType, namespaces)
- if attrName in launcherActivity.attrib:
- del launcherActivity.attrib[attrName]
- tree.write(manifest, encoding)
-
- return 0
- def changeLauncherAttr(manifest, attrType, attrValue):
- '''
- 更改启动的activity的属性
- '''
- for key in namespaces:
- ET.register_namespace(key, namespaces[key])
- tree = ET.parse(manifest)
- root = tree.getroot()
- launcherActivity = getLauncherActivity(root)
- if launcherActivity is None:
- return 1
- attrName = getNamespacesFormat('android:%s' % attrType, namespaces)
- if attrName in launcherActivity.attrib:
- launcherActivity.attrib[attrName] = attrValue
- tree.write(manifest, encoding)
- return 0
- def changeAppIcon(manifest, iconRes):
- '''
- 更改app icon
- '''
-
- removeLauncherAttr(manifest, 'icon')
- return changeApplicationAttr(manifest, 'icon', iconRes)
- def changeApplicationAttr(manifest, attrType, attrValue):
- '''
- 更改Application的某个属性
- '''
- for key in namespaces:
- ET.register_namespace(key, namespaces[key])
- tree = ET.parse(manifest)
- root = tree.getroot()
- application = root.find('application')
-
- attrName = getNamespacesFormat('android:%s' % attrType, namespaces)
- application.attrib[attrName] = attrValue
- tree.write(manifest, encoding)
- return 0
- def addApplicationAttr(manifest, attrType, attrValue):
- '''
- 更改Application的某个属性
- '''
- for key in namespaces:
- ET.register_namespace(key, namespaces[key])
- tree = ET.parse(manifest)
- root = tree.getroot()
- application = root.find('application')
-
- attrName = getNamespacesFormat('android:%s' % attrType, namespaces)
- application.set(attrName,attrValue)
- tree.write(manifest, encoding)
- return 0
- def getApplicationAttr(manifest, attrType):
- '''
- 获取Application的某个属性
- '''
- for key in namespaces:
- ET.register_namespace(key, namespaces[key])
- tree = ET.parse(manifest)
- root = tree.getroot()
- application = root.find('application')
- attrName = getNamespacesFormat('android:%s' % attrType, namespaces)
- if attrName in application.attrib:
- return application.attrib[attrName]
-
- return None
- def getNamespacesFormat(text, namespaces):
- '''
- 格式化带namespaces的属性
- '''
- for key in namespaces:
- text = text.replace('%s:' % key, '{%s}' % namespaces[key])
- return text
- def mergeManifestRes(appManifest, libManifest):
- '''
- 合并主文件
- '''
- if not os.path.exists(libManifest):
- print('file "%s" not exists' % libManifest)
- return 1
- if not os.path.exists(appManifest):
- print('file "%s" not exists' % appManifest)
- return 1
- libInfo = getLibManifestInfo(libManifest)
- appPermission = getManifestPermission(appManifest)
- diffPermission = mergeManifestPermission(appPermission, libInfo['permissionList'])
- mergeManifest(appManifest, diffPermission, libInfo['activityList'])
- return 0
- def getLibManifestInfo(libManifest):
- '''
- 获取框架的主文件参数
- '''
- for key in namespaces:
- ET.register_namespace(key, namespaces[key])
- tree = ET.parse(libManifest)
- root = tree.getroot()
- permissionList = root.findall('permissions/*')
- activityList = root.findall('application/*')
- info = {'permissionList' : permissionList, 'activityList' : activityList}
- return info
- def getManifestPermission(appManifest):
- '''
- 获取主文件参数
- '''
- for key in namespaces:
- ET.register_namespace(key, namespaces[key])
- tree = ET.parse(appManifest)
- root = tree.getroot()
- return root.findall('uses-permission')
- def mergeManifestPermission(appPermission, libPermission):
- '''
- 合并主文件参数
- '''
- newPermissionList = []
- for permission in libPermission:
- if contain(appPermission, permission):
- continue
- newPermissionList.append(permission)
- return newPermissionList
- def contain(nodeList, item):
- '''
- 是否存在
- '''
- attrName = getNamespacesFormat('android:name', namespaces)
- for node in nodeList:
- if node.attrib[attrName] == item.attrib[attrName]:
- return True
- return False
- def mergeManifest(appManifest, permissionList, activityList):
- '''
- 将权限和activity加入到主文件
- '''
- for key in namespaces:
- ET.register_namespace(key, namespaces[key])
- tree = ET.parse(appManifest)
- root = tree.getroot()
-
- for item in permissionList:
- root.insert(0, item)
-
- application = root.find('application')
-
- attrName = getNamespacesFormat('android:roundIcon', namespaces)
- if attrName in application.attrib:
- del application.attrib[attrName]
-
- attrName = getNamespacesFormat('android:testOnly', namespaces)
- if attrName in application.attrib:
- del application.attrib[attrName]
-
- attrName = getNamespacesFormat('android:debuggable', namespaces)
- if attrName in application.attrib:
- del application.attrib[attrName]
-
-
- attrName = getNamespacesFormat('android:name', namespaces)
- for item in application.getchildren():
- if contain(activityList, item):
- application.remove(item)
- for item in activityList:
- application.insert(1, item)
- tree.write(appManifest, encoding)
- def addMetaData(manifest, meta):
- '''
- 添加meta-data
- '''
- for key in namespaces:
- ET.register_namespace(key, namespaces[key])
- tree = ET.parse(manifest)
- root = tree.getroot()
- application = root.find('application')
- for key in meta:
- val = meta[key]
- '''if type(val) == str and val.isdigit():
- element = ET.Element('meta-data', {'android:name' : key, 'android:value' : '\\ ' + val})
- else:
- element = ET.Element('meta-data', {'android:name' : key, 'android:value' : val})'''
- element = ET.Element('meta-data', {'android:name' : key, 'android:value' : val})
- application.append(element)
- tree.write(manifest, encoding)
- def readAllRes(resFile, resList):
- '''
- 读取资源文件
- '''
- tree = ET.parse(resFile)
- root = tree.getroot()
- resList += root.getchildren()
- return resList
- def removeIdFromPublic(pubFile, removeList):
- '''
- 删除重复的资源
- '''
- tree = ET.parse(pubFile)
- root = tree.getroot()
- same = False
- for node in root.getchildren():
- if containPublic(node, removeList):
- print('delete public node : type is %s, name is %s' % (node.attrib['type'], node.attrib['name']))
- root.remove(node)
- same = True
- if same:
- tree.write(pubFile, encoding)
- def removeSameRes2(resFile, resList, removeList):
- '''
- 删除重复的资源
- '''
- tree = ET.parse(resFile)
- root = tree.getroot()
- same = False
- for node in root.getchildren():
- if containRes(node, resList):
-
- root.remove(node)
- removeList.append(node)
- same = True
- if same:
- tree.write(resFile, encoding)
- return removeList
- def removeSameRes(resFile, resList):
- '''
- 删除重复的资源
- '''
- tree = ET.parse(resFile)
- root = tree.getroot()
- same = False
- for node in root.getchildren():
- if containRes(node, resList):
-
- root.remove(node)
- same = True
- if same:
- tree.write(resFile, encoding)
- def containRes(node, resList):
- '''
- 是否重复
- '''
- for item in resList:
- if item.tag == node.tag and item.attrib['name'] == node.attrib['name']:
- return True
- return False
- def containPublic(node, removeList):
- '''
- 是否重复
- '''
- for item in removeList:
- if item.tag == node.attrib['type'] and item.attrib['name'] == node.attrib['name']:
- return True
- return False
- def removeRootAttr(manifest, attrType):
- for key in namespaces:
- ET.register_namespace(key, namespaces[key])
- tree = ET.parse(manifest)
- root = tree.getroot()
- attrName = getNamespacesFormat('android:%s' % attrType, namespaces)
- if attrName in root.attrib:
- del root.attrib[attrName]
- tree.write(manifest, encoding)
-
- return 0
- def deleteActivityByName(manifest,activityName):
- '''
- 删除activity
- '''
- attrName = getNamespacesFormat('android:name', namespaces)
- for key in namespaces:
- ET.register_namespace(key, namespaces[key])
- targetTree = ET.parse(manifest)
- targetRoot = targetTree.getroot()
- appNode = targetRoot.find('application')
- activitys = appNode.findall('activity')
- for activity in activitys:
- if activity.attrib[attrName] == activityName:
- print('delete ------------------> ' + activityName)
- appNode.remove(activity)
- targetTree.write(manifest, encoding)
- break
- def getActivityByName(root,activityName):
- '''
- 获取activity
- '''
- attrName = getNamespacesFormat('android:name', namespaces)
- for node in root.findall('application/activity'):
- print ('activity name = ' + node.attrib[attrName])
- if node.attrib[attrName] == activityName:
- return node
- return None
- def formatXml(manifest):
- indent = '\t'
- newline = '\n'
- tree = ET.parse(manifest)
- root = tree.getroot()
- prettyXml(root, indent, newline, level=0)
- ET.dump(root)
- return 0
- def prettyXml(element, indent, newline, level = 0):
- if element:
- if element.text == None or element.text.isspace():
- element.text = newline + indent * (level + 1)
- else:
- element.text = newline + indent * (level + 1) + element.text.strip() + newline + indent * (level + 1)
-
-
- temp = list(element)
- for subelement in temp:
- if temp.index(subelement) < (len(temp) - 1):
- subelement.tail = newline + indent * (level + 1)
- else:
- subelement.tail = newline + indent * level
- prettyXml(subelement, indent, newline, level = level + 1)
|