Flutter Plugin中依赖aar文件编译报错

前言

在Flutter项目中开发难免会遇到使用到Flutter Plugin的场景,在Flutter Plugin有可能会使用到第三方AAR。在以上情况下Flutter Application编译Apk会报错,本篇文章将解决这个问题。

工程准备

首先创建四个工程分别为: Android 原生工程,Flutter application, Flutter module, Flutter plugin 为了方便管理这四个工程放在同一个目录下(FlutterProject目录):

cd  Desktop/FlutterProject/

  //创建 flutter application

fluttercreate--org com.tmt.flutterapp flutter_app

//创建 fluttermodule

fluttercreate--org com.tmt --template=module  flutter_module

//创建 flutterplugin插件,用来封装aar sdk

fluttercreate--org com.tmt.flutter_plugin_aar --template=plugin flutter_plugin_aar




使用Android Studio创建AndroidApp工程,创建完4个工程后目录结构如下:

need-to-insert-img

Flutter Plugin中集成AAR

打开flutter_plugin_aar工程,在.android目录下创建libs,再将aar文件放入到libs下,并在build.gradle中导入aar。

need-to-insert-img

dependencies{

implementationfileTree(dir:"libs",include: ['*.aar'])

}




在FlutterPluginAarPlugin中去使用aar中的api,

publicvoidonMethodCall(@NonNullMethodCall call,@NonNullResult result) {

if(call.method.equals("getPlatformVersion")) {

result.success("Android "+ android.os.Build.VERSION.RELEASE);

}elseif(call.method.equals("aarPrint")) {

//调用aar中的api

AarTest.print();

result.success("success");

}else{

result.notImplemented();

        }

    }




AarTest.print api的源码如下,

packagecom.tmt.mylibrary;

importandroid.util.Log;

publicclassAarTest{

publicstaticvoidprint(){

Log.d("AarTest","this is aar output log");

    }

}




Android原生项目中集成flutter_module

首先打开flutetr_module工程,在flutetr_module中依赖flutter_plugin_aar(原生项目引入Flutter Module工程 Flutter Add to App )。

need-to-insert-img

在flutter_module中依赖flutter_plugin_aar,

dev_dependencies:

flutter_test:

sdk:flutter

#依赖flutter_plugin_aar

flutter_plugin_aar:

path:../flutter_plugin_aar




在flutter_module目录下运行flutter pub get 生成 .android 目录,

打开AndroidApp工程,

need-to-insert-img

修改AndroidApp中settings.gradle文件,

include':app'

rootProject.name ="AndroidApp"

// 加入下面配置

setBinding(newBinding([gradle: this]))

evaluate(newFile(

        settingsDir.parentFile,

'flutter_module/.android/include_flutter.groovy'

//更改成自己的项目目录

))

include':flutter_module'

project(':flutter_module').projectDir =newFile('../flutter_module')




为了方便直接把MainActivity继承FlutterActivity,

packagecom.tmt.androidapp;

importandroid.os.Bundle;

importio.flutter.embedding.android.FlutterActivity;

publicclassMainActivityextendsFlutterActivity{

@Override

protectedvoidonCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

    }

}




此时在Android Studio中运行AndroidApp是正常的,但是使用./gradlew assembleRelease打包会报错,报错信息如下:

> Task :flutter_plugin_aar:bundleReleaseAar FAILED

FAILURE: Build failedwithan exception.

* What went wrong:

Execution failedfortask':flutter_plugin_aar:bundleReleaseAar'.

> Direct local .aar file dependencies are not supported when building an AAR. The resulting AAR would be broken because the classes and Android resourcesfromanylocal .aar file dependencies would not be packagedinthe resulting AAR. Previous versionsofthe Android Gradle Plugin produce broken AARsinthiscasetoo (despite not throwingthiserror). The following direct local .aar file dependenciesofthe :flutter_plugin_aar project causedthiserror:/xxx/xxx/Desktop/FlutterProject/flutter_plugin_aar/android/libs/mylibrary-release.aar

BUILD FAILEDin39s




从上面的报错信息可以看出来是bundleReleaseAar出错了,原因是因为构建aar中不能依赖aar。(ps:虽然报错了,但是apk已经编译成功了)。

Flutter Application中使用flutter_plugin_aar

Android Studio中打开flutter_app工程,同样在flutter_app中依赖flutter_plugin_aar,运行flutter pub get 这个时候我们去运行项目也会出现aar的报错。项目不能运行起来也不会生成apk(flutter build apk 也不行)。

解决Flutter plugin中aar编译报错问题

首先看一下 Apk的构建流程,

