123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455 |
- 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 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
- '''<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名
- '''
- # 移除主activity的label
- 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 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
- '''
- # 移除主activity的图标
- 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')
- # Namespaces
- attrName = getNamespacesFormat('android:%s' % attrType, namespaces)
- application.attrib[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)
- # activity
- 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 removeSameRes(resFile, resList):
- '''
- 删除重复的资源
- '''
- tree = ET.parse(resFile)
- root = tree.getroot()
- same = False
- for node in root.getchildren():
- if containRes(node, resList):
- print('delete node : tag is %s, name is %s' % (node.tag, node.attrib['name']))
- 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 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
|