gradle脚本合并libs ,manifest, jnilib

2022-04-20  本文已影响0人  钢镚koala

最近在合并modules或者aar , jar等工作上遇到了一些问题。查找各种文章,最后找到一些解决思路和办法。
希望能帮助到大家。下面这个是早期作者的处理libs, 清单文件等合并的办法。

import com.android.annotations.NonNull
import com.android.manifmerger.ManifestMerger2
import com.android.manifmerger.ManifestMerger2.Invoker
import com.android.manifmerger.ManifestMerger2.MergeType
import com.android.manifmerger.MergingReport
import com.android.manifmerger.PlaceholderEncoder
import com.android.manifmerger.XmlDocument
import com.android.utils.ILogger
import com.google.common.base.Charsets
import com.google.common.io.Files

/**

buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:manifest-merger:25.2.0'
}
}

configurations {
embedded
}

dependencies {
compile configurations.embedded
}

// Paths to embedded jar files
ext.embeddedJars = new ArrayList<String>()
// Paths to embedded aar projects
ext.embeddedAarDirs = new ArrayList<String>()
// List of embedded R classes
ext.embeddedRClasses = new ArrayList<String>()

// Change backslash to forward slash on windows
ext.build_dir = buildDir.path.replace(File.separator, '/');

ext.exploded_aar_dir = "build_dir/intermediates/exploded-aar"; ext.classs_release_dir = "build_dir/intermediates/classes/release";
ext.bundle_release_dir = "build_dir/intermediates/bundles/release"; ext.manifest_aaapt_dir = "build_dir/intermediates/manifests/aapt/release";
ext.generated_rsrc_dir = "$build_dir/generated/source/r/release";

ext.base_r2x_dir = "$build_dir/fat-aar/release/";

afterEvaluate {
// the list of dependency must be reversed to use the right overlay order.
def dependencies = new ArrayList(configurations.embedded.resolvedConfiguration.firstLevelModuleDependencies)
dependencies.reverseEach {
def aarPath = "{exploded_aar_dir}/{it.moduleGroup}/{it.moduleName}/{it.moduleVersion}"
it.moduleArtifacts.each {
artifact ->
if (artifact.type == 'aar') {
if (!embeddedAarDirs.contains(aarPath)) {
embeddedAarDirs.add(aarPath)
}
} else if (artifact.type == 'jar') {
def artifactPath = artifact.file
if (!embeddedJars.contains(artifactPath))
embeddedJars.add(artifactPath)
} else {
throw new Exception("Unhandled Artifact of type ${artifact.type}")
}
}
}

if (dependencies.size() > 0) {
    // Merge Assets
    generateReleaseAssets.dependsOn embedAssets
    embedAssets.dependsOn prepareReleaseDependencies

    // Embed Resources by overwriting the inputResourceSets
    packageReleaseResources.dependsOn embedLibraryResources
    embedLibraryResources.dependsOn prepareReleaseDependencies

    // Embed JNI Libraries
    bundleRelease.dependsOn embedJniLibs
    embedJniLibs.dependsOn transformNative_libsWithSyncJniLibsForRelease

    // Merge Embedded Manifests
    bundleRelease.dependsOn embedManifests
    embedManifests.dependsOn processReleaseManifest

    // Merge proguard files
    embedLibraryResources.dependsOn embedProguard
    embedProguard.dependsOn prepareReleaseDependencies

    // Generate R.java files
    compileReleaseJavaWithJavac.dependsOn generateRJava
    generateRJava.dependsOn processReleaseResources

    // Bundle the java classes
    bundleRelease.dependsOn embedJavaJars
    embedJavaJars.dependsOn compileReleaseJavaWithJavac

    // If proguard is enabled, run the tasks that bundleRelease should depend on before proguard
    if (tasks.findByPath('proguardRelease') != null) {
        proguardRelease.dependsOn embedJavaJars
    } else if (tasks.findByPath('transformClassesAndResourcesWithProguardForRelease') != null) {
        transformClassesAndResourcesWithProguardForRelease.dependsOn embedJavaJars
    }
}

}

task embedLibraryResources << {
println "Running FAT-AAR Task :embedLibraryResources"

def oldInputResourceSet = packageReleaseResources.inputResourceSets
packageReleaseResources.conventionMapping.map("inputResourceSets") {
    getMergedInputResourceSets(oldInputResourceSet)
}

}

private List getMergedInputResourceSets(List inputResourceSet) {
//We need to do this trickery here since the class declared here and that used by the runtime
//are different and results in class cast error
def ResourceSetClass = inputResourceSet.get(0).class

List newInputResourceSet = new ArrayList(inputResourceSet)

embeddedAarDirs.each { aarPath ->
    try {
        def resname = (aarPath.split(exploded_aar_dir)[1]).replace('/', ':');
        def rs = ResourceSetClass.newInstance([resname, true] as Object[])
        rs.addSource(file("$aarPath/res"))
        // println "ResourceSet is " + rs
        newInputResourceSet += rs
    } catch (Exception e) {
        e.printStackTrace();
        throw e;
    }
}

return newInputResourceSet

}

/**

/**

task generateRJava << {
println "Running FAT-AAR Task :generateRJava"

// Now generate the R.java file for each embedded dependency
def libPackageName = new XmlParser().parse(android.sourceSets.main.manifest.srcFile).@package

embeddedAarDirs.each { aarPath ->

    def aarManifest = new XmlParser().parse(file("$aarPath/AndroidManifest.xml"));
    def aarPackageName = aarManifest.@package
    String packagePath = aarPackageName.replace('.', '/')

    // Generate the R.java file and map to current project's R.java
    // This will recreate the class file
    def rTxt = file("$aarPath/R.txt")
    def rMap = new ConfigObject()

    if (rTxt.exists()) {
        rTxt.eachLine {
            line ->
                //noinspection GroovyUnusedAssignment
                def (type, subclass, name, value) = line.tokenize(' ')
                rMap[subclass].putAt(name, type)
        }
    }

    def sb = "package $aarPackageName;" << '\n' << '\n'
    sb << 'public final class R {' << '\n'

    rMap.each {
        subclass, values ->
            sb << "  public static final class $subclass {" << '\n'
            values.each {
                name, type ->
                    sb << "    public static $type $name = ${libPackageName}.R.${subclass}.${name};" << '\n'
            }
            sb << "    }" << '\n'
    }

    sb << '}' << '\n'

    mkdir("$generated_rsrc_dir/$packagePath")
    file("$generated_rsrc_dir/$packagePath/R.java").write(sb.toString())

    embeddedRClasses += "$packagePath/R.class"
    embeddedRClasses += "$packagePath/R\$*.class"
}

}

task collectRClass << {
delete base_r2x_dir
mkdir base_r2x_dir

copy {
    from classs_release_dir
    include embeddedRClasses
    into base_r2x_dir
}

}

task embedRClass(type: org.gradle.jvm.tasks.Jar, dependsOn: collectRClass) {
destinationDir file("$bundle_release_dir/libs/")
from base_r2x_dir
}

/**

/**

task embedManifests << {
println "Running FAT-AAR Task :embedManifests"

ILogger mLogger = new MiLogger()
List<File> libraryManifests = new ArrayList<>()

embeddedAarDirs.each { aarPath ->
    if (!libraryManifests.contains(aarPath)) {
        libraryManifests.add(file("$aarPath/AndroidManifest.xml"))
    }
}

File reportFile = file("${build_dir}/embedManifestReport.txt")

File origManifest = file("$bundle_release_dir/AndroidManifest.xml")
File copyManifest = file("$bundle_release_dir/AndroidManifest.orig.xml")
File aaptManifest = file("$manifest_aaapt_dir/AndroidManifest.xml")

copy {
    from origManifest.parentFile
    into copyManifest.parentFile
    include origManifest.name
    rename(origManifest.name, copyManifest.name)
}

try {
    Invoker manifestMergerInvoker = ManifestMerger2.newMerger(copyManifest, mLogger, MergeType.APPLICATION)

    manifestMergerInvoker.addLibraryManifests(libraryManifests.toArray(new File[libraryManifests.size()]))

    // manifestMergerInvoker.setPlaceHolderValues(placeHolders)
    manifestMergerInvoker.setMergeReportFile(reportFile);

    MergingReport mergingReport = manifestMergerInvoker.merge();

    mLogger.info("Merging result:" + mergingReport.getResult());
    MergingReport.Result result = mergingReport.getResult();
    switch (result) {
        case MergingReport.Result.WARNING:
            mergingReport.log(mLogger);
    // fall through since these are just warnings.
        case MergingReport.Result.SUCCESS:
            XmlDocument xmlDocument = mergingReport.getMergedXmlDocument(MergingReport.MergedManifestKind.MERGED);
            try {
                String annotatedDocument = mergingReport.getActions().blame(xmlDocument);
                mLogger.verbose(annotatedDocument);
            } catch (Exception e) {
                mLogger.error(e, "cannot print resulting xml");
            }
            save(xmlDocument, origManifest);
            mLogger.info("Merged manifest saved to " + origManifest);
            if (aaptManifest.exists()) {
                new PlaceholderEncoder().visit(xmlDocument);
                save(xmlDocument, aaptManifest);
                mLogger.info("Merged aapt safe manifest saved to " + aaptManifest);
            }
            break;
        case MergingReport.Result.ERROR:
            mergingReport.log(mLogger);
            throw new RuntimeException(mergingReport.getReportString());
        default:
            throw new RuntimeException("Unhandled result type : " + mergingReport.getResult());
    }
} catch (RuntimeException e) {
    // Unacceptable error
    e.printStackTrace()
    throw new RuntimeException(e);
}

}

private void save(XmlDocument xmlDocument, File out) {
try {
Files.write(xmlDocument.prettyPrint(), out, Charsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

class MiLogger implements ILogger {

@Override
void error(
        @com.android.annotations.Nullable Throwable t,
        @com.android.annotations.Nullable String msgFormat, Object... args) {
    System.err.println(String.format("========== ERROR : " + msgFormat, args))
    if (t) t.printStackTrace(System.err)
}

@Override
void warning(@NonNull String msgFormat, Object... args) {
    System.err.println(String.format("========== WARNING : " + msgFormat, args))
}

@Override
void info(@NonNull String msgFormat, Object... args) {
    System.out.println(String.format("========== INFO : " + msgFormat, args))
}

@Override
void verbose(@NonNull String msgFormat, Object... args) {
    // System.out.println(String.format("========== DEBUG : " + msgFormat, args))
}

}

当然综合各处,现在也有很多人在用此版本的方案处理:https://github.com/kezong/fat-aar-android
里面有中文文档。

欢迎大家提供更多的解决办法。

上一篇下一篇

猜你喜欢

热点阅读