need-to-insert-img

从上图可以知道编译器会把source code,jar包,aar包编译到dex文件中去,然后再生成的apk。

思考:

Q:为什么Flutter Plugin依赖aar编译会报错,而Android原生开发中module依赖aar不会报错?

A: Flutter Application的编译流程会把每个plugin中的android相关文件编译成aar。

Q:有什么办法绕过aar编译到Flutter Plugin中?

A:1)把aar文件依赖到Android Application中去编译,Plugin中仅仅做compileOnly依赖(compileOnly在构建时会被忽略);

2)把aar解压成jar和资源文件放入flutter_plugin中(本篇文章不做演示了)。

修改flutter_plugin_aar中build.gradle文件绕过plugin中编译aar,

group'com.tmt.flutter_plugin_aar'

version'1.0'

buildscript {

    repositories {

        google()

        jcenter()

    }

    dependencies {

classpath'com.android.tools.build:gradle:4.1.0'

    }

}

rootProject.allprojects {

    repositories {

        google()

        jcenter()

    }

}

apply plugin:'com.android.library'

//1.aar_tools.gradle为拷贝aar到host工程的脚本,

//放在com.android.library后面,

applyfrom:'./aar_tools.gradle'

android {

compileSdkVersion30

    defaultConfig {

minSdkVersion16

    }

}

dependencies {

// implementation fileTree(dir: "libs", include: ['*.aar'])

//2.implementation改成compileOnly表示libs目录下的文件在编译过程中会被忽略

compileOnlyfileTree(dir:"libs", include: ['*.aar'])

}




在android目录下创建aar_tools.gradle脚本,

importjava.util.zip.ZipEntry

importjava.util.zip.ZipFile

staticaarFileCopy(StringsrcPathStr,StringdesPathStr){

System.out.println("拷贝aar源文件${srcPathStr} 到 ${desPathStr}");

try{

FileInputStream fis =newFileInputStream(srcPathStr)

FileOutputStream fos =newFileOutputStream(desPathStr)

byte[] datas =newbyte[1024*8]

int len =0;

while((len = fis.read(datas)) != -1)

        {

fos.write(datas,0, len);

        }

        fis.close();

        fos.close();

}catch(Exception e) {

        e.printStackTrace();

    }

}

copyAar2Host('com.tmt.flutter_plugin_aar')

voidcopyAar2Host(StringpluginGroup){

Project currentProject =null

Project appProject =null

    rootProject.allprojects.each {

        p ->

booleanisApp = p.plugins.hasPlugin("com.android.application")

println("${p.name} isHost --> ${isApp}")

if(p.group == pluginGroup) {

                currentProject = p

println("Plugin project name --> $currentProject")

            }

if(isApp) {

                appProject = p

println("Host project name -->  ${p.name}")

            }

    }

Set aarFiles =newHashSet<>()

if(appProject !=null&& currentProject !=null) {

File libs =newFile("${currentProject.projectDir}",'libs')

if(libs.isDirectory()) {

            libs.listFiles().each {

                f ->

if(f.name.endsWith('.aar')) {

println("aar name --> ${f.name}")

                        aarFiles.add(f)

                    }

            }

        }

if(!aarFiles.isEmpty()) {

File applibs =newFile("${appProject.projectDir}${File.separator}libs");

if(!applibs.isDirectory()) {

                applibs.mkdirs()

            }

            aarFiles.each {

                f ->

File copyAar =newFile("${appProject.projectDir}${File.separator}libs", f.name)

if(!copyAar.exists()) {

                        copyAar.createNewFile()

                        aarFileCopy(f.path, copyAar.path)

}else{

// 可以读取aar中的manifest处理aar包版本的问题,

// 这里暂不处理了

                    }

            }

            appProject.dependencies {

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

            }

        }

    }

}

repositories {

    flatDir {

dirs'libs'

    }

}




至此flutter_app就可以运行起来了,也可以通过flutter build apk顺利打包成功(AndroidApp工程打包同样也不会报错了)。

总结

本文章主要探索了Flutter plugin中依赖aar编译报错原因,并且把Flutter plugin中aar的依赖编译转到Android Application工程中。

如果对Flutter构建apk的流程有兴趣的同学可以去查看:

$FlutterSDK/packages/flutter_tools/gradle/目录下相关的gradle脚本文件

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,820评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,648评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,324评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,714评论 1 297
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,724评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,328评论 1 310
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,897评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,804评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,345评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,431评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,561评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,238评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,928评论 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,417评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,528评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,983评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,573评论 2 359

推荐阅读更多精彩内容