Browse Source

兼容aapt2

yhz 5 years ago
parent
commit
e1209deb48
7 changed files with 193 additions and 48 deletions
  1. 4 0
      config_utils.py
  2. 4 0
      config_utils_record.py
  3. 4 0
      config_utils_shanshen.py
  4. 15 3
      file_utils.py
  5. 66 19
      package_utils.py
  6. 50 13
      package_utils_record.py
  7. 50 13
      package_utils_shanshen.py

+ 4 - 0
config_utils.py

@@ -38,6 +38,10 @@ def checkChannelConfig(config):
         config['splitDex'] = True
     if 'clearCache' not in config:
         config['clearCache'] = True
+    if 'aapt2disable' not in config:
+        config['aapt2disable'] = False
+    if 'v2disable' not in config:
+        config['v2disable'] = False
     if 'screenOrientation' not in config:
         config['screenOrientation'] = 'landscape'
     if 'outName' not in config:

+ 4 - 0
config_utils_record.py

@@ -35,6 +35,10 @@ def checkChannelConfig(config):
         config['splitDex'] = True
     if 'clearCache' not in config:
         config['clearCache'] = True
+    if 'aapt2disable' not in config:
+        config['aapt2disable'] = False
+    if 'v2disable' not in config:
+        config['v2disable'] = False
     if 'screenOrientation' not in config:
         config['screenOrientation'] = 'landscape'
     if 'outName' not in config:

+ 4 - 0
config_utils_shanshen.py

@@ -29,6 +29,10 @@ def checkChannelConfig(config):
         config['splitDex'] = True
     if 'clearCache' not in config:
         config['clearCache'] = True
+    if 'aapt2disable' not in config:
+        config['aapt2disable'] = False
+    if 'v2disable' not in config:
+        config['v2disable'] = False
     if 'outName' not in config:
         config['outName'] = config['name']
         

+ 15 - 3
file_utils.py

@@ -72,7 +72,7 @@ def getCurrentPath():
     '''
     return sys.path[0]
 
-def execFormatCmd(cmd):
+def execFormatCmd(cmd, cd = None):
     '''
     执行cmd命令
 
@@ -86,7 +86,7 @@ def execFormatCmd(cmd):
     print(p.read())'''
     ret = 0
     try:
-        s = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
+        s = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, cwd=cd)
         stdoutput, erroutput = s.communicate()
 
         if platform.system() == 'Windows':
@@ -256,6 +256,12 @@ def getAAPTPath():
     '''
     return getToolWithSystem('aapt')
 
+def getAAPT2Path():
+    '''
+    获取aapt2
+    '''
+    return getToolWithSystem('aapt2')
+
 def getAndroidCompileToolPath():
     '''
     获取android.jar
@@ -268,6 +274,12 @@ def getDxPath():
     '''
     return getFullToolPath('dx.jar')
 
+def getD8Path():
+    '''
+    获取d8.jar
+    '''
+    return getFullToolPath('d8.jar')
+
 def getAlignPath():
     '''
     获取zipalign
@@ -284,7 +296,7 @@ def getApkToolPath():
     '''
     获取apktool.jar
     '''
-    return getFullToolPath('apktool_2.3.4.jar')
+    return getFullToolPath('apktool_2.4.0.jar')
 
 def getBaksmaliPath():
     '''

+ 66 - 19
package_utils.py

@@ -21,6 +21,7 @@ import json
 import sys
 import importlib
 import uuid
+import zipfile
 
 ignoreLauncher = ['jm_ysdk', 'jm_yijie', 'jm_quick', 'jm_beiyu', 'jm_xq_jrtt']
 
