diff --git a/.github/workflows/jnigen.yaml b/.github/workflows/jnigen.yaml index ac3b971919..53dd63c5b1 100644 --- a/.github/workflows/jnigen.yaml +++ b/.github/workflows/jnigen.yaml @@ -90,12 +90,6 @@ jobs: distribution: 'zulu' java-version: '17' cache: maven - ## Committed bindings are formatted with clang-format. - ## So this is required to format generated bindings identically - - name: install clang tools - run: | - sudo apt-get update -y - sudo apt-get install -y clang-format - name: Install dependencies run: dart pub get - name: build in_app_java APK @@ -172,8 +166,11 @@ jobs: working-directory: ./pkgs/jni - name: install clang tools & CMake run: | + wget https://apt.llvm.org/llvm.sh + chmod +x llvm.sh + sudo ./llvm.sh 20 sudo apt-get update -y - sudo apt-get install -y clang-format build-essential cmake + sudo apt-get install -y clang-format-20 build-essential cmake - run: flutter pub get - name: Check formatting run: dart format --output=none --set-exit-if-changed . @@ -224,6 +221,14 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} parallel: true path-to-lcov: ./pkgs/jni/coverage/lcov.info + - name: building the example project succeeds + working-directory: ./pkgs/jni/example/ + run: | + flutter build apk + - name: regenerate & compare jnigen bindings + run: | + dart run tool/generate_jni_bindings.dart + git diff --exit-code -- lib/src/plugin # TODO(https://github.com/dart-lang/ffigen/issues/555): FFIgen generated # on my machine has macOS specific stuff and CI does not. # We should just generate the struct as opaque, but we currently can't. @@ -419,7 +424,7 @@ jobs: java-version: '17' - run: | sudo apt-get update -y - sudo apt-get install -y ninja-build libgtk-3-dev clang-format + sudo apt-get install -y ninja-build libgtk-3-dev - run: flutter config --enable-linux-desktop - run: dart pub get - name: Generate full bindings diff --git a/pkgs/jni/CHANGELOG.md b/pkgs/jni/CHANGELOG.md index 32074f7c65..a2f619b00c 100644 --- a/pkgs/jni/CHANGELOG.md +++ b/pkgs/jni/CHANGELOG.md @@ -3,6 +3,10 @@ - **Breaking Change**: Made `Jni.env` internal. - **Breaking Change**: Renamed `JObjType` to `JType`. - **Breaking Change**: Made all of the type classes internal. +- **Breaking Change**: Removed `Jni.getApplicationClassLoader()`, + `Jni.getCurrentActivity()`, and `Jni.getCachedApplicationContext()`. Instead + use `Jni.androidApplicationContext(engineId)` to access the application + context and use `Jni.androidActivity(engineId)` to acccess the activity. - Update to the latest lints. ## 0.14.2 @@ -13,12 +17,13 @@ ## 0.14.1 -- Updated `bin/setup.dart` to use Gradle instead of Maven for building Java sources. Added gradle executables - and bootstrap jars [#2003](https://github.com/dart-lang/native/issues/2003) -- Added `JObject.isInstanceOf` which checks whether a `JObject` is an instance +- Updated `bin/setup.dart` to use Gradle instead of Maven for building Java + sources. Added gradle executables and bootstrap jars + [#2003](https://github.com/dart-lang/native/issues/2003) +- Added `JObject.isInstanceOf` which checks whether a `JObject` is an instance of a java class. -- Fixed a [bug](https://github.com/dart-lang/native/issues/1908) where - Java interfaces implemented in on the main thread in Dart could deadlock when +- Fixed a [bug](https://github.com/dart-lang/native/issues/1908) where Java + interfaces implemented in on the main thread in Dart could deadlock when invoked from the main thread outside the context of a Dart isolate. ## 0.14.0 diff --git a/pkgs/jni/android/src/main/java/com/github/dart_lang/jni/JniPlugin.java b/pkgs/jni/android/src/main/java/com/github/dart_lang/jni/JniPlugin.java index ba41a22250..e27b883898 100644 --- a/pkgs/jni/android/src/main/java/com/github/dart_lang/jni/JniPlugin.java +++ b/pkgs/jni/android/src/main/java/com/github/dart_lang/jni/JniPlugin.java @@ -7,48 +7,72 @@ import android.app.Activity; import android.content.Context; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.embedding.engine.plugins.activity.ActivityAware; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; public class JniPlugin implements FlutterPlugin, ActivityAware { + private static final ConcurrentHashMap pluginMap = new ConcurrentHashMap<>(); + + private long engineId; + private volatile Context context; + private volatile Activity activity; + + public static @NonNull Context getApplicationContext(long engineId) { + return Objects.requireNonNull(pluginMap.get(engineId)).context; + } + + public static @Nullable Activity getActivity(long engineId) { + return Objects.requireNonNull(pluginMap.get(engineId)).activity; + } @Override + @SuppressWarnings("deprecation") public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { - setup(binding.getApplicationContext()); + //noinspection deprecation + engineId = binding.getFlutterEngine().getEngineId(); + context = binding.getApplicationContext(); + pluginMap.put(engineId, this); } - private void setup(Context context) { - initializeJni(context, getClass().getClassLoader()); + @Override + public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { + context = null; + activity = null; + pluginMap.remove(engineId); } - @Override - public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {} + private void setActivity(Activity newActivity) { + activity = newActivity; + } - // Activity handling methods @Override public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { - Activity activity = binding.getActivity(); - setJniActivity(activity, activity.getApplicationContext()); + setActivity(binding.getActivity()); } @Override - public void onDetachedFromActivityForConfigChanges() {} + public void onDetachedFromActivityForConfigChanges() { + setActivity(null); + } @Override public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { - Activity activity = binding.getActivity(); - setJniActivity(activity, activity.getApplicationContext()); + setActivity(binding.getActivity()); } @Override - public void onDetachedFromActivity() {} - - native void initializeJni(Context context, ClassLoader classLoader); + public void onDetachedFromActivity() { + setActivity(null); + } - native void setJniActivity(Activity activity, Context context); + static native void setClassLoader(ClassLoader classLoader); static { System.loadLibrary("dartjni"); + setClassLoader(JniPlugin.class.getClassLoader()); } } diff --git a/pkgs/jni/example/android/settings.gradle b/pkgs/jni/example/android/settings.gradle index 27029b3eb8..4f520718dc 100644 --- a/pkgs/jni/example/android/settings.gradle +++ b/pkgs/jni/example/android/settings.gradle @@ -19,7 +19,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" id "com.android.application" version "8.6.0" apply false - id "org.jetbrains.kotlin.android" version "1.8.10" apply false + id "org.jetbrains.kotlin.android" version "2.1.0" apply false } include ":app" diff --git a/pkgs/jni/example/lib/main.dart b/pkgs/jni/example/lib/main.dart index 29dd29ec93..a159a43620 100644 --- a/pkgs/jni/example/lib/main.dart +++ b/pkgs/jni/example/lib/main.dart @@ -5,6 +5,7 @@ // ignore_for_file: library_private_types_in_public_api import 'dart:io'; +import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:jni/jni.dart'; @@ -32,18 +33,17 @@ String backAndForth() { } void quit() { - JObject.fromReference(Jni.getCurrentActivity()).use((ac) => - ac.jClass.instanceMethodId("finish", "()V").call(ac, jvoid.type, [])); + final activity = Jni.androidActivity(PlatformDispatcher.instance.engineId!); + if (activity == null) return; + activity.jClass + .instanceMethodId("finish", "()V") + .call(activity, jvoid.type, []); + activity.release(); } void showToast(String text) { - // This is example for calling your app's custom java code. - // Place the Toaster class in the app's android/ source Folder, with a Keep - // annotation or appropriate proguard rules to retain classes in release mode. - // - // In this example, Toaster class wraps android.widget.Toast so that it - // can be called from any thread. See - // android/app/src/main/java/com/github/dart_lang/jni_example/Toaster.java + final activity = Jni.androidActivity(PlatformDispatcher.instance.engineId!); + if (activity == null) return; final toasterClass = JClass.forName('com/github/dart_lang/jni_example/Toaster'); final makeText = toasterClass.staticMethodId( @@ -51,17 +51,24 @@ void showToast(String text) { '(Landroid/app/Activity;Landroid/content/Context;' 'Ljava/lang/CharSequence;I)' 'Lcom/github/dart_lang/jni_example/Toaster;'); - final toaster = makeText.call(toasterClass, JObject.type, [ - Jni.getCurrentActivity(), - Jni.getCachedApplicationContext(), - '😀'.toJString(), + final applicationContext = + Jni.androidApplicationContext(PlatformDispatcher.instance.engineId!); + final toaster = makeText(toasterClass, JObject.type, [ + activity, + applicationContext, + text.toJString(), 0, ]); final show = toasterClass.instanceMethodId('show', '()V'); show(toaster, jvoid.type, []); + toaster.release(); + applicationContext.release(); + activity.release(); + text.toJString().release(); } void main() { + WidgetsFlutterBinding.ensureInitialized(); if (!Platform.isAndroid) { Jni.spawn(); } @@ -80,13 +87,22 @@ void main() { }), Example( "Package name", - () => JObject.fromReference(Jni.getCurrentActivity()).use((activity) => - activity.jClass - .instanceMethodId("getPackageName", "()Ljava/lang/String;") - .call(activity, JString.type, [])), + () { + final activity = + Jni.androidActivity(PlatformDispatcher.instance.engineId!); + if (activity == null) return "Activity not available"; + final packageName = activity.jClass + .instanceMethodId("getPackageName", "()Ljava/lang/String;") + .call(activity, JString.type, []); + activity.release(); + return packageName; + }, + ), + Example( + "Show toast", + () => showToast("Hello from JNI!"), + runInitially: false, ), - Example("Show toast", () => showToast("Hello from JNI!"), - runInitially: false), Example( "Quit", quit, @@ -104,20 +120,10 @@ class Example { Example(this.title, this.callback, {this.runInitially = true}); } -class MyApp extends StatefulWidget { +class MyApp extends StatelessWidget { const MyApp(this.examples, {super.key}); final List examples; - @override - _MyAppState createState() => _MyAppState(); -} - -class _MyAppState extends State { - @override - void initState() { - super.initState(); - } - @override Widget build(BuildContext context) { return MaterialApp( @@ -126,11 +132,12 @@ class _MyAppState extends State { title: const Text('JNI Examples'), ), body: ListView.builder( - itemCount: widget.examples.length, - itemBuilder: (context, i) { - final eg = widget.examples[i]; - return ExampleCard(eg); - }), + itemCount: examples.length, + itemBuilder: (context, i) { + final eg = examples[i]; + return ExampleCard(eg); + }, + ), ), ); } diff --git a/pkgs/jni/lib/src/jni.dart b/pkgs/jni/lib/src/jni.dart index 3c7191d910..6bed9c2d91 100644 --- a/pkgs/jni/lib/src/jni.dart +++ b/pkgs/jni/lib/src/jni.dart @@ -14,6 +14,7 @@ import 'accessors.dart'; import 'errors.dart'; import 'jobject.dart'; import 'jreference.dart'; +import 'plugin/generated_plugin.dart'; import 'third_party/generated_bindings.dart'; import 'types.dart'; @@ -212,22 +213,77 @@ abstract final class Jni { @internal static final env = GlobalJniEnv(_fetchGlobalEnv()); - /// Returns current application context on Android. - static JReference getCachedApplicationContext() { - return JGlobalReference(_bindings.GetApplicationContext()); + /// Retrieves the global Android `ApplicationContext` associated with a + /// Flutter engine. + /// + /// Pass `PlatformDispatcher.instance.engineId` to the [engineId] field. + /// + /// The `ApplicationContext` is a long-lived singleton tied to the + /// application's lifecycle. It is safe to store and use from any thread + /// for non-UI tasks. + static JObject androidApplicationContext(int engineId) { + return JniPlugin.getApplicationContext(engineId); } - /// Returns current activity. - static JReference getCurrentActivity() => - JGlobalReference(_bindings.GetCurrentActivity()); - - /// Get the initial classLoader of the application. + /// Retrieves the current Android `Activity` associated with a Flutter engine. + /// + /// The `engineId` can be obtained from `PlatformDispatcher.instance.engineId` + /// in Dart. + /// + /// **WARNING: This reference is volatile and must be used with care.** + /// + /// The Android `Activity` lifecycle is asynchronous. The `Activity` returned + /// by this function can become `null` or stale (destroyed) at any moment, + /// such as during screen rotation or when the app is backgrounded. + /// + /// To prevent native crashes, this function has two strict usage rules: + /// + /// 1. **Platform Thread Only**: It must *only* be called from the platform + /// thread. + /// 2. **Synchronous Use Only**: The returned `JObject` must be used + /// immediately and synchronously, with no asynchronous gaps (`await`). /// - /// This is especially useful on Android, where - /// JNI threads cannot access application classes using - /// the usual `JniEnv.FindClass` method. - static JReference getApplicationClassLoader() => - JGlobalReference(_bindings.GetClassLoader()); + /// Do not store the returned `JObject` in a field or local variable that + /// persists across an `await`. + /// + /// --- + /// + /// ### Correct Usage (Synchronous, "Get-and-Use"): + /// + /// ```dart + /// void safeCall() { + /// // This is safe because the `Activity` is retrieved and used + /// // in a single, unbroken, synchronous block. + /// final activity = Jni.androidActivity(engineId); + /// if (activity != null) { + /// someGeneratedApi.doSomething(activity); + /// activity.release(); + /// } + /// } + /// ``` + /// + /// ### **DANGEROUS** Usage (Asynchronous Gap): + /// + /// ```dart + /// Future dangerousCall() async { + /// // 1. Get the Activity (e.g., Activity "A") + /// final activity = Jni.androidActivity(engineId); + /// + /// // 2. An `await` occurs. The main thread is freed. + /// // While waiting, Android might destroy Activity "A" and create "B". + /// await someOtherFuture(); + /// + /// // 3. CRASH: The code resumes, but `activity` is now a stale + /// // reference to the destroyed Activity "A". + /// if (activity != null) { + /// someGeneratedApi.doSomething(activity); // This will crash + /// activity.release(); + /// } + /// } + /// ``` + static JObject? androidActivity(int engineId) { + return JniPlugin.getActivity(engineId); + } } /// Extensions for use by JNIgen generated code. diff --git a/pkgs/jni/lib/src/plugin/generated_plugin.dart b/pkgs/jni/lib/src/plugin/generated_plugin.dart new file mode 100644 index 0000000000..cc4b90198c --- /dev/null +++ b/pkgs/jni/lib/src/plugin/generated_plugin.dart @@ -0,0 +1,372 @@ +// AUTO GENERATED BY JNIGEN 0.15.0. DO NOT EDIT! + +// Copyright (c) 2025, 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. + +// ignore_for_file: prefer_relative_imports +// ignore_for_file: annotate_overrides +// ignore_for_file: argument_type_not_assignable +// ignore_for_file: camel_case_extensions +// ignore_for_file: camel_case_types +// ignore_for_file: constant_identifier_names +// ignore_for_file: comment_references +// ignore_for_file: doc_directive_unknown +// ignore_for_file: file_names +// ignore_for_file: inference_failure_on_untyped_parameter +// ignore_for_file: invalid_internal_annotation +// ignore_for_file: invalid_use_of_internal_member +// ignore_for_file: library_prefixes +// ignore_for_file: lines_longer_than_80_chars +// ignore_for_file: no_leading_underscores_for_library_prefixes +// ignore_for_file: no_leading_underscores_for_local_identifiers +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: only_throw_errors +// ignore_for_file: overridden_fields +// ignore_for_file: prefer_double_quotes +// ignore_for_file: unintended_html_in_doc_comment +// ignore_for_file: unnecessary_cast +// ignore_for_file: unnecessary_non_null_assertion +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: unused_element +// ignore_for_file: unused_field +// ignore_for_file: unused_import +// ignore_for_file: unused_local_variable +// ignore_for_file: unused_shown_name +// ignore_for_file: use_super_parameters + +import 'dart:core' as core$_; +import 'dart:core' show Object, String, bool, double, int; + +import 'package:jni/_internal.dart' as jni$_; +import 'package:jni/jni.dart' as jni$_; + +/// from: `com.github.dart_lang.jni.JniPlugin` +class JniPlugin extends jni$_.JObject { + @jni$_.internal + @core$_.override + final jni$_.JType $type; + + @jni$_.internal + JniPlugin.fromReference( + jni$_.JReference reference, + ) : $type = type, + super.fromReference(reference); + + static final _class = + jni$_.JClass.forName(r'com/github/dart_lang/jni/JniPlugin'); + + /// The type which includes information such as the signature of this class. + static const jni$_.JType nullableType = + $JniPlugin$NullableType$(); + + /// The type which includes information such as the signature of this class. + static const jni$_.JType type = $JniPlugin$Type$(); + static final _id_new$ = _class.constructorId( + r'()V', + ); + + static final _new$ = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_NewObject') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public void ()` + /// The returned object must be released after use, by calling the [release] method. + factory JniPlugin() { + return JniPlugin.fromReference( + _new$(_class.reference.pointer, _id_new$ as jni$_.JMethodIDPtr) + .reference); + } + + static final _id_getApplicationContext = _class.staticMethodId( + r'getApplicationContext', + r'(J)Landroid/content/Context;', + ); + + static final _getApplicationContext = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.VarArgs<(jni$_.Int64,)>)>>( + 'globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, jni$_.JMethodIDPtr, int)>(); + + /// from: `static public android.content.Context getApplicationContext(long j)` + /// The returned object must be released after use, by calling the [release] method. + static jni$_.JObject getApplicationContext( + int j, + ) { + return _getApplicationContext(_class.reference.pointer, + _id_getApplicationContext as jni$_.JMethodIDPtr, j) + .object(const jni$_.$JObject$Type$()); + } + + static final _id_getActivity = _class.staticMethodId( + r'getActivity', + r'(J)Landroid/app/Activity;', + ); + + static final _getActivity = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JniResult Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.VarArgs<(jni$_.Int64,)>)>>( + 'globalEnv_CallStaticObjectMethod') + .asFunction< + jni$_.JniResult Function( + jni$_.Pointer, jni$_.JMethodIDPtr, int)>(); + + /// from: `static public android.app.Activity getActivity(long j)` + /// The returned object must be released after use, by calling the [release] method. + static jni$_.JObject? getActivity( + int j, + ) { + return _getActivity( + _class.reference.pointer, _id_getActivity as jni$_.JMethodIDPtr, j) + .object(const jni$_.$JObject$NullableType$()); + } + + static final _id_onAttachedToEngine = _class.instanceMethodId( + r'onAttachedToEngine', + r'(Lio/flutter/embedding/engine/plugins/FlutterPlugin$FlutterPluginBinding;)V', + ); + + static final _onAttachedToEngine = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void onAttachedToEngine(io.flutter.embedding.engine.plugins.FlutterPlugin$FlutterPluginBinding flutterPluginBinding)` + void onAttachedToEngine( + jni$_.JObject flutterPluginBinding, + ) { + final _$flutterPluginBinding = flutterPluginBinding.reference; + _onAttachedToEngine( + reference.pointer, + _id_onAttachedToEngine as jni$_.JMethodIDPtr, + _$flutterPluginBinding.pointer) + .check(); + } + + static final _id_onDetachedFromEngine = _class.instanceMethodId( + r'onDetachedFromEngine', + r'(Lio/flutter/embedding/engine/plugins/FlutterPlugin$FlutterPluginBinding;)V', + ); + + static final _onDetachedFromEngine = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void onDetachedFromEngine(io.flutter.embedding.engine.plugins.FlutterPlugin$FlutterPluginBinding flutterPluginBinding)` + void onDetachedFromEngine( + jni$_.JObject flutterPluginBinding, + ) { + final _$flutterPluginBinding = flutterPluginBinding.reference; + _onDetachedFromEngine( + reference.pointer, + _id_onDetachedFromEngine as jni$_.JMethodIDPtr, + _$flutterPluginBinding.pointer) + .check(); + } + + static final _id_onAttachedToActivity = _class.instanceMethodId( + r'onAttachedToActivity', + r'(Lio/flutter/embedding/engine/plugins/activity/ActivityPluginBinding;)V', + ); + + static final _onAttachedToActivity = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void onAttachedToActivity(io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding activityPluginBinding)` + void onAttachedToActivity( + jni$_.JObject activityPluginBinding, + ) { + final _$activityPluginBinding = activityPluginBinding.reference; + _onAttachedToActivity( + reference.pointer, + _id_onAttachedToActivity as jni$_.JMethodIDPtr, + _$activityPluginBinding.pointer) + .check(); + } + + static final _id_onDetachedFromActivityForConfigChanges = + _class.instanceMethodId( + r'onDetachedFromActivityForConfigChanges', + r'()V', + ); + + static final _onDetachedFromActivityForConfigChanges = + jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public void onDetachedFromActivityForConfigChanges()` + void onDetachedFromActivityForConfigChanges() { + _onDetachedFromActivityForConfigChanges(reference.pointer, + _id_onDetachedFromActivityForConfigChanges as jni$_.JMethodIDPtr) + .check(); + } + + static final _id_onReattachedToActivityForConfigChanges = + _class.instanceMethodId( + r'onReattachedToActivityForConfigChanges', + r'(Lio/flutter/embedding/engine/plugins/activity/ActivityPluginBinding;)V', + ); + + static final _onReattachedToActivityForConfigChanges = + jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + jni$_.VarArgs<(jni$_.Pointer,)>)>>( + 'globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function(jni$_.Pointer, + jni$_.JMethodIDPtr, jni$_.Pointer)>(); + + /// from: `public void onReattachedToActivityForConfigChanges(io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding activityPluginBinding)` + void onReattachedToActivityForConfigChanges( + jni$_.JObject activityPluginBinding, + ) { + final _$activityPluginBinding = activityPluginBinding.reference; + _onReattachedToActivityForConfigChanges( + reference.pointer, + _id_onReattachedToActivityForConfigChanges as jni$_.JMethodIDPtr, + _$activityPluginBinding.pointer) + .check(); + } + + static final _id_onDetachedFromActivity = _class.instanceMethodId( + r'onDetachedFromActivity', + r'()V', + ); + + static final _onDetachedFromActivity = jni$_.ProtectedJniExtensions.lookup< + jni$_.NativeFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>>('globalEnv_CallVoidMethod') + .asFunction< + jni$_.JThrowablePtr Function( + jni$_.Pointer, + jni$_.JMethodIDPtr, + )>(); + + /// from: `public void onDetachedFromActivity()` + void onDetachedFromActivity() { + _onDetachedFromActivity( + reference.pointer, _id_onDetachedFromActivity as jni$_.JMethodIDPtr) + .check(); + } +} + +final class $JniPlugin$NullableType$ extends jni$_.JType { + @jni$_.internal + const $JniPlugin$NullableType$(); + + @jni$_.internal + @core$_.override + String get signature => r'Lcom/github/dart_lang/jni/JniPlugin;'; + + @jni$_.internal + @core$_.override + JniPlugin? fromReference(jni$_.JReference reference) => reference.isNull + ? null + : JniPlugin.fromReference( + reference, + ); + @jni$_.internal + @core$_.override + jni$_.JType get superType => const jni$_.$JObject$NullableType$(); + + @jni$_.internal + @core$_.override + jni$_.JType get nullableType => this; + + @jni$_.internal + @core$_.override + final superCount = 1; + + @core$_.override + int get hashCode => ($JniPlugin$NullableType$).hashCode; + + @core$_.override + bool operator ==(Object other) { + return other.runtimeType == ($JniPlugin$NullableType$) && + other is $JniPlugin$NullableType$; + } +} + +final class $JniPlugin$Type$ extends jni$_.JType { + @jni$_.internal + const $JniPlugin$Type$(); + + @jni$_.internal + @core$_.override + String get signature => r'Lcom/github/dart_lang/jni/JniPlugin;'; + + @jni$_.internal + @core$_.override + JniPlugin fromReference(jni$_.JReference reference) => + JniPlugin.fromReference( + reference, + ); + @jni$_.internal + @core$_.override + jni$_.JType get superType => const jni$_.$JObject$NullableType$(); + + @jni$_.internal + @core$_.override + jni$_.JType get nullableType => const $JniPlugin$NullableType$(); + + @jni$_.internal + @core$_.override + final superCount = 1; + + @core$_.override + int get hashCode => ($JniPlugin$Type$).hashCode; + + @core$_.override + bool operator ==(Object other) { + return other.runtimeType == ($JniPlugin$Type$) && other is $JniPlugin$Type$; + } +} diff --git a/pkgs/jni/pubspec.yaml b/pkgs/jni/pubspec.yaml index dc5a8b8757..26fe9545fd 100644 --- a/pkgs/jni/pubspec.yaml +++ b/pkgs/jni/pubspec.yaml @@ -17,7 +17,7 @@ topics: environment: sdk: '>=3.3.0 <4.0.0' - flutter: '>=2.11.0' + flutter: '>=3.35.6' dependencies: args: ^2.5.0 @@ -31,6 +31,8 @@ dev_dependencies: dart_flutter_team_lints: ^3.5.2 ffigen: path: ../ffigen + jnigen: + path: ../jnigen logging: ^1.2.0 test: ^1.25.8 diff --git a/pkgs/jni/src/dartjni.c b/pkgs/jni/src/dartjni.c index fe0651fe12..eb91a8c0bc 100644 --- a/pkgs/jni/src/dartjni.c +++ b/pkgs/jni/src/dartjni.c @@ -8,8 +8,9 @@ #include "dartjni.h" -#ifndef _WIN32 +#if !defined(_WIN32) pthread_key_t tlsKey; +pthread_mutex_t spawnLock = PTHREAD_MUTEX_INITIALIZER; #endif jclass FindClassUnchecked(const char* name) { @@ -47,8 +48,6 @@ JniContext jni_context = { .jvm = NULL, .classLoader = NULL, .loadClassMethod = NULL, - .appContext = NULL, - .currentActivity = NULL, }; JniContext* jni = &jni_context; @@ -56,7 +55,7 @@ THREAD_LOCAL JNIEnv* jniEnv = NULL; JniExceptionMethods exceptionMethods; void init() { -#ifndef _WIN32 +#if !defined(_WIN32) // Init TLS keys. pthread_key_create(&tlsKey, detach_thread); #endif @@ -83,7 +82,7 @@ void init() { } void deinit() { -#ifndef _WIN32 +#if !defined(_WIN32) // Delete TLS keys. pthread_key_delete(tlsKey); #endif @@ -120,30 +119,15 @@ jobject GetClassLoader() { return (*jniEnv)->NewGlobalRef(jniEnv, jni_context.classLoader); } -FFI_PLUGIN_EXPORT -jobject GetApplicationContext() { - attach_thread(); - return (*jniEnv)->NewGlobalRef(jniEnv, jni_context.appContext); -} - -FFI_PLUGIN_EXPORT -jobject GetCurrentActivity() { - attach_thread(); - return (*jniEnv)->NewGlobalRef(jniEnv, jni_context.currentActivity); -} - // JNI Initialization - -#ifdef __ANDROID__ +#if defined(__ANDROID__) JNIEXPORT void JNICALL -Java_com_github_dart_1lang_jni_JniPlugin_initializeJni(JNIEnv* env, - jobject obj, - jobject appContext, - jobject classLoader) { +Java_com_github_dart_1lang_jni_JniPlugin_setClassLoader(JNIEnv* env, + jclass clazz, + jobject classLoader) { jniEnv = env; (*env)->GetJavaVM(env, &jni_context.jvm); jni_context.classLoader = (*env)->NewGlobalRef(env, classLoader); - jni_context.appContext = (*env)->NewGlobalRef(env, appContext); jclass classLoaderClass = (*env)->GetObjectClass(env, classLoader); jni_context.loadClassMethod = (*env)->GetMethodID(env, classLoaderClass, "loadClass", @@ -151,22 +135,6 @@ Java_com_github_dart_1lang_jni_JniPlugin_initializeJni(JNIEnv* env, init(); } -JNIEXPORT void JNICALL -Java_com_github_dart_1lang_jni_JniPlugin_setJniActivity(JNIEnv* env, - jobject obj, - jobject activity, - jobject context) { - jniEnv = env; - if (jni_context.currentActivity != NULL) { - (*env)->DeleteGlobalRef(env, jni_context.currentActivity); - } - jni_context.currentActivity = (*env)->NewGlobalRef(env, activity); - if (jni_context.appContext != NULL) { - (*env)->DeleteGlobalRef(env, jni_context.appContext); - } - jni_context.appContext = (*env)->NewGlobalRef(env, context); -} - // Sometimes you may get linker error trying to link JNI_CreateJavaVM APIs // on Android NDK. So IFDEF is required. #else @@ -183,8 +151,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) { } return TRUE; } -#else -pthread_mutex_t spawnLock = PTHREAD_MUTEX_INITIALIZER; #endif FFI_PLUGIN_EXPORT JniErrorCode SpawnJvm(JavaVMInitArgs* initArgs) { diff --git a/pkgs/jni/src/dartjni.h b/pkgs/jni/src/dartjni.h index fcda339a35..6d14ae70cc 100644 --- a/pkgs/jni/src/dartjni.h +++ b/pkgs/jni/src/dartjni.h @@ -13,30 +13,8 @@ #include #include -#ifdef _WIN32 -#include -#else -#include -#include -#endif - -#ifdef _WIN32 -#define FFI_PLUGIN_EXPORT __declspec(dllexport) -#else -#define FFI_PLUGIN_EXPORT -#endif - -#ifdef _WIN32 -#define THREAD_LOCAL __declspec(thread) -#else -#define THREAD_LOCAL __thread -#endif - -#ifdef __ANDROID__ +#if defined(__ANDROID__) #include -#endif - -#ifdef __ANDROID__ #define __ENVP_CAST (JNIEnv**) #else #define __ENVP_CAST (void**) @@ -44,8 +22,10 @@ /// Locking functions for windows and pthread. -#ifdef _WIN32 +#if defined(_WIN32) #include +#define FFI_PLUGIN_EXPORT __declspec(dllexport) +#define THREAD_LOCAL __declspec(thread) typedef SRWLOCK MutexLock; typedef CONDITION_VARIABLE ConditionVariable; @@ -88,6 +68,9 @@ static inline void free_mem(void* mem) { #else #include +#include +#define FFI_PLUGIN_EXPORT +#define THREAD_LOCAL __thread typedef pthread_mutex_t MutexLock; typedef pthread_cond_t ConditionVariable; @@ -145,8 +128,6 @@ typedef struct JniContext { JavaVM* jvm; jobject classLoader; jmethodID loadClassMethod; - jobject currentActivity; - jobject appContext; JniLocks locks; } JniContext; @@ -157,7 +138,7 @@ extern THREAD_LOCAL JNIEnv* jniEnv; extern JniContext* jni; /// Handling the lifetime of thread-local jniEnv. -#ifndef _WIN32 +#if !defined(_WIN32) extern pthread_key_t tlsKey; #endif @@ -172,7 +153,7 @@ static inline void detach_thread(void* data) { static inline void attach_thread() { if (jniEnv == NULL) { (*jni->jvm)->AttachCurrentThread(jni->jvm, __ENVP_CAST & jniEnv, NULL); -#ifndef _WIN32 +#if !defined(_WIN32) pthread_setspecific(tlsKey, &jniEnv); #endif } @@ -253,7 +234,7 @@ FFI_PLUGIN_EXPORT jobject GetCurrentActivity(void); /// Load class into [cls] using platform specific mechanism static inline void load_class_platform(jclass* cls, const char* name) { -#ifdef __ANDROID__ +#if defined(__ANDROID__) jstring className = (*jniEnv)->NewStringUTF(jniEnv, name); *cls = (*jniEnv)->CallObjectMethod(jniEnv, jni->classLoader, jni->loadClassMethod, className); diff --git a/pkgs/jni/tool/generate_jni_bindings.dart b/pkgs/jni/tool/generate_jni_bindings.dart new file mode 100644 index 0000000000..bd334d92a4 --- /dev/null +++ b/pkgs/jni/tool/generate_jni_bindings.dart @@ -0,0 +1,32 @@ +// Copyright (c) 2025, 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:io'; + +import 'package:jnigen/jnigen.dart'; + +void main() { + generateJniBindings( + Config( + androidSdkConfig: AndroidSdkConfig( + addGradleDeps: true, + androidExample: 'example/', + ), + outputConfig: OutputConfig( + dartConfig: DartCodeOutputConfig( + path: Platform.script + .resolve('../lib/src/plugin/generated_plugin.dart'), + structure: OutputStructure.singleFile, + ), + ), + classes: ['com.github.dart_lang.jni.JniPlugin'], + preamble: ''' +// Copyright (c) 2025, 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. + +// ignore_for_file: prefer_relative_imports''', + ), + ); +} diff --git a/pkgs/jnigen/CHANGELOG.md b/pkgs/jnigen/CHANGELOG.md index 8188beb767..4bb2fd6383 100644 --- a/pkgs/jnigen/CHANGELOG.md +++ b/pkgs/jnigen/CHANGELOG.md @@ -2,7 +2,8 @@ - Changed the names of internal type classes. - **Breaking Change**: Removed `exclude` from config. -- Update to the latest lints. +- Updated to the latest lints. +- Sorted imports. ## 0.14.2 diff --git a/pkgs/jnigen/example/in_app_java/lib/android_utils.g.dart b/pkgs/jnigen/example/in_app_java/lib/android_utils.g.dart index 949ae5c357..1f86a3b535 100644 --- a/pkgs/jnigen/example/in_app_java/lib/android_utils.g.dart +++ b/pkgs/jnigen/example/in_app_java/lib/android_utils.g.dart @@ -30,8 +30,8 @@ // ignore_for_file: unused_shown_name // ignore_for_file: use_super_parameters -import 'dart:core' show Object, String, bool, double, int; import 'dart:core' as core$_; +import 'dart:core' show Object, String, bool, double, int; import 'package:jni/_internal.dart' as jni$_; import 'package:jni/jni.dart' as jni$_; diff --git a/pkgs/jnigen/example/in_app_java/lib/main.dart b/pkgs/jnigen/example/in_app_java/lib/main.dart index adab59c7d4..f06354dfc7 100644 --- a/pkgs/jnigen/example/in_app_java/lib/main.dart +++ b/pkgs/jnigen/example/in_app_java/lib/main.dart @@ -2,6 +2,7 @@ // 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 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:jni/jni.dart'; @@ -9,8 +10,8 @@ import 'package:jni/jni.dart'; // structure. import 'android_utils.g.dart'; -JObject activity = JObject.fromReference(Jni.getCurrentActivity()); -JObject context = JObject.fromReference(Jni.getCachedApplicationContext()); +JObject context = + Jni.androidApplicationContext(PlatformDispatcher.instance.engineId!); final hashmap = HashMap(K: JString.type, V: JString.type); @@ -38,7 +39,11 @@ void showToast() { : ':cool:'; final message = '${newToastCount.toDartString()} - ${Build.MODEL!.toDartString()} $emoji'; - AndroidUtils.showToast(activity, message.toJString(), 0); + AndroidUtils.showToast( + Jni.androidActivity(PlatformDispatcher.instance.engineId!), + message.toJString(), + 0, + ); } void main() { diff --git a/pkgs/jnigen/example/kotlin_plugin/lib/kotlin_bindings.dart b/pkgs/jnigen/example/kotlin_plugin/lib/kotlin_bindings.dart index d3c49bb664..a6b68485a1 100644 --- a/pkgs/jnigen/example/kotlin_plugin/lib/kotlin_bindings.dart +++ b/pkgs/jnigen/example/kotlin_plugin/lib/kotlin_bindings.dart @@ -30,8 +30,8 @@ // ignore_for_file: unused_shown_name // ignore_for_file: use_super_parameters -import 'dart:core' show Object, String, bool, double, int; import 'dart:core' as core$_; +import 'dart:core' show Object, String, bool, double, int; import 'package:jni/_internal.dart' as jni$_; import 'package:jni/jni.dart' as jni$_; diff --git a/pkgs/jnigen/example/notification_plugin/example/android/app/src/debug/AndroidManifest.xml b/pkgs/jnigen/example/notification_plugin/example/android/app/src/debug/AndroidManifest.xml index 822a20815a..aff0881254 100644 --- a/pkgs/jnigen/example/notification_plugin/example/android/app/src/debug/AndroidManifest.xml +++ b/pkgs/jnigen/example/notification_plugin/example/android/app/src/debug/AndroidManifest.xml @@ -5,4 +5,5 @@ to allow setting breakpoints, to provide hot reload, etc. --> + diff --git a/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/AndroidManifest.xml b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/AndroidManifest.xml index 60e7eab802..8a9fd685bf 100644 --- a/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/AndroidManifest.xml +++ b/pkgs/jnigen/example/notification_plugin/example/android/app/src/main/AndroidManifest.xml @@ -1,6 +1,7 @@ - + diff --git a/pkgs/jnigen/example/notification_plugin/example/android/app/src/profile/AndroidManifest.xml b/pkgs/jnigen/example/notification_plugin/example/android/app/src/profile/AndroidManifest.xml index 822a20815a..aff0881254 100644 --- a/pkgs/jnigen/example/notification_plugin/example/android/app/src/profile/AndroidManifest.xml +++ b/pkgs/jnigen/example/notification_plugin/example/android/app/src/profile/AndroidManifest.xml @@ -5,4 +5,5 @@ to allow setting breakpoints, to provide hot reload, etc. --> + diff --git a/pkgs/jnigen/example/notification_plugin/example/lib/main.dart b/pkgs/jnigen/example/notification_plugin/example/lib/main.dart index 7b978c7ace..796db1e96a 100644 --- a/pkgs/jnigen/example/notification_plugin/example/lib/main.dart +++ b/pkgs/jnigen/example/notification_plugin/example/lib/main.dart @@ -2,6 +2,7 @@ // 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 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:jni/jni.dart'; // The hierarchy created in generated code will mirror the java package @@ -9,15 +10,18 @@ import 'package:jni/jni.dart'; // more customization in future. import 'package:notification_plugin/notifications.dart'; -JObject activity = JObject.fromReference(Jni.getCurrentActivity()); - int i = 0; void showNotification(String title, String text) { i = i + 1; var jTitle = JString.fromString(title); var jText = JString.fromString(text); - Notifications.showNotification(activity, i, jTitle, jText); + Notifications.showNotification( + Jni.androidActivity(PlatformDispatcher.instance.engineId!), + i, + jTitle, + jText, + ); jTitle.release(); jText.release(); } diff --git a/pkgs/jnigen/example/notification_plugin/lib/notifications.dart b/pkgs/jnigen/example/notification_plugin/lib/notifications.dart index c2a2e039c1..c1fd0c4dbb 100644 --- a/pkgs/jnigen/example/notification_plugin/lib/notifications.dart +++ b/pkgs/jnigen/example/notification_plugin/lib/notifications.dart @@ -34,8 +34,8 @@ // ignore_for_file: unused_shown_name // ignore_for_file: use_super_parameters -import 'dart:core' show Object, String, bool, double, int; import 'dart:core' as core$_; +import 'dart:core' show Object, String, bool, double, int; import 'package:jni/_internal.dart' as jni$_; import 'package:jni/jni.dart' as jni$_; diff --git a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart index fb2478c9e2..3b468b245e 100644 --- a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart +++ b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart @@ -48,8 +48,8 @@ // ignore_for_file: unused_shown_name // ignore_for_file: use_super_parameters -import 'dart:core' show Object, String, bool, double, int; import 'dart:core' as core$_; +import 'dart:core' show Object, String, bool, double, int; import 'package:jni/_internal.dart' as jni$_; import 'package:jni/jni.dart' as jni$_; diff --git a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocumentInformation.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocumentInformation.dart index a563fa219c..46fd071541 100644 --- a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocumentInformation.dart +++ b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocumentInformation.dart @@ -48,8 +48,8 @@ // ignore_for_file: unused_shown_name // ignore_for_file: use_super_parameters -import 'dart:core' show Object, String, bool, double, int; import 'dart:core' as core$_; +import 'dart:core' show Object, String, bool, double, int; import 'package:jni/_internal.dart' as jni$_; import 'package:jni/jni.dart' as jni$_; diff --git a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/text/PDFTextStripper.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/text/PDFTextStripper.dart index e33a8f97b4..1ae3c990fc 100644 --- a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/text/PDFTextStripper.dart +++ b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/text/PDFTextStripper.dart @@ -48,8 +48,8 @@ // ignore_for_file: unused_shown_name // ignore_for_file: use_super_parameters -import 'dart:core' show Object, String, bool, double, int; import 'dart:core' as core$_; +import 'dart:core' show Object, String, bool, double, int; import 'package:jni/_internal.dart' as jni$_; import 'package:jni/jni.dart' as jni$_; diff --git a/pkgs/jnigen/lib/src/bindings/dart_generator.dart b/pkgs/jnigen/lib/src/bindings/dart_generator.dart index bee93d0dd1..d92ed11dd3 100644 --- a/pkgs/jnigen/lib/src/bindings/dart_generator.dart +++ b/pkgs/jnigen/lib/src/bindings/dart_generator.dart @@ -144,8 +144,8 @@ class DartGenerator extends Visitor> { static const autoGeneratedNotice = '// AUTO GENERATED BY JNIGEN $version. ' 'DO NOT EDIT!\n'; static const defaultImports = ''' -import 'dart:core' show Object, String, bool, double, int; import 'dart:core' as $_core; +import 'dart:core' show Object, String, bool, double, int; import 'package:jni/_internal.dart' as $_jni; import 'package:jni/jni.dart' as $_jni; diff --git a/pkgs/jnigen/pubspec.yaml b/pkgs/jnigen/pubspec.yaml index cd2dd31b73..352f43a922 100644 --- a/pkgs/jnigen/pubspec.yaml +++ b/pkgs/jnigen/pubspec.yaml @@ -34,7 +34,7 @@ dependencies: dev_dependencies: build_runner: ^2.4.12 dart_flutter_team_lints: ^3.5.2 - jni: ^0.13.0 + jni: ^0.14.0 json_serializable: ^6.8.0 test: ^1.25.8 diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonFactory.dart b/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonFactory.dart index 5f1c056513..6f5c1cb6fa 100644 --- a/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonFactory.dart +++ b/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonFactory.dart @@ -47,8 +47,8 @@ // ignore_for_file: unused_shown_name // ignore_for_file: use_super_parameters -import 'dart:core' show Object, String, bool, double, int; import 'dart:core' as core$_; +import 'dart:core' show Object, String, bool, double, int; import 'package:jni/_internal.dart' as jni$_; import 'package:jni/jni.dart' as jni$_; diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonParser.dart b/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonParser.dart index b890712bd3..f8ed9e7036 100644 --- a/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonParser.dart +++ b/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonParser.dart @@ -47,8 +47,8 @@ // ignore_for_file: unused_shown_name // ignore_for_file: use_super_parameters -import 'dart:core' show Object, String, bool, double, int; import 'dart:core' as core$_; +import 'dart:core' show Object, String, bool, double, int; import 'package:jni/_internal.dart' as jni$_; import 'package:jni/jni.dart' as jni$_; diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonToken.dart b/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonToken.dart index 7d327bfd10..aa075dc602 100644 --- a/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonToken.dart +++ b/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonToken.dart @@ -47,8 +47,8 @@ // ignore_for_file: unused_shown_name // ignore_for_file: use_super_parameters -import 'dart:core' show Object, String, bool, double, int; import 'dart:core' as core$_; +import 'dart:core' show Object, String, bool, double, int; import 'package:jni/_internal.dart' as jni$_; import 'package:jni/jni.dart' as jni$_; diff --git a/pkgs/jnigen/test/kotlin_test/bindings/kotlin.dart b/pkgs/jnigen/test/kotlin_test/bindings/kotlin.dart index d929299b14..2a14012ab0 100644 --- a/pkgs/jnigen/test/kotlin_test/bindings/kotlin.dart +++ b/pkgs/jnigen/test/kotlin_test/bindings/kotlin.dart @@ -34,8 +34,8 @@ // ignore_for_file: unused_shown_name // ignore_for_file: use_super_parameters -import 'dart:core' show Object, String, bool, double, int; import 'dart:core' as core$_; +import 'dart:core' show Object, String, bool, double, int; import 'package:jni/_internal.dart' as jni$_; import 'package:jni/jni.dart' as jni$_; diff --git a/pkgs/jnigen/test/simple_package_test/bindings/simple_package.dart b/pkgs/jnigen/test/simple_package_test/bindings/simple_package.dart index 7969db39a4..e41c179208 100644 --- a/pkgs/jnigen/test/simple_package_test/bindings/simple_package.dart +++ b/pkgs/jnigen/test/simple_package_test/bindings/simple_package.dart @@ -34,8 +34,8 @@ // ignore_for_file: unused_shown_name // ignore_for_file: use_super_parameters -import 'dart:core' show Object, String, bool, double, int; import 'dart:core' as core$_; +import 'dart:core' show Object, String, bool, double, int; import 'package:jni/_internal.dart' as jni$_; import 'package:jni/jni.dart' as jni$_; diff --git a/pkgs/jnigen/tool/regenerate_all_bindings.dart b/pkgs/jnigen/tool/regenerate_all_bindings.dart index a19c7a0f02..05be28daba 100644 --- a/pkgs/jnigen/tool/regenerate_all_bindings.dart +++ b/pkgs/jnigen/tool/regenerate_all_bindings.dart @@ -14,10 +14,10 @@ const scripts = [ 'test/jackson_core_test/generate.dart', 'test/simple_package_test/generate.dart', 'test/kotlin_test/generate.dart', + 'example/in_app_java/tool/jnigen.dart', ]; const yamlBasedExamples = [ - 'example/in_app_java', 'example/pdfbox_plugin', 'example/notification_plugin', 'example/kotlin_plugin',