Flutter原生功能交互插件native_bridge的使用
Flutter原生功能交互插件native_bridge的使用
NativeBridge
是一个基于 webview_flutter
的插件,实现了 App 和 H5 之间的 JSBridge 方法调用能力。
NativeBridge 的优点
- 支持 H5 调用 App 中的 JSBridge 方法,并可以直接获取返回值。
- 支持 App 调用 H5 的 JSBridge 方法,并可以直接获取返回值。
- 使用简单,集成后可以通过扩展
NativeBridgeController
类来支持 App 的 JavaScript 调用能力。
NativeBridge 依赖
在 pubspec.yaml
文件中添加依赖:
dependencies:
native_bridge: ^latest_version
使用 NativeBridge
1. 扩展 NativeBridgeController
class AppBridgeController extends NativeBridgeController {
AppBridgeController(WebViewController controller) : super(controller);
/// 定义 JSChannel 名称
[@override](/user/override)
get name => "nativeBridge";
[@override](/user/override)
Map<String, Function?> get callMethodMap => {
// 版本号
"getVersionCode": (data) async {
return await AppUtil.getVersion();
},
// 其他方法...
};
}
2. 初始化 AppBridgeController
// 初始化 WebViewController
_controller = WebViewController()
..enableZoom(true)
..loadFlutterAsset('assets/test/index.html');
// 初始化 AppBridgeController
_appBridgeController = AppBridgeController(_controller);
3. 在 H5 中添加 receiveMessage
方法
function receiveMessage(jsonStr) {
if(jsonStr != undefined && jsonStr != "") {
let data = JSON.parse(JSON.stringify(jsonStr));
window.jsBridgeHelper.receiveMessage(data);
}
}
H5 获取 App 的值
1. 在 App 中定义方法名称和函数调用
// 版本号
"getVersionCode": (data) async {
return await AppUtil.getVersion();
}
2. 在 H5 中调用相应的方法
async function getVersionName() {
// 获取 App 的值
let appVersionName = await window.jsBridgeHelper.sendMessage("getVersionName", null);
}
App 获取 H5 的值
通过 AppBridgeController
的 sendMessage
方法
// 是否为首页
bool? isHome = await _appBridgeController.sendMessage(Message(api: 'isHome'));
通过 AppBridgeController
的 runJavaScriptReturningResult
方法
// 获取 UserAgent
var userAgent = await _appBridgeController.runJavaScriptReturningResult('getUserAgent()');
两种方法的区别在于第一种通过 WebViewController
的 runJavaScript
发送消息并等待 H5 返回消息。后者直接通过 WebViewController
的 runJavaScriptReturningResult
方法获取返回值。前者更适用于多种业务场景,而后者更适合获取与窗口相关的属性。
相关文章
- 系列 1:NativeBridge:基于webivew_flutter的JSBridge插件
- 系列 2:NativeBridge:实现原理解析
- 系列 3:App实现JSBridge的最佳方案
- 系列 4:NativeBridge:我在Pub上发布的第一个插件
示例代码
以下是完整的示例代码:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:native_bridge/native_bridge.dart';
import 'package:native_bridge_example/native_bridge_controller.dart';
import 'package:native_bridge_example/utils/app_util.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized(); // 确保初始化
SystemChrome.setPreferredOrientations([ // 使设备竖屏显示
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Native Bridge',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const WebViewPage(),
);
}
}
/// 名称: WebViewPage
/// 创建者: Fitem
class WebViewPage extends StatefulWidget {
const WebViewPage({Key? key}) : super(key: key);
[@override](/user/override)
_WebViewPageState createState() => _WebViewPageState();
}
class _WebViewPageState extends State<WebViewPage> {
late final WebViewController _controller;
late final AppBridgeController _appBridgeController;
[@override](/user/override)
void initState() {
super.initState();
// 初始化 WebViewController
_controller = WebViewController()
..enableZoom(true)
..loadFlutterAsset('assets/test/index.html');
// 初始化 AppBridgeController
_appBridgeController = AppBridgeController(_controller);
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Native Bridge'),
actions: [
PopupMenuButton(itemBuilder: (context) {
return [
const PopupMenuItem<int>(
value: 0,
child: Text('App获取H5数据'),
),
const PopupMenuItem<int>(
value: 1,
child: Text('App获取H5数据(直接获取)'),
)
];
}, onSelected: (value) async {
switch (value) {
case 0:
bool? isHome = await _appBridgeController.sendMessage(Message(api: 'isHome'));
AppUtil.show('isHome:$isHome');
break;
case 1:
var userAgent = await _appBridgeController.runJavaScriptReturningResult('getUserAgent()');
AppUtil.show('userAgent:$userAgent');
break;
}
})
],
),
body: WebViewWidget(controller: _controller),
);
}
}
更多关于Flutter原生功能交互插件native_bridge的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter原生功能交互插件native_bridge的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter项目中使用native_bridge
插件来实现原生功能交互的代码案例。native_bridge
插件允许你在Flutter应用中调用原生(iOS和Android)代码。
首先,确保你已经在Flutter项目中添加了native_bridge
依赖。在你的pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter:
sdk: flutter
native_bridge: ^x.y.z # 请替换为最新版本号
然后运行flutter pub get
来安装依赖。
1. 配置原生代码
iOS
在ios/Runner
目录下,打开AppDelegate.swift
或AppDelegate.m
文件,并添加以下代码来注册原生方法:
Swift:
import UIKit
import Flutter
import native_bridge
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
// 注册原生方法
NativeBridge.register(name: "showAlert", handler: { (args, reply) in
let message = args["message"] as? String ?? "Default message"
let alert = UIAlertController(title: "Alert", message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: true, completion: nil)
reply(["status": "success"])
})
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
Objective-C:
如果你使用的是Objective-C,则需要添加Objective-C版本的注册代码。
Android
在android/app/src/main/kotlin/.../MainActivity.kt
(如果你使用的是Kotlin)或android/app/src/main/java/.../MainActivity.java
(如果你使用的是Java)中,添加以下代码来注册原生方法:
Kotlin:
package com.example.yourapp
import android.app.AlertDialog
import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterActivity() {
private val CHANNEL = "com.example.yourapp/channel"
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
GeneratedPluginRegistrant.registerWith(flutterEngine)
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
if (call.method == "showAlert") {
val message = call.argument<String>("message") ?: "Default message"
showAlert(message)
result.success(mapOf("status" to "success"))
} else {
result.notImplemented()
}
}
}
private fun showAlert(message: String) {
AlertDialog.Builder(this)
.setTitle("Alert")
.setMessage(message)
.setPositiveButton("OK") { _, _ -> }
.show()
}
}
Java:
package com.example.yourapp;
import android.app.AlertDialog;
import android.os.Bundle;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;
import java.util.HashMap;
import java.util.Map;
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "com.example.yourapp/channel";
@Override
public void configureFlutterEngine(FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
GeneratedPluginRegistrant.registerWith(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler(
(call, result) -> {
if (call.method.equals("showAlert")) {
String message = call.argument("message");
if (message == null) {
message = "Default message";
}
showAlert(message);
Map<String, String> response = new HashMap<>();
response.put("status", "success");
result.success(response);
} else {
result.notImplemented();
}
}
);
}
private void showAlert(String message) {
new AlertDialog.Builder(this)
.setTitle("Alert")
.setMessage(message)
.setPositiveButton("OK", (dialog, which) -> {})
.show();
}
}
2. 在Flutter中调用原生方法
在你的Flutter项目中,你可以使用MethodChannel
来调用已经注册的原生方法。以下是一个简单的示例:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
static const platform = MethodChannel('com.example.yourapp/channel');
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Native Bridge Example'),
),
body: Center(
child: ElevatedButton(
onPressed: _showNativeAlert,
child: Text('Show Native Alert'),
),
),
),
);
}
Future<void> _showNativeAlert() async {
try {
final Map<String, dynamic> result = await platform.invokeMethod('showAlert', <String, dynamic>{'message': 'Hello from Flutter!'});
print(result); // 打印原生方法返回的结果
} on PlatformException catch (e) {
print("Failed to invoke: '${e.message}'.");
}
}
}
以上代码展示了如何在Flutter中调用原生方法,并在iOS和Android平台上分别实现该方法。确保你已经按照平台要求正确配置了原生代码,并在Flutter中通过MethodChannel
进行了调用。