Skip to content
This repository has been archived by the owner on Feb 11, 2024. It is now read-only.

Flutter support #18

Merged
merged 22 commits into from
Aug 4, 2021
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
cf87c48
flutter support: initial commit
unsuitable001 Jul 27, 2021
11e8c11
implement: android support
unsuitable001 Jul 27, 2021
d0ea739
CI: exclude flutter sample from dart analyze
unsuitable001 Jul 27, 2021
1b6a8a2
flutter: add linux support
unsuitable001 Jul 28, 2021
6094162
update tools/setup for android
unsuitable001 Jul 28, 2021
bafdd35
flutter: add windows support
unsuitable001 Jul 28, 2021
bd49741
update readme for android support
unsuitable001 Jul 28, 2021
875cc3a
str interpolate -> package:path join & adding constants
unsuitable001 Jul 29, 2021
a631548
remove circular ref in map
unsuitable001 Jul 29, 2021
0488e0e
make androidPath final
unsuitable001 Jul 29, 2021
2481e54
add flutter platform keys for desktops
unsuitable001 Aug 1, 2021
e0bdfb8
readme fixes and CI from Dart -> Flutter
unsuitable001 Aug 2, 2021
3870e67
update ci
unsuitable001 Aug 4, 2021
9fa8327
remove boilerplate widget_test
unsuitable001 Aug 4, 2021
edb24bd
ci check success on each step
unsuitable001 Aug 4, 2021
59da4ee
ci: remove successs check at wrong place
unsuitable001 Aug 4, 2021
3adf06f
change exit code in case of build failure
unsuitable001 Aug 4, 2021
3a4c1d7
remove linking with dart.lib (windows) and int -> size_t for strlen
unsuitable001 Aug 4, 2021
3dbaf29
add `flutter create` boilerplate modification notes
unsuitable001 Aug 4, 2021
d26ed08
Network -> network
unsuitable001 Aug 4, 2021
5c58ed6
yet another typo :sweat:
unsuitable001 Aug 4, 2021
4cdcc6c
change download url
unsuitable001 Aug 4, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 19 additions & 12 deletions .github/workflows/test-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ env:

jobs:
# Check code formatting and static analysis on a single OS (linux)
# against Dart stable.
# against Flutter stable.
analyze:
runs-on: ubuntu-latest
strategy:
Expand All @@ -27,17 +27,20 @@ jobs:
sdk: [stable]
steps:
- uses: actions/checkout@v2
- uses: dart-lang/setup-dart@v1.0
- uses: actions/setup-java@v1
with:
sdk: ${{ matrix.sdk }}
java-version: '12.x'
- uses: subosito/flutter-action@v1
with:
channel: ${{ matrix.sdk }}
- id: install
name: Install dependencies
run: dart pub get
run: flutter pub get
- name: Check formatting
run: dart format --output=none --set-exit-if-changed .
run: flutter format --set-exit-if-changed .
if: always() && steps.install.outcome == 'success'
- name: Analyze code
run: dart analyze --fatal-infos
run: flutter analyze --fatal-infos
if: always() && steps.install.outcome == 'success'

# Run tests on a matrix consisting of two dimensions:
Expand All @@ -51,18 +54,22 @@ jobs:
matrix:
# Add macos-latest and/or windows-latest if relevant for this package.
os: [ubuntu-latest, macos-latest, windows-latest]
sdk: [2.13.0, dev]
sdk: [stable, dev]
steps:
- uses: actions/checkout@v2
- uses: dart-lang/setup-dart@v1.0
- uses: actions/setup-java@v1
with:
java-version: '12.x'
- uses: subosito/flutter-action@v1
with:
sdk: ${{ matrix.sdk }}
channel: ${{ matrix.sdk }}
- id: install
name: Install dependencies
run: dart pub get
run: flutter pub get
- id: get_binaries
name: Download/Build Cronet Binaries
run: dart run cronet:setup
run: flutter pub run cronet:setup
if: always() && steps.install.outcome == 'success'
- name: Run VM tests
run: dart test --platform vm
run: flutter test
if: always() && steps.install.outcome == 'success'
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ doc/api/
.history
.vscode
compile_commands.json
*.log

# IntelliJ
*.iml
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.0.4

* Added support for Android and Flutter Desktops (Windows/Linux).

## 0.0.3

