|
4 | 4 |
|
5 | 5 | package io.flutter.plugin.editing;
|
6 | 6 |
|
| 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 | + |
7 | 13 | import android.content.ClipData;
|
8 | 14 | import android.content.ClipboardManager;
|
9 | 15 | import android.content.Context;
|
|
23 | 29 | import android.view.inputmethod.ExtractedText;
|
24 | 30 | import android.view.inputmethod.ExtractedTextRequest;
|
25 | 31 | 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 | + |
26 | 38 | import io.flutter.Log;
|
27 | 39 | import io.flutter.embedding.android.KeyboardManager;
|
28 | 40 | import io.flutter.embedding.engine.FlutterJNI;
|
@@ -473,6 +485,79 @@ public boolean performEditorAction(int actionCode) {
|
473 | 485 | return true;
|
474 | 486 | }
|
475 | 487 |
|
| 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 | + |
476 | 561 | // -------- Start: ListenableEditingState watcher implementation -------
|
477 | 562 | @Override
|
478 | 563 | public void didChangeEditingState(
|
|
0 commit comments