fixes: #172259 The contents of the files (pom, .jar) produced by android also reference the artifacts version number (which includes the git-hash). The flutter recipies are just dumb re-uploaders for the content hash at the moment. In order to change the contents, we can just update some GN files. This has some local duplication of files, but is acceptible for now. I've also added the content-hash as a string in the .so file and its printed out next to the hash. "Why is the folder name the git-hash?" The recipies have a quirk - the logs will have you believe they upload individual files such that "gsutil cp a.jar b.jar" would produce "b.jar"; but that's not what's going on. The recipies recurisively upload from the root of the temporary folder the files are copied to. At the moment, the "Ensure" step of builder.py updates the URL path, so it will handling uploading to the correct path, but not the file or its contents (hence this change). Plan for the future: at some point we can stop producing git-ref hashes. E.g. git-hash: dfd7318efc71019bce1665bc41c0e8c21d1344f9 content-hash: 3bfa6013b7be2b0bbadc22a9c3495d4efa46aba7 ```shell zip_archives └── download.flutter.io └── io └── flutter ├── arm64_v8a_debug │ └── 1.0.0-dfd7318efc71019bce1665bc41c0e8c21d1344f9 │ ├── arm64_v8a_debug-1.0.0-3bfa6013b7be2b0bbadc22a9c3495d4efa46aba7.jar │ ├── arm64_v8a_debug-1.0.0-3bfa6013b7be2b0bbadc22a9c3495d4efa46aba7.pom │ ├── arm64_v8a_debug-1.0.0-dfd7318efc71019bce1665bc41c0e8c21d1344f9.jar │ └── arm64_v8a_debug-1.0.0-dfd7318efc71019bce1665bc41c0e8c21d1344f9.pom └── flutter_embedding_debug └── 1.0.0-dfd7318efc71019bce1665bc41c0e8c21d1344f9 ├── flutter_embedding_debug-1.0.0-3bfa6013b7be2b0bbadc22a9c3495d4efa46aba7-sources.jar ├── flutter_embedding_debug-1.0.0-3bfa6013b7be2b0bbadc22a9c3495d4efa46aba7.jar ├── flutter_embedding_debug-1.0.0-3bfa6013b7be2b0bbadc22a9c3495d4efa46aba7.pom ├── flutter_embedding_debug-1.0.0-dfd7318efc71019bce1665bc41c0e8c21d1344f9-sources.jar ├── flutter_embedding_debug-1.0.0-dfd7318efc71019bce1665bc41c0e8c21d1344f9.jar └── flutter_embedding_debug-1.0.0-dfd7318efc71019bce1665bc41c0e8c21d1344f9.pom ```
Android Platform Embedder
Android embedder for Flutter, including Java io.flutter sources
and Android specific engine-side C++.
This code provides the glue between the Flutter engine and the Android platform, and is responsible for:
- Initializing the Flutter engine.
- Providing a platform view for the Flutter engine to render into.
- Dispatching events to the Flutter engine.
Caution
This is a best effort attempt to document the Android embedder. It is not guaranteed to be up to date or complete. If you find a discrepancy, please send a pull request!
See also:
../../tools/android_lint/bin/main.dart- Android Platform Views
- Hosting native Android views in your Flutter app with Platform Views
- Testing Android Changes in the Devicelab on an Emulator
- Texture Layer Hybrid Composition
Testing
There are two classes of tests for the Android embedder: unit tests that tend to test contracts within the embedder, and integration tests that test the engine and embedder together, typically coupled with a Flutter app (that's how our users interact with the engine and embedder).
Unit tests
Unit tests for the Android embedder are located in:
test: Java unit tests.- C++ files that end in
_unittests.ccinshell/platform/android.
The easiest way (though not the quickest) is to use run_tests.py:
# Assuming you're at the root of the engine repo where `run_tests.py` is located.
./testing/run_tests.py --type java
# Confusingly, these are C++ tests for Android.
./testing/run_tests.py --type android
# If you're using android_debug_unopt_arm64 builds:
./testing/run_tests.py --type android --android-variant android_debug_unopt_arm64
./testing/run_tests.py --type java --android-variant android_debug_unopt_arm64
Tip
Trying to debug tests or timeouts/hangs?
Run the tests directly from Android Studio, or set
maxParallelForksto1:+ maxParallelForks availableProcessors // The CI bot has 8 CPUs. - maxParallelForks 1
Integration tests
Integration tests for the Android embedder mostly exist outside of the engine for dubious historical reasons.
To run these tests, you'll need to have a Flutter checkout and a working Android emulator or device:
# Build an up-to-date Flutter engine for Android.
cd $ENGINE/src
# Or, use your favorite arguments and build variant.
ninja -j1000 -C ../out/android_debug_unopt_arm64 android_jar
# Run the tests. Here is *1* example:
cd $FLUTTER/dev/integration_tests/external_textures
flutter drive \
--local-engine-host=$ENGINE/out/host_debug_unopt_arm64 \
--local-engine=$ENGINE/out/android_debug_unopt_arm64
Another good source of (unfortunately, manual) testing is flutter/packages:
cd $PACKAGES/packages/video_player/video_player_android/example
flutter run \
--local-engine-host=$ENGINE/out/host_debug_unopt_arm64 \
--local-engine=$ENGINE/out/android_debug_unopt_arm64
Note
External texture rendering on Android is based on the device API level. For example to test the OpenGLES branch (which uses
SurfaceTexture), you'll typically need an older device or emulator with an API version 29 or lower.You can also (locally) "force" the engine to use
SurfaceTextures:// shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java - @VisibleForTesting static boolean debugForceSurfaceProducerGlTextures = false; + @VisibleForTesting static boolean debugForceSurfaceProducerGlTextures = true;... and rebuild the engine.
See our wiki also.
Developing
How to edit and contribute to the Android embedder.
Tip
This guide assumes you already have a working Engine development environment:
You should also have a working Android development environment:
It is also recommended (but not required) to install Visual Studio Code.
Depending on what you are trying to do, you may need to edit the Java code in
io.flutter or the C++ code in shell/platform/android,
sometimes both. Let's start with the C++ code, as it is more similar to
developing for other platforms or platform-agnostic parts of the engine.
Editing C++ code
The C++ code for the Android embedder is located in
shell/platform/android and subdirectories.
Some notable files include:
context/android_context.h: Holds state that is shared across Android surfaces.jni/platform_view_android_jni.h: Allows calling Java code running in the JVM.AndroidManifest.xml: Used byandroid_lint.BUILD.gn: Used by GN to build the C++-side embedder tests and theflutter.jarfile for the engine.ndk_helpers.h: Helper functions for dynamically loading and calling Android NDK (C/C++) functions.platform_view_android.h: The main entry point for the Android embedder.
See VSCode with C/C++ Intellisense
for how to use the clangd extension to get C++ code
completion:
Note
--compile-commands-dirmust point to an Android build output:{ /* ... */ "clangd.path": "buildtools/mac-arm64/clang/bin/clangd", "clangd.arguments": ["--compile-commands-dir=out/android_debug_unopt_arm64"] /* ... */ }... but remember to change it back when editing other parts of the engine.
Editing Java code
The Java code for the Android embedder is located in
io/flutter/ and subdirectories.
The tests are located in test/io/flutter/, and the test
runner in test_runner.
Some notable files include:
io/flutter/embedding/android/FlutterActivity.java: An activity that displays a full-screen Flutter UI.io/flutter/embedding/engine/FlutterJNI.java: The Java interface for the C++ engine.io/flutter/view/TextureRegistry.java: Registry of backend textures used by a Flutter View.
It is non-trivial to get a working IDE setup for editing Java code in the Flutter engine. Some developers have had success using VSCode as an IDE for the Android Embedding, but the following instructions are for if that doesn't work, or you want to use Android Studio:
-
Open
shell/platform/androidin Android Studio. -
Configure the following:
-
Preferences | Build, Execution, Deployment | Gradle-Android CompilerCommand-line Options:
-Pbuild_dir="/tmp/build_dir" -Pflutter_jar="$ENGINE/src/out/android_debug_unopt_arm64/flutter.jar" -
Preferences | Build, Execution, Deployment | Build Tools | GradleDistribution of
Local Installationwith:$ENGINE/src/third_party/gradleGradle SDK using Android Studio (path depends on your machine):
/Applications/Android Studio.app/Contents/jbr/Contents/Home
-
-
Sync Gradle.
At this point you should be able to open Java files in Android Studio and get
code completion in the io/flutter and test/io/flutter folders. For example, FlutterJNI.java:
To get code coverage displayed in line: go to the test class you wish to run and
- Right click > Modify Run Configuration...,
- In the window that pops up click Modify options > Specify classes and packages (under "code coverage").
- In the new box that appears at the bottom of the window, click the + > Add package, and then add
io.flutter.*.