This repository has been archived by the owner on Apr 29, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 12
Initial JNI support #11
Merged
Merged
Changes from 20 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
7551ff3
Add JNI support
mahesh-hegde 8bbeda4
Some general cleanup:
mahesh-hegde c0b1a49
add integration tests, remove macos target in CI
mahesh-hegde 686ae25
specify package versions in pubspec
mahesh-hegde 852691f
README
mahesh-hegde 2a1e7e0
try to run test coverage in both packages
mahesh-hegde f09ddda
workflow: fix coverage file path
mahesh-hegde ab793ae
add coveralls finish step
mahesh-hegde 01aef56
Fix typo in coveralls flag
mahesh-hegde e4e3fd0
Windows support
mahesh-hegde 2fa0c92
temporarily skip testing on windows
mahesh-hegde 7e443a2
Implement suggestions in PR Review 1
mahesh-hegde 9b85ac5
check use-after-free and double-free
mahesh-hegde f820996
Some suggestions from PR Review 1
mahesh-hegde dd7dfef
bin/setup.dart
mahesh-hegde ea680d5
Most changes suggested in Review 1
mahesh-hegde 5b0ed0c
update workflow: try bin/setup.dart
mahesh-hegde f92678a
update workflow: try bin/setup.dart (attempt 2)
mahesh-hegde a72f63b
Add issue references to TODOs
mahesh-hegde 87f60e2
Fix C warning on desktop targets
mahesh-hegde 87f0f41
Some minor changes
mahesh-hegde 849901e
add coverage:ignore-file and exclude some ffigen variables
mahesh-hegde 36fee46
use package_config to find sources during setup
mahesh-hegde 6a61e92
coverage ignore - fix possible typo
mahesh-hegde File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,92 +1,37 @@ | ||
# jni | ||
# jni (experimental module) | ||
mahesh-hegde marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
A new Flutter FFI plugin project. | ||
This is a utility library to access JNI from Dart / Flutter code, intended as a supplement for `jnigen` code generator, as well as provide the common base components (such as managing the JVM instance) to the code generated by `jni_gen`. | ||
|
||
## Getting Started | ||
This library contains: | ||
|
||
This project is a starting point for a Flutter | ||
[FFI plugin](https://docs.flutter.dev/development/platform-integration/c-interop), | ||
a specialized package that includes native code directly invoked with Dart FFI. | ||
* functions to access the JNIEnv and JavaVM variables from JNI, and wrapper functions to those provided by JNI. (`Jni.getEnv`, `Jni.getJavaVM`). | ||
|
||
## Project stucture | ||
* Functions to spawn a JVM on desktop platforms (`Jni.spawn`). | ||
|
||
This template uses the following structure: | ||
* Some utility functions to make it easier to work with JNI in Dart; eg: To convert a java string object to Dart string (mostly as extension methods on `Pointer<JniEnv>`). | ||
|
||
* `src`: Contains the native source code, and a CmakeFile.txt file for building | ||
that source code into a dynamic library. | ||
* Some Android-specific helpers (get application context and current activity references). | ||
|
||
* `lib`: Contains the Dart code that defines the API of the plugin, and which | ||
calls into the native code using `dart:ffi`. | ||
* Some helper classes and functions to simplify one-off uses (`JniObject` and `JniClass` intended for calling functions by specifying the name and arguments. It will reduce some boilerplate when you're debugging. Note: this API is slightly incomplete). | ||
|
||
* platform folders (`android`, `ios`, `windows`, etc.): Contains the build files | ||
for building and bundling the native code library with the platform application. | ||
This is intended for one-off / debugging uses of JNI, as well as providing a base library for code generated by jni_gen. | ||
|
||
## Buidling and bundling native code | ||
__To interface a complete java library, look forward for `jni_gen`.__ | ||
|
||
The `pubspec.yaml` specifies FFI plugins as follows: | ||
## Platform support | ||
The focus of this project is Flutter Android, since Flutter Android apps already have a JVM, and JNI enables interop with existing Java code and Android Platform APIs. This project also (partially) supports Linux desktop by spawning a JVM through JNI. | ||
|
||
```yaml | ||
plugin: | ||
platforms: | ||
some_platform: | ||
ffiPlugin: true | ||
``` | ||
## Version note | ||
This library is at an early stage of development and we do not provide backwards compatibility of the API at this point. | ||
|
||
This configuration invokes the native build for the various target platforms | ||
and bundles the binaries in Flutter applications using these FFI plugins. | ||
## Documentation | ||
The test/ directory contains files with comments explaining the basics of this module, and the example/ directory contains a flutter example which also touches some Android-specifics. | ||
|
||
This can be combined with dartPluginClass, such as when FFI is used for the | ||
implementation of one platform in a federated plugin: | ||
Using this library assumes some familiarity with JNI - it's threading model and object references, among other things. | ||
|
||
```yaml | ||
plugin: | ||
implements: some_other_plugin | ||
platforms: | ||
some_platform: | ||
dartPluginClass: SomeClass | ||
ffiPlugin: true | ||
``` | ||
## jni_gen | ||
|
||
A plugin can have both FFI and method channels: | ||
This library is a part of `jni_gen` - a 2022 GSoC project. | ||
|
||
```yaml | ||
plugin: | ||
platforms: | ||
some_platform: | ||
pluginClass: SomeName | ||
ffiPlugin: true | ||
``` | ||
|
||
The native build systems that are invoked by FFI (and method channel) plugins are: | ||
|
||
* For Android: Gradle, which invokes the Android NDK for native builds. | ||
* See the documentation in android/build.gradle. | ||
* For iOS and MacOS: Xcode, via CocoaPods. | ||
* See the documentation in ios/jni.podspec. | ||
* See the documentation in macos/jni.podspec. | ||
* For Linux and Windows: CMake. | ||
* See the documentation in linux/CMakeLists.txt. | ||
* See the documentation in windows/CMakeLists.txt. | ||
|
||
## Binding to native code | ||
|
||
To use the native code, bindings in Dart are needed. | ||
To avoid writing these by hand, they are generated from the header file | ||
(`src/jni.h`) by `package:ffigen`. | ||
Regenerate the bindings by running `flutter pub run ffigen --config ffigen.yaml`. | ||
|
||
## Invoking native code | ||
|
||
Very short-running native functions can be directly invoked from any isolate. | ||
For example, see `sum` in `lib/jni.dart`. | ||
|
||
Longer-running functions should be invoked on a helper isolate to avoid | ||
dropping frames in Flutter applications. | ||
For example, see `sumAsync` in `lib/jni.dart`. | ||
|
||
## Flutter help | ||
|
||
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. | ||
The broader aim of jni_gen is making Java APIs accessible from dart in an idiomatic way. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,13 @@ | ||
include: package:flutter_lints/flutter.yaml | ||
|
||
analyzer: | ||
exclude: [build/**] | ||
language: | ||
strict-raw-types: true | ||
|
||
linter: | ||
rules: | ||
- prefer_final_locals | ||
- prefer_const_declarations | ||
# Additional information about this file can be found at | ||
# https://dart.dev/guides/language/analysis-options |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package dev.dart.jni; | ||
|
||
import androidx.annotation.Keep; | ||
import androidx.annotation.NonNull; | ||
import android.util.Log; | ||
import android.app.Activity; | ||
import io.flutter.plugin.common.PluginRegistry.Registrar; | ||
import io.flutter.embedding.engine.plugins.FlutterPlugin; | ||
import io.flutter.embedding.engine.plugins.activity.ActivityAware; | ||
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; | ||
|
||
import android.content.Context; | ||
|
||
@Keep | ||
public class JniPlugin implements FlutterPlugin, ActivityAware { | ||
|
||
@Override | ||
public void | ||
onAttachedToEngine(@NonNull FlutterPluginBinding binding) { | ||
setup(binding.getApplicationContext()); | ||
} | ||
|
||
public static void registerWith(Registrar registrar) { | ||
JniPlugin plugin = new JniPlugin(); | ||
plugin.setup(registrar.activeContext()); | ||
} | ||
|
||
private void setup(Context context) { | ||
initializeJni(context, getClass().getClassLoader()); | ||
} | ||
|
||
@Override | ||
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {} | ||
|
||
// Activity handling methods | ||
@Override | ||
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { | ||
Activity activity = binding.getActivity(); | ||
setJniActivity(activity, activity.getApplicationContext()); | ||
} | ||
|
||
@Override | ||
public void onDetachedFromActivityForConfigChanges() {} | ||
|
||
@Override | ||
public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { | ||
Activity activity = binding.getActivity(); | ||
setJniActivity(activity, activity.getApplicationContext()); | ||
} | ||
|
||
@Override | ||
public void onDetachedFromActivity() {} | ||
|
||
native void initializeJni(Context context, ClassLoader classLoader); | ||
native void setJniActivity(Activity activity, Context context); | ||
|
||
static { | ||
System.loadLibrary("dartjni"); | ||
} | ||
} | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice!