innovationmauritiustelecom / screenshotshareimage_plugin_flutter

A Flutter plugin to capture and share a screenshot of your device current state.
MIT License
5 stars 5 forks source link

Crashes every time I call it... #4

Open devmenezes opened 4 years ago

devmenezes commented 4 years ago

Throws it:

[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: MissingPluginException(No implementation found for method takeScreenshotAndShare on channel screenshot_share_image)


Full stack if you need...

Performing hot restart... Syncing files to device ASUS X00TDB... Restarted application in 1,905ms. E/flutter ( 9891): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: MissingPluginException(No implementation found for method takeScreenshotAndShare on channel screenshot_share_image) E/flutter ( 9891): #0 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:154:7) E/flutter ( 9891): E/flutter ( 9891): #1 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:329:12) E/flutter ( 9891): #2 ScreenshotShareImage.takeScreenshotShareImage (package:screenshot_share_image/screenshot_share_image.dart:11:20) E/flutter ( 9891): #3 ResultPage_State._botaoCompartilhar. (package:calculodeimc/result_page.dart:219:32) E/flutter ( 9891): #4 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:779:14) E/flutter ( 9891): #5 _InkResponseState.build. (package:flutter/src/material/ink_well.dart:862:36) E/flutter ( 9891): #6 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24) E/flutter ( 9891): #7 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:486:11) E/flutter ( 9891): #8 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:264:5) E/flutter ( 9891): #9 BaseTapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:236:7) E/flutter ( 9891): #10 GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:156:27) E/flutter ( 9891): #11 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:222:20) E/flutter ( 9891): #12 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:198:22) E/flutter ( 9891): #13 GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:156:7) E/flutter ( 9891): #14 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:102:7) E/flutter ( 9891): #15 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:86:7) E/flutter ( 9891): #16 _rootRunUnary (dart:async/zone.dart:1138:13) E/flutter ( 9891): #17 _CustomZone.runUnary (dart:async/zone.dart:1031:19) E/flutter ( 9891): #18 _CustomZone.runUnaryGuarded (dart:async/zone.dart:933:7) E/flutter ( 9891): #19 _invoke1 (dart:ui/hooks.dart:275:10) E/flutter ( 9891): #20 _dispatchPointerDataPacket (dart:ui/hooks.dart:184:5) E/flutter ( 9891):

betoflakes commented 4 years ago

Some change?

casualcoder404 commented 4 years ago

Try Android Studio>File>Invalidate caches and restart

tnc1997 commented 4 years ago

I am experiencing the same issue with the latest version of the Flutter master channel and it looks like it could be related to this. It looks like the Android platform of this plugin needs to be updated to implement both FlutterPlugin and MethodCallHandler in order to support the two different methods of plugin registration. I have been able to make a start on adding support for these two different methods of plugin registration, however I have unfortunately hit a blocker on the FlutterView because it has since been deprecated.

package mt.innovation.screenshotshareimage;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.StrictMode;
import android.util.Log;
import android.view.View;
import java.io.File;
import java.io.FileOutputStream;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import io.flutter.view.FlutterView;
import android.widget.Toast;

/** ScreenshotShareImagePlugin */
public class ScreenshotShareImagePlugin implements ActivityAware, FlutterPlugin, MethodCallHandler {

  private static final String TAG = "ScreenshotShareImagePlugin";

  private Registrar registrar;
  private Activity activity;
  private FlutterView flutterView;
  private MethodChannel channel;
  private final int WRITE_ACCESS_REQUEST_ID = 12;

  private ScreenshotShareImagePlugin(Registrar registrar, Activity activity, FlutterView flutterView, MethodChannel channel) {
    this.registrar = registrar;
    this.activity = activity;
    this.flutterView = flutterView;
    this.channel = channel;
    this.channel.setMethodCallHandler(this);
    setRequestPermissionListener();
  }

  public ScreenshotShareImagePlugin() {}

  private void setRequestPermissionListener() {

    registrar.addRequestPermissionsResultListener(new PluginRegistry.RequestPermissionsResultListener() {
      @Override
      public boolean onRequestPermissionsResult(int i, String[] strings, int[] ints) {
        if (i == WRITE_ACCESS_REQUEST_ID) {

          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (activity.checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
              takeScreenshot("screenshot");
              return true;
            } else {

              activity.requestPermissions(new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 11);
              return false;
            }
          }
        }
        return false;
      }
    });
  }

  @Override
  public void onAttachedToEngine(FlutterPluginBinding binding) {
    channel = new MethodChannel(binding.getBinaryMessenger(), "screenshot_share_image");
  }

  @Override
  public void onDetachedFromEngine(FlutterPluginBinding binding) {}

  @Override
  public void onAttachedToActivity(ActivityPluginBinding binding) {
    activity = binding.getActivity();
    channel.setMethodCallHandler(this);
  }

  @Override
  public void onDetachedFromActivityForConfigChanges() {
    activity = null;
  }

  @Override
  public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding) {
    activity = binding.getActivity();
  }

  @Override
  public void onDetachedFromActivity() {
    activity = null;
    channel.setMethodCallHandler(null);
  }

  // This static function is optional and equivalent to onAttachedToEngine. It supports the old
  // pre-Flutter-1.12 Android projects. You are encouraged to continue supporting
  // plugin registration via this function while apps migrate to use the new Android APIs
  // post-flutter-1.12 via https://flutter.dev/go/android-project-migration.
  //
  // It is encouraged to share logic between onAttachedToEngine and registerWith to keep
  // them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called
  // depending on the user's project. onAttachedToEngine or registerWith must both be defined
  // in the same class.
  public static void registerWith(Registrar registrar) {
    final MethodChannel channel = new MethodChannel(registrar.messenger(), "screenshot_share_image");
    channel.setMethodCallHandler(new ScreenshotShareImagePlugin(registrar, registrar.activity(), registrar.view(), channel));
  }

  @Override
  public void onMethodCall(MethodCall call, Result result) {
    if (call.method.equals("takeScreenshotAndShare")) {
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        activity.requestPermissions(new String[]{ android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_ACCESS_REQUEST_ID);
      } else {
        takeScreenshot("screenshot");
      }

    } else {
      result.notImplemented();
    }
  }

  private void takeScreenshot(String fileName) {
    try {
      // image naming and path  to include sd card  appending name you choose for file
      String mPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString() + "/" + fileName + ".jpg";
      Bitmap bitmap = flutterView.getBitmap();

      File imageFile = new File(mPath);

      FileOutputStream outputStream = new FileOutputStream(imageFile);
      int quality = 100;
      bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
      outputStream.flush();
      outputStream.close();

      openScreenshot(imageFile);

    } catch (Throwable e) {
      e.printStackTrace();
    }
  }

  private void openScreenshot(File imageFile) {
    StrictMode.VmPolicy.Builder builder = null;
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) {
      builder = new StrictMode.VmPolicy.Builder();
      StrictMode.setVmPolicy(builder.build());
    }

    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_VIEW);
    Uri uri = Uri.fromFile(imageFile);
    intent.setDataAndType(uri, "image/*");
    activity.startActivity(intent);
  }
}
Psiale commented 3 years ago

I was having the same error and in my case adding this to the application tag inside the manifest.xml file:

android:requestLegacyExternalStorage="true" and this to the info.plist file:

` NSLocationWhenInUseUsageDescription

This app needs access to location when open.
<key>NSLocationAlwaysUsageDescription</key>
<string>This app needs access to location when in the background.</string>`

solved it.