blob: f1d12bc681111c7ba200bb11fbcd90fed3427c29 [file] [log] [blame]
// 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);
}
}