Flutter plugin集成 aar 出现错误

2023-03-21  本文已影响0人  吻_风

当我们编写flutter程序时候经常会遇到要集成ios或者android sdk。其中android有些sdk不是jar而是aar。如果直接集成打包会是正常的,但是为了结构清晰我们一般会把这些功能单独用一个flutter plugin去集成。然后我们的flutter application再依赖这个plugin。当问我们去编写flutter plugin的时候会出现以下错误。

  1. 用android studio打开plugin项目的android文件夹会发现里面的java/kotlin文件的import都是灰色。里面的方法或者参数都是红色。这是因为插件没有识别到flutter的sdk。(由于plugin最终是会被application去依赖,所以项目编译是可以通过的不会报错)。这时我们只需在build.gradle文件的末尾添加以下内容
//读取配置
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
    localPropertiesFile.withReader('UTF-8') {
        reader-> localProperties.load(reader)
    }
}
//获取flutter sdk路径
def flutterRoot = localProperties.getProperty('flutter.sdk')
if(flutterRoot == null) {
    throw new GradleException('Flutter sdk not found.')
}
dependencies {
    compileOnly files("$flutterRoot/bin/cache/artifacts/engine/android-arm/flutter.jar")
    compileOnly("androidx.annotation:annotation:1.0.0")
}

上面这段脚本是用来依赖flutter.jar 以及annotation的。用的是complieOnly所以不会参与编译。这项文件就不再试红色了。

  1. 编译时候出现Error while evaluating property 'hasLocalAarDeps' of task ':xxxx插件名:bundleDebugAar'

Direct local .aar file dependencies are not supported when building an AAR. The resulting AAR would be broken because the classes and Android resources from any local .aar file dependencies would not be packaged in the resulting AAR.Previous versions of the Android Gradle Plugin produce broken AARs in this case too (despite not throwing this error). The following direct local .aar file dependencies of the :xxxx project caused this error: xxxxx\xxxx\xxxx.aar

这时候你看下你依赖aar的模式implementation fileTree(includes: [".aar"],dir:"libs"),implementation表示的是依赖只作用在本项目并参与编译。如果你是在flutter application中这么用是不会报错的。但是这是flutter pluigin。每个flutter plugin会编译成一个aar。相当于你把一个aar又编译进了另一个aar当然会报错。所以你这里要换成compileOnly fileTree(includes: [".aar"],dir:"libs")。这样就可以编译通过了。

  1. 当编译通过后你在使用到这个aar中的内容时候又会报以下错误

Caused by: java.lang.ClassNotFoundException: Didn't find class "XXXXXXX" on path: DexPathList[[zip file "/data/app/~~LmWMF6d-aNOCfQQ32bhOsQ==/

内容可能和我的不一样,但是意思是一样的。就是找不到这个aar中的类。这是为什么因为你用的是compileOnly没有吧aar编译进去。当然会找不到。那么如何去解决?我网上找了很久很多答案都不行。最终自己折腾了出来,方法有两个

import java.util.zip.ZipEntry
import java.util.zip.ZipFile

// 拷贝aar的方法
static aarFileCopy(String srcPath,String desPath) {
    System.out.println("copy aar from <<${srcPath}>> to <<${desPath}>>")
    try {
        FileInputStream fis = new FileInputStream(srcPath)
        FileOutputStream fos = new FileOutputStream(desPath)
        byte[] data = new byte[1024*8]
        int len = 0
        while ((len = fis.read(data))!=-1) {
            fos.write(data,0,len)
        }
        fis.close()
        fos.close()
    }catch(Exception e) {
        e.printStackTrace()
    }
}
//把aar拷贝进入主项目的方法 com.example.android_control换成你自己的插件名
copyAar2Host('com.example.android_control')
void copyAar2Host(String pluginGroup) {
    Project currentProject = null
    Project appProject = null
    rootProject.allprojects.each {
        p->
            boolean  isApp = p.plugins.hasPlugin("com.android.application")
            println("<<${p.name}>> isHost ? ${isApp}")
            if (p.group == pluginGroup) {
                currentProject = p
                println("Plugin project name is $currentProject")
            }
            if(isApp) {
                appProject = p
                println("Host project name is <<${p.name}>>")
            }
    }
    Set<File> aarFiles = new HashSet<File>()
    if (appProject != null && currentProject != null) {
        File libs = new File("${currentProject.projectDir}","libs")
        if(libs.isDirectory()) {
            libs.listFiles().each {
                f->
                    if(f.name.endsWith(".aar")) {
                        println("The aar file name to be copied is <<${f.name}>>")
                        aarFiles.add(f)
                    }

            }
        }
        if (!aarFiles.isEmpty()) {
            File applibs = new File("${appProject.projectDir}${File.separator}libs")
            if(!applibs.isDirectory()) {
                applibs.mkdirs()
            }
            aarFiles.each {
                f->
                    File copyAar = new File("${appProject.projectDir}${File.separator}libs",f.name)
                    if(!copyAar.exists()) {
                        copyAar.createNewFile()
                        aarFileCopy(f.path,copyAar.path)
                    } else {

                    }
            }
            appProject.dependencies {
                implementation fileTree(dir:"${appProject.projectDir}${File.separator}libs",include:["*.jar","*.aar"])
            }
        }
    }
}

repositories{
    flatDir {
        dirs 'libs'
    }
}

apply plugin: 'com.android.library'

apply from: './aar_tools.gradle'
...
//省略部分内容
dependencies {
//    compileOptions files('libs/SdkApiJar-V1.0.0.221128.0.aar')
//    provided files('libs/SdkApiJar-V1.0.0.221128.0.aar.aar')
    compileOnly fileTree(includes: ["*.aar"],dir:"libs")
    compileOnly files("$flutterRoot/bin/cache/artifacts/engine/android-arm/flutter.jar")
    compileOnly("androidx.annotation:annotation:1.0.0")
}

修改完之后愉快的编译吧。

上一篇 下一篇

猜你喜欢

热点阅读