Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -3091,6 +3091,7 @@ ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/syst
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/NavigationChannel.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformViewsChannel.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/ProcessTextChannel.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/RestorationChannel.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/SpellCheckChannel.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/SystemChannel.java + ../../../flutter/LICENSE
Expand Down Expand Up @@ -3133,6 +3134,7 @@ ORIGIN: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/Platf
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/PlatformViewsController.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/VirtualDisplayController.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/plugin/text/ProcessTextPlugin.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/util/HandlerCompat.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/util/PathUtils.java + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/util/Preconditions.java + ../../../flutter/LICENSE
Expand Down Expand Up @@ -5861,6 +5863,7 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/system
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/NavigationChannel.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformChannel.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/PlatformViewsChannel.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/ProcessTextChannel.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/RestorationChannel.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/SettingsChannel.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/systemchannels/SpellCheckChannel.java
Expand Down Expand Up @@ -5908,6 +5911,7 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/Platfor
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/SingleViewPresentation.java
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/SurfaceTexturePlatformViewRenderTarget.java
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/platform/VirtualDisplayController.java
FILE: ../../../flutter/shell/platform/android/io/flutter/plugin/text/ProcessTextPlugin.java
FILE: ../../../flutter/shell/platform/android/io/flutter/util/HandlerCompat.java
FILE: ../../../flutter/shell/platform/android/io/flutter/util/PathUtils.java
FILE: ../../../flutter/shell/platform/android/io/flutter/util/Preconditions.java
Expand Down
8 changes: 8 additions & 0 deletions shell/platform/android/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,12 @@
</intent-filter>
</activity>
</application>