* Using `package:args` for handling CLI arguments.
Expand Down
50 changes: 37 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,37 @@ This is a [GSoC 2021 project](https://summerofcode.withgoogle.com/projects/#4757

## Supported Platforms

Currently, 64 bit Desktop Platforms (Linux, Windows and MacOS) are supported.
Currently, 64 bit Android and Desktop Platforms (Linux, Windows and MacOS) are supported.

## Requirements

1. Dart SDK 2.12.0 or above.
2. CMake 3.15 or above. (If on windows, Visual Studio 2019 with C++ tools)
2. CMake 3.10 or above. (If on windows, Visual Studio 2019 with C++ tools)
3. C++ compiler. (g++/clang/msvc)
4. Android NDK if targeting Android.

## Usage

1. Add package as a dependency in your `pubspec.yaml`.

2. Run this from the `root` of your project.

**Dart CLI**

```bash
dart pub get
dart run cronet:setup # Downloads the cronet binaries.
flutter pub get
flutter pub run cronet:setup # Downloads the cronet binaries.
```

We need to use `flutter pub` even if we want to use it with Dart CLI. See <https://github.com/dart-lang/pub/issues/2606> for further details.

***Note for Android:** Remember to Add the following permissions in `AndroidManifest.xml` file.

```xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
```

Optionally, enable cleartext traffic by adding `android:usesCleartextTraffic="true"` to `AndroidManifest.xml` file.

3. Import

```dart
Expand Down Expand Up @@ -56,22 +66,34 @@ Currently, 64 bit Desktop Platforms (Linux, Windows and MacOS) are supported.

## Run Example

### Flutter

```bash
cd example
dart run cronet:setup # Downloads the cronet binaries.
dart run
cd example/flutter
flutter pub get
flutter pub run cronet:setup # Downloads the cronet binaries.
flutter run
```

### Dart CLI

```bash
cd example/cli
flutter pub get
flutter pub run cronet:setup # Downloads the cronet binaries.
dart run bin/example_dart.dart
```

## Run Tests

```bash
dart pub get
dart run cronet:setup # Downloads the cronet binaries.
dart test --platform vm
flutter pub get
flutter pub run cronet:setup # Downloads the cronet binaries.
flutter test
```

You can also verify your cronet binaries using `dart run cronet:setup verify`.
Make sure to have `cmake 3.15`.
Make sure to have `cmake 3.10`.

## Benchmarking

Expand All @@ -98,3 +120,5 @@ Note: Test results may get affected by: <https://github.com/google/cronet.dart/i
2. Run `dart run cronet:setup build` from the root of your project.

**Note for Windows:** Run `step 2` from `x64 Native Tools Command Prompt for VS 2019` shell.

**Note for Android:** Copy the produced jar files in `android/libs` and `.so` files in `android/src/main/jniLibs` subdirectory from the root of this package.
8 changes: 8 additions & 0 deletions android/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
50 changes: 50 additions & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
group 'dev.google.cronet'
version '1.0-SNAPSHOT'

buildscript {
ext.kotlin_version = '1.3.50'
repositories {
google()
jcenter()
}

dependencies {
classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

rootProject.allprojects {
repositories {
google()
jcenter()
}
}

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'

android {
compileSdkVersion 30

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}

externalNativeBuild {
// Encapsulates your CMake build configurations.
cmake {
// Provides a relative path to your CMake build script.
path "../src/CMakeLists.txt"
}
}

defaultConfig {
minSdkVersion 16
}
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation files(fileTree(dir: 'libs', includes: ['*.jar']))
}
3 changes: 3 additions & 0 deletions android/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
5 changes: 5 additions & 0 deletions android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
1 change: 1 addition & 0 deletions android/settings.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rootProject.name = 'cronet'
6 changes: 6 additions & 0 deletions android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dev.google.cronet">
<!-- Flutter Boilerplate Modifications: Internet & netwrok Permissions-->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

netwrok -> network (it was the spelling I meant, not the capitalization 🙈 )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops 😓 my bad.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update the binaries and I'll change the download url and commit both the changes together 🙈. 1 less task for our CI vm.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do we need the jars for in the Android binaries?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need those jar files too :) Again, I need to refer this issue: unsuitable001/dart_cronet_sample#3

I don't know the exact reason. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm re-testing it on my device and I'll paste the exact error log here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried in 3 variation. Logs below.

Attempt 1: Include jar files but do not load the .so files from kotlin.
Output: Crashing as soon as it's getting launch. Only getting

http://127.0.0.1:34017/YTBP04h-Lu4=/

Attempt 2: Remove jars but load so files from kotlin

✓ Built build/app/outputs/flutter-apk/app-debug.apk.
Installing build/app/outputs/flutter-apk/app.apk...                 8.9s
F/chromium(21501): [0804/174650.092879:FATAL:jni_android.cc(138)] Failed to find class J/N
F/chromium(21501): #00 pc 0x00000000002e09bf /data/app/dev.google.cronet_example-ZSU7uPvW02OfcK8Ob4tYpQ==/lib/arm64/libcronet.86.0.4240.198.so
F/chromium(21501): #01 pc 0x00000000002eb60f /data/app/dev.google.cronet_example-ZSU7uPvW02OfcK8Ob4tYpQ==/lib/arm64/libcronet.86.0.4240.198.so
F/chromium(21501): #02 pc 0x00000000003418af /data/app/dev.google.cronet_example-ZSU7uPvW02OfcK8Ob4tYpQ==/lib/arm64/libcronet.86.0.4240.198.so
F/chromium(21501): #03 pc 0x00000000001e1aa3 /data/app/dev.google.cronet_example-ZSU7uPvW02OfcK8Ob4tYpQ==/lib/arm64/libcronet.86.0.4240.198.so
F/chromium(21501): #04 pc 0x00000000002c1a3f /system/lib64/libart.so
F/chromium(21501): #05 pc 0x000000000000403b /system/lib64/libopenjdkjvm.so
F/chromium(21501): #06 pc 0x0000000000000bcb /system/framework/arm64/boot-core-oj.oat
F/chromium(21501): 
Error connecting to the service protocol: failed to connect to
http://127.0.0.1:37607/pQcwEtK-emc=/

Attempt 3: Remove jars and do not load .so files from kotlin

✓ Built build/app/outputs/flutter-apk/app-debug.apk.
Installing build/app/outputs/flutter-apk/app.apk...                 7.4s
I/OpenGLRenderer(21802): Davey! duration=906ms; Flags=1, IntendedVsync=29271908984223, Vsync=29272625650861, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=29272634604821, AnimationStart=29272634798155, PerformTraversalsStart=29272634807217, DrawStart=29272653090655, SyncQueued=29272657276280, SyncStart=29272657438155, IssueDrawCommandsStart=29272657732217, SwapBuffers=29272812535446, FrameCompleted=29272815417269, DequeueBufferDuration=11718000, QueueBufferDuration=765000, 
F/libc    (21802): Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 21827 (1.ui), pid 21802 (.cronet_example)
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***         
Build fingerprint: 'asus/WW_X00TD/ASUS_X00T_2:9/PKQ1/16.2017.2009.087-20200826:user/release-keys'
Revision: '0'                                                           
ABI: 'arm64'                                                            
pid: 21802, tid: 21827, name: 1.ui  >>> dev.google.cronet_example <<<   
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0               
Cause: null pointer dereference                                         
    x0  0000000000000000  x1  00000078b2bfac78  x2  0000000000010002  x3  00000078a7281588
    x4  00000078a7281500  x5  0000007950719f88  x6  00000078a72814f0  x7  0000000000000000
    x8  0f5c9418fa297d4e  x9  0f5c9418fa297d4e  x10 0000000000000001  x11 0000000000000000
    x12 00000078a7281500  x13 00000078a72814f0  x14 0000000000004100  x15 aaaaaaaaaaaaaaab
    x16 00000078a7a6ced0  x17 000000795071b040  x18 0000000000000001  x19 00000078a7a74000
    x20 0000000000000002  x21 00000078b2bfc588  x22 00000078b1108041  x23 00000078b4755b90
    x24 00000078b1108041  x25 00000078b2b1e000  x26 00000078b2bfc588  x27 00000078a7387430
    x28 0000000000000004  x29 00000078b2bfaca0                          
    sp  00000078b2bfac50  lr  00000078a7717ca8  pc  00000078a78773a4    
backtrace:                                                              
    #00 pc 00000000003413a4  /data/app/dev.google.cronet_example-1jJaFkoD6WqfgexC4ieOzA==/lib/arm64/libcronet.86.0.4240.198.so
    #01 pc 00000000001e1ca4  /data/app/dev.google.cronet_example-1jJaFkoD6WqfgexC4ieOzA==/lib/arm64/libcronet.86.0.4240.198.so
    #02 pc 00000000002baba8  /data/app/dev.google.cronet_example-1jJaFkoD6WqfgexC4ieOzA==/lib/arm64/libcronet.86.0.4240.198.so
    #03 pc 0000000000006694  <anonymous:00000078b1080000>               
Syncing files to device ASUS X00TD...                                  ⣾

Lost connection to device.                                      
Syncing files to device ASUS X00TD...                              702ms
Oops; flutter has exited unexpectedly: "getIsolate: (112) Service has
disappeared".
⣻Oops; flutter has exited unexpectedly: "getIsolate: (112) Service has
disappeared".

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah of course, we're compiling that Kotlin helper code to a jar. Silly me. :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dcharkes Links are updated!

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
41 changes: 41 additions & 0 deletions android/src/main/kotlin/dev/google/cronet/CronetPlugin.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package dev.google.cronet

import androidx.annotation.NonNull

import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry.Registrar

import org.chromium.base.ContextUtils

/** CronetPlugin */
class CronetPlugin: FlutterPlugin, MethodCallHandler {
/// The MethodChannel that will the communication between Flutter and native Android
///
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
/// when the Flutter Engine is detached from the Activity
private lateinit var channel : MethodChannel

override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
System.loadLibrary("cronet.86.0.4240.198")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we loading these in Kotlin rather than using DynamicLibrary.open?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we do not load it using Kotlin first, we get this error -

F/chromium(17045): [0418/210141.455792:FATAL:jni_android.cc(96)] Check failed: g_jvm. 

Though we're not using Platform Channel from our side in our package itself. Loading the library via Kotlin first then doing DynamicLibrary.open on Dart side fixes the issue. (I'm yet to figure out why this is happening though.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It sounds similar to this: flutter/flutter#73318

Lets just keep it for now and file an issue to look at it later.

System.loadLibrary("wrapper")
ContextUtils.initApplicationContext(flutterPluginBinding.applicationContext)
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "cronet")
channel.setMethodCallHandler(this)
}

override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
if (call.method == "getPlatformVersion") {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
} else {
result.notImplemented()
}
}

override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
channel.setMethodCallHandler(null)
}
}