diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9a27b1117..73ad2c4d6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,6 +26,7 @@ jobs: components: clippy - uses: Swatinem/rust-cache@v1 if: ${{ !contains(github.event.head_commit.message, '[fresh ci]') }} + - run: make rustup.android - run: make lint rustfmt: @@ -57,6 +58,31 @@ jobs: - uses: azure/setup-helm@v1 - run: make helm.lint chart=${{ matrix.chart }} + dartfmt: + if: ${{ github.ref == 'refs/heads/master' + || startsWith(github.ref, 'refs/tags/medea-') + || !contains(github.event.head_commit.message, '[skip ci]') }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: subosito/flutter-action@v1 + with: + channel: stable + - run: make flutter.fmt check=yes + + dartanalyzer: + if: ${{ github.ref == 'refs/heads/master' + || startsWith(github.ref, 'refs/tags/medea-') + || !contains(github.event.head_commit.message, '[skip ci]') }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: subosito/flutter-action@v1 + with: + channel: stable + - run: make flutter + - run: make flutter.lint + @@ -217,6 +243,52 @@ jobs: - run: make test.integration up=yes dockerized=no + test-flutter: + name: Flutter Android tests + if: ${{ github.ref == 'refs/heads/master' + || startsWith(github.ref, 'refs/tags/medea-jason-') + || !contains(github.event.head_commit.message, '[skip ci]') }} + runs-on: macos-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + target: i686-linux-android + - uses: Swatinem/rust-cache@v1 + if: ${{ !contains(github.event.head_commit.message, '[fresh ci]') }} + + - uses: actions-rs/install@v0.1 + with: + crate: cargo-ndk + use-tool-cache: true + - uses: subosito/flutter-action@v1 + with: + channel: stable + + - name: Parse Android NDK versions + id: ndk-version + run: | + echo ::set-output name=min::$(make flutter.android.version.min) + echo ::set-output name=target::$(make flutter.android.version.compile) + + - name: Compile shared object + run: make cargo.build crate=medea-jason platform=android targets=x86 + + - uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: ${{ steps.ndk-version.outputs.min }} + target: google_apis + profile: Nexus 6 + script: make test.flutter + - uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: ${{ steps.ndk-version.outputs.target }} + target: google_apis + profile: Nexus 6 + script: make test.flutter + @@ -224,8 +296,8 @@ jobs: # Building # ############ - crate-jason: - name: Build medea-jason + crate-jason-web: + name: Build medea-jason for web platform if: ${{ !startsWith(github.ref, 'refs/tags/medea-') && (github.ref == 'refs/heads/master' || !contains(github.event.head_commit.message, '[skip ci]')) }} @@ -242,6 +314,28 @@ jobs: - uses: jetli/wasm-pack-action@v0.3.0 - run: make cargo.build crate=medea-jason dockerized=no debug=yes + crate-jason-android: + name: Build medea-jason shared object for Android platform + if: ${{ !startsWith(github.ref, 'refs/tags/medea-') + && (github.ref == 'refs/heads/master' + || !contains(github.event.head_commit.message, '[skip ci]')) }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + - uses: Swatinem/rust-cache@v1 + if: ${{ !contains(github.event.head_commit.message, '[fresh ci]') }} + - uses: actions-rs/install@v0.1 + with: + crate: cargo-ndk + use-tool-cache: true + - run: make rustup.android + - run: make cargo.build crate=medea-jason platform=android + dockerized=no debug=yes + crate-medea: name: Build medea if: ${{ !startsWith(github.ref, 'refs/tags/medea-') diff --git a/Makefile b/Makefile index 5e270c650..b671ec481 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,22 @@ RUST_VER := 1.51 CHROME_VERSION := 89.0 FIREFOX_VERSION := 87.0 +CARGO_NDK_VER := 2.2.0-ndkr22b-rust$(RUST_VER) +ANDROID_NDK_TARGETS := arm64-v8a \ + armeabi-v7a \ + x86 \ + x86_64 +ANDROID_RUST_TARGETS := aarch64-linux-android \ + armv7-linux-androideabi \ + i686-linux-android \ + x86_64-linux-android +ANDROID_SDK_COMPILE_VERSION := $(strip \ + $(shell grep compileSdkVersion jason/flutter/android/build.gradle \ + | awk '{print $$2}')) +ANDROID_SDK_MIN_VERSION := $(strip \ + $(shell grep minSdkVersion jason/flutter/android/build.gradle \ + | awk '{print $$2}')) + crate-dir = . ifeq ($(crate),medea-jason) crate-dir = jason @@ -70,7 +86,9 @@ build.medea: build.jason: - @make cargo.build crate=medea-jason debug=$(debug) dockerized=$(dockerized) + @make cargo.build crate=medea-jason \ + platform=$(platform) targets=$(targets) \ + debug=$(debug) dockerized=$(dockerized) # Resolve all project dependencies. @@ -78,7 +96,7 @@ build.jason: # Usage: # make deps -deps: cargo yarn +deps: cargo flutter yarn docs: docs.rust @@ -208,16 +226,24 @@ cargo: # Build medea's related crates. # # Usage: -# make cargo.build [crate=(@all|medea|medea-jason)] -# [debug=(yes|no)] -# [dockerized=(no|yes)] +# make cargo.build +# [( [crate=@all] +# | crate=medea +# | crate=medea-jason [debug=(yes|no)] [dockerized=(no|yes)] +# [( [platform=web] +# | platform=android +# [targets=($(ANDROID_NDK_TARGETS)|[,...])] )] )] cargo-build-crate = $(if $(call eq,$(crate),),@all,$(crate)) +cargo-build-platform = $(if $(call eq,$(platform),),web,$(platform)) +cargo-build-targets = $(strip \ + $(if $(call eq,$(targets),),$(ANDROID_NDK_TARGETS),$(targets))) cargo.build: ifeq ($(cargo-build-crate),@all) @make build crate=medea - @make build crate=medea-jason + @make build crate=medea-jason platform=web + @make build crate=medea-jason platform=android targets=$(targets) endif ifeq ($(cargo-build-crate),medea) ifeq ($(dockerized),yes) @@ -233,6 +259,7 @@ endif endif ifeq ($(cargo-build-crate),medea-jason) ifeq ($(dockerized),yes) +ifeq ($(cargo-build-platform),web) docker run --rm --network=host -v "$(PWD)":/app -w /app \ -u $(shell id -u):$(shell id -g) \ -v "$(HOME)/.cargo/registry":/usr/local/cargo/registry \ @@ -242,14 +269,42 @@ ifeq ($(dockerized),yes) make cargo.build crate=$(cargo-build-crate) \ debug=$(debug) dockerized=no \ pre-install=yes +endif +ifeq ($(cargo-build-platform),android) + docker run --rm --network=host -v "$(PWD)":/app -w /app \ + -u $(shell id -u):$(shell id -g) \ + -v "$(HOME)/.cargo/registry":/usr/local/cargo/registry \ + -v "$(HOME):$(HOME)" \ + -e XDG_CACHE_HOME=$(HOME) \ + instrumentisto/cargo-ndk:$(CARGO_NDK_VER) \ + make cargo.build crate=$(cargo-build-crate) \ + debug=$(debug) dockerized=no \ + platform=$(platform) targets=$(targets) +endif else +ifeq ($(cargo-build-platform),web) ifeq ($(pre-install),yes) curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh endif @rm -rf $(crate-dir)/pkg/ wasm-pack build -t web $(crate-dir) $(if $(call eq,$(debug),no),,--dev) endif +ifeq ($(cargo-build-platform),android) + $(foreach target,$(subst $(comma), ,$(cargo-build-targets)),\ + $(call cargo.build.medea-jason.android,$(target),$(debug))) +endif +endif endif +# TODO: Replace with actual `medea-jason` crate. +define cargo.build.medea-jason.android + $(eval target := $(strip $(1))) + $(eval debug := $(strip $(2))) + cd jason/jason-dummy/ && \ + cargo ndk -p $(ANDROID_SDK_COMPILE_VERSION) -t $(target) \ + -o ../flutter/android/src/main/jniLibs \ + --manifest-path=Cargo.toml \ + build $(if $(call eq,$(debug),no),--release,) +endef # Show permalink to CHANGELOG of a concrete version of project's Cargo crate. @@ -294,6 +349,14 @@ endif cargo.lint: cargo clippy --all -- -D clippy::pedantic -D warnings + $(foreach target,$(subst $(comma), ,$(ANDROID_RUST_TARGETS)),\ + $(call cargo.lint.medea-jason.android,$(target))) +# TODO: Replace with actual `medea-jason` crate. +define cargo.lint.medea-jason.android + $(eval target := $(strip $(1))) + cd jason/jason-dummy/ && \ + cargo clippy --target=$(target) -- -D clippy::pedantic -D warnings +endef # Show version of project's Cargo crate. @@ -305,6 +368,79 @@ cargo.version: @printf "$(crate-ver)" +# Install or upgrade project's Android targets for Rust. +# +# Usage: +# make rustup.android + +rustup.android: + rustup target add $(ANDROID_RUST_TARGETS) + + + + +#################### +# Flutter commands # +#################### + +# Show Android SDK compile API version of medea_jason Flutter plugin. +# +# Usage: +# make flutter.android.compile_api_version + +flutter.android.version.compile: + @printf "$(ANDROID_SDK_COMPILE_VERSION)" + + +# Show Android SDK minimal API version of medea_jason Flutter plugin. +# +# Usage: +# make flutter.android.version.min + +flutter.android.version.min: + @printf "$(ANDROID_SDK_MIN_VERSION)" + + +# Resolve Flutter project dependencies. +# +# Usage: +# make flutter [cmd=(pub get|)] + +flutter: + cd jason/flutter && \ + flutter $(if $(call eq,$(cmd),),pub get,$(cmd)) + + +# Format Flutter Dart sources with dartfmt. +# +# Usage: +# make flutter.fmt [check=(no|yes)] + +flutter.fmt: + flutter format $(if $(call eq,$(check),yes),-n --set-exit-if-changed,) \ + jason/flutter/ + + +# Lint Flutter Dart sources with dartanalyzer. +# +# Usage: +# make flutter.lint + +flutter.lint: + flutter analyze jason/flutter/ + + +# Runs medea_jason Flutter plugin example app on attached device. +# +# Usage: +# make flutter.run [debug=(yes|no)] [device=] + +flutter.run: + cd jason/flutter/example/ && \ + flutter run $(if $(call eq,$(debug),no),--release,) \ + $(if $(call eq,$(device),),,-d $(device)) + + ################# @@ -488,6 +624,18 @@ ifeq ($(up),yes) endif +# Runs Flutter plugin integration tests on an attached device. +# +# Usage: +# make test.flutter [device=] + +test.flutter: + cd jason/flutter/example/ && \ + flutter drive --driver=test_driver/integration_test.dart \ + --target=integration_test/jason.dart \ + $(if $(call eq,$(device),),,-d $(device)) + + #################### @@ -1096,11 +1244,15 @@ endef docker.up.medea docker.up.webdriver \ docs docs.rust \ down down.control down.coturn down.demo down.dev down.medea \ + flutter flutter.fmt flutter.lint flutter.run flutter.test \ + flutter.android.compile_api_version \ + flutter.android.min_api_version \ helm helm.dir helm.down helm.lint helm.list \ helm.package helm.package.release helm.up \ minikube.boot \ release release.crates release.helm release.npm \ - test test.e2e test.integration test.unit \ + rustup.android \ + test test.e2e test.flutter test.integration test.unit \ up up.control up.coturn up.demo up.dev up.jason up.medea \ wait.port \ yarn yarn.version diff --git a/jason/flutter/.editorconfig b/jason/flutter/.editorconfig new file mode 100644 index 000000000..38088492b --- /dev/null +++ b/jason/flutter/.editorconfig @@ -0,0 +1,15 @@ +[*.dart] +indent_style = space +indent_size = 2 + +[*.kt] +indent_style = space +indent_size = 4 + +[*.gradle] +indent_style = space +indent_size = 4 + +[*.xml] +indent_style = space +indent_size = 4 diff --git a/jason/flutter/.gitignore b/jason/flutter/.gitignore new file mode 100644 index 000000000..62be51074 --- /dev/null +++ b/jason/flutter/.gitignore @@ -0,0 +1,10 @@ +/.dart_tool/ +/.pub/ +/.packages +/.flutter-plugins-dependencies +/.flutter-plugins + +/pubspec.lock + +/doc/api/ +/build/ diff --git a/jason/flutter/CHANGELOG.md b/jason/flutter/CHANGELOG.md new file mode 100644 index 000000000..8c0f24e97 --- /dev/null +++ b/jason/flutter/CHANGELOG.md @@ -0,0 +1,29 @@ +`medea_jason` Flutter plugin changelog +====================================== + +All user visible changes to this project will be documented in this file. This project uses [Semantic Versioning 2.0.0]. + + + + +## [0.1.0] · 2021-??-?? ~TBD +[0.1.0]: /../../tree/medea-jason-flutter-0.1.0/jason/flutter + +[Milestone](/../../milestone/3) | [Roadmap](/../../issues/182) + +#### Added + +... + +#### Changed + +... + +#### Fixed + +... + + + + +[Semantic Versioning 2.0.0]: https://semver.org diff --git a/jason/flutter/LICENSE.md b/jason/flutter/LICENSE.md new file mode 100644 index 000000000..49c86075f --- /dev/null +++ b/jason/flutter/LICENSE.md @@ -0,0 +1,56 @@ +Blue Oak Model License +====================== + +Version 1.0.0 + +## Purpose + +This license gives everyone as much permission to work with +this software as possible, while protecting contributors +from liability. + +## Acceptance + +In order to receive this license, you must agree to its +rules. The rules of this license are both obligations +under that agreement and conditions to your license. +You must not do anything with this software that triggers +a rule that you cannot or will not follow. + +## Copyright + +Each contributor licenses you to do everything with this +software that would otherwise infringe that contributor's +copyright in it. + +## Notices + +You must ensure that everyone who gets a copy of +any part of this software from you, with or without +changes, also gets the text of this license or a link to +. + +## Excuse + +If anyone notifies you in writing that you have not +complied with [Notices](#notices), you can keep your +license by taking all practical steps to comply within 30 +days after the notice. If you do not do so, your license +ends immediately. + +## Patent + +Each contributor licenses you to do everything with this +software that would otherwise infringe any patent claims +they can license or become able to license. + +## Reliability + +No contributor can revoke this license. + +## No Liability + +***As far as the law allows, this software comes as is, +without any warranty or condition, and no contributor +will be liable to anyone for any damages related to this +software or this license, under any kind of legal claim.*** diff --git a/jason/flutter/README.md b/jason/flutter/README.md new file mode 100644 index 000000000..5dcb3cb77 --- /dev/null +++ b/jason/flutter/README.md @@ -0,0 +1,19 @@ +Jason Flutter plugin +==================== + +[Changelog](https://github.com/instrumentisto/medea/blob/master/jason/flutter/CHANGELOG.md) + +Client library for integration with [Medea] media server in Flutter applications. + +__Currently, in early development phase.__ + +## License + +Copyright © 2021 Instrumentisto Team, + +This software is subject to the terms of the [Blue Oak Model License 1.0.0](https://github.com/instrumentisto/medea/blob/master/jason/flutter/LICENSE.md). If a copy of the [BlueOak-1.0.0](https://spdx.org/licenses/BlueOak-1.0.0.html) license was not distributed with this file, You can obtain one at . + + + + +[Medea]: https://github.com/instrumentisto/medea diff --git a/jason/flutter/analysis_options.yaml b/jason/flutter/analysis_options.yaml new file mode 100644 index 000000000..108d1058a --- /dev/null +++ b/jason/flutter/analysis_options.yaml @@ -0,0 +1 @@ +include: package:pedantic/analysis_options.yaml diff --git a/jason/flutter/android/.gitignore b/jason/flutter/android/.gitignore new file mode 100644 index 000000000..baabfb39b --- /dev/null +++ b/jason/flutter/android/.gitignore @@ -0,0 +1,7 @@ +/.gradle/ + +/build/ +/captures/ +/src/main/jniLibs/ + +/local.properties diff --git a/jason/flutter/android/build.gradle b/jason/flutter/android/build.gradle new file mode 100644 index 000000000..9c7175b6b --- /dev/null +++ b/jason/flutter/android/build.gradle @@ -0,0 +1,40 @@ +group 'com.medea.jason' +version '1.0-SNAPSHOT' + +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath "com.android.tools.build:gradle:" + + "${ANDROID_GRADLE_PLUGIN_VERSION}" + 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' + } + defaultConfig { + minSdkVersion 21 + } +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${KOTLIN_VERSION}" +} diff --git a/jason/flutter/android/gradle.properties b/jason/flutter/android/gradle.properties new file mode 100644 index 000000000..ee4ec8f8e --- /dev/null +++ b/jason/flutter/android/gradle.properties @@ -0,0 +1,6 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true + +KOTLIN_VERSION=1.4.21 +ANDROID_GRADLE_PLUGIN_VERSION=4.1.0 diff --git a/jason/flutter/android/gradle/wrapper/gradle-wrapper.properties b/jason/flutter/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..3c9d0852b --- /dev/null +++ b/jason/flutter/android/gradle/wrapper/gradle-wrapper.properties @@ -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 diff --git a/jason/flutter/android/settings.gradle b/jason/flutter/android/settings.gradle new file mode 100644 index 000000000..387f69f60 --- /dev/null +++ b/jason/flutter/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'jason' diff --git a/jason/flutter/android/src/main/AndroidManifest.xml b/jason/flutter/android/src/main/AndroidManifest.xml new file mode 100644 index 000000000..95edfb515 --- /dev/null +++ b/jason/flutter/android/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + + diff --git a/jason/flutter/android/src/main/kotlin/com/medea/jason/JasonPlugin.kt b/jason/flutter/android/src/main/kotlin/com/medea/jason/JasonPlugin.kt new file mode 100644 index 000000000..489f37024 --- /dev/null +++ b/jason/flutter/android/src/main/kotlin/com/medea/jason/JasonPlugin.kt @@ -0,0 +1,17 @@ +package com.medea.jason + +import androidx.annotation.NonNull + +import io.flutter.embedding.engine.plugins.FlutterPlugin + +class JasonPlugin: FlutterPlugin { + override fun onAttachedToEngine( + @NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding, + ) { + } + + override fun onDetachedFromEngine( + @NonNull binding: FlutterPlugin.FlutterPluginBinding, + ) { + } +} diff --git a/jason/flutter/example/.gitignore b/jason/flutter/example/.gitignore new file mode 100644 index 000000000..34de75190 --- /dev/null +++ b/jason/flutter/example/.gitignore @@ -0,0 +1,11 @@ +**/doc/api/ +**/ios/Flutter/.last_build_id + +/.dart_tool/ +/.flutter-plugins +/.flutter-plugins-dependencies +/.packages +/.pub-cache/ +/.pub/ + +/build/ diff --git a/jason/flutter/example/android/.gitignore b/jason/flutter/example/android/.gitignore new file mode 100644 index 000000000..d013aa02d --- /dev/null +++ b/jason/flutter/example/android/.gitignore @@ -0,0 +1,10 @@ +/.gradle/ +/gradle-wrapper.jar +/gradlew +/gradlew.bat + +/captures/ +/GeneratedPluginRegistrant.java + +/local.properties +/key.properties diff --git a/jason/flutter/example/android/app/build.gradle b/jason/flutter/example/android/app/build.gradle new file mode 100644 index 000000000..5e9e2c49d --- /dev/null +++ b/jason/flutter/example/android/app/build.gradle @@ -0,0 +1,60 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with " + + "flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 30 + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + applicationId "com.instrumentisto.medea_jason_example" + minSdkVersion 21 + targetSdkVersion 30 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` + // works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${KOTLIN_VERSION}" +} diff --git a/jason/flutter/example/android/app/src/debug/AndroidManifest.xml b/jason/flutter/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..a1c7b5847 --- /dev/null +++ b/jason/flutter/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + diff --git a/jason/flutter/example/android/app/src/main/AndroidManifest.xml b/jason/flutter/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..b1280010e --- /dev/null +++ b/jason/flutter/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + diff --git a/jason/flutter/example/android/app/src/main/kotlin/com/instrumentisto/medea_jason_example/MainActivity.kt b/jason/flutter/example/android/app/src/main/kotlin/com/instrumentisto/medea_jason_example/MainActivity.kt new file mode 100644 index 000000000..047452faa --- /dev/null +++ b/jason/flutter/example/android/app/src/main/kotlin/com/instrumentisto/medea_jason_example/MainActivity.kt @@ -0,0 +1,6 @@ +package com.instrumentisto.medea_jason_example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/jason/flutter/example/android/app/src/main/res/drawable-v21/launch_background.xml b/jason/flutter/example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 000000000..c4e2870ca --- /dev/null +++ b/jason/flutter/example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/jason/flutter/example/android/app/src/main/res/drawable/launch_background.xml b/jason/flutter/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 000000000..fb0214fa4 --- /dev/null +++ b/jason/flutter/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/jason/flutter/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/jason/flutter/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..db77bb4b7 Binary files /dev/null and b/jason/flutter/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/jason/flutter/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/jason/flutter/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..17987b79b Binary files /dev/null and b/jason/flutter/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/jason/flutter/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/jason/flutter/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..09d439148 Binary files /dev/null and b/jason/flutter/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/jason/flutter/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/jason/flutter/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..d5f1c8d34 Binary files /dev/null and b/jason/flutter/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/jason/flutter/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/jason/flutter/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..4d6372eeb Binary files /dev/null and b/jason/flutter/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/jason/flutter/example/android/app/src/main/res/values-night/styles.xml b/jason/flutter/example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 000000000..c57360edc --- /dev/null +++ b/jason/flutter/example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/jason/flutter/example/android/app/src/main/res/values/styles.xml b/jason/flutter/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..8b9f32bc7 --- /dev/null +++ b/jason/flutter/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,20 @@ + + + + + + + diff --git a/jason/flutter/example/android/app/src/profile/AndroidManifest.xml b/jason/flutter/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 000000000..a1c7b5847 --- /dev/null +++ b/jason/flutter/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + diff --git a/jason/flutter/example/android/build.gradle b/jason/flutter/example/android/build.gradle new file mode 100644 index 000000000..cb3a54951 --- /dev/null +++ b/jason/flutter/example/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath "com.android.tools.build:gradle:" + + "${ANDROID_GRADLE_PLUGIN_VERSION}" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${KOTLIN_VERSION}" + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/jason/flutter/example/android/gradle.properties b/jason/flutter/example/android/gradle.properties new file mode 100644 index 000000000..ee4ec8f8e --- /dev/null +++ b/jason/flutter/example/android/gradle.properties @@ -0,0 +1,6 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true + +KOTLIN_VERSION=1.4.21 +ANDROID_GRADLE_PLUGIN_VERSION=4.1.0 diff --git a/jason/flutter/example/android/gradle/wrapper/gradle-wrapper.properties b/jason/flutter/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..bc6a58afd --- /dev/null +++ b/jason/flutter/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +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 diff --git a/jason/flutter/example/android/settings.gradle b/jason/flutter/example/android/settings.gradle new file mode 100644 index 000000000..505bb97ba --- /dev/null +++ b/jason/flutter/example/android/settings.gradle @@ -0,0 +1,12 @@ +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle" + + "/app_plugin_loader.gradle" diff --git a/jason/flutter/example/integration_test/jason.dart b/jason/flutter/example/integration_test/jason.dart new file mode 100644 index 000000000..916609c8f --- /dev/null +++ b/jason/flutter/example/integration_test/jason.dart @@ -0,0 +1,11 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; +import 'package:medea_jason/jason.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets('add test', (WidgetTester tester) async { + expect(add(2, 2), equals(4)); + }); +} diff --git a/jason/flutter/example/lib/main.dart b/jason/flutter/example/lib/main.dart new file mode 100644 index 000000000..dd1d21ffc --- /dev/null +++ b/jason/flutter/example/lib/main.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; +import 'package:medea_jason/jason.dart'; + +void main() { + runApp(MyApp()); +} + +class MyApp extends StatefulWidget { + @override + _MyAppState createState() => _MyAppState(); +} + +class _MyAppState extends State { + int _sum = 0; + + @override + void initState() { + super.initState(); + _sum = add(2, 2); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Plugin example app'), + ), + body: Center( + child: Text('2 + 2 = $_sum\n'), + ), + ), + ); + } +} diff --git a/jason/flutter/example/pubspec.yaml b/jason/flutter/example/pubspec.yaml new file mode 100644 index 000000000..61e8d2bf8 --- /dev/null +++ b/jason/flutter/example/pubspec.yaml @@ -0,0 +1,29 @@ +name: medea_jason_example +description: Demonstrates how to use the medea_jason plugin. + +environment: + sdk: ">=2.7.0 <3.0.0" + +dependencies: + flutter: + sdk: flutter + + # When depending on this package from a real application you should use: + # medea_jason: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + medea_jason: + path: ../ + + cupertino_icons: ^1.0.2 + +dev_dependencies: + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + pedantic: ^1.9.0 + +flutter: + uses-material-design: true diff --git a/jason/flutter/example/test_driver/integration_test.dart b/jason/flutter/example/test_driver/integration_test.dart new file mode 100644 index 000000000..b38629cca --- /dev/null +++ b/jason/flutter/example/test_driver/integration_test.dart @@ -0,0 +1,3 @@ +import 'package:integration_test/integration_test_driver.dart'; + +Future main() => integrationDriver(); diff --git a/jason/flutter/lib/jason.dart b/jason/flutter/lib/jason.dart new file mode 100644 index 000000000..0c4bc9746 --- /dev/null +++ b/jason/flutter/lib/jason.dart @@ -0,0 +1,18 @@ +import 'dart:ffi'; +import 'dart:io'; + +typedef _add_C = Int64 Function(Int64 a, Int64 b); +typedef _add_Dart = int Function(int a, int b); + +final DynamicLibrary _dl = _load(); + +final _add_Dart _add = _dl.lookupFunction<_add_C, _add_Dart>('add'); + +DynamicLibrary _load() { + if (Platform.isAndroid) return DynamicLibrary.open('libjason.so'); + throw UnsupportedError('This platform is not supported.'); +} + +int add(int a, int b) { + return _add(a, b); +} diff --git a/jason/flutter/pubspec.yaml b/jason/flutter/pubspec.yaml new file mode 100644 index 000000000..d09436e8b --- /dev/null +++ b/jason/flutter/pubspec.yaml @@ -0,0 +1,24 @@ +name: medea_jason +description: Cross-platform client library of Medea media server for Flutter. +version: 0.2.0 +author: Instrumentisto Team +homepage: https://github.com/instrumentisto/medea + +environment: + sdk: ">=2.12.0 <3.0.0" + flutter: ">=2.0.0" + +dependencies: + flutter: + sdk: flutter + ffi: ^1.0.0 + +dev_dependencies: + pedantic: ^1.9.0 + +flutter: + plugin: + platforms: + android: + package: com.medea.jason + pluginClass: JasonPlugin diff --git a/jason/jason-dummy/.gitignore b/jason/jason-dummy/.gitignore new file mode 100644 index 000000000..042776aad --- /dev/null +++ b/jason/jason-dummy/.gitignore @@ -0,0 +1,2 @@ +/Cargo.lock +/target/ diff --git a/jason/jason-dummy/Cargo.toml b/jason/jason-dummy/Cargo.toml new file mode 100644 index 000000000..890c625ca --- /dev/null +++ b/jason/jason-dummy/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "jason-dummy" +version = "0.0.1" +edition = "2018" +description = "Temp crate to help us bootstrap flutter + rust builds" + +[lib] +name = "jason" +crate-type = ["staticlib", "cdylib"] + +[dependencies] + +[workspace] diff --git a/jason/jason-dummy/src/lib.rs b/jason/jason-dummy/src/lib.rs new file mode 100644 index 000000000..d793cdba3 --- /dev/null +++ b/jason/jason-dummy/src/lib.rs @@ -0,0 +1,4 @@ +#[no_mangle] +pub extern "C" fn add(a: i64, b: i64) -> i64 { + a + b +}