<!-- Required for io.flutter.plugin.text.ProcessTextPlugin to query activities that can process text. -->
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT" />
<data android:mimeType="text/plain" />
</intent>
</queries>
</manifest>
2 changes: 2 additions & 0 deletions shell/platform/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ android_java_sources = [
"io/flutter/embedding/engine/systemchannels/NavigationChannel.java",
"io/flutter/embedding/engine/systemchannels/PlatformChannel.java",
"io/flutter/embedding/engine/systemchannels/PlatformViewsChannel.java",
"io/flutter/embedding/engine/systemchannels/ProcessTextChannel.java",
"io/flutter/embedding/engine/systemchannels/RestorationChannel.java",
"io/flutter/embedding/engine/systemchannels/SettingsChannel.java",
"io/flutter/embedding/engine/systemchannels/SpellCheckChannel.java",
Expand Down Expand Up @@ -312,6 +313,7 @@ android_java_sources = [
"io/flutter/plugin/platform/SingleViewPresentation.java",
"io/flutter/plugin/platform/SurfaceTexturePlatformViewRenderTarget.java",
"io/flutter/plugin/platform/VirtualDisplayController.java",
"io/flutter/plugin/text/ProcessTextPlugin.java",
"io/flutter/util/HandlerCompat.java",
"io/flutter/util/PathUtils.java",
"io/flutter/util/Preconditions.java",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@
import io.flutter.embedding.engine.systemchannels.MouseCursorChannel;
import io.flutter.embedding.engine.systemchannels.NavigationChannel;
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
import io.flutter.embedding.engine.systemchannels.ProcessTextChannel;
import io.flutter.embedding.engine.systemchannels.RestorationChannel;
import io.flutter.embedding.engine.systemchannels.SettingsChannel;
import io.flutter.embedding.engine.systemchannels.SpellCheckChannel;
import io.flutter.embedding.engine.systemchannels.SystemChannel;
import io.flutter.embedding.engine.systemchannels.TextInputChannel;
import io.flutter.plugin.localization.LocalizationPlugin;
import io.flutter.plugin.platform.PlatformViewsController;
import io.flutter.plugin.text.ProcessTextPlugin;
import io.flutter.util.ViewUtils;
import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -95,6 +97,7 @@ public class FlutterEngine implements ViewUtils.DisplayUpdater {
@NonNull private final NavigationChannel navigationChannel;
@NonNull private final RestorationChannel restorationChannel;
@NonNull private final PlatformChannel platformChannel;
@NonNull private final ProcessTextChannel processTextChannel;
@NonNull private final SettingsChannel settingsChannel;
@NonNull private final SpellCheckChannel spellCheckChannel;
@NonNull private final SystemChannel systemChannel;
Expand Down Expand Up @@ -329,6 +332,7 @@ public FlutterEngine(
mouseCursorChannel = new MouseCursorChannel(dartExecutor);
navigationChannel = new NavigationChannel(dartExecutor);
platformChannel = new PlatformChannel(dartExecutor);
processTextChannel = new ProcessTextChannel(dartExecutor, context.getPackageManager());
restorationChannel = new RestorationChannel(dartExecutor, waitForRestorationData);
settingsChannel = new SettingsChannel(dartExecutor);
spellCheckChannel = new SpellCheckChannel(dartExecutor);
Expand Down Expand Up @@ -384,6 +388,9 @@ public FlutterEngine(
}

ViewUtils.calculateMaximumDisplayMetrics(context, this);

ProcessTextPlugin processTextPlugin = new ProcessTextPlugin(this.getProcessTextChannel());
this.pluginRegistry.add(processTextPlugin);
}

private void attachToJni() {
Expand Down Expand Up @@ -545,6 +552,12 @@ public PlatformChannel getPlatformChannel() {
return platformChannel;
}

/** System channel that sends text processing requests from Flutter to Android. */
@NonNull
public ProcessTextChannel getProcessTextChannel() {
return processTextChannel;
}

/**
* System channel to exchange restoration data between framework and engine.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.embedding.engine.systemchannels;

import android.content.pm.PackageManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.StandardMethodCodec;
import java.util.ArrayList;
import java.util.Map;

/**
* {@link ProcessTextChannel} is a platform channel that is used by the framework to initiate text
* processing feature in the embedding and for the embedding to send back the results.
*
* <p>When the framework needs to query the list of text processing actions (for instance to expose
* them in the selected text context menu), it will send to the embedding the message {@code
* ProcessText.queryTextActions}. In response, the {@link io.flutter.plugin.text.ProcessTextPlugin}
* will return a map of all activities that can process text. The map keys are generated IDs and the
* values are the activities labels. On the first request, the {@link
* io.flutter.plugin.text.ProcessTextPlugin} will make a call to Android's package manager to query
* all activities that can be performed for the {@code Intent.ACTION_PROCESS_TEXT} intent.
*
* <p>When a text processing action has to be executed, the framework will send to the embedding the
* message {@code ProcessText.processTextAction} with the {@code int id} of the choosen text action
* and the {@code String} of text to process as arguments. In response, the {@link
* io.flutter.plugin.text.ProcessTextPlugin} will make a call to the Android application activity to
* start the activity exposing the text action. The {@link io.flutter.plugin.text.ProcessTextPlugin}
* will return the processed text if there is one, or null if the activity did not return a
* transformed text.
*
* <p>{@link io.flutter.plugin.text.ProcessTextPlugin} implements {@link ProcessTextMethodHandler}
* that parses incoming messages from Flutter.
*/
public class ProcessTextChannel {
private static final String TAG = "ProcessTextChannel";
private static final String CHANNEL_NAME = "flutter/processtext";
private static final String METHOD_QUERY_TEXT_ACTIONS = "ProcessText.queryTextActions";
private static final String METHOD_PROCESS_TEXT_ACTION = "ProcessText.processTextAction";

public final MethodChannel channel;
public final PackageManager packageManager;
private ProcessTextMethodHandler processTextMethodHandler;

@NonNull
public final MethodChannel.MethodCallHandler parsingMethodHandler =
new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
if (processTextMethodHandler == null) {
return;
}
String method = call.method;
Object args = call.arguments;
switch (method) {
case METHOD_QUERY_TEXT_ACTIONS:
try {
Map<String, String> actions = processTextMethodHandler.queryTextActions();
result.success(actions);
} catch (IllegalStateException exception) {
result.error("error", exception.getMessage(), null);
}
break;
case METHOD_PROCESS_TEXT_ACTION:
try {
final ArrayList<Object> argumentList = (ArrayList<Object>) args;
String id = (String) (argumentList.get(0));
String text = (String) (argumentList.get(1));
boolean readOnly = (boolean) (argumentList.get(2));
processTextMethodHandler.processTextAction(id, text, readOnly, result);
} catch (IllegalStateException exception) {
result.error("error", exception.getMessage(), null);
}
break;
default:
result.notImplemented();
break;
}
}
};

public ProcessTextChannel(
@NonNull DartExecutor dartExecutor, @NonNull PackageManager packageManager) {
this.packageManager = packageManager;
channel = new MethodChannel(dartExecutor, CHANNEL_NAME, StandardMethodCodec.INSTANCE);
channel.setMethodCallHandler(parsingMethodHandler);
}

/**
* Sets the {@link ProcessTextMethodHandler} which receives all requests to the text processing
* feature sent through this channel.
*/
public void setMethodHandler(@Nullable ProcessTextMethodHandler processTextMethodHandler) {
this.processTextMethodHandler = processTextMethodHandler;
}

public interface ProcessTextMethodHandler {
/** Requests the map of text actions. Each text action has a unique id and a localized label. */
Map<String, String> queryTextActions();

/**
* Requests to run a text action on a given input text.
*
* @param id The ID of the text action returned by {@code ProcessText.queryTextActions}.
* @param input The text to be processed.
* @param readOnly Indicates to the activity if the processed text will be used as read-only.
* see
* https://developer.android.com/reference/android/content/Intent#EXTRA_PROCESS_TEXT_READONLY
* @param result The method channel result instance used to reply.
*/
void processTextAction(
@NonNull String id,
@NonNull String input,
@NonNull boolean readOnly,
@NonNull MethodChannel.Result result);
}
}
Loading