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 5 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
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
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@ Currently, 64 bit Desktop Platforms (Linux, Windows and MacOS) are supported.

## Run Example

### Dart CLI

```bash
cd example
cd example/cli
dart run cronet:setup # Downloads the cronet binaries.
dart run
```
Expand Down
1 change: 1 addition & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
include: package:lints/recommended.yaml

analyzer:
exclude: [example/flutter/**]
strong-mode:
implicit-casts: false
implicit-dynamic: false
Expand Down
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'
5 changes: 5 additions & 0 deletions android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="dev.google.cronet">
<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)
}
}
31 changes: 31 additions & 0 deletions bin/setup.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:args/command_runner.dart';
import 'package:cli_util/cli_logging.dart' show Ansi, Logger;
import 'package:cronet/src/constants.dart';
import 'package:cronet/src/third_party/ffigen/find_resource.dart';
import 'package:path/path.dart';

// Extracts a tar.gz file.
void extract(String fileName, [String dir = '']) {
Expand All @@ -28,13 +29,40 @@ void extract(String fileName, [String dir = '']) {
}
}

/// Places downloaded mobile binaries to proper location.
void placeMobileBinaries(String platform, String fileName) {
final android =
'${findPackageRoot().toFilePath(windows: Platform.isWindows)}/android';
unsuitable001 marked this conversation as resolved.
Show resolved Hide resolved
Directory('$android/libs').createSync();
Directory('$binaryStorageDir/$platform/libs').listSync().forEach((jar) {
if (jar is File) {
jar.renameSync('$android/libs/${basename(jar.path)}');
}
});
Directory('$android/src/main/jniLibs').createSync();
unsuitable001 marked this conversation as resolved.
Show resolved Hide resolved
Directory('$binaryStorageDir/$platform/jniLibs')
.listSync(recursive: true)
.forEach((cronet) {
if (cronet is File) {
Directory('$android/src/main/jniLibs/${basename(cronet.parent.path)}')
.createSync();
cronet.renameSync(
'$android/src/main/jniLibs/${basename(cronet.parent.path)}'
'/${basename(cronet.path)}');
}
});
}

/// Places downloaded binaries to proper location.
void placeBinaries(String platform, String fileName) {
final logger = Logger.standard();
final ansi = Ansi(Ansi.terminalSupportsAnsi);
logger.stdout('${ansi.yellow}Extracting Cronet for $platform${ansi.none}');
Directory(binaryStorageDir).createSync(recursive: true);
extract(fileName, binaryStorageDir);
if (mobilePlatforms.contains(platform)) {
placeMobileBinaries(platform, fileName);
}
logger.stdout('Done! Cleaning up...');

File(fileName).deleteSync();
Expand Down Expand Up @@ -238,6 +266,9 @@ Future<void> main(List<String> args) async {
if (validPlatforms.contains('${Platform.operatingSystem}64')) {
await downloadCronetBinaries('${Platform.operatingSystem}64');
}
if (Directory('android').existsSync()) {
await downloadCronetBinaries('android');
}
} else {
await runner.run(args);
}
Expand Down
3 changes: 2 additions & 1 deletion example/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
## Examples

- [Bare Minimum](https://github.com/google/cronet.dart#example)
- [Simple (Dart CLI)](https://github.com/google/cronet.dart/tree/main/example/)
- [Simple (Dart CLI)](https://github.com/google/cronet.dart/tree/main/example/cli)
- [Simple (Flutter)](https://github.com/google/cronet.dart/tree/main/example/flutter)
14 changes: 14 additions & 0 deletions example/cli/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.

include: package:lints/recommended.yaml

analyzer:
strong-mode:
implicit-casts: false
implicit-dynamic: false
linter:
rules:
- directives_ordering
- lines_longer_than_80_chars
33 changes: 33 additions & 0 deletions example/cli/bin/example_dart.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:convert';

import 'package:cronet/cronet.dart';

/* Trying to re-impliment: https://chromium.googlesource.com/chromium/src/+/master/components/cronet/native/sample/main.cc */

void main(List<String> args) {
final stopwatch = Stopwatch()..start();
final client = HttpClient();
for (var i = 0; i < 3; i++) {
// Demo - with concurrent requests
client
.getUrl(Uri.parse('https://example.com'))
.then((HttpClientRequest request) {
if (i == 2) {
client.close(); // We will shut down the client after 3 connections.
}
return request.close();
}).then((HttpClientResponse response) {
response.transform(utf8.decoder).listen((contents) {
print(contents);
}, onDone: () {
print('cronet implemenation took: ${stopwatch.elapsedMilliseconds} ms');
}, onError: (Object e) {
print(e);
});
});
}
}
2 changes: 1 addition & 1 deletion example/pubspec.yaml → example/cli/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ environment:

dependencies:
cronet:
path: ../
path: ../../

dev_dependencies:
lints: ^1.0.1
Expand Down
46 changes: 46 additions & 0 deletions example/flutter/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/

# Web related
lib/generated_plugin_registrant.dart

# Symbolication related
app.*.symbols

# Obfuscation related
app.*.map.json

# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
10 changes: 10 additions & 0 deletions example/flutter/.metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: 1d9032c7e1d867f071f2277eb1673e8f9b0274e3
channel: stable

project_type: app
16 changes: 16 additions & 0 deletions example/flutter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# cronet_example
Copy link
Member

Choose a reason for hiding this comment

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

Replace this boilerplate readme with a description of what the Flutter example is doing.

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'll delete the cli example as we're going flutter only for now :). So, I'll delete this readme file also and pub will index the actual code under Example tab by it's own. :)

Copy link
Member

Choose a reason for hiding this comment

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

Why only Flutter? The Dart CLI things just keep working if you have a dart on your path correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When I try to do dart run, I get -

Resolving dependencies... 
Because example_dart depends on cronet from path which requires the Flutter
  SDK, version solving failed.

Flutter users should run `flutter pub get` instead of `pub get`.

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. It does work.
If I do - dart run bin/example_dart.dart it works.
But, if I do dart run, it gives the error I mentioned above. Keep the CLI example then. :)


A new Flutter project.

## Getting Started

This project is a starting point for a Flutter application.

A few resources to get you started if this is your first Flutter project:

- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)

For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
14 changes: 14 additions & 0 deletions example/flutter/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.

include: package:lints/recommended.yaml

analyzer:
strong-mode:
implicit-casts: false
implicit-dynamic: false
linter:
rules:
- directives_ordering
- lines_longer_than_80_chars
11 changes: 11 additions & 0 deletions example/flutter/android/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java

# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties