前端 使用Uniapp与安卓/IOS混合交互开发

发布于:2025-03-17 ⋅ 阅读:(18) ⋅ 点赞:(0)

场景描述: 公司经常为了加快项目的推进,常常需要咱们前端写一些H5页面嵌入到原生的APP开发当中去,例如
调用设备的摄像头、地理位置、文件系统、显示原生的对话框、提示框等,以提供更好的用户体验。
疑难问题:如何和安卓/IOS产生交互…

前言:

uni.getSystemInfoSync().platform:Uni-app 框架中用于获取当前运行平台信息的同步方法。它返回一个字符串,表示当前应用运行的操作系统平台。

uni.getSystemInfoSync().platform获取平台信息
返回值可以是以下几种之一:
android:表示当前设备是安卓系统。
ios:表示当前设备是iOS系统。
devtools:表示当前是在开发者工具中运行。
其他平台:如微信小程序、H5等,具体取决于Uni-app支持的平台。

安卓与H5混合开发流程

  1. 安卓WebView 注入
    window.安卓提供方法名 调用 Android 原生方法并传递参数(如 android.args)是通过 WebView 和 JavaScript Bridge 实现的。
    安卓人员在 WebView 中注入一个 Java 对象(即代码中的Android),并通过 addJavascriptInterface 方法将该对象暴露给 JavaScript 环境。
    // 在 Android 原生代码中设置 WebView 并注入 JavaScript Interface
	WebView webView = findViewById(R.id.webview);
	webView.getSettings().setJavaScriptEnabled(true);
	// 创建一个 Java 类来处理 JavaScript 的调用
	webView.addJavascriptInterface(new WebAppInterface(this), "Android"); // 安卓类的名称Android
	public class WebAppInterface {
	    Context mContext;
	    WebAppInterface(Context c) {
	        mContext = c;
	    }
	    @JavascriptInterface // 该类包含需要暴露给 JavaScript 的方法,
	    public String doSomething(String args) { //方法名称
	        // 处理传入的参数并返回结果
	        return "Result from Android: " + args;
	    }
	}
  1. 前端 JavaScript 调用
    window.className [ android.name方法名 ] (android.args传递参数)
if (window.rentalAndroid) {
    const result = window.rentalAndroid.doSomething('someArgument'); // 调用方法类并传参
    console.log(result); // 输出 "Result from Android: someArgument"
} else {
    console.error('获取 android 事件对象失败');
}

IOS与H5混合开发流程

  1. IOS设置 WKWebViewWKScriptMessageHandler
    首先,在 iOS 原生代码中设置 WKWebView 并注册 WKScriptMessageHandler,以便处理来自 JavaScript 的消息。
import WebKit
class ViewController: UIViewController, WKScriptMessageHandler {
    var webView: WKWebView!
    override func viewDidLoad() {
        super.viewDidLoad()
        // 创建 WKWebView 配置
        let config = WKWebViewConfiguration()
        config.userContentController.add(self, name: "nativeHandler")
        // 初始化 WKWebView
        webView = WKWebView(frame: self.view.frame, configuration: config)
        self.view.addSubview(webView)
        // 加载 H5 页面
        if let url = URL(string: "https://example.com") { // H5页面链接
            let request = URLRequest(url: url)
            webView.load(request)
        }
    }
    // 处理来自 JavaScript 的消息
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if message.name == "nativeHandler" { //IOS定义方法名称
            if let args = message.body as? [String: Any] {
                // 处理传入的参数
                handleNativeCall(args: args)
            }
        }
    }
    // 处理具体的原生方法调用
    func handleNativeCall(args: [String: Any]) {
        if let action = args["action"] as? String {
            switch action {
            case "doSomething": // 定义类别
                if let param = args["param"] as? String {
                    // 处理参数并执行相应操作
                    print("Received parameter: \(param)")
                    // 返回结果给 JavaScript
                    let result = "Result from iOS: \(param)"
                    webView.evaluateJavaScript("window.postMessage('\(result)', '*')")
                }
            default:
                print("Unknown action: \(action)")
            }
        }
    }
}

  1. 前端JavaScript 调用
    在前端代码中,你可以通过 window.webkit.messageHandlers 发送消息到原生代码。
 const messageBody = {
    action: ios.name,
    param: ios.args || null
};
// 发送消息到原生代码
window.webkit.messageHandlers.nativeHandler.postMessage(messageBody);

