OWASP-BLT / BLT-Flutter

The official OWASP BLT App repository/ Heist 'em bugs!
https://owasp.org/www-project-bug-logging-tool/
BSD 3-Clause "New" or "Revised" License
22 stars 29 forks source link

2️⃣6️⃣ allow the user to be able to past an image into the bug report page in the app #231

Open fredfalcon opened 1 year ago

fredfalcon commented 1 year ago

Need custom function for copying image from clipboard as Pasteboard package does not supports android platform

to get this functionality switch to the flutter master channel (command flutter channel master), this will now include PR 110052 which adds this functionality.

to use it simply add this to your TextField:

//... contentInsertionConfiguration: ContentInsertionConfiguration( onContentInserted : (_){/your cb here/} allowedMimeTypes: ["image/png",/.../], }), //... this will then use the android specific content commit api to (as you guessed) tell the OS that your TextField accepts the given mimetypes; gboard will recognize this and suggest the content with fitting mimetypes in your clipboard

letsintegreat commented 1 year ago

Regarding this, I did some research but could not find anything for android. Therefore, 12 days ago I started a thread on Stack Overflow, but it went unanswered. I have now started a bounty on that thread, hopefully we will get something now - https://stackoverflow.com/questions/75658357/how-to-accept-images-in-textfield-flutter

fredfalcon commented 1 year ago

Please excuse the un formatted AI response

Currently, Flutter's TextField widget does not have built-in support for pasting images directly from the clipboard. However, you can achieve this functionality by implementing a workaround using a combination of platform channels and a third-party package.

Here's a step-by-step guide to implementing this feature:

Create a MethodChannel to communicate with native Android code: First, you'll need to create a platform channel for invoking native Android methods from Flutter. In your main.dart file, add the following code:

dart Copy code import 'package:flutter/services.dart';

const platform = const MethodChannel('com.example.app/image_paste'); Replace com.example.app with your app's package name.

Implement the native Android code for accessing clipboard images: In your Android project, navigate to the MainActivity.kt file and add the following code:

kotlin Copy code package com.example.app

import android.content.ClipData import android.content.ClipDescription import android.graphics.Bitmap import android.graphics.BitmapFactory import androidx.annotation.NonNull import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel import java.io.ByteArrayOutputStream

class MainActivity : FlutterActivity() { private val CHANNEL = "com.example.app/image_paste"

override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine)
    MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
        when (call.method) {
            "getImageFromClipboard" -> {
                val clipboard = getSystemService(CLIPBOARD_SERVICE) as android.content.ClipboardManager
                if (clipboard.hasPrimaryClip() && clipboard.primaryClipDescription?.hasMimeType(ClipDescription.MIMETYPE_TEXT_HTML) == true) {
                    val item: ClipData.Item = clipboard.primaryClip!!.getItemAt(0)
                    val imageUri = item.uri

                    // Read image from URI
                    val inputStream = contentResolver.openInputStream(imageUri)
                    val bitmap = BitmapFactory.decodeStream(inputStream)

                    // Convert bitmap to PNG byte array
                    val byteArrayOutputStream = ByteArrayOutputStream()
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream)
                    val byteArray: ByteArray = byteArrayOutputStream.toByteArray()

                    result.success(byteArray)
                } else {
                    result.success(null)
                }
            }
            else -> result.notImplemented()
        }
    }
}

} Replace com.example.app with your app's package name.

Handle pasting images in Flutter: Now, you can create a button in your Flutter app that fetches images from the clipboard and displays them. Use the Image.memory widget to display the image bytes.

dart Copy code import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart';

// ...

Future<Uint8List?> _getImageFromClipboard() async { try { final Uint8List? imageBytes = await platform.invokeMethod('getImageFromClipboard'); return imageBytes; } on PlatformException catch (e) { print('Failed to get image from clipboard: ${e.message}'); return null; } }

// ...

ElevatedButton( onPressed: () async { Uint8List? imageBytes = await _getImageFromClipboard(); if (imageBytes != null) { setState(() { _image = Image.memory(imageBytes); }); } }, child: Text('Paste Image'), ),

// ...

_image, // display the pasted image Replace _image with a variable of type Image? in your widget's state.

This implementation allows you to paste images from the clipboard into your Flutter app

letsintegreat commented 1 year ago

This is interesting, let me give it a shot!

letsintegreat commented 1 year ago

@fredfalcon It doesn't work, getImageFromClipboard always returns null.

fredfalcon commented 1 year ago

You could try giving the error and code to ChatGPT4 and work it out. I'm rate limited currently