2

I was following along a tutorial described in this article.
The code of the article can be found here: https://github.com/seamusv/event_channel_sample.
I basically do the same only that i use kotlin instead of java.

In native code (MainActivity.kt):

class MainActivity: FlutterActivity() {
  private val STREAM_TAG = "alarm.eventchannel.sample/stream";

  private var timerSubscription : Disposable? = null

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    GeneratedPluginRegistrant.registerWith(this)

    EventChannel(getFlutterView(), STREAM_TAG).setStreamHandler(
      object : EventChannel.StreamHandler {
        override fun onListen(arguments: Any?, events: EventChannel.EventSink) {
          Log.w("TAG", "adding listener")
          this@MainActivity.timerSubscription = Observable.interval(0, 1, TimeUnit.SECONDS)
             .subscribe (
               {  
                 Log.w("Test", "Result we just received: $it");
                 events.success(1);
               }, // OnSuccess
               { error -> events.error("STREAM", "Error in processing observable", error); }, // OnError
               { println("Complete"); } // OnCompletion
             )
        }

        override fun onCancel(arguments: Any?) {
          Log.w("TAG", "adding listener")
          if (this@MainActivity.timerSubscription != null) {
            this@MainActivity.timerSubscription?.dispose()
            this@MainActivity.timerSubscription = null
          }
        }
      }
    )

  }
}

In my main.dart i do the following:

int _timer = 0;
  StreamSubscription _timerSubscription = null;

void _enableTimer() {
  if (_timerSubscription == null) {
    _timerSubscription = stream.receiveBroadcastStream().listen(_updateTimer);
  }
}

void _disableTimer() {
  if (_timerSubscription != null) {
    _timerSubscription.cancel();
    _timerSubscription = null;
  }
}

void _updateTimer(timer) {
  debugPrint("Timer $timer");
  setState(() => _timer = timer);
}

In the build function i also create a button which then calls _enableTimer() onPressed.

new FlatButton(
  child: const Text('Enable'),
  onPressed: _enableTimer,
)

Whenever i now press the button to call _enableTimer() the app crashes and i get the output "Lost connection to device"...
Am i doing something wrong or is this a bug in a newer version of Flutter since the article is from December 2017?

  • I forgot to mention that the same crash occurs in the code of the article which which reinforces my guess that there's a bug in the current version of flutter. – hendrik hendrikson Dec 22 '19 at 14:55
  • 1
    On mobile, so can't mark as duplicate. Search for a question a few weeks back starting "create method channel" – Richard Heap Dec 22 '19 at 16:23
  • Found nothing concerned to my question. My problem are not normal method channels. I'm talking about Event Channel Streams... – hendrik hendrikson Dec 23 '19 at 21:05
  • 1
    https://stackoverflow.com/questions/59228006/create-method-channel-after-upgrading-flutter-can-not-resolve-method-getflutter/59229000#59229000 – Richard Heap Dec 24 '19 at 00:23
  • If i replace `getFlutterView()` with `getFlutterEngine().getDartExecutor().getBinaryMessenger()`, i get the error: `Unresolved reference: getFlutterEngine` – hendrik hendrikson Dec 24 '19 at 10:23
  • You must be on a very old version of flutter. Which channel are you on? – Richard Heap Dec 24 '19 at 10:36
  • Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel stable, v1.12.13+hotfix.5, on Linux, locale en_US.UTF-8) [✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2) [!] Android Studio (version 3.5) ✗ Flutter plugin not installed; this adds Flutter specific functionality. ✗ Dart plugin not installed; this adds Dart specific functionality. [✓] VS Code (version 1.41.1) [!] Connected device ! No devices available ! Doctor found issues in 2 categories – hendrik hendrikson Dec 24 '19 at 17:22
  • More up to beta or dev, until you can resolve get flutter engine. Also, consider creating a plugin to encapsulate your event channel logic. The connectivity plugin is the perfect template. Check that you can build and run that, then adapt. – Richard Heap Dec 24 '19 at 18:28
  • tried both channels (dev and beta) but the error still exists. – hendrik hendrikson Dec 26 '19 at 11:10
  • am i missing a certain package import? – hendrik hendrikson Dec 26 '19 at 11:10

1 Answers1

1

The solution to my problem was basically to start the stream in the main thread:

class MainActivity: FlutterActivity() {
  private val CHANNEL = "alarm.flutter.dev/audio"

  private val STREAM_TAG = "alarm.eventchannel.sample/stream";

  private var timerSubscription : Disposable? = null

  override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
    GeneratedPluginRegistrant.registerWith(flutterEngine)

    EventChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), STREAM_TAG).setStreamHandler(
      object : EventChannel.StreamHandler {
        override fun onListen(arguments: Any?, events: EventChannel.EventSink) {
          Log.w("TAG", "adding listener")
          this@MainActivity.timerSubscription = Observable
             .interval(1000, TimeUnit.MILLISECONDS)
             .observeOn(AndroidSchedulers.mainThread())
             .subscribe (
               {  
                 Log.w("Test", "Result we just received: $it"); 
                 events.success(it);
               }, // OnSuccess
               { error -> events.error("STREAM", "Error in processing observable", error); }, // OnError
               { println("Complete"); } // OnCompletion
             )
        }

        override fun onCancel(arguments: Any?) {
          Log.w("TAG", "adding listener")
          if (this@MainActivity.timerSubscription != null) {
            this@MainActivity.timerSubscription?.dispose()
            this@MainActivity.timerSubscription = null
          }
        }
      }
    )

  }