@@ -655,7 +656,6 @@ def generateNewRFile(game, sdk, subChannel, config):
     生成新的R文件
     '''
     decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
-    aapt = file_utils.getAAPTPath()
     androidPlatforms = file_utils.getAndroidCompileToolPath()
     manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
     decomplieResPath = file_utils.getFullPath(decompliePath, 'res')
@@ -664,32 +664,67 @@ def generateNewRFile(game, sdk, subChannel, config):
     if not os.path.exists(compliePath):
         os.makedirs(compliePath)
 
-    ret = file_utils.getExecPermission(aapt)
-    if ret:
-        return ret
-
     # 生成R文件
     print('create R.java ...')
-    createRCmd = '"%s" p -f -m -J "%s" -S "%s" -I "%s" -M "%s"' % (aapt, compliePath, decomplieResPath, androidPlatforms, manifest)
-    ret = file_utils.execFormatCmd(createRCmd)
-    if ret:
-        return ret
+    if config['aapt2disable']:
+        aapt = file_utils.getAAPTPath()
+        ret = file_utils.getExecPermission(aapt)
+        if ret:
+            return ret
+        createRCmd = '"%s" p -f -m -J "%s" -S "%s" -I "%s" -M "%s"' % (aapt, compliePath, decomplieResPath, androidPlatforms, manifest)
+        ret = file_utils.execFormatCmd(createRCmd)
+        if ret:
+            return ret
+    else:
+        # compile
+        aapt = file_utils.getAAPT2Path()
+        ret = file_utils.getExecPermission(aapt)
+        if ret:
+            return ret
+
+        print('compiled res ...')
+        complieResPath = os.path.join(compliePath, 'compiled')
+        complieResCmd = '"%s" compile --dir "%s" -o "%s"' % (aapt, decomplieResPath, complieResPath)
+        file_utils.execFormatCmd(complieResCmd)
+
+        # unzip
+        print('unzip compiled res ...')
+        unzipResPath = os.path.join(compliePath, 'aapt2_res')
+        with zipfile.ZipFile(complieResPath) as zf:
+            zf.extractall(unzipResPath)
+            print('create unzip %s' % unzipResPath)
+
+        # link
+        print('link res ...')
+        outApk = os.path.join(compliePath, 'res.apk')
+        linkResCmd = '"%s" link -o "%s" -I "%s" --manifest "%s" --java "%s" --auto-add-overlay' % (aapt, outApk, androidPlatforms, manifest, compliePath)
+        for filename in os.listdir(unzipResPath):
+            linkResCmd += ' -R "%s"' % filename
+        ret = file_utils.execFormatCmd(linkResCmd, unzipResPath)
+        if ret:
+            return ret
 
     # 编译R文件
     print('complie R.java ...')
     packageName = xml_utils.getPackageName(manifest)
     packagePath = file_utils.getPackagePath(compliePath, packageName)
     RSourceFile = os.path.join(packagePath, 'R.java')
-    complieRCmd = 'javac -source 1.7 -target 1.7 -encoding UTF-8 "%s"' % RSourceFile
+    complieRCmd = 'javac -source 1.8 -target 1.8 -encoding UTF-8 "%s"' % RSourceFile
     ret = file_utils.execFormatCmd(complieRCmd)
     if ret:
         return ret
 
     # 生成dex
     print('dex R.class ...')
-    dx = file_utils.getDxPath()
     outDex = os.path.join(compliePath, 'classes.dex')
-    ret = file_utils.execJarCmd(dx, '--dex --output="%s" "%s"' % (outDex, compliePath))
+    if config['aapt2disable']:
+        dx = file_utils.getDxPath()
+        dexCmd = '--dex --no-warning --output="%s" "%s"' % (outDex, compliePath)
+    else:
+        dx = file_utils.getD8Path()
+        clazz = os.path.join(packagePath, '*.class')
+        dexCmd = '--lib "%s" --output "%s" %s' % (androidPlatforms, compliePath, clazz)
+    ret = file_utils.execJarCmd(dx, dexCmd)
     if ret:
         return ret
 
@@ -715,13 +750,17 @@ def packJar(game, sdk, subChannel, config):
     splitDex = config['splitDex']
     decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
     outPath = file_utils.getFullPath(decompliePath, 'gen')
-    dx = file_utils.getDxPath()
 
     if not os.path.exists(outPath):
         os.makedirs(outPath)
 
-    # --no-warning
-    dexCmd = '--dex --multi-dex --no-warning --output="%s"' % outPath
+    if config['aapt2disable']:
+        dx = file_utils.getDxPath()
+        dexCmd = '--dex --multi-dex --no-warning --output="%s"' % outPath
+    else:
+        dx = file_utils.getD8Path()
+        androidPlatforms = file_utils.getAndroidCompileToolPath()
+        dexCmd = '--lib "%s" --output "%s"' % (androidPlatforms, outPath)
 
     # 找到所有lib依赖
     sdkPath = file_utils.getFullSDKPath(sdk)
@@ -785,13 +824,17 @@ def packLogJar(game, sdk, subChannel, config, logSdk):
     '''
     decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
     outPath = file_utils.getFullPath(decompliePath, 'gen')
