本文背景#
最近 uni-app x 發布了全新版本,其中有一點是 uni-app x 4.25 支持原生混編了,也就是可以直接使用 kotlin/java/swift 代碼了,客戶端原生大佬們可以火力全開了!
新增 編譯器 uts 插件支持 Kotlin、Java、Swift 代碼混編
很多人和我一樣,需要使用 uni-app x 開發 app,但對客戶端原生開發 (後面統一叫 “原生開發”) 比較陌生,又不熟悉相關領域知識。可以借助 UTS 語言來進行原生功能開發。
也有很多原生開發老手參與開發 uni-app x,熟悉原生開發的各種底層細節,更傾向於使用已有的原生開發經驗。
兩個不同的人群需求不同,會有一些不同角度的產品建議反饋:
- 前端反饋實現頁面佈局、業務開發快,但是原生開發不熟,有問題解決不了
- 原生開發反饋,希望復用已有的原生 SDK、原生工具包
大家的目標是一樣的,加速 app 開發落地,早完工不加班!
本文簡單介紹原生混編的基礎概念、相關用法、進階提升等。
為什麼會有原生混編?#
這個功能目標群體是誰,有什麼用,對我有影響嗎?
uni-app x 開發應用,以往要實現業務邏輯,調用原生功能時之前需要使用 UTS 語言來編寫兼容代碼,通過編譯器來轉換成 Kotlin 和 Swift。
這對前端同學比較友好:因為 UTS 的語法是和 TS 很像,只要知道原生怎麼寫,轉換一下就可以上手了。實現了讓前端工程師有能力調用客戶端原生功能。
另一方面,對原生開發老手來說就有需要吐槽的地方了,還要額外學習 UTS 和 UTS 插件等東西,希望可以復用以後的原生開發知識。
這次更新就支持了在 UTS 插件中使用原生混編功能。這裡舉一個例子來進行說明。
關聯文章:
- [[如何快速學習和測試 Swift 和 UIKit 代碼?]]
- [[如何快速學習和測試 Android Kotlin 代碼?]]
這裡以 iOS 為主要介紹平台,安卓大同小異,為了一致的閱讀體驗,在文章的末尾放出安卓相關代碼。
新概念主要先看思路。
iOS 裡查詢當前電量#
熟悉 uni-app x 的用戶可能聽過好幾次查詢當前手機電量的案例了,沒辦法這個是在太經典了。
假設現在我要求在 app 查詢當前手機電量,如果當前電量比較高,比如 80% 以上時候 app 應用就使用高級動畫,低於這個值就開啟普通動畫。
如果使用 uni-app x 獲取當前手機電量,這個需求是一個原生需求,需要調用客戶端的 api 來獲取。這個需求 uni-app x 已經封裝好了這個 api,直接使用 uni.getBatteryInfo
就得到了。
這裡我們假裝沒有,需要自己實現。
iOS 原生代碼舉例#
可以通過問原生同事、問 AI、翻閱 uni-app x 的開源代碼,得知 iOS 查詢電量的邏輯是這樣。
import UIKit
func getBatteryLevel() -> Float {
// 開啟電池監測
UIDevice.current.isBatteryMonitoringEnabled = true
// 獲取當前電量
let batteryLevel = UIDevice.current.batteryLevel
// 轉換為百分比
return batteryLevel * 100
}
// 獲取電量並打印·
let currentBatteryLevel = getBatteryLevel()
print("當前電量: \(currentBatteryLevel)%")
在混編開發之前#
在 uni-app x 支持混編功能之前,我們需要使用 UTS 翻譯以上代碼,通過 UTS 編譯器轉為原生:知道原生如何寫 - 翻譯為 UTS - 翻譯為 Swift。
UTS 代碼大致如下,刪除了函數導出、格式化等邏輯。
import { UIDevice } from "UIKit";
UIDevice.current.isBatteryMonitoringEnabled = true
const batteryLevel = Number(UIDevice.current.batteryLevel * 100)
通過講邏輯拆分為 UTS 插件,在編譯時候通過 UTS 編譯器轉換為 Swift 代碼。
這裡安卓平台導入包的過程不完全一樣,一般推薦的做法還是按照平台拆分實現功能。
在混編開發之後#
有了原生混編,很多事情就簡單多了。這裡如果你對 UTS 開發插件還不熟悉,可以參考 [[新手向:包裝 UTS 插件]],主要介紹了 UTS 插件如何開發。本文主要展示混編的大致思路,細節不一一展開了。
經典的 UTS 插件目錄結構是
uni_modules
- webworker-batteryStatus
-- utssdk
--- app-ios
---- index.uts
-- package.json
在 UTS 插件的 app-ios/index.uts
中新建 NativeCode.swift
,人如其名,這個文件是原生 swift
文件。
NativeCode.swfit
文件內容如下,這是官方推薦的一種寫法。
import UIKit
public class NativeCode {
static func getBatteryLevelSwift() -> Float {
// 開啟電池監測
UIDevice.current.isBatteryMonitoringEnabled = true
// 獲取當前電量
let batteryLevel = UIDevice.current.batteryLevel
// 轉換為百分比
return batteryLevel * 100
}
}
在 UTS 中如何調用?
index.uts
代碼如下
export function getBatteryLevelSwift() : Float {
return NativeCode.getBatteryLevelSwift()
}
使用就很簡單了,引用包,調用方法即可。
<template>
<view>
<view>{{currentLevel}}</view>
<button @click="getLevel"> 電量</button>
</view>
</template>
<script setup>
import { getBatteryLevelSwift } from '../../uni_modules/webworker-batteryLevel'
const currentLevel = ref(0)
const getLevel = () => {
console.log('click button')
// console.log(getBatteryLevelSwift())
const res = getBatteryLevelSwift()
currentLevel.value = res
}
</script>
通過
- 原生開發邏輯
- uts 包裝邏輯
- uvue 中調用
可以輕鬆實現混編開發。
安卓實現混編#
和 iOS 類似,也是在 uni_moduels 的 app-android
目錄添加 index.uts
和 NativeCode.kt
其中 NativeCode.kt
內容大致
package uts.sdk.modules.ottoBatteryLevel;
import android.content.Context
import android.os.BatteryManager
object NativeCode {
fun getBatteryLevel(context: Context): Int {
val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
val batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
return batteryLevel
}
}
其中 index.uts
內容如下
import Context from "android.content.Context";
export function getBatteryLevel() : Int {
const context = UTSAndroid.getAppContext()!;
return NativeCode.getBatteryLevel(context)
}
其他部分和 ios 一致,在 uvue 調用 uts 插件。
接下來做什麼?#
希望通過這篇文章介紹,可以讓你對 UTS 插件開發、原生混編、uni-app x 開發有進一步的理解。
有了大殺器可以探索更多內容了。接下來可以做什麼?
官方的 demo 實現學習更多細節#
官方開源了 hello uts 倉庫,可以從這個案例了解更多細節。
uni_modules/uts-tests/utssdk/NativeCode.uts · dev · DCloud / Hello UTS · GitCode
官方文檔了解更多技術細節#
詳細說明了原生混編的來龍去脈,更加詳細。
https://doc.dcloud.net.cn/uni-app-x/plugin/uts-plugin-hybrid.htm
學習 uts 插件開發#
參考 《[[新手向:包裝 UTS 插件]]》