英文:
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("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: Uri? = intent.getParcelableExtra(Intent.EXTRA_STREAM) as Uri?
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")
}
}
}
I have made the required changes to AndroidManifest
as well
<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>
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<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;
});
}......
答案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;
});
}
希望这有所帮助。谢谢
英文:
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("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: Uri? = intent.getParcelableExtra(Intent.EXTRA_STREAM) as Uri?
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")
}
}
}
Replace your dart code with the following
@override
void initState() {
super.initState();
_eventChannel.receiveBroadcastStream().listen((dynamic event) {
debugPrint("TAG123Flutter $event");
setState(() {
data = event;
});
// return event;
});
}
Hope this helps.
Thanks
答案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<dynamic>? _eventSubscription;
@override
void initState() {
super.initState();
_eventSubscription = _eventChannel.receiveBroadcastStream().listen((dynamic event) {
debugPrint("TAG123Flutter $event");
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<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');
});
答案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, "sharePlatform").setStreamHandle
Why do you need to use flutterEngine!!.dartExecutor.binaryMessenger
?
in Flutter you create EventChannel like this EventChannel('sharePlatform')
So I think in ADR code you should use the default executor as messager
like this: EventChannel(flutterEngine!!.dartExecutor, "sharePlatform")
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("TAG123","onCreate")
/// 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("TAG123", "here123")
events.success(text)
}
override fun onCancel(arguments: Any) {
Log.e("TAG123", "here123456")
}
}
Then call:
EventChannel(flutterEngine!!.dartExecutor.binaryMessenger,
"sharePlatform").setStreamHandler(
MyStreamHandler(receivedText))
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论