-    dx = file_utils.getDxPath()
 
     if not os.path.exists(outPath):
         os.makedirs(outPath)
 
-    # --no-warning
-    dexCmd = '--dex --multi-dex --no-warning --output="%s"' % outPath
+    if config['aapt2disable']:
+        dx = file_utils.getDxPath()
+        dexCmd = '--dex --multi-dex --no-warning --output="%s"' % outPath
+    else:
+        dx = file_utils.getD8Path()
+        androidPlatforms = file_utils.getAndroidCompileToolPath()
+        dexCmd = '--lib "%s" --output "%s"' % (androidPlatforms, outPath)
 
     # 找到所有lib依赖
     sdkPath = file_utils.getFullLogSDKPath(logSdk)
@@ -953,7 +996,11 @@ def recomplie(game, sdk, subChannel, config):
     decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
     outApk = file_utils.getOutApkPath(game, sdk, subChannel, config['cache'])
 
-    return file_utils.execJarCmd(apktoolPath, 'b -f "%s" -o "%s"' % (decompliePath, outApk))
+    useAppt2 = ' --use-aapt2'
+    if config['aapt2disable']:
+        useAppt2 = ''
+
+    return file_utils.execJarCmd(apktoolPath, 'b -f "%s" -o "%s" %s' % (decompliePath, outApk, useAppt2))
 
 def alignApk(game, sdk, subChannel, config):
     '''

+ 50 - 13
package_utils_record.py

@@ -21,6 +21,7 @@ import json
 import sys
 import importlib
 import uuid
+import zipfile
 
 from xml.etree import ElementTree as ET
 from xml.etree.ElementTree import SubElement
@@ -710,7 +711,6 @@ def generateNewRFile(game, sdk, subChannel, config):
     生成新的R文件
     '''
     decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
-    aapt = file_utils.getAAPTPath()
     androidPlatforms = file_utils.getAndroidCompileToolPath()
     manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
     decomplieResPath = file_utils.getFullPath(decompliePath, 'res')
@@ -719,16 +719,45 @@ def generateNewRFile(game, sdk, subChannel, config):
     if not os.path.exists(compliePath):
         os.makedirs(compliePath)
 
-    ret = file_utils.getExecPermission(aapt)
-    if ret:
-        return ret
-
     # 生成R文件
     print('create R.java ...')
