Flutter原生功能交互插件native_bridge的使用

发布于 1周前 作者 phonegap100 来自 Flutter

Flutter原生功能交互插件native_bridge的使用

NativeBridge 是一个基于 webview_flutter 的插件,实现了 App 和 H5 之间的 JSBridge 方法调用能力。

NativeBridge 的优点

  1. 支持 H5 调用 App 中的 JSBridge 方法,并可以直接获取返回值。
  2. 支持 App 调用 H5 的 JSBridge 方法,并可以直接获取返回值。
  3. 使用简单,集成后可以通过扩展 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 的值

通过 AppBridgeControllersendMessage 方法

// 是否为首页
bool? isHome = await _appBridgeController.sendMessage(Message(api: 'isHome'));

通过 AppBridgeControllerrunJavaScriptReturningResult 方法

// 获取 UserAgent
var userAgent = await _appBridgeController.runJavaScriptReturningResult('getUserAgent()');

两种方法的区别在于第一种通过 WebViewControllerrunJavaScript 发送消息并等待 H5 返回消息。后者直接通过 WebViewControllerrunJavaScriptReturningResult 方法获取返回值。前者更适用于多种业务场景,而后者更适合获取与窗口相关的属性。

相关文章


示例代码

以下是完整的示例代码:

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

1 回复

更多关于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.swiftAppDelegate.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进行了调用。

回到顶部