先說一下項目背景惜颇,
uni-app
開發(fā)同事已經(jīng)寫好的項目汽畴,需要用到一個iOS原生的視頻上傳SDK,uni-app
開發(fā)同事將錄制好的視頻路徑從uni-app
傳遞給iOS原生坏匪,iOS原生使用視頻上傳SDK將視頻上傳成功以后淘这,需要在回調(diào)中再將參數(shù)回傳給uni-app
剥扣。
這里我分為幾個階段去進(jìn)行講解
一、項目配置修改
可以先看一下uni官方的集成教程铝穷。
安裝完所需要的編輯器以后钠怯,需要下載App離線SDK。
找到App離線SDK壓縮包曙聂,解壓后進(jìn)入目錄晦炊,找到HBuilder-Hello
文件夾,打開原生工程宁脊,然后準(zhǔn)備配置工程断国。
HBuilder-Hello
文件夾下的打包工程 是按照uni-app
項目來配置的,所以基礎(chǔ)配置不需要動榆苞。
SDK目錄說明
|-- HBuilder-Hello 給用戶打uni-app項目的離線打包工程
|-- Feature-iOS.xls 配置表(依賴的庫稳衬、資源文件、參數(shù)配置等)
|-- SDK 工程需要的庫文件坐漏,.h頭文件薄疚,配置文件,資源文件
打開項目后赊琳,bundle ID
無法修改街夭,需要在signing & Capabilities
中修改Team
和 bundle ID
。
修改完以后慨畸,debug
這里產(chǎn)生了這樣的警告莱坎。
HBuilder has conflicting provisioning settings.
HBuilder is automatically signed, but provisioning profile a7e03077-46db-4b91-b0c4-20fd613c1e14 has been manually specified. Set the provisioning profile value to "Automatic" in the build settings editor, or switch to manual signing in the Signing & Capabilities editor.
修復(fù)方式很簡單,將警告圖中選中的這段標(biāo)識復(fù)制寸士,然后在build setting
里面搜索檐什,找到以后刪除掉這段內(nèi)容。
release
這里也有一個警告
HBuilder has conflicting provisioning settings.
HBuilder is automatically signed for development, but a conflicting code signing identity iPhone Distribution has been manually specified. Set the code signing identity value to "Apple Development" in the build settings editor, or switch to manual signing in the Signing & Capabilities editor.
解決方式也很簡單弱卡,在build setting
中搜索 signing
乃正,將code signing identity
全部改為 apple development
,然后關(guān)閉項目重新打開就可以了婶博。
3.1.10版本起需要申請Appkey,先去申請Appkey
申請成功后瓮具,打開info.plist
創(chuàng)建key
為dcloud_appkey
,Value
選擇String
類型凡人,內(nèi)容為申請的AppKey
用離線打包工程制作自定義調(diào)試基座
1名党、在打包原生工程里找到control.xml
文件,在HBuilder節(jié)點里查看是否有這2個: debug="true" syncDebug="true"
配置(注意打AppStore包的時候挠轴,這個配置需要去掉传睹,否則會導(dǎo)致熱更新失敗岸晦!)欧啤,沒有的話增加上,然后保存启上。
2邢隧、 確保Xcode工程的Bundle identifier
不為 io.dcloud.HBuidler
。
3冈在、在原生工程里找到info.plist
文件并增加一項倒慧,如下圖:
4、確保原生工程里Pandora文件夾下的apps文件夾里只有一個文件夾(文件夾的名稱和里面的manifest的id值相同)
5包券、確保control.xml
文件里的appid的值和apps目錄下的第一個文件夾的名稱一致
6迫靖、確保HBuilderX里要調(diào)試的代碼的appid和control.xml
的appid值一致
7、使用Xcode的Product下的archive 打包兴使,然后生成ipa系宜,并把ipa名稱命名為:iOS_debug.ipa
。
8发魄、在js工程里主目錄下新建一個名稱為unpackage
的文件夾(如果有不用新建)盹牧,再在unpackage
文件夾下新建一個名稱為debug
文件夾,并把生成的iOS_debug.ipa
包放入debug
文件夾励幼。
9汰寓、在HBuildX里,找到之前appid相同的js工程準(zhǔn)備調(diào)試苹粟,點擊“運行” --“運行到手機(jī)或模擬器“--“使用自定義基座運行(iOS)”有滑,等待連接成功之后就可以了。
10嵌削、連接手機(jī)毛好,編譯運行望艺,如果App成功跑起來了,說明原生工程配置完成肌访。
然后在HBuilderX中找默,選中項目文件夾,右鍵選擇發(fā)行->原生APP本地打包->生成本地打包App資源
等待HBuilderX編譯成功以后會在控制臺輸出生成的資源路徑吼驶,點擊路徑就能看到和一個和iOS原生工程里Pandora文件夾下的apps文件夾里一個同名的文件夾文件夾
然后我們將iOS項目目錄下的 Pandora -> apps
路徑下的這個文件夾刪除掉惩激,替換成資源路徑里的文件夾。刪除掉手機(jī)里的舊程序蟹演,就可以運行了风钻。
這里需要注意,前端代碼修改后重新導(dǎo)入資源時酒请,需要在xcode工程中刪除之前導(dǎo)入的資源骡技,同時將手機(jī)里的舊App程序刪除,防止因為緩存問題導(dǎo)致加載的還是舊的資源
二蚌父、集成所需視頻上傳SDK
這部分沒什么太多可講的內(nèi)容哮兰,主要就是SDK集成,但是這里遇到一個集成的問題需要注意一下苟弛。
集成完以后喝滞,編譯會報錯
解決方法如圖,在 other linker flags
里面添加一行 $(inherited)
膏秫。
還有另一個報錯右遭,bitcode bundle could not be generated because
解決操作為在Build Settings
中搜索Enable Bitcode
,將值設(shè)置為No
;
然后在Project-> Targets-> Build Settings-> Custom Compiler Flags-> Other C Flags
添加一行缤削,內(nèi)容為 "-fembed-bitcode"
三窘哈、兩平臺交互
uni官方的原生插件教程
uni原生插件指的是將您原生開發(fā)的功能按照規(guī)范封裝成插件包,然后即可在 uni-app
前端項目中通過js調(diào)用您開發(fā)的原生能力亭敢。
原生插件是基于
DCUniPlugin
規(guī)范來實現(xiàn)滚婉,擴(kuò)展原生功能有兩種方式:
module
:不需要參與頁面布局,只需要通過 API 調(diào)用原生功能帅刀,比如:獲取當(dāng)前定位信息让腹、數(shù)據(jù)請求等功能,通過擴(kuò)展module
的方式來實現(xiàn)扣溺;
component
:需要參與頁面布局骇窍,比如:map、image等需要顯示UI的功能锥余,通過擴(kuò)展component
即組件的方法來實現(xiàn)腹纳;
這里我們只是用了視頻上傳功能,和頁面布局沒有關(guān)系,所以使用module
就足夠了嘲恍。
在iOS原生平臺暴露接口給uni-app
新建AppModule
類足画,繼承 DCUniModule
,引入 DCUniModule.h
頭文件蛔钙。
#import <Foundation/Foundation.h>
// 引入 DCUniModule.h 頭文件
#import "DCUniModule.h"
@interface AppModule : DCUniModule
@end
然后在 AppModule.m
文件中添加實現(xiàn)方法
異步方法實現(xiàn)
/// 異步方法(注:異步方法會在主線程(UI線程)執(zhí)行)
/// @param options js 端調(diào)用方法時傳遞的參數(shù) 支持:String锌云、Number荠医、Boolean吁脱、JsonObject 類型
/// @param callback 回調(diào)方法,回傳參數(shù)給 js 端 支持: NSString彬向、NSDictionary(只能包含基本數(shù)據(jù)類型)兼贡、NSNumber 類型
- (void)testAsyncFunc:(NSDictionary *)options callback:(UniModuleKeepAliveCallback)callback {
// options 為 js 端調(diào)用此方法時傳遞的參數(shù) NSLog(@"%@",options); // 可以在該方法中實現(xiàn)原生能力,然后通過 callback 回調(diào)到 js
if (callback) {
// 第一個參數(shù)為回傳給js端的數(shù)據(jù)娃胆,第二個參數(shù)為標(biāo)識遍希,表示該回調(diào)方法是否支持多次調(diào)用,如果原生端需要多次回調(diào)js端則第二個參數(shù)傳 YES;
callback(@"success",NO);
}
}
通過宏 UNI_EXPORT_METHOD
將異步方法暴露給 js 端里烦,只有通過UNI_EXPORT_METHOD
暴露的原生方法才能被 js 端識別到
// 通過宏 UNI_EXPORT_METHOD 將異步方法暴露給 js 端
UNI_EXPORT_METHOD(@selector(testAsyncFunc:callback:))
同步方法實現(xiàn)
/// 同步方法(注:同步方法會在 js 線程執(zhí)行)
/// @param options js 端調(diào)用方法時傳遞的參數(shù) 支持:String凿蒜、Number、Boolean胁黑、JsonObject 類型
- (NSString *)testSyncFunc:(NSDictionary *)options {
// options 為 js 端調(diào)用此方法時傳遞的參數(shù)
NSLog(@"%@",options);
/*
可以在該方法中實現(xiàn)原生功能废封,然后直接通過 return 返回參數(shù)給 js
*/
// 同步返回參數(shù)給 js 端 支持:NSString、NSDictionary(只能包含基本數(shù)據(jù)類型)丧蘸、NSNumber 類型
return @"success";
}
通過宏 UNI_EXPORT_METHOD_SYNC
將同步方法暴露給 js 端
// 通過宏 UNI_EXPORT_METHOD_SYNC 將同步方法暴露給 js 端
UNI_EXPORT_METHOD_SYNC(@selector(testSyncFunc:))
如果需要在 App 啟動時初始化或者需要獲取系統(tǒng)的一些事件漂洋, 需要新建一個XXXXProxy
類(注意命名加前綴防止沖突),繼承 NSObject
遵守UniPluginProtocol
協(xié)議力喷。這個功能項目中沒有用到刽漂,不在此贅述。如有需求弟孟,可以查看官方教程相關(guān)內(nèi)容贝咙。
配置插件信息
選中工程中的HBuilder-uniPlugin-Info.plis
t文件右鍵Open As->Source Code
找到dcloud_uniplugins
節(jié)點,拷貝下面的內(nèi)容添加到dcloud_uniplugins
節(jié)點下拂募,按您插件的實際信息填寫對應(yīng)的項
<dict>
<key>hooksClass</key>
<string>填寫 hooksClass 類名 </string>
<key>plugins</key>
<array>
<dict>
<key>class</key>
<string>填寫 module 或 component 的類名</string>
<key>name</key>
<string>填寫暴露給js端對應(yīng)的 module 或 component 名稱</string>
<key>type</key>
<string>填寫 module 或 component</string>
</dict>
</array>
</dict>
如果不在HBuilder-uniPlugin-Info.plist
正確配置這些鍵值對庭猩,手機(jī)運行以后,控制臺會報警告
<Weex>[warn]WXBridgeContext.m:1310, jsLog: [JS Framework] 當(dāng)前運行的基座不包含原生插件[HBuilder-Hello-AppModule]没讲,請在manifest中配置該插件眯娱,重新制作包括該原生插件的自定義運行基座 __WARN
在 uni-app 項目中調(diào)用 module 方法
<template>
<div>
<button type="primary" @click="testAsyncFunc">testAsyncFunc</button>
<button type="primary" @click="testSyncFunc">testSyncFunc</button>
</div>
</template>
<script>
// 首先需要通過 uni.requireNativePlugin("ModuleName") 獲取 module
var testModule = uni.requireNativePlugin("HBuilder-Hello-AppModule")
export default {
methods: {
testAsyncFunc() {
// 調(diào)用異步方法
testModule.testAsyncFunc({
'name': 'uni-app',
'age': 1
},
(ret) => {
uni.showToast({
title:'調(diào)用異步方法 ' + ret,
icon: "none"
})
})
},
testSyncFunc() {
// 調(diào)用同步方法
var ret = testModule.testSyncFunc({
'name': 'uni-app',
'age': 1
})
uni.showToast({
title:'調(diào)用同步方法 ' + ret,
icon: "none"
})
}
}
}
</script>
這個時候我們就可以按照上面已經(jīng)說過的方法生成 uni-app
項目的本地打包資源,將資源放入到xcode中的相應(yīng)路徑下爬凑,測試uni-app
調(diào)用iOS原生功能是否正常了徙缴。
番外篇
當(dāng)在手機(jī)成功運行以后,需要調(diào)用相機(jī)錄制視頻,點擊錄制按鈕調(diào)用相機(jī)功能時于样,出現(xiàn)HTML5+Runtime打包時未添加Camera模塊
彈窗警告且相機(jī)不能正常調(diào)用,這是因為調(diào)用了相關(guān)模塊的 API 但是原生工程沒有添加相關(guān)依賴導(dǎo)致的疏叨。
具體缺少哪個模塊,可以參考下載的SDK目錄下Feature-iOS.xls
功能模塊配置表穿剖。例如我這里是需要調(diào)用相機(jī)蚤蔓,缺少camera
模塊,那么就看camera
模塊需要配置什么糊余。
在build phases
中的link binary with libraries
中添加上缺少的六個庫文件即可秀又。
在build settings
中的other linker flags
添加一行-llibCamera
。
再次運行贬芥,相機(jī)功能可以正常調(diào)用了吐辙。
通過路徑獲取沙盒文件
這里又遇到了一個坑,當(dāng)在uni-app
中使用相機(jī)拍攝了視頻以后蘸劈,使用uni.chooseVideo
方法獲取到的視頻路徑為_doc/uniapp_temp_1655703702857/camera/video_001.mp4
,我們一眼就能看出來昏苏,這個地址肯定不是我們想要的地址,因為iOS沙盒地址不是這種格式的威沫,我們需要轉(zhuǎn)一下才能用贤惯。
//res = "_doc/uniapp_temp_1655703702857/camera/video_001.mp4";
//這樣轉(zhuǎn)換以后,就是iOS沙盒的路徑了棒掠。
var path = plus.io.convertLocalFileSystemURL(res);
如果需要需要調(diào)用uni-app
的uploadFile
方法進(jìn)行上傳孵构,需要在path
路徑前面再拼接一下
path = 'file://' + path;
如果文件名中包含中文,需要使用decodeURIComponent(path)
,將地址的url進(jìn)行反編碼句柠。