public class FlutterJNI extends Object
FlutterJNI
. There are multiple reasons
that all such calls are centralized in one class. First, JNI calls are inherently static and
contain no Java implementation, therefore there is little reason to associate calls with different
classes. Second, every JNI call must be registered in C/C++ code and this registration becomes
more complicated with every additional Java class that contains JNI calls. Third, most Android
developers are not familiar with native development or JNI intricacies, therefore it is in the
interest of future maintenance to reduce the API surface that includes JNI declarations. Thus,
all Flutter JNI calls are centralized in FlutterJNI
.
Despite the fact that individual JNI calls are inherently static, there is state that exists
within FlutterJNI
. Most calls within FlutterJNI
correspond to a specific
"platform view", of which there may be many. Therefore, each FlutterJNI
instance holds
onto a "native platform view ID" after attachToNative(boolean)
, which is shared with
the native C/C++ engine code. That ID is passed to every platform-view-specific native method.
ID management is handled within FlutterJNI
so that developers don't have to hold onto
that ID.
To connect part of an Android app to Flutter's C/C++ engine, instantiate a FlutterJNI
and
then attach it to the native side:
// Instantiate FlutterJNI and attach to the native side.
FlutterJNI flutterJNI = new FlutterJNI();
flutterJNI.attachToNative();
// Use FlutterJNI as desired.
flutterJNI.dispatchPointerDataPacket(...);
// Destroy the connection to the native side and cleanup.
flutterJNI.detachFromNativeAndReleaseResources();
To provide a visual, interactive surface for Flutter rendering and touch events, register a
RenderSurface
with #setRenderSurface(RenderSurface)
To receive callbacks for certain events that occur on the native side, register listeners:
#addEngineLifecycleListener(EngineLifecycleListener)
addIsDisplayingFlutterUiListener(FlutterUiDisplayListener)
setPlatformMessageHandler(PlatformMessageHandler)
To invoke a native method that is not associated with a platform view, invoke it statically:
bool enabled = FlutterJNI.nativeGetIsSoftwareRenderingEnabled();
Modifier and Type | Class and Description |
---|---|
static interface |
FlutterJNI.AccessibilityDelegate
Delegate responsible for creating and updating Android-side caches of Flutter's semantics
tree and custom accessibility actions.
|
static interface |
FlutterJNI.AsyncWaitForVsyncDelegate |
Constructor and Description |
---|
FlutterJNI() |
Modifier and Type | Method and Description |
---|---|
void |
addEngineLifecycleListener(FlutterEngine.EngineLifecycleListener engineLifecycleListener)
Adds the given
engineLifecycleListener to be notified of Flutter engine lifecycle
events, e.g., FlutterEngine.EngineLifecycleListener.onPreEngineRestart() . |
void |
addIsDisplayingFlutterUiListener(FlutterUiDisplayListener listener)
Adds a
FlutterUiDisplayListener , which receives a callback when Flutter's
engine notifies FlutterJNI that Flutter is painting pixels to the Surface that
was provided to Flutter. |
void |
attachToNative(boolean isBackgroundView)
Attaches this
FlutterJNI instance to Flutter's native engine, which allows
for communication between Android code and Flutter's platform agnostic engine. |
void |
detachFromNativeAndReleaseResources()
Detaches this
FlutterJNI instance from Flutter's native engine, which precludes
any further communication between Android code and Flutter's platform agnostic engine. |
void |
dispatchEmptyPlatformMessage(String channel,
int responseId)
Sends an empty reply (identified by
responseId ) from Android to Flutter over the given
channel . |
void |
dispatchPlatformMessage(String channel,
ByteBuffer message,
int position,
int responseId)
Sends a reply
message from Android to Flutter over the given channel . |
void |
dispatchPointerDataPacket(ByteBuffer buffer,
int position)
Sends a packet of pointer data to Flutter's engine.
|
void |
dispatchSemanticsAction(int id,
AccessibilityBridge.Action action)
Sends a semantics action to Flutter's engine, without any additional arguments.
|
void |
dispatchSemanticsAction(int id,
AccessibilityBridge.Action action,
Object args)
Sends a semantics action to Flutter's engine, with additional arguments.
|
void |
dispatchSemanticsAction(int id,
int action,
ByteBuffer args,
int argsPosition)
Sends a semantics action to Flutter's engine, given arguments that are already encoded for
the engine.
|
Bitmap |
getBitmap() |
static String |
getObservatoryUri() |
void |
invokePlatformMessageEmptyResponseCallback(int responseId) |
void |
invokePlatformMessageResponseCallback(int responseId,
ByteBuffer message,
int position) |
boolean |
isAttached()
Returns true if this instance of
FlutterJNI is connected to Flutter's native
engine via a Java Native Interface (JNI). |
void |
markTextureFrameAvailable(long textureId)
Call this method to inform Flutter that a texture previously registered with
registerTexture(long, SurfaceTexture) has a new frame available. |
boolean |
nativeGetIsSoftwareRenderingEnabled() |
static void |
nativeInit(Context context,
String[] args,
String bundlePath,
String appStoragePath,
String engineCachesPath) |
static FlutterCallbackInformation |
nativeLookupCallbackInformation(long handle) |
static void |
nativeOnVsync(long frameTimeNanos,
long frameTargetTimeNanos,
long cookie) |
static void |
nativeRecordStartTimestamp(long initTimeMillis) |
void |
onSurfaceChanged(int width,
int height)
Call this method when the
Surface changes that was previously registered with
onSurfaceCreated(Surface) . |
void |
onSurfaceCreated(Surface surface)
Call this method when a
Surface has been created onto which you would like Flutter
to paint. |
void |
onSurfaceDestroyed()
Call this method when the
Surface is destroyed that was previously registered with
onSurfaceCreated(Surface) . |
void |
registerTexture(long textureId,
SurfaceTexture surfaceTexture)
Gives control of a
SurfaceTexture to Flutter so that Flutter can display that
texture within Flutter's UI. |
void |
removeEngineLifecycleListener(FlutterEngine.EngineLifecycleListener engineLifecycleListener)
Removes the given
engineLifecycleListener , which was previously added using
addIsDisplayingFlutterUiListener(FlutterUiDisplayListener) . |
void |
removeIsDisplayingFlutterUiListener(FlutterUiDisplayListener listener)
Removes a
FlutterUiDisplayListener that was added with
addIsDisplayingFlutterUiListener(FlutterUiDisplayListener) . |
void |
runBundleAndSnapshotFromLibrary(String bundlePath,
String entrypointFunctionName,
String pathToEntrypointFunction,
AssetManager assetManager)
Executes a Dart entrypoint.
|
void |
setAccessibilityDelegate(FlutterJNI.AccessibilityDelegate accessibilityDelegate)
Sets the
FlutterJNI.AccessibilityDelegate for the attached Flutter context. |
void |
setAccessibilityFeatures(int flags) |
static void |
setAsyncWaitForVsyncDelegate(FlutterJNI.AsyncWaitForVsyncDelegate delegate) |
void |
setPlatformMessageHandler(PlatformMessageHandler platformMessageHandler)
Sets the handler for all platform messages that come from the attached platform view to Java.
|
static void |
setRefreshRateFPS(float refreshRateFPS) |
void |
setSemanticsEnabled(boolean enabled)
Instructs Flutter to enable/disable its semantics tree, which is used by Flutter to support
accessibility and related behaviors.
|
void |
setViewportMetrics(float devicePixelRatio,
int physicalWidth,
int physicalHeight,
int physicalPaddingTop,
int physicalPaddingRight,
int physicalPaddingBottom,
int physicalPaddingLeft,
int physicalViewInsetTop,
int physicalViewInsetRight,
int physicalViewInsetBottom,
int physicalViewInsetLeft,
int systemGestureInsetTop,
int systemGestureInsetRight,
int systemGestureInsetBottom,
int systemGestureInsetLeft)
Call this method to notify Flutter of the current device viewport metrics that are
applies to the Flutter UI that is being rendered.
|
void |
unregisterTexture(long textureId)
Unregisters a texture that was registered with
registerTexture(long, SurfaceTexture) . |
public static void nativeInit(@NonNull Context context, @NonNull String[] args, @Nullable String bundlePath, @NonNull String appStoragePath, @NonNull String engineCachesPath)
public static void nativeRecordStartTimestamp(long initTimeMillis)
@UiThread public boolean nativeGetIsSoftwareRenderingEnabled()
public static void setRefreshRateFPS(float refreshRateFPS)
public static void setAsyncWaitForVsyncDelegate(@Nullable FlutterJNI.AsyncWaitForVsyncDelegate delegate)
public static void nativeOnVsync(long frameTimeNanos, long frameTargetTimeNanos, long cookie)
@NonNull public static FlutterCallbackInformation nativeLookupCallbackInformation(long handle)
public boolean isAttached()
FlutterJNI
is connected to Flutter's native
engine via a Java Native Interface (JNI).@UiThread public void attachToNative(boolean isBackgroundView)
FlutterJNI
instance to Flutter's native engine, which allows
for communication between Android code and Flutter's platform agnostic engine.
This method must not be invoked if FlutterJNI
is already attached to native.
@UiThread public void detachFromNativeAndReleaseResources()
FlutterJNI
instance from Flutter's native engine, which precludes
any further communication between Android code and Flutter's platform agnostic engine.
This method must not be invoked if FlutterJNI
is not already attached to native.
Invoking this method will result in the release of all native-side resources that were
setup during attachToNative(boolean)
, or accumulated thereafter.
It is permissable to re-attach this instance to native after detaching it from native.
@UiThread public void addIsDisplayingFlutterUiListener(@NonNull FlutterUiDisplayListener listener)
FlutterUiDisplayListener
, which receives a callback when Flutter's
engine notifies FlutterJNI
that Flutter is painting pixels to the Surface
that
was provided to Flutter.@UiThread public void removeIsDisplayingFlutterUiListener(@NonNull FlutterUiDisplayListener listener)
FlutterUiDisplayListener
that was added with
addIsDisplayingFlutterUiListener(FlutterUiDisplayListener)
.@UiThread public void onSurfaceCreated(@NonNull Surface surface)
Surface
has been created onto which you would like Flutter
to paint.
See SurfaceHolder.Callback.surfaceCreated(SurfaceHolder)
for an example
of where this call might originate.
@UiThread public void onSurfaceChanged(int width, int height)
Surface
changes that was previously registered with
onSurfaceCreated(Surface)
.
See SurfaceHolder.Callback.surfaceChanged(SurfaceHolder, int, int, int)
for an example of where this call might originate.
@UiThread public void onSurfaceDestroyed()
Surface
is destroyed that was previously registered with
onSurfaceCreated(Surface)
.
See SurfaceHolder.Callback.surfaceDestroyed(SurfaceHolder)
for an example
of where this call might originate.
@UiThread public void setViewportMetrics(float devicePixelRatio, int physicalWidth, int physicalHeight, int physicalPaddingTop, int physicalPaddingRight, int physicalPaddingBottom, int physicalPaddingLeft, int physicalViewInsetTop, int physicalViewInsetRight, int physicalViewInsetBottom, int physicalViewInsetLeft, int systemGestureInsetTop, int systemGestureInsetRight, int systemGestureInsetBottom, int systemGestureInsetLeft)
This method should be invoked with initial values upon attaching to native. Then,
it should be invoked any time those metrics change while FlutterJNI
is
attached to native.
@UiThread public void dispatchPointerDataPacket(@NonNull ByteBuffer buffer, int position)
@UiThread public void setAccessibilityDelegate(@Nullable FlutterJNI.AccessibilityDelegate accessibilityDelegate)
FlutterJNI.AccessibilityDelegate
for the attached Flutter context.
The FlutterJNI.AccessibilityDelegate
is responsible for maintaining an Android-side cache of
Flutter's semantics tree and custom accessibility actions. This cache should be hooked up
to Android's accessibility system.
See AccessibilityBridge
for an example of an FlutterJNI.AccessibilityDelegate
and the
surrounding responsibilities.public void dispatchSemanticsAction(int id, @NonNull AccessibilityBridge.Action action)
public void dispatchSemanticsAction(int id, @NonNull AccessibilityBridge.Action action, @Nullable Object args)
@UiThread public void dispatchSemanticsAction(int id, int action, @Nullable ByteBuffer args, int argsPosition)
To send a semantics action that has not already been encoded, see
dispatchSemanticsAction(int, AccessibilityBridge.Action)
and
dispatchSemanticsAction(int, AccessibilityBridge.Action, Object)
.
@UiThread public void setSemanticsEnabled(boolean enabled)
@UiThread public void setAccessibilityFeatures(int flags)
@UiThread public void registerTexture(long textureId, @NonNull SurfaceTexture surfaceTexture)
SurfaceTexture
to Flutter so that Flutter can display that
texture within Flutter's UI.@UiThread public void markTextureFrameAvailable(long textureId)
registerTexture(long, SurfaceTexture)
has a new frame available.
Invoking this method instructs Flutter to update its presentation of the given texture so that the new frame is displayed.
@UiThread public void unregisterTexture(long textureId)
registerTexture(long, SurfaceTexture)
.@UiThread public void runBundleAndSnapshotFromLibrary(@NonNull String bundlePath, @Nullable String entrypointFunctionName, @Nullable String pathToEntrypointFunction, @NonNull AssetManager assetManager)
This can only be done once per JNI attachment because a Dart isolate can only be entered once.
@UiThread public void setPlatformMessageHandler(@Nullable PlatformMessageHandler platformMessageHandler)
Communication between a specific Flutter context (Dart) and the host platform (Java) is
accomplished by passing messages. Messages can be sent from Java to Dart with the corresponding
FlutterJNI
methods:
FlutterJNI
is also the recipient of all platform messages sent from its attached
Flutter context. FlutterJNI
does not know what to do with these messages, so a handler
is exposed to allow these messages to be processed in whatever manner is desired:
setPlatformMessageHandler(PlatformMessageHandler)
If a message is received but no PlatformMessageHandler
is registered, that message will
be dropped (ignored). Therefore, when using FlutterJNI
to integrate a Flutter context
in an app, a PlatformMessageHandler
must be registered for 2-way Java/Dart communication
to operate correctly. Moreover, the handler must be implemented such that fundamental platform
messages are handled as expected. See FlutterNativeView
for an example implementation.
@UiThread public void dispatchEmptyPlatformMessage(@NonNull String channel, int responseId)
responseId
) from Android to Flutter over the given
channel
.@UiThread public void dispatchPlatformMessage(@NonNull String channel, @Nullable ByteBuffer message, int position, int responseId)
message
from Android to Flutter over the given channel
.@UiThread public void invokePlatformMessageEmptyResponseCallback(int responseId)
@UiThread public void invokePlatformMessageResponseCallback(int responseId, @Nullable ByteBuffer message, int position)
@UiThread public void addEngineLifecycleListener(@NonNull FlutterEngine.EngineLifecycleListener engineLifecycleListener)
engineLifecycleListener
to be notified of Flutter engine lifecycle
events, e.g., FlutterEngine.EngineLifecycleListener.onPreEngineRestart()
.@UiThread public void removeEngineLifecycleListener(@NonNull FlutterEngine.EngineLifecycleListener engineLifecycleListener)
engineLifecycleListener
, which was previously added using
addIsDisplayingFlutterUiListener(FlutterUiDisplayListener)
.