-    createRCmd = '"%s" p -f -m -J "%s" -S "%s" -I "%s" -M "%s"' % (aapt, compliePath, decomplieResPath, androidPlatforms, manifest)
-    ret = file_utils.execFormatCmd(createRCmd)
-    if ret:
-        return ret
+    if config['aapt2disable']:
+        aapt = file_utils.getAAPTPath()
+        ret = file_utils.getExecPermission(aapt)
+        if ret:
+            return ret
+        createRCmd = '"%s" p -f -m -J "%s" -S "%s" -I "%s" -M "%s"' % (aapt, compliePath, decomplieResPath, androidPlatforms, manifest)
+        ret = file_utils.execFormatCmd(createRCmd)
+        if ret:
+            return ret
+    else:
+        # compile
+        aapt = file_utils.getAAPT2Path()
+        ret = file_utils.getExecPermission(aapt)
+        if ret:
+            return ret
+
+        print('compiled res ...')
+        complieResPath = os.path.join(compliePath, 'compiled')
+        complieResCmd = '"%s" compile --dir "%s" -o "%s"' % (aapt, decomplieResPath, complieResPath)
+        file_utils.execFormatCmd(complieResCmd)
+
+        # unzip
+        print('unzip compiled res ...')
+        unzipResPath = os.path.join(compliePath, 'aapt2_res')
+        with zipfile.ZipFile(complieResPath) as zf:
+            zf.extractall(unzipResPath)
+            print('create unzip %s' % unzipResPath)
+
+        # link
+        print('link res ...')
+        outApk = os.path.join(compliePath, 'res.apk')
+        linkResCmd = '"%s" link -o "%s" -I "%s" --manifest "%s" --java "%s" --auto-add-overlay' % (aapt, outApk, androidPlatforms, manifest, compliePath)
+        for filename in os.listdir(unzipResPath):
+            linkResCmd += ' -R "%s"' % filename
+        ret = file_utils.execFormatCmd(linkResCmd, unzipResPath)
+        if ret:
+            return ret
 
     # 编译R文件
     print('complie R.java ...')
@@ -770,13 +799,17 @@ def packJar(game, sdk, subChannel, config):
     splitDex = config['splitDex']
     decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
     outPath = file_utils.getFullPath(decompliePath, 'gen')
-    dx = file_utils.getDxPath()
 
     if not os.path.exists(outPath):
         os.makedirs(outPath)
 
-    # --no-warning
-    dexCmd = '--dex --multi-dex --no-warning --output="%s"' % outPath
+    if config['aapt2disable']:
+        dx = file_utils.getDxPath()
+        dexCmd = '--dex --multi-dex --no-warning --output="%s"' % outPath
+    else:
+        dx = file_utils.getD8Path()
+        androidPlatforms = file_utils.getAndroidCompileToolPath()
+        dexCmd = '--lib "%s" --output "%s"' % (androidPlatforms, outPath)
 
     # 找到所有lib依赖
     sdkPath = file_utils.getFullSDKPath(sdk)
@@ -956,7 +989,11 @@ def recomplie(game, sdk, subChannel, config):
     decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
     outApk = file_utils.getOutApkPath(game, sdk, subChannel, config['cache'])
 
-    return file_utils.execJarCmd(apktoolPath, 'b -f "%s" -o "%s"' % (decompliePath, outApk))
+    useAppt2 = ' --use-aapt2'
+    if config['aapt2disable']:
+        useAppt2 = ''
+
+    return file_utils.execJarCmd(apktoolPath, 'b -f "%s" -o "%s" %s' % (decompliePath, outApk, useAppt2))
 
 def alignApk(game, sdk, subChannel, config):
     '''

+ 50 - 13
package_utils_shanshen.py

@@ -21,6 +21,7 @@ import json
 import sys
 import importlib
 import uuid
+import zipfile
 
 def pack(game, sdk, config):
     config['cache'] = uuid.uuid1()
@@ -598,7 +599,6 @@ def generateNewRFile(game, sdk, subChannel, config):
     生成新的R文件
     '''
     decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
-    aapt = file_utils.getAAPTPath()
     androidPlatforms = file_utils.getAndroidCompileToolPath()
     manifest = os.path.join(decompliePath, 'AndroidManifest.xml')
     decomplieResPath = file_utils.getFullPath(decompliePath, 'res')
@@ -607,16 +607,45 @@ def generateNewRFile(game, sdk, subChannel, config):
     if not os.path.exists(compliePath):
         os.makedirs(compliePath)
 
