[英]How do I use a Flutter MethodChannel to invoke a method in dart code from the native swift code?
我看過關於這個主題很多類似的問題,但沒有解決方案,為我工作。我正在開發中的顫振應用程序,但要調用特定的方法在我main.dart
從文件AppDelegate.swift
在本機iOS項目。
為了刪除所有其他變量,我已將問題提取到一個新的 dart 項目中。 我正在嘗試使用setChannelText()
從AppDelegate.swift
調用setChannelText()
methodChannel.invokeMethod()
,但沒有成功。
有誰知道我哪里出錯了? 我知道我沒有對methodChannel.invokeMethod()
的“name”參數采取行動,但那是因為我只想調用調用方法......
這是我的 main.dart 文件:
import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; void main() { runApp(MyApp()); } class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { MethodChannel channel = new MethodChannel("com.example.channeltest/changetext"); String centerText; @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( backgroundColor: Colors.purple, body: Center( child: Text( centerText, style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 30.0, ), ), ), ), ); } @override void initState() { super.initState(); this.channel.setMethodCallHandler((call) async => await setChannelText()); this.centerText = "Hello World!"; } Future setChannelText() async { Future.delayed(Duration(milliseconds: 200)); setState(() => this.centerText = "Another Text."); } }
這是我的 AppDelegate.swift 文件:
import UIKit import Flutter @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { var methodChannel: FlutterMethodChannel! override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { let rootViewController : FlutterViewController = window?.rootViewController as! FlutterViewController methodChannel = FlutterMethodChannel(name: "com.example.channeltest/changetext", binaryMessenger: rootViewController as! FlutterBinaryMessenger) //This call would obviously be somewhere else in a real world example, but I'm just //testing if I can invoke the method in my dart code at all.. methodChannel.invokeMethod("some_method_name", arguments: nil) GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } }
最后,我試圖在啟動后立即更改文本,但事實並非如此。
在此先感謝您的幫助!!
顫振側代碼:
import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class _MyHomePageState extends State<MyHomePage> { static const platform = MethodChannel('samples.flutter.dev/battery'); // Get battery level. String _batteryLevel = 'Unknown battery level.'; Future<void> _getBatteryLevel() async { String batteryLevel; try { final int result = await platform.invokeMethod('getBatteryLevel'); batteryLevel = 'Battery level at $result % .'; } on PlatformException catch (e) { batteryLevel = "Failed to get battery level: '${e.message}'."; } setState(() { _batteryLevel = batteryLevel; }); } @override Widget build(BuildContext context) { return Material( child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ ElevatedButton( child: Text('Get Battery Level'), onPressed: _getBatteryLevel, ), Text(_batteryLevel), ], ), ), ); } }
Swift 代碼在這里:
@UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let controller : FlutterViewController = window?.rootViewController as! FlutterViewController let batteryChannel = FlutterMethodChannel(name: "samples.flutter.dev/battery", binaryMessenger: controller.binaryMessenger) batteryChannel.setMethodCallHandler({ [weak self] (call: FlutterMethodCall, result: FlutterResult) -> Void in // Note: this method is invoked on the UI thread. guard call.method == "getBatteryLevel" else { result(FlutterMethodNotImplemented) return } self?.receiveBatteryLevel(result: result) }) GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } }
或者參考這個鏈接:
問題是您的平台端(在本例中為 iOS)在Flutter 准備就緒之前調用 Flutter 端的方法。 無法從平台端檢查,因此您的Flutter 應用程序必須告訴您的平台端。 你會在 Android 上遇到同樣的問題。
為了克服這個問題,您必須告訴平台端應用程序已准備就緒(通過發送平台方法)並將其保存在一個布爾值中。 然后平台端就可以開始發送消息了。
你應該真正閱讀日志,它應該警告你一些類似的東西:“沒有任何東西在聽這個,或者 Flutter 引擎沒有連接”。
import 'dart:async';
import 'package:flutter/src/services/platform_channel.dart';
class StringService {
final methodChannel =
const MethodChannel("com.example.app_name.method_channel.strings");
final StreamController<String> _stringStreamController =
StreamController<String>();
Stream<String> get stringStream => _stringStreamController.stream;
StringService() {
// Set method call handler before telling platform side we are ready to receive.
methodChannel.setMethodCallHandler((call) async {
print('Just received ${call.method} from platform');
if (call.method == "new_string") {
_stringStreamController.add(call.arguments as String);
} else {
print("Method not implemented: ${call.method}");
}
});
// Tell platform side we are ready!
methodChannel.invokeMethod("isReady");
}
}
你可以在reverse_platform_methods看到一個工作項目,尤其是AppDelegate.swift
。 我沒有為 Android 實現它,但你可以在MainActivity.kt
中以類似的方式實現它。
大多數應用程序不希望代碼首先從平台端調用。 你的用例是什么? 根據您的回答,我可能會提供更好的建議。 我實現了這個來處理傳遞到設備的推送通知,所以“事件”肯定是從平台端觸發的。
此外,如果您遇到錯誤和警告,您應該顯示它們,例如No implementation found for method $method on channel $name'
。
嗯,問題全在於初始化過程。 在 dart/flutter 部分准備好處理它之前,您嘗試從 swift 代碼中調用您的方法。
您必須執行以下步驟才能獲得結果:
AppDelegate
for ios 中使用這個方法@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
var methodChannel: FlutterMethodChannel? = nil
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
print("Setup methodChannel from Swift")
let rootViewController : FlutterViewController = window?.rootViewController as! FlutterViewController
methodChannel = FlutterMethodChannel(name: "com.example.channeltest/changetext", binaryMessenger: rootViewController as! FlutterBinaryMessenger)
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
//THIS METHOD
override func applicationDidBecomeActive(_ application: UIApplication) {
methodChannel?.invokeMethod("some_method_name", arguments: "ios string")
}
}
對於安卓:
class MainActivity : FlutterActivity() {
var channel: MethodChannel? = null
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
channel = MethodChannel(
flutterEngine.dartExecutor.binaryMessenger,
"com.example.channeltest/changetext"
)
}
override fun onStart() {
super.onStart()
channel?.invokeMethod("some_method_name", "android str")
}
}
MethodChannel
創建您自己的類( MethodChannel
答案)class TestChannel {
static MethodChannel channel =
const MethodChannel("com.example.channeltest/changetext");
final StreamController<String> _controller =
StreamController<String>();
Stream<String> get stringStream => _controller.stream;
TestChannel() {
channel.setMethodCallHandler((call) async {
if (call.method == "some_method_name") {
_controller.add(call.arguments as String);
} else {
print("Method not implemented: ${call.method}");
}
});
}
}
final _changeTextChannel = TestChannel(); //<--- like this
void main() {
runApp(MyApp());
}
class TestPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: StreamBuilder<String>(
stream: _changeTextChannel.stringStream,
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasError) {
return Text("Error");
}
if (!snapshot.hasData) {
return Text("Loading");
}
return Text(snapshot.data ?? "NO_DATA");
},
)),
);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.