Merge pull request #2673 from jason-simmons/gradle_example

Example that builds a Flutter Android app using Gradle
This commit is contained in:
Jason Simmons 2016-03-14 16:04:20 -07:00
commit 2fdcb59fec
13 changed files with 262 additions and 0 deletions

View File

@ -0,0 +1,16 @@
# Example of building a Flutter app for Android using Gradle
This project demonstrates how to embed Flutter within an Android application
and build the Android and Flutter components with Gradle.
To build this project:
* Create a `local.properties` file with these entries:
* `sdk.dir=[path to the Android SDK]`
* `flutter.sdk=[path to the Flutter SDK]`
* `flutter.jar=[path to the flutter.jar file in your build of the Flutter engine]`
Then run:
* `gradle wrapper`
* `./gradlew build`

View File

@ -0,0 +1,15 @@
apply plugin: 'com.android.application'
apply plugin: 'flutter'
android {
compileSdkVersion 22
buildToolsVersion '22.0.1'
lintOptions {
disable 'InvalidPackage'
}
}
flutter {
source 'src/flutter'
}

View File

@ -0,0 +1,7 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/widgets.dart';
void main() => runApp(new Center(child: new Text('Hello from Flutter!')));

View File

@ -0,0 +1,4 @@
name: gradle
dependencies:
flutter:
path: ../../../../../packages/flutter

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.flutter"
android:versionCode="1"
android:versionName="1.0.0" >
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.INTERNET"/>
<application android:name="org.domokit.sky.shell.SkyApplication" android:label="@string/app_name" >
<activity
android:name=".FlutterActivity"
android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
android:launchMode="singleTask"
android:theme="@android:style/Theme.Black.NoTitleBar"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -0,0 +1,39 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package com.example.flutter;
import android.app.Activity;
import android.os.Bundle;
import org.chromium.base.PathUtils;
import org.domokit.sky.shell.SkyApplication;
import org.domokit.sky.shell.SkyMain;
import org.domokit.sky.shell.PlatformViewAndroid;
import java.io.File;
public class FlutterActivity extends Activity {
private PlatformViewAndroid flutterView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SkyMain.ensureInitialized(getApplicationContext(), null);
setContentView(R.layout.flutter_layout);
flutterView = (PlatformViewAndroid) findViewById(R.id.flutter_view);
File appBundle = new File(PathUtils.getDataDirectory(this), SkyApplication.APP_BUNDLE);
flutterView.runFromBundle(appBundle.getPath(), null);
}
@Override
protected void onDestroy() {
if (flutterView != null) {
flutterView.destroy();
}
super.onDestroy();
}
}

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/text_view"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/title"
/>
<org.domokit.sky.shell.PlatformViewAndroid
android:id="@+id/flutter_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Flutter App</string>
<string name="title">Flutter Application</string>
</resources>

View File

@ -0,0 +1,17 @@
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.0'
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
task wrapper(type: Wrapper) {
gradleVersion = '2.8'
}

View File

@ -0,0 +1,7 @@
repositories {
jcenter()
}
dependencies {
compile "com.android.tools.build:gradle:1.5.0"
}

View File

@ -0,0 +1,107 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.domokit.sky.gradle
import com.android.builder.model.AndroidProject
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.Plugin
import org.gradle.api.Task
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.Copy
import org.gradle.api.tasks.InputDirectory
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
class FlutterPlugin implements Plugin<Project> {
private File sdkDir
@Override
void apply(Project project) {
Properties properties = new Properties()
properties.load(project.rootProject.file("local.properties").newDataInputStream())
String enginePath = properties.getProperty("flutter.jar")
if (enginePath == null) {
throw new GradleException("flutter.jar must be defined in local.properties")
}
FileCollection flutterEngine = project.files(enginePath)
if (!flutterEngine.singleFile.isFile()) {
throw new GradleException("flutter.jar must point to a Flutter engine JAR")
}
String sdkPath = properties.getProperty("flutter.sdk")
if (sdkPath == null) {
throw new GradleException("flutter.sdk must be defined in local.properties")
}
sdkDir = project.file(sdkPath)
if (!sdkDir.isDirectory()) {
throw new GradleException("flutter.sdk must point to the Flutter SDK directory")
}
project.extensions.create("flutter", FlutterExtension)
project.dependencies.add("compile", flutterEngine)
project.afterEvaluate this.&addFlutterTask
}
private void addFlutterTask(Project project) {
if (project.flutter.source == null) {
throw new GradleException("Must provide Flutter source directory")
}
FlutterTask flutterTask = project.tasks.create("flutterBuild", FlutterTask) {
sdkDir this.sdkDir
sourceDir project.file(project.flutter.source)
intermediateDir project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter")
}
project.android.applicationVariants.all { variant ->
Task copyFlxTask = project.tasks.create(name: "copyFlx${variant.name.capitalize()}", type: Copy) {
dependsOn flutterTask
dependsOn variant.mergeAssets
from flutterTask.flxPath
into variant.mergeAssets.outputDir
}
variant.outputs[0].processResources.dependsOn(copyFlxTask)
}
}
}
class FlutterExtension {
String source
}
class FlutterTask extends DefaultTask {
File sdkDir
@InputDirectory
File sourceDir
@OutputDirectory
File intermediateDir
String getFlxPath() {
return "${intermediateDir}/app.flx"
}
@TaskAction
void build() {
if (!sourceDir.isDirectory()) {
throw new GradleException("Invalid Flutter source directory: ${sourceDir}")
}
intermediateDir.mkdirs()
project.exec {
executable "${sdkDir}/bin/flutter"
workingDir sourceDir
args "build"
args "-o", flxPath
args "--snapshot", "${intermediateDir}/snapshot_blob.bin"
args "--depfile", "${intermediateDir}/snapshot_blob.bin.d"
args "--working-dir", "${intermediateDir}/flx"
}
}
}

View File

@ -0,0 +1 @@
implementation-class=org.domokit.sky.gradle.FlutterPlugin

View File

@ -0,0 +1 @@
include ':app'