Flutter的EventChannel未将数据发送到Dart端。

huangapple go评论70阅读模式
英文:

Flutter's EventChannel not sending data to dart side

问题

我正在尝试在Android的共享菜单中显示我的应用程序,我成功地完成了这个任务,但我无法从本地代码发送数据到Dart代码,使用EventChannel

我已经更新了我的MainActivity如下:

class MainActivity: FlutterActivity() {

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

        Log.i("TAG123","onCreate")
        onSharedIntent()
    }

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        Log.i("TAG123","configure flutter engine")
    }

    private fun onSharedIntent() {
        val receivedAction: String? = intent.action
        val receivedType: String? = intent.type
        if (receivedAction == Intent.ACTION_SEND) {

            // check mime type
            if (receivedType?.startsWith("text/") == true) {
                val receivedText: String? = intent.getStringExtra(Intent.EXTRA_TEXT)
                if (receivedText != null) {
                    //do your stuff
                    Log.e("TAG123", receivedText.toString())
                    if(flutterEngine?.dartExecutor?.binaryMessenger != null){
                        Log.i("TAG123","flutter engine not null")
                    }
                    Log.e("TAG123", "here")
                    EventChannel(
                        flutterEngine!!.dartExecutor.binaryMessenger,
                        "sharePlatform"
                    ).setStreamHandler(object : EventChannel.StreamHandler {

                        override fun onListen(arguments: Any, events: EventSink) {
                            Log.e("TAG123", "here123")
                            events.success(receivedText)
                        }

                        override fun onCancel(arguments: Any) {
                            Log.e("TAG123", "here123456")
                        }
                    })
                } else {
                    Log.e("TAG123", "no data")
                }
            } else if (receivedType?.startsWith("image/") == true) {
                val receiveUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                    intent.getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java)
                } else {
                    intent.getParcelableExtra(Intent.EXTRA_STREAM) as Uri?
                }

                if (receiveUri != null) {
                    Log.e("TAG123", receiveUri.toString())
                    if(flutterEngine?.dartExecutor?.binaryMessenger != null){
                        Log.i("TAG123","flutter engine not null")
                    }
                    EventChannel(
                        flutterEngine!!.dartExecutor.binaryMessenger,
                        "sharePlatform"
                    ).setStreamHandler(object : EventChannel.StreamHandler {

                        override fun onListen(arguments: Any, events: EventSink) {
                            Log.e("TAG123", "here123")
                            events.success(receiveUri)
                        }

                        override fun onCancel(arguments: Any) {
                            Log.e("TAG123", "here123456")
                        }
                    })
                } else {
                    Log.e("TAG123", "no image data")
                }
            }
        } else if (receivedAction == Intent.ACTION_MAIN) {
            Log.e("TAG123", "onSharedIntent: nothing shared")
        }
    }

}

我还对AndroidManifest进行了必要的更改:

<intent-filter>
    <action android:name="android.intent.action.SEND" />

    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="image/*" />
    <data android:mimeType="text/*" />
</intent-filter>

当我从其他应用程序共享图像到我的应用程序时,我可以在日志中看到图像的URL或URI,但EventChannel从未生效。

以下是我的Dart代码:

class _MyHomePageState extends State<MyHomePage> {
  var data = "";
  final _eventChannel = const EventChannel('sharePlatform');

  @override
  void initState() {
    super.initState();

    _eventChannel.receiveBroadcastStream().distinct().map((dynamic event) {
      debugPrint("TAG123Flutter $event");
      setState(() {
        data = event;
      });
      // return event;
    });
  }
  // 其他部分...
}
英文:

I am trying to show my app in share sheet of android and I was able to successfully do it but I am not able to send data from native side to dart using EventChannel.

I have updated my MainActivity to following