使用js封装调用安卓、IOS方法

platformHandler 是一个封装方法,接收一个对象参数,包含以下属性:
android: 对应安卓平台的方法配置。
ios: 对应iOS平台的方法配置。
success: 成功回调函数。
fail: 失败回调函数。

如果是Android平台:
检查是否提供了有效的Android方法配置 (android.name)。
使用 window.rentalAndroid 调用Android原生方法,并传递参数 (android.args)。
如果成功调用,将结果传递给 success 回调;否则,显示错误提示并执行 fail 回调。

如果是iOS平台:
检查是否提供了有效的iOS方法配置 (ios.name)。
使用 window.webkit.messageHandlers 调用iOS原生方法,并传递参数 (ios.args)。
如果成功调用,执行 success 回调;否则,显示错误提示并执行 fail 回调。

1. 封装方法+平台判断

const platform = uni.getSystemInfoSync().platform; // 获取平台信息
// 判断平台
function isIOS() {
	return platform === 'ios';
}
function isAndroid() {
	return platform === 'android';
}

function platformHandler({
	android,
	ios,
	success,
	fail
}) {
	if (isIOS()) {
		// console.log('调用ios函数')
		if (!ios || !ios.name) return $mHelper.toast('未添加相应的ios方法');
		if (window.webkit && window.webkit.messageHandlers) {
			window.webkit.messageHandlers[ios.name].postMessage(ios.args || null);
			if (success) success();
		} else {
			$mHelper.toast('获取ios事件对象失败');
			if (fail) fail()
		}
		// document.location = 'buyCar://appointment?arg1=1号参数&arg2=2号参数'
	} else if (isAndroid()) {
		if (!android || !android.name) return $mHelper.toast('未添加相应的android方法');
		if (window.rentalAndroid) { // rentalAndroid 安卓命名定义
		const result = (android.args || android.args === 0) ? window.rentalAndroid[android.name](android.args): window.rentalAndroid[android.name]();
			if (success) success(result);
		} else {
			$mHelper.toast('获取android事件对象失败');
			if (fail) fail();
		}
	}
}
// 单独暴露
export platformHandler

2. 调用封装的方法

	platformHandler({
	   	android: {
	   		name: 'mapNavigation', // 方法名
	   		args: startString // 参数-- 需要安卓定义好格式,可能不能传递对象结构数据等
	   	},
	   	ios: {
	   		name: 'mapNavigation',
	   		args: startString 	
	    })

3. 扩展

全局挂载该封装文件的方法platformHandler

  1. 直接挂载
    在 Vue 项目的入口文件(通常是 main.js 或 main.ts)中,将对应的方法挂载到 Vue 的原型上,使其成为全局可用的方法。
    直接挂载:是指在 Vue 的原型(Vue.prototype)上直接添加属性或方法,而不需要通过插件机制。
    main.js
import { platformHandler } from '/untils/platformFn'
Vue.prototype.$platformHandler  = platformHandler 
  1. 插件注册(Vue.use)引入全局
    封装的方法相当于插件,可以通过 Vue.use(more) 将插件注册到 Vue 实例中,使其在全局范围内可用。

插件:通常是一个对象,包含一个函数。函数方法会在 Vue.use 调用时执行。

① 定义一个插件

more.js

function isIOS() {
	return platform === 'ios';
}
function isAndroid() {
	return platform === 'android';
}
export defalut function(Vue){
	Vue.prototype.$isIOS = isIOS();
	Vue.prototype.$isAndroid = isAndroid();
	Vue.prototype.$iosStatusHeight = 44; // px
	Vue.prototype.$androidStatusHeight = 20; // px
}
② 注册插件

在 Vue 项目的入口文件(如 main.js)中使用 Vue.use 注册插件。
main.js

import more from '/untils/more'
Vue.use(more)
  1. 引用该方法
this.$platformHandler({
   	android: {
   		name: 'mapNavigation', // 方法名
   		args: startString // 参数-- 需要安卓定义好格式,可能不能传递对象结构数据等
   	},
   	ios: {
   		name: 'mapNavigation',
   		args: startString 	
})

this.$isIOS
this.$iosStatusHeight 

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到