-    ret = file_utils.getExecPermission(aapt)
-    if ret:
-        return ret
-
     # 生成R文件
     print('create R.java ...')
-    createRCmd = '"%s" p -f -m -J "%s" -S "%s" -I "%s" -M "%s"' % (aapt, compliePath, decomplieResPath, androidPlatforms, manifest)
-    ret = file_utils.execFormatCmd(createRCmd)
-    if ret:
-        return ret
+    if config['aapt2disable']:
+        aapt = file_utils.getAAPTPath()
+        ret = file_utils.getExecPermission(aapt)
+        if ret:
+            return ret
+        createRCmd = '"%s" p -f -m -J "%s" -S "%s" -I "%s" -M "%s"' % (aapt, compliePath, decomplieResPath, androidPlatforms, manifest)
+        ret = file_utils.execFormatCmd(createRCmd)
+        if ret:
+            return ret
+    else:
+        # compile
+        aapt = file_utils.getAAPT2Path()
+        ret = file_utils.getExecPermission(aapt)
+        if ret:
+            return ret
+
+        print('compiled res ...')
+        complieResPath = os.path.join(compliePath, 'compiled')
+        complieResCmd = '"%s" compile --dir "%s" -o "%s"' % (aapt, decomplieResPath, complieResPath)
+        file_utils.execFormatCmd(complieResCmd)
+
+        # unzip
+        print('unzip compiled res ...')
+        unzipResPath = os.path.join(compliePath, 'aapt2_res')
+        with zipfile.ZipFile(complieResPath) as zf:
+            zf.extractall(unzipResPath)
+            print('create unzip %s' % unzipResPath)
+
+        # link
+        print('link res ...')
+        outApk = os.path.join(compliePath, 'res.apk')
+        linkResCmd = '"%s" link -o "%s" -I "%s" --manifest "%s" --java "%s" --auto-add-overlay' % (aapt, outApk, androidPlatforms, manifest, compliePath)
+        for filename in os.listdir(unzipResPath):
+            linkResCmd += ' -R "%s"' % filename
+        ret = file_utils.execFormatCmd(linkResCmd, unzipResPath)
+        if ret:
+            return ret
 
     # 编译R文件
     print('complie R.java ...')
@@ -658,13 +687,17 @@ def packJar(game, sdk, subChannel, config):
     splitDex = config['splitDex']
     decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
     outPath = file_utils.getFullPath(decompliePath, 'gen')
-    dx = file_utils.getDxPath()
 
     if not os.path.exists(outPath):
         os.makedirs(outPath)
 
-    # --no-warning
-    dexCmd = '--dex --multi-dex --no-warning --output="%s"' % outPath
+    if config['aapt2disable']:
+        dx = file_utils.getDxPath()
+        dexCmd = '--dex --multi-dex --no-warning --output="%s"' % outPath
+    else:
+        dx = file_utils.getD8Path()
+        androidPlatforms = file_utils.getAndroidCompileToolPath()
+        dexCmd = '--lib "%s" --output "%s"' % (androidPlatforms, outPath)
 
     # 找到所有lib依赖
     sdkPath = file_utils.getFullSDKPath(sdk)
@@ -844,7 +877,11 @@ def recomplie(game, sdk, subChannel, config):
     decompliePath = file_utils.getDecompliePath(game, sdk, subChannel, config['cache'])
     outApk = file_utils.getOutApkPath(game, sdk, subChannel, config['cache'])
 
-    return file_utils.execJarCmd(apktoolPath, 'b -f "%s" -o "%s"' % (decompliePath, outApk))
+    useAppt2 = ' --use-aapt2'
+    if config['aapt2disable']:
+        useAppt2 = ''
+
+    return file_utils.execJarCmd(apktoolPath, 'b -f "%s" -o "%s" %s' % (decompliePath, outApk, useAppt2))
 
 def alignApk(game, sdk, subChannel, config):
     '''