更多方法交流可以家魏鑫:lixiaowu1129,一起探讨iOS相关技术!
需求分析:
最近项目需求需要麦克风录音权限,因为整体上的UI界面是前端wkwebview搭建的,实现功能逻辑是由iOS实现,没有用原生!然后就出现了需要麦克风录音机跟H5交互的功能模块!
查了资料都文章说iOS对h5交互麦克风录音不友好
现在具体工作流程步骤如下:
- 首先创建了一个wkwebview
//加载webview视图
override func loadView() {
let preference = WKPreferences()
preference.minimumFontSize = 0
preference.javaScriptEnabled = true
preference.javaScriptCanOpenWindowsAutomatically = true
preference.setValue("TRUE", forKey: "allowFileAccessFromFileURLs")
debugPrint("这里已经进来了")
// swift 提供给 h5 调用方法
let userContentController = WKUserContentController()
userContentController.add(self, name: "callAudio") //调起iOS音频权限
userContentController.add(self, name: "recorderStart") //开始录音
userContentController.add(self, name: "recorderStop") //停止录音
let conf = WKWebViewConfiguration()
conf.userContentController = userContentController
conf.preferences = preference
// let conf = WKWebViewConfiguration();
// conf.userContentController.add(self, name: "callAudio") //调起iOS音频权限
// conf.userContentController.add(self, name: "recorderStart") //开始录音
// conf.userContentController.add(self, name: "recorderStop") //停止录音
webView = WKWebView(frame: CGRect(x:0, y:0, width:SCREEN_WIDTH, height:SCREEN_HEIGHT), configuration: conf)
webView.navigationDelegate = self;
webView.scrollView.isScrollEnabled = false //禁止webview滑动滚动
if #available(iOS 11.0, *) {
webView.scrollView.contentInsetAdjustmentBehavior = .never;
}
view = webView;
}
其中:callAudio、recorderStart、recorderStop是iOS跟webview定义好协议接收的方法
2. **重点:**加载完成后接收H5调用的协议方法:
// 接受 h5 调用
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
guard let name = message.value(forKey: "name") as? String, let body = message.value(forKey: "body") as? String else { return }
debugPrint("测试链接8888+:\(name)")
if name == "callAudio" {
SystemAuth.authMicrophone { result in
if result{
self.webView.evaluateJavaScript("getPermission('\(result)')", completionHandler: nil)
}else{
DispatchQueue.main.async {
let alertView = UIAlertView(title: "无法访问您的麦克风" , message: "请到设置 -> 隐私 -> 麦克风 ,打开访问权限", delegate: nil, cancelButtonTitle: "取消", otherButtonTitles: "好的")
alertView.show()
}
}
}
}
}
SystemAuth.authMicrophone 调用录音麦克风权限返回true跟false
self.webView.evaluateJavaScript(“getPermission(’(result)’)”, completionHandler: nil) iOS拦截到方法注入新方法getPermission()携带参数true或者false返回给H5接收
Swift开启iOS的录音权限包括其他照相机权限的代码文件
我整理好在下面的代码了
SystemAuth.Swift
//
// SystemAuth.swift
// Authorization
//
// Created by 柯南 on 2020/9/4.
// Copyright © 2020 LTM. All rights reserved.
//
import UIKit
/// 媒体资料库/Apple Music
import MediaPlayer
import Photos
import UserNotifications
import Contacts
/// Siri权限
import Intents
/// 语音转文字权限
import Speech
/// 日历、提醒事项
import EventKit
/// Face、TouchID
import LocalAuthentication
import HealthKit
import HomeKit
/// 运动与健身权限
import CoreMotion
/// 防止获取无效 计步器
private let cmPedometer = CMPedometer()
typealias AuthClouser = ((Bool)->())
/// 定义私有全局变量,解决在iOS 13 定位权限弹框自动消失的问题
private let locationAuthManager = CLLocationManager()
/**
escaping 逃逸闭包的生命周期:
1,闭包作为参数传递给函数;
2,退出函数;
3,闭包被调用,闭包生命周期结束
即逃逸闭包的生命周期长于函数,函数退出的时候,逃逸闭包的引用仍被其他对象持有,不会在函数结束时释放
经常使用逃逸闭包的2个场景:
异步调用: 如果需要调度队列中异步调用闭包,比如网络请求成功的回调和失败的回调,这个队列会持有闭包的引用,至于什么时候调用闭包,或闭包什么时候运行结束都是不确定,上边的例子。
存储: 需要存储闭包作为属性,全局变量或其他类型做稍后使用,例子待补充
*/
public class SystemAuth {
// /**
// 媒体资料库/Apple Music权限
//
// - parameters: action 权限结果闭包
// */
// class func authMediaPlayerService(clouser :@escaping AuthClouser) {
// let authStatus = MPMediaLibrary.authorizationStatus()
// switch authStatus {
// /// 未作出选择
// case .notDetermined:
// MPMediaLibrary.requestAuthorization { (status) in
// if status == .authorized{
// DispatchQueue.main.async {
// clouser(true)
// }
// }else{
// DispatchQueue.main.async {
//