flutter_blue icon indicating copy to clipboard operation
flutter_blue copied to clipboard

Activity com.timeyaa.ccell_flutter.MainActivity has leaked IntentReceiver

Open fengqiangboy opened this issue 5 years ago • 9 comments

When back to desktop use back button on Android, Logcat will print this error.

E/ActivityThread(25543): Activity com.pauldemarco.flutterblueexample.MainActivity has leaked IntentReceiver com.pauldemarco.flutterblue.FlutterBluePlugin$1$1@34c34b0 that was originally registered here. Are you missing a call to unregisterReceiver()?
E/ActivityThread(25543): android.app.IntentReceiverLeaked: Activity com.pauldemarco.flutterblueexample.MainActivity has leaked IntentReceiver com.pauldemarco.flutterblue.FlutterBluePlugin$1$1@34c34b0 that was originally registered here. Are you missing a call to unregisterReceiver()?
E/ActivityThread(25543): 	at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:1030)
E/ActivityThread(25543): 	at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:817)
E/ActivityThread(25543): 	at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1260)
E/ActivityThread(25543): 	at android.app.ContextImpl.registerReceiver(ContextImpl.java:1240)
E/ActivityThread(25543): 	at android.app.ContextImpl.registerReceiver(ContextImpl.java:1234)
E/ActivityThread(25543): 	at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:576)
E/ActivityThread(25543): 	at com.pauldemarco.flutterblue.FlutterBluePlugin$1.onListen(FlutterBluePlugin.java:578)
E/ActivityThread(25543): 	at io.flutter.plugin.common.EventChannel$IncomingStreamRequestHandler.onListen(EventChannel.java:181)
E/ActivityThread(25543): 	at io.flutter.plugin.common.EventChannel$IncomingStreamRequestHandler.onMessage(EventChannel.java:160)
E/ActivityThread(25543): 	at io.flutter.view.FlutterNativeView$PlatformMessageHandlerImpl.handleMessageFromDart(FlutterNativeView.java:188)
E/ActivityThread(25543): 	at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:202)
E/ActivityThread(25543): 	at android.os.MessageQueue.nativePollOnce(Native Method)
E/ActivityThread(25543): 	at android.os.MessageQueue.next(MessageQueue.java:323)
E/ActivityThread(25543): 	at android.os.Looper.loop(Looper.java:143)
E/ActivityThread(25543): 	at android.app.ActivityThread.main(ActivityThread.java:7225)
E/ActivityThread(25543): 	at java.lang.reflect.Method.invoke(Native Method)
E/ActivityThread(25543): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
E/ActivityThread(25543): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

fengqiangboy avatar Apr 02 '19 02:04 fengqiangboy

me too

long0521293923 avatar May 08 '19 06:05 long0521293923

How to fix it up

zhaoxwgit avatar May 14 '19 02:05 zhaoxwgit

Now, I kill my app on exit.

public class MainActivity extends FlutterActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    GeneratedPluginRegistrant.registerWith(this);
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    android.os.Process.killProcess(android.os.Process.myPid());
  }
}

fengqiangboy avatar May 14 '19 02:05 fengqiangboy

Exact same issue. To be clear, the issue occurs on the example provided in this repo.

D/InputEventReceiver(21256): channel '8ca4ddb com.pauldemarco.flutter_blue_example/com.pauldemarco.flutter_blue_example.MainActivity (client)' ~NativeInputEventReceiver.
E/ActivityThread(21256): Activity com.pauldemarco.flutter_blue_example.MainActivity has leaked IntentReceiver com.pauldemarco.flutter_blue.FlutterBluePlugin$1$1@abbbc8 that was originally registered here. Are you missing a call to unregisterReceiver()?
E/ActivityThread(21256): android.app.IntentReceiverLeaked: Activity com.pauldemarco.flutter_blue_example.MainActivity has leaked IntentReceiver com.pauldemarco.flutter_blue.FlutterBluePlugin$1$1@abbbc8 that was originally registered here. Are you missing a call to unregisterReceiver()?
E/ActivityThread(21256): 	at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:1357)
E/ActivityThread(21256): 	at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:1122)
E/ActivityThread(21256): 	at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1428)
E/ActivityThread(21256): 	at android.app.ContextImpl.registerReceiver(ContextImpl.java:1401)
E/ActivityThread(21256): 	at android.app.ContextImpl.registerReceiver(ContextImpl.java:1389)
E/ActivityThread(21256): 	at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:622)
E/ActivityThread(21256): 	at com.pauldemarco.flutter_blue.FlutterBluePlugin$1.onListen(FlutterBluePlugin.java:638)
E/ActivityThread(21256): 	at io.flutter.plugin.common.EventChannel$IncomingStreamRequestHandler.onListen(EventChannel.java:193)
E/ActivityThread(21256): 	at io.flutter.plugin.common.EventChannel$IncomingStreamRequestHandler.onMessage(EventChannel.java:172)
E/ActivityThread(21256): 	at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:93)
...

Just consume the state stream (FlutterBlue.instance.state) and then, press back button on Android (or just switch app) and you'll get the exception in your debug console

flutter doctor -v

[✓] Flutter (Channel stable, v1.12.13+hotfix.8, on Linux, locale en_US.UTF-8)
    • Flutter version 1.12.13+hotfix.8 at /opt/flutter
    • Framework revision 0b8abb4724 (7 weeks ago), 2020-02-11 11:44:36 -0800
    • Engine revision e1e6ced81d
    • Dart version 2.7.0

 
[✓] Android toolchain - develop for Android devices (Android SDK version 28.0.3)
    • Android SDK at /opt/android-sdk/
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-29, build-tools 28.0.3
    • ANDROID_HOME = /opt/android-sdk
    • ANDROID_SDK_ROOT = /opt/android-sdk
    • Java binary at: /opt/android-studio/jre/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b4-5784211)
    • All Android licenses accepted.

[✓] Android Studio (version 3.6)
    • Android Studio at /opt/android-studio
    • Flutter plugin version 44.0.2
    • Dart plugin version 192.7761
    • Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b4-5784211)

[✓] Connected device (1 available)
    • SM G935F • 988678454e47515938 • android-arm64 • Android 8.0.0 (API 26)

• No issues found!

rdehouss avatar Apr 01 '20 20:04 rdehouss

Sorry to maybe state the obvious but I'm searching for a solution :) In FlutterBluePlugin.java, the onCancel seems to not be called

@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
    sink = eventSink;
    IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
    activity.registerReceiver(mReceiver, filter);
}

@Override
public void onCancel(Object o) {
    sink = null;
    activity.unregisterReceiver(mReceiver);
}

rdehouss avatar Apr 01 '20 21:04 rdehouss

Somehow, seems related: https://github.com/flutter/flutter/issues/12956#issuecomment-343930468

rdehouss avatar Apr 01 '20 21:04 rdehouss

I succeeded to work around the issue with the following, which, seems to me, a good solution but could be implemented in FlutterBlue it self I think:

// In the widget normally consuming FlutterBlue.instance.state

StreamController<BluetoothState> bluetoothStateStreamController = ((Stream<BluetoothState> state) {
    StreamController<BluetoothState> controller;
    StreamSubscription stateStreamSub;

    void onListen() {
      stateStreamSub = state.listen((state) {
        controller.add(state);
      });
    }

    void onCancel() {
      stateStreamSub?.cancel();
      stateStreamSub = null;
    }

    controller = StreamController<BluetoothState>(
      onListen: onListen,
      onPause: onCancel,
      onResume: onListen,
      onCancel: onCancel,
    );

    return controller;
  })(FlutterBlue.instance.state);

  Stream<BluetoothState> bluetoothStateStream;

  // further in the State<StatefullWidget>

  @override
  void initState() {
    bluetoothStateStream = bluetoothStateStreamController.stream.asBroadcastStream();

    super.initState();
  }

  @override
  void dispose() {
    bluetoothStateStreamController?.close();

    super.dispose();
  }

The important part is bluetoothStateStreamController?.close(); in the dispose()

rdehouss avatar Apr 02 '20 06:04 rdehouss

Same here. Pease fix it :)

Arley011 avatar Oct 12 '20 14:10 Arley011

Activity io.flutter.embedding.android.FlutterActivity has leaked IntentReceiver io.flutter.plugins.camera.features.sensororientation.DeviceOrientationManager$1@b951b24 that was originally registered here. Are you missing a call to unregisterReceiver()?

i am facing this error how can i resolve this error?

ravi9837 avatar Aug 04 '23 13:08 ravi9837