class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.i(&quot;TAG123&quot;,&quot;onCreate&quot;)
onSharedIntent()
}
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
Log.i(&quot;TAG123&quot;,&quot;configure flutter engine&quot;)
}
private fun onSharedIntent() {
val receivedAction: String? = intent.action
val receivedType: String? = intent.type
if (receivedAction == Intent.ACTION_SEND) {
// check mime type
if (receivedType?.startsWith(&quot;text/&quot;) == true) {
val receivedText: String? = intent.getStringExtra(Intent.EXTRA_TEXT)
if (receivedText != null) {
//do your stuff
Log.e(&quot;TAG123&quot;, receivedText.toString())
if(flutterEngine?.dartExecutor?.binaryMessenger != null){
Log.i(&quot;TAG123&quot;,&quot;flutter engine not null&quot;)
}
Log.e(&quot;TAG123&quot;, &quot;here&quot;)
EventChannel(
flutterEngine!!.dartExecutor.binaryMessenger,
&quot;sharePlatform&quot;
).setStreamHandler(object : EventChannel.StreamHandler {
override fun onListen(arguments: Any, events: EventSink) {
Log.e(&quot;TAG123&quot;, &quot;here123&quot;)
events.success(receivedText)
}
override fun onCancel(arguments: Any) {
Log.e(&quot;TAG123&quot;, &quot;here123456&quot;)
}
})
} else {
Log.e(&quot;TAG123&quot;, &quot;no data&quot;)
}
} else if (receivedType?.startsWith(&quot;image/&quot;) == true) {
//                val receiveUri: Uri? = intent.getParcelableExtra(Intent.EXTRA_STREAM) as Uri?
val receiveUri = if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.TIRAMISU) {
intent.getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java)
} else {
intent.getParcelableExtra(Intent.EXTRA_STREAM) as Uri?
}
if (receiveUri != null) {
Log.e(&quot;TAG123&quot;, receiveUri.toString())
if(flutterEngine?.dartExecutor?.binaryMessenger != null){
Log.i(&quot;TAG123&quot;,&quot;flutter engine not null&quot;)
}
EventChannel(
flutterEngine!!.dartExecutor.binaryMessenger,
&quot;sharePlatform&quot;
).setStreamHandler(object : EventChannel.StreamHandler {
override fun onListen(arguments: Any, events: EventSink) {
Log.e(&quot;TAG123&quot;, &quot;here123&quot;)
events.success(receiveUri)
}
override fun onCancel(arguments: Any) {
Log.e(&quot;TAG123&quot;, &quot;here123456&quot;)
}
})
} else {
Log.e(&quot;TAG123&quot;, &quot;no image data&quot;)
}
}
} else if (receivedAction == Intent.ACTION_MAIN) {
Log.e(&quot;TAG123&quot;, &quot;onSharedIntent: nothing shared&quot;)
}
}
}

I have made the required changes to AndroidManifest as well

&lt;intent-filter&gt;
&lt;action android:name=&quot;android.intent.action.SEND&quot; /&gt;
&lt;category android:name=&quot;android.intent.category.DEFAULT&quot; /&gt;
&lt;data android:mimeType=&quot;image/*&quot; /&gt;
&lt;data android:mimeType=&quot;text/*&quot; /&gt;
&lt;/intent-filter&gt;

I can see the url or uri of image when I share it from some other app to my app in logs but EventChannel never works

Below is my dart code

class _MyHomePageState extends State&lt;MyHomePage&gt; {
var data = &quot;&quot;;
final _eventChannel = const EventChannel(&#39;sharePlatform&#39;);
@override
void initState() {
super.initState();
_eventChannel.receiveBroadcastStream().distinct().map((dynamic event) {
debugPrint(&quot;TAG123Flutter $event&quot;);
setState(() {
data = event;
});
// return event;
});
}......

答案1

得分: 1

我查看了这篇博客来解决您的问题,并找到了以下解决方案。

请用以下内容替换您的MainActivity代码:

class MainActivity: FlutterActivity() {

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

        Log.i("TAG123","onCreate")
    }

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        Log.i("TAG123","configure flutter engine")
        EventChannel(
            flutterEngine.dartExecutor.binaryMessenger,
            "sharePlatform"
        ).setStreamHandler(object : EventChannel.StreamHandler {

            override fun onListen(arguments: Any?, events: EventChannel.EventSink) {
                Log.e("TAG123", "configure here123")
                Log.e("TAG123", "$intent")
                onSharedIntent(events)
            }

            override fun onCancel(arguments: Any?) {
                Log.e("TAG123", "configure here123456")
            }
        })
    }

    private fun onSharedIntent(events: EventChannel.EventSink) {
        val receivedAction: String? = intent.action
        val receivedType: String? = intent.type
        if (receivedAction == Intent.ACTION_SEND) {

            // check mime type
            if (receivedType?.startsWith("text/") == true) {
                val receivedText: String? = intent.getStringExtra(Intent.EXTRA_TEXT)
                if (receivedText != null) {
                    //do your stuff
                    Log.e("TAG123", receivedText.toString())
                    if(flutterEngine?.dartExecutor?.binaryMessenger != null){
                        Log.i("TAG123","flutter engine not null")
                    }
                    Log.e("TAG123", "here")
                    events.success(receivedText)
                } else {
                    Log.e("TAG123", "no data")
                }
            } else if (receivedType?.startsWith("image/") == true) {
                val receiveUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                    intent.getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java)
                } else {
                    intent.getParcelableExtra(Intent.EXTRA_STREAM) as Uri?
                }
                if (receiveUri != null) {
                    Log.e("TAG123", receiveUri.toString())
                    if(flutterEngine?.dartExecutor?.binaryMessenger != null){
                        Log.i("TAG123","flutter engine not null")
                    }
                    events.success(receiveUri.toString())
                } else {
                    Log.e("TAG123", "no image data")
                }
            }
        } else if (receivedAction == Intent.ACTION_MAIN) {
            Log.e("TAG123", "onSharedIntent: nothing shared")
        }
    }
}

请用以下内容替换您的Dart代码:

@override
void initState() {
  super.initState();
  _eventChannel.receiveBroadcastStream().listen((dynamic event) {
    debugPrint("TAG123Flutter $event");
    setState(() {
      data = event;
    });
    // return event;
  });
}

希望这有所帮助。谢谢 Flutter的EventChannel未将数据发送到Dart端。

英文:

I went through this blog to resolve your issue and came upon with the following solution.

Replace your MainActivity Code with the following

class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.i(&quot;TAG123&quot;,&quot;onCreate&quot;)
}
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
Log.i(&quot;TAG123&quot;,&quot;configure flutter engine&quot;)
EventChannel(
flutterEngine.dartExecutor.binaryMessenger,
&quot;sharePlatform&quot;
).setStreamHandler(object : EventChannel.StreamHandler {
override fun onListen(arguments: Any?, events: EventChannel.EventSink) {
Log.e(&quot;TAG123&quot;, &quot;configure here123&quot;)
Log.e(&quot;TAG123&quot;, &quot;$intent&quot;)
onSharedIntent(events)
}
override fun onCancel(arguments: Any?) {
Log.e(&quot;TAG123&quot;, &quot;configure here123456&quot;)
}
})
}
private fun onSharedIntent(events: EventChannel.EventSink) {
val receivedAction: String? = intent.action
val receivedType: String? = intent.type
if (receivedAction == Intent.ACTION_SEND) {
// check mime type
if (receivedType?.startsWith(&quot;text/&quot;) == true) {
val receivedText: String? = intent.getStringExtra(Intent.EXTRA_TEXT)
if (receivedText != null) {
//do your stuff
Log.e(&quot;TAG123&quot;, receivedText.toString())
if(flutterEngine?.dartExecutor?.binaryMessenger != null){
Log.i(&quot;TAG123&quot;,&quot;flutter engine not null&quot;)
}
Log.e(&quot;TAG123&quot;, &quot;here&quot;)
events.success(receivedText)
} else {
Log.e(&quot;TAG123&quot;, &quot;no data&quot;)
}
} else if (receivedType?.startsWith(&quot;image/&quot;) == true) {
//                val receiveUri: Uri? = intent.getParcelableExtra(Intent.EXTRA_STREAM) as Uri?
val receiveUri = if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.TIRAMISU) {
intent.getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java)
} else {
intent.getParcelableExtra(Intent.EXTRA_STREAM) as Uri?
}
if (receiveUri != null) {
Log.e(&quot;TAG123&quot;, receiveUri.toString())
if(flutterEngine?.dartExecutor?.binaryMessenger != null){
Log.i(&quot;TAG123&quot;,&quot;flutter engine not null&quot;)
}
events.success(receiveUri.toString())
} else {
Log.e(&quot;TAG123&quot;, &quot;no image data&quot;)
}
}
} else if (receivedAction == Intent.ACTION_MAIN) {
Log.e(&quot;TAG123&quot;, &quot;onSharedIntent: nothing shared&quot;)
}
}
}

Replace your dart code with the following

  @override
void initState() {
super.initState();
_eventChannel.receiveBroadcastStream().listen((dynamic event) {
debugPrint(&quot;TAG123Flutter $event&quot;);
setState(() {
data = event;
});
// return event;
});
}

Hope this helps.
Thanks Flutter的EventChannel未将数据发送到Dart端。

答案2

得分: 0

这是因为您没有订阅该流。您只在初始化MyHomePage时操作流。如果您对此主题不熟悉,我建议更多地学习事件驱动编程,Dart中的读取、写入和可视化都会令人困惑。

StreamSubscription<dynamic>? _eventSubscription;

@override
void initState() {
  super.initState();

  _eventSubscription = _eventChannel.receiveBroadcastStream().listen((dynamic event) {
    debugPrint("TAG123Flutter $event");
    setState(() {
      data = event;
    });
  });
}

@override
void dispose() {
  _eventSubscription?.cancel(); // 在小部件被处理时取消事件订阅
  super.dispose();
}

这样,小部件将在其存活期间监听事件。

如果您想使用 distinct,您可以使用 StreamTransformer。例如,

StreamTransformer<String, String> distinctTransformer =
    StreamTransformer<String, String>.fromHandlers(
  handleData: (String data, EventSink<String> sink) {
    Set<String> uniqueItems = Set<String>();
    if (!uniqueItems.contains(data)) {
      uniqueItems.add(data);
      sink.add(data);
    }
  },
);

StreamSubscription<String> _streamSubscription;
_streamSubscription = _streamController.stream
    .transform(distinctTransformer)
    .listen((data) {
      print('Received distinct data: $data');
    });
英文:

This is because you didn't subscribe to the stream. You are operating on the stream only at the moment MyHomePage is initialized. If you're not familiar with the topic, I suggest studying event driven programming more, it's confusing in Dart to read write visualize it.

StreamSubscription&lt;dynamic&gt;? _eventSubscription;
@override
void initState() {
super.initState();
_eventSubscription = _eventChannel.receiveBroadcastStream().listen((dynamic event) {
debugPrint(&quot;TAG123Flutter $event&quot;);
setState(() {
data = event;
});
});
}
@override
void dispose() {
_eventSubscription?.cancel(); // Cancel the event subscription when the widget is disposed
super.dispose();
}

This way the widget will listen to events that come as long as it is alive.

If you want to use distinct, you can use a StreamTransformer. For example,

StreamTransformer&lt;String, String&gt; distinctTransformer =
StreamTransformer&lt;String, String&gt;.fromHandlers(
handleData: (String data, EventSink&lt;String&gt; sink) {
Set&lt;String&gt; uniqueItems = Set&lt;String&gt;();
if (!uniqueItems.contains(data)) {
uniqueItems.add(data);
sink.add(data);
}
},
);
StreamSubscription&lt;String&gt; _streamSubscription;
_streamSubscription = _streamController.stream
.transform(distinctTransformer)
.listen((data) {
print(&#39;Received distinct data: $data&#39;);
});

答案3

得分: 0

我认为原因是因为

EventChannel(flutterEngine!!.dartExecutor.binaryMessenger, "sharePlatform").setStreamHandle

为什么需要使用 flutterEngine!!.dartExecutor.binaryMessenger

在Flutter中,您可以像这样创建EventChannel:EventChannel('sharePlatform')

所以我认为在ADR代码中,您应该使用默认的执行器作为messenger
像这样:EventChannel(flutterEngine!!.dartExecutor, "sharePlatform")

希望这有所帮助。

英文:

I think the reason is because of

EventChannel(flutterEngine!!.dartExecutor.binaryMessenger, &quot;sharePlatform&quot;).setStreamHandle

Why do you need to use flutterEngine!!.dartExecutor.binaryMessenger?

in Flutter you create EventChannel like this EventChannel(&#39;sharePlatform&#39;)

So I think in ADR code you should use the default executor as messager
like this: EventChannel(flutterEngine!!.dartExecutor, &quot;sharePlatform&quot;)

Hope it helps.

答案4

得分: 0

你正在直接在onCreate方法中调用onSharedIntent方法。看起来这可能是问题的原因,因为在这种情况下onSharedIntent不会被调用。你应该像这样将onSharedIntent包装在一个Handler中:

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

    Log.i("TAG123","onCreate")

    /// 使用这个Handler包装onSharedIntent。
    Handler(Looper.getMainLooper()).postDelayed(Runnable {
        onSharedIntent()  
    }, 0)
}

尝试这样做。这应该可以解决问题。

更新继续自评论中。

似乎没有明显的原因。但你也可以尝试将streamHandler制作成另一个类,而不是一个对象类型。只是尝试作为一个hack,因为你说问题似乎在eventChannel的调用中。

这样做:

class MyStreamHandler(private val text: String) : EventChannel.StreamHandler {
    override fun onListen(arguments: Any, events: EventSink) {
        Log.e("TAG123", "here123")
        events.success(text)
    }

    override fun onCancel(arguments: Any) {
        Log.e("TAG123", "here123456")
    }
}

然后调用:

EventChannel(flutterEngine!!.dartExecutor.binaryMessenger, "sharePlatform").setStreamHandler(
    MyStreamHandler(receivedText))
英文:

You are calling onSharedIntent method inside onCreate method directly.
Looks like that can be the issue because onSharedIntent won't be invoked in this case. You should wrap the onSharedIntent inside a Handler like this:

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.i(&quot;TAG123&quot;,&quot;onCreate&quot;)
/// Wrap onSharedIntent with this Handler.
Handler(Looper.getMainLooper()).postDelayed(Runnable {
onSharedIntent()  
}, 0)
}

Try this. This should work.


>Update continued from the comment.

There doesn't seem any obvious reason. But you can also try to make the streamHandler another class rather than an object type. Just try it as a hack as you said the problem seems to be in the eventChannel invocation.

Do this:

class MyStreamHandler(private val text: String) : EventChannel.StreamHandler{
override fun onListen(arguments: Any, events: EventSink) {
Log.e(&quot;TAG123&quot;, &quot;here123&quot;)
events.success(text)
}
override fun onCancel(arguments: Any) {
Log.e(&quot;TAG123&quot;, &quot;here123456&quot;)
}
}

Then call:

EventChannel(flutterEngine!!.dartExecutor.binaryMessenger,
&quot;sharePlatform&quot;).setStreamHandler(
MyStreamHandler(receivedText))

huangapple
  • 本文由 发表于 2023年6月1日 19:20:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76381332.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定