Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 54a9657

Browse files
zlshamestneotia
authored andcommitted
Android GIF/Image Insertion
1 parent b90fe8f commit 54a9657

File tree

3 files changed

+104
-0
lines changed

3 files changed

+104
-0
lines changed

shell/platform/android/io/flutter/embedding/engine/systemchannels/TextInputChannel.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,13 @@ public void previous(int inputClientId) {
285285
"TextInputClient.performAction", Arrays.asList(inputClientId, "TextInputAction.previous"));
286286
}
287287

288+
/** Instructs flutter to commit content back to the text channel */
289+
public void commitContent(int inputClientId, Map<String, Object> content) {
290+
Log.v(TAG, "Sending 'commitContent' message.");
291+
channel.invokeMethod(
292+
"TextInputClient.performAction", Arrays.asList(inputClientId, "TextInputAction.commitContent", content));
293+
}
294+
288295
/** Instructs Flutter to execute an "unspecified" action. */
289296
public void unspecifiedAction(int inputClientId) {
290297
Log.v(TAG, "Sending 'unspecified' message.");

shell/platform/android/io/flutter/plugin/editing/InputConnectionAdaptor.java

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44

55
package io.flutter.plugin.editing;
66

7+
import java.io.FileNotFoundException;
8+
import java.io.ByteArrayOutputStream;
9+
import java.io.InputStream;
10+
import java.util.Map;
11+
import java.util.HashMap;
12+
713
import android.content.ClipData;
814
import android.content.ClipboardManager;
915
import android.content.Context;
@@ -23,6 +29,12 @@
2329
import android.view.inputmethod.ExtractedText;
2430
import android.view.inputmethod.ExtractedTextRequest;
2531
import android.view.inputmethod.InputMethodManager;
32+
import android.view.inputmethod.InputContentInfo;
33+
import android.net.Uri;
34+
35+
import androidx.core.view.inputmethod.InputConnectionCompat;
36+
import androidx.core.os.BuildCompat;
37+
2638
import io.flutter.Log;
2739
import io.flutter.embedding.android.KeyboardManager;
2840
import io.flutter.embedding.engine.FlutterJNI;
@@ -473,6 +485,79 @@ public boolean performEditorAction(int actionCode) {
473485
return true;
474486
}
475487

488+
@Override
489+
public boolean commitContent(InputContentInfo inputContentInfo, int flags, Bundle opts) {
490+
Log.d("HackFlutterEngine", "Content Commit Invoked");
491+
492+
// Ensure permission is granted
493+
if (BuildCompat.isAtLeastNMR1() && (flags & InputConnectionCompat.INPUT_CONTENT_GRANT_READ_URI_PERMISSION) != 0) {
494+
try {
495+
inputContentInfo.requestPermission();
496+
Log.d("HackFlutterEngine", "Content Commit request permissions: PASS");
497+
} catch (Exception e) {
498+
Log.d("HackFlutterEngine", "Content Commit reqest permissions: FAIL");
499+
return false;
500+
}
501+
}
502+
503+
if (inputContentInfo.getDescription().getMimeTypeCount() > 0) {
504+
inputContentInfo.requestPermission();
505+
506+
final Uri uri = inputContentInfo.getContentUri();
507+
final String mimeType = inputContentInfo.getDescription().getMimeType(0);
508+
Log.d("HackFlutterEngine", "Content Commit received URI: " + uri + " (MIME: " + mimeType + ")");
509+
Context context = mFlutterView.getContext();
510+
Boolean retval = false;
511+
512+
try {
513+
final InputStream is = context.getContentResolver().openInputStream(uri);
514+
final byte[] data = this.readStreamFully(is, 64 * 1024);
515+
Log.d("HackFlutterEngine", "Content Commit data length: " + data.length);
516+
517+
final Map<String, Object> obj = new HashMap<>();
518+
obj.put("mimeType", mimeType);
519+
obj.put("data", data);
520+
obj.put("uri", uri != null ? uri.toString() : null);
521+
522+
// Commit the content to the text input channel
523+
textInputChannel.commitContent(mClient, obj);
524+
retval = true;
525+
} catch (FileNotFoundException ex) {
526+
Log.d("HackFlutterEngine", "Content Commit load file: FAIL (Not Found)");
527+
} catch (Exception ex) {
528+
Log.d("HackFlutterEngine", "Content Commit load data: FAIL");
529+
} finally {
530+
inputContentInfo.releasePermission();
531+
}
532+
533+
if (retval) {
534+
Log.d("HackFlutterEngine", "Content Commit Result: PASS");
535+
}
536+
537+
return retval;
538+
}
539+
540+
// If it gets to this point, it failed
541+
Log.d("HackFlutterEngine", "Content Commit Result: FAIL");
542+
return false;
543+
}
544+
545+
public byte[] readStreamFully(InputStream is, int blocksize) {
546+
try {
547+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
548+
549+
byte[] buffer = new byte[blocksize];
550+
while (true) {
551+
int len = is.read(buffer);
552+
if (len == -1) break;
553+
baos.write(buffer, 0, len);
554+
}
555+
return baos.toByteArray();
556+
} catch (Exception e) {}
557+
558+
return new byte[0];
559+
}
560+
476561
// -------- Start: ListenableEditingState watcher implementation -------
477562
@Override
478563
public void didChangeEditingState(

shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import androidx.annotation.NonNull;
2626
import androidx.annotation.Nullable;
2727
import androidx.annotation.VisibleForTesting;
28+
import androidx.core.view.inputmethod.EditorInfoCompat;
2829
import io.flutter.Log;
2930
import io.flutter.embedding.android.KeyboardManager;
3031
import io.flutter.embedding.engine.systemchannels.TextInputChannel;
@@ -330,6 +331,17 @@ public InputConnection createInputConnection(
330331
}
331332
outAttrs.imeOptions |= enterAction;
332333

334+
String[] imgTypeString = new String[] {
335+
"image/png",
336+
"image/bmp",
337+
"image/jpg",
338+
"image/tiff",
339+
"image/gif",
340+
"image/jpeg",
341+
"image/webp"
342+
};
343+
EditorInfoCompat.setContentMimeTypes(outAttrs, imgTypeString);
344+
333345
InputConnectionAdaptor connection =
334346
new InputConnectionAdaptor(
335347
view, inputTarget.id, textInputChannel, keyboardManager, mEditable, outAttrs);

0 commit comments

Comments
 (0)