| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725 |
- //
- // MainController.swift
- //
- // Created by 方楚豪 on 2022/05/13.
- //
- import UIKit
- import WebKit
- import Foundation
- import Toast_Swift
- import ImSDK_Plus
- import QuickLook
- import MMKV
- import SwiftEntryKit
- import NotificationBannerSwift
- import Alamofire
- import swiftScan
- import SwiftGifOrigin
- import AdSupport
- import CoreLocation
- import Photos
- import TUICore
- import AVFoundation
- import YJNetManager
- import YJTaskMark
- import LGAlertHUD
- import YJExtensions
- // IMID
- #if DEBUG
- let IMID: Int32 = 33365
- #else
- let IMID: Int32 = 33364
- #endif
- // WkWebView加载地址 http://m.lancooedu.com/#/login http://isca.lancooedu.com/airobot/AndroidWeb/index.html
- #if DEBUG
- let mainUrl:String = "http://m.lancooedu.com/#/login"
- #else
- let mainUrl:String = "http://m.lancooedu.com"
- #endif
- class MainController: UIViewController,WKUIDelegate, WKNavigationDelegate, WKScriptMessageHandler,UINavigationControllerDelegate {
- var webView: WKWebView!
- var payView: WKWebView!
- var mmkv:MMKV = MMKV.default()!
- var payScheme:String = ""
- let filePath:String = NSHomeDirectory () + "/Documents/"
- var testBtn: UIButton!
- var stopTestBtn: UIButton!
- static var preViewFilePath:String = ""
- // 在线消息推送队列 实现堆叠的通知
- let bannerQueueToDisplaySeveralBanners = NotificationBannerQueue(maxBannersOnScreenSimultaneously: 3)
- let appId = "1598062593" // appId,为了跳转到App Store下载
- let imageView = UIImageView()
-
- //定位管理器
- let locationManager:CLLocationManager = CLLocationManager()
-
- private lazy var session:URLSession = {
- //只执行一次
- let config = URLSessionConfiguration.default
- // 设置超时时常 单位是s
- config.timeoutIntervalForRequest = 100
- let currentSession = URLSession(configuration: config, delegate: self,delegateQueue: nil)
- return currentSession
- }()
-
-
- var taskId:Int = 0
- var fileName:String = ""
- var uploadFileUrl:String = ""
- var uploadFileTaskId:Int = 0
- var uploadParam:UploadParam = UploadParam.init()
- var scanCodeTaskId:Int = 0
- var getLocationTaskId:Int = 0
-
- let loading = UIActivityIndicatorView()
- override func viewDidLayoutSubviews() {
- super.viewDidLayoutSubviews()
- view.bringSubviewToFront(loading)
- }
-
- var callingVC = UIViewController()
-
- var updateMessage:String = "" // 获取到的更新App的信息
- var trackViewUrlString:String = "" // 一个地址,提示用户更新的时候需要的
-
- // 加载的动态图
- var gifView = WKWebView()
-
- var soundId: SystemSoundID?
-
- override func loadView() {
- let configuration=WKWebViewConfiguration()
-
- // 为WKWebViewController设置偏好设置
- let preference = WKWebpagePreferences()
- // 允许native与js交互
- preference.allowsContentJavaScript = true
- configuration.defaultWebpagePreferences = preference
- let userContentController = WKUserContentController.init()
- userContentController.add(self, name: "IosStorage")
- userContentController.add(self, name: "IosDevices")
- userContentController.add(self, name: "IosNet")
- configuration.userContentController = userContentController
-
- configuration.allowsInlineMediaPlayback = true;
- webView = WKWebView(frame: .zero,configuration: configuration)
- webView.uiDelegate = self
- webView.navigationDelegate = self
- webView.allowsBackForwardNavigationGestures = true
- webView.scrollView.contentInsetAdjustmentBehavior = UIScrollView.ContentInsetAdjustmentBehavior.never
- view = webView
-
- // testAction()
-
- if(mmkv.contains(key: "userInfo")) {
- self.rtcLogin()
- }
- }
- func testAction() {
- testBtn = UIButton.init(frame: CGRect(x: 100, y: 200, width: 100, height: 50))
- testBtn.setTitle("测试识别", for: .normal)
- testBtn.setTitleColor(UIColor.red, for: .normal)
- testBtn.addTarget(self, action: #selector(startSpeechMark), for: .touchUpInside)
- view.addSubview(testBtn)
- stopTestBtn = UIButton.init(frame: CGRect(x: 100, y: 260, width: 100, height: 50))
- stopTestBtn.setTitle("停止测试", for: .normal)
- stopTestBtn.setTitleColor(UIColor.red, for: .normal)
- stopTestBtn.addTarget(self, action: #selector(stopSpeechMark), for: .touchUpInside)
- view.addSubview(stopTestBtn)
- }
- @objc func refuslt(){
-
- }
-
- override func viewWillAppear(_ animated: Bool) {
- self.navigationController?.navigationBar.isHidden = true
- }
-
- override func viewDidLoad() {
- super.viewDidLoad()
-
- let myURL = URL(string: mainUrl)!
- // if (mmkv.contains(key: "homeUrl")) {
- // myURL = URL(string: mmkv.string(forKey: "homeUrl")!)!
- // }
-
- let myRequest = URLRequest(url: myURL)
- self.webView.load(myRequest)
-
- self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
- if(mmkv.contains(key: "userInfo")) {
- self.rtcAuthLogin()
- }
-
- // 未读通知设置为0
- AppDelegate.unreadNumber = 0
- UIApplication.shared.applicationIconBadgeNumber = 0
-
- //设置状态监听
- NotificationCenter.default.addObserver(self, selector: #selector(appWillEnterForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
- NotificationCenter.default.addObserver(self, selector: #selector(appDidEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
-
- if (AppDelegate.PUSH_URL != nil) {
- let myURL = URL(string: AppDelegate.PUSH_URL!)!
- let myRequest = URLRequest(url: myURL)
- webView.load(myRequest)
- AppDelegate.PUSH_URL = nil
- }
-
- if mmkv.contains(key: "__APP_ONLY_LOG_SUCCESS_KEY__") {
- // 登录了
- // 判断有没有url,没有url,不做任何处理,有url,加载url
- if mmkv.contains(key: "scheme_to_url") {
- let url = mmkv.string(forKey: "scheme_to_url")!
- let myURL = URL(string: url)!
- let myRequest = URLRequest(url: myURL)
- webView.load(myRequest)
- mmkv.removeValue(forKey: "scheme_to_url")
- }else {
-
- }
- }else {
- // 未登录
- }
- // 检查版本更新
- AppCheckVersion.checkVersion(appId, nil)
- }
- // 即将进入前台通知
- @objc func appWillEnterForeground(){
- // 检查版本更新
- AppCheckVersion.checkVersion(appId, nil)
- AppDelegate.unreadNumber = 0
-
- if mmkv.contains(key: "__APP_ONLY_LOG_SUCCESS_KEY__") {
- // 登录了
- // 判断有没有url,没有url,不做任何处理,有url,加载url
- if mmkv.contains(key: "scheme_to_url") {
- let url = mmkv.string(forKey: "scheme_to_url")!
- let myURL = URL(string: url)!
- let myRequest = URLRequest(url: myURL)
- webView.load(myRequest)
- mmkv.removeValue(forKey: "scheme_to_url")
- }else {
- // if(mmkv.contains(key: "homeUrl")) {
- // let homeUrl:String = mmkv.string(forKey: "homeUrl")!
- // print("homeUrl:\(homeUrl)")
- // if !homeUrl.isEmpty {
- // let myURL = URL(string: homeUrl)!
- // let myRequest = URLRequest(url: myURL)
- // webView.load(myRequest)
- // }
- // }else {
- // self.view.makeToast("无法跳转到主页")
- // }
- }
- }else {
- // 未登录
- }
-
- print("周期 ---将进入前台通知")
- }
- //应用程序确实进入了后台
- @objc func appDidEnterBackground(){
- print("周期 ---应用程序确实进入了后台")
- }
-
- //语音识别授权
- func authSpeechMark(userID:String){
- YJNetManager.default().userID = userID
- if (!YJSpeechManager.default().isInitEngine()){
- YJSpeechManager.default().initEngine()
- YJSpeechManager.default().updateWarrntIdAuth()
- }
- }
-
- //开启语音识别
- @objc func startSpeechMark() {
- if (!YJSpeechManager.default().microphoneAuthorization()){
- LGAlertHUD.shareInstance().showInfo(withStatus: "麦克风权限未打开")
- return
- }
- self.webView.evaluateJavaScript("startRecognitionAnima()")
- YJSpeechManager.default().startEngine(atRefText: nil, markType: .chineseASR, symbol: true)
- YJSpeechManager.default().speechEngineResult { resultModel in
- if (resultModel!.isError){
- LGAlertHUD.shareInstance().showError(withStatus: resultModel?.errorMsg)
- }else {
- let answer:String = resultModel?.recognition.yj_deleteWhitespaceCharacter() ?? ""
- if (answer.count > 0){
- print("识别内容:\(answer)")
- self.webView.evaluateJavaScript("onAndroidRecognitionResult('\(answer)')") { obj, error in
- print("识别上传错误:",error ?? "无错")
- }
- }else{
- LGAlertHUD.shareInstance().showInfo(withStatus: "语音输入为空")
- }
- }
- }
- }
- //停止语音识别
- @objc func stopSpeechMark() {
- YJSpeechManager.default().stopEngine(withTip: NSString.yj_Char1())
- }
-
- // RTC login
- func rtcLogin() {
- let userInfo = self.mmkv.string(forKey: "userInfo", defaultValue: "")!
- if userInfo.count > 0 {
- // userInfo不为空,转化为字典,取出SchoolID和UserID,拼接出实时音的登录用户名
- let userInfoDict = userInfo.toDictionary()
- let schoolId = userInfoDict["SchoolID"]!
- let userId = userInfoDict["UserID"]!
- let userName = userInfoDict["UserName"] as! String
- let avatar = userInfoDict["PhotoPath"] as! String
- let userInfo:[String:String] = ["userId":"\(schoolId)_\(userId)","userName":userName,"avatar": avatar]
- ProfileManager.shared.login(phone: dicValueString(userInfo)!, code: "") { [weak self] in
- guard let `self` = self else { return }
- self.loading.stopAnimating()
- self.loginIM { [weak self] (success) in
- guard let `self` = self else { return }
- if success {
- if ProfileManager.shared.curUserModel?.name.count == 0 {
- ProfileManager.shared.synchronizUserInfo()
- ProfileManager.shared.setNickName(name: "\(userName)") { [weak self] in
- guard self != nil else { return }
- let confg:V2TIMAPNSConfig = V2TIMAPNSConfig.init()
- // 推送证书 ID,上传推送证书(p.12)到 IM 控制台后生成
- confg.businessID = IMID
- // 苹果后台请求的 deviceToken
- confg.token = AppDelegate.deviceToken;
- print("deviceToken:\(AppDelegate.deviceToken)")
- V2TIMManager.sharedInstance()?.setAPNS(confg, succ: {
- print("-----> 设置 APNS 成功")
- }, fail: { (code,msg) in
- print("-----> 设置 APNS 失败")
- })
- } failed: { (err) in
- self.loading.stopAnimating()
- //self.view.makeToast(err)
- DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
- self.navigationController?.popViewController(animated: true)
- }
- }
- } else {
- //self.view.makeToast(LoginLocalize(key:"V2.Live.LinkMicNew.loginsuccess"))
- }
- }
- }
- }
- }
- }
-
-
- // RTC authLogin
- func rtcAuthLogin() {
- let userInfo = mmkv.string(forKey: "userInfo",defaultValue: "")!
- if userInfo.count > 0{
- // userInfo不为空,转化为字典,取出SchoolID和UserID,拼接出实时音的登录用户名
- let userInfoDict = userInfo.toDictionary()
- let userName = userInfoDict["UserName"] as! String
- let userId = userInfoDict["UserID"]!
-
- authSpeechMark(userID: userId as! String)
-
- if ProfileManager.shared.autoLogin(success: {
- self.loginIM { [weak self] (success) in
- guard let `self` = self else { return }
- self.loading.stopAnimating()
- if success {
- if ProfileManager.shared.curUserModel?.name.count == 0 {
- ProfileManager.shared.synchronizUserInfo()
- // name: "S-11261527_jz_S03004"
- ProfileManager.shared.setNickName(name: "\(userName)") { [weak self] in
- print(self as Any)
- } failed: { (err) in
- self.loading.stopAnimating()
- //self.view.makeToast(err)
- DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
- self.navigationController?.popViewController(animated: true)
- }
- }
- } else {
- //self.view.makeToast(LoginLocalize(key:"V2.Live.LinkMicNew.loginsuccess"))
- }
- let confg:V2TIMAPNSConfig = V2TIMAPNSConfig.init()
- // 推送证书 ID,上传推送证书(p.12)到 IM 控制台后生成
- confg.businessID = IMID;
- // 苹果后台请求的 deviceToken
- confg.token = AppDelegate.deviceToken;
- print("deviceToken:\(AppDelegate.deviceToken)")
- V2TIMManager.sharedInstance()?.setAPNS(confg, succ: {
- print("-----> 设置 APNS 成功")
- }, fail: { (code,msg) in
- print("-----> 设置 APNS 失败")
- })
- }
- }
- }, failed: { [weak self] (err) in
- guard let self = self else {return}
- self.loading.stopAnimating()
- //self.view.makeToast(err)
- }) {
-
- }
- }
- }
-
- func loginIM(complete: @escaping (_ success: Bool)->Void) {
- guard let userID = ProfileManager.shared.curUserID() else { return }
- let userSig = ProfileManager.shared.curUserSig()
- V2TIMManager.sharedInstance()
- if V2TIMManager.sharedInstance()?.getLoginUser() != userID {
- ProfileManager.shared.IMLogin(userSig: userSig) {
- debugPrint("IM login success.")
- complete(true)
- } failed: { [weak self] (error) in
- guard self != nil else { return }
- //self.view.makeToast(LoginLocalize(key: "App.PortalViewController.loginimfailed"))
- complete(false)
- }
- }
- }
-
- var payPreUrl:String = "" // 跳转支付前,记录一下,跳转回APP时,需要加载的页面地址
- var preUrl:String = "" // 记录每次跳转页面的时候,前一个页面的地址
-
- // 支付跳转
- func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
- // 拦截请求头,支付跳转回APP,需要修改请求的referer地址
- let headers:[String:String] = navigationAction.request.allHTTPHeaderFields!
- let keys = headers.keys
- let b = keys.contains("Referer")
- if b {
- let referer = headers["Referer"]!
- // https://pay.lancooedu.com/mobilePay/pay.html
- print("【Referer】:\(referer)")
- if self.payScheme != "" && referer.contains("https://\(self.payScheme)") {
- var newRequest = navigationAction.request.urlRequest
- newRequest!.setValue("main.pay.lancooedu.com://", forHTTPHeaderField: "Referer")
- webView.load(newRequest!)
- decisionHandler(WKNavigationActionPolicy.cancel)
- return
- }
- }
- var reqUrl = navigationAction.request.url!.absoluteString
- print("reqUrl:\(reqUrl)")
- if reqUrl.hasPrefix("lancoopay://") {
- payPreUrl = preUrl
- // 跳转到微信 或 支付宝
- let lancoopay: String = "https"
- let range: Range = reqUrl.range(of: lancoopay)!
- let indexOfUrl = reqUrl.distance(from:reqUrl.startIndex, to:range.lowerBound)
- var navUrl = String(reqUrl.suffix(reqUrl.count-indexOfUrl))
- navUrl.insert(":", at: navUrl.firstIndex(of: "/")!)
-
- if let url = URL(string: navUrl) {
- if let hostName = url.host {
- // 设置跳转回App的scheme
- self.payScheme = hostName
- }
- }
- let configuration = WKWebViewConfiguration()
- let preference = WKWebpagePreferences()
- configuration.defaultWebpagePreferences = preference
- preference.allowsContentJavaScript = true
- let userContentController = WKUserContentController.init()
- userContentController.add(self, name: "IosStorage")
- userContentController.add(self, name: "IosDevices")
- userContentController.add(self, name: "IosNet")
- configuration.userContentController = userContentController
- payView = WKWebView(frame: .zero,configuration: configuration)
- payView.uiDelegate = self
- payView.navigationDelegate = self
- payView.allowsBackForwardNavigationGestures = true
- payView.scrollView.contentInsetAdjustmentBehavior = UIScrollView.ContentInsetAdjustmentBehavior.never
- let myURL = URL(string: navUrl)!
- let myRequest = URLRequest(url: myURL)
- payView.load(myRequest)
- webView.addSubview(payView)
- decisionHandler(.cancel)
- return
- }
- // 跳转到微信支付
- else if reqUrl.hasPrefix("weixin://") {
- mmkv.removeValues(forKeys: ["__pay__url","__pay__type","__pay__form"])
- // 跳转微信App
- if let toUrl = URL(string: reqUrl) {
- if #available(iOS 10, *) {
- UIApplication.shared.open(toUrl, options: [:], completionHandler: {(success) in
- if (!success) {
- let content = "当前手机暂未下载微信,是否前往 AppStore 下载"
- let appStoreURL = "https://itunes.apple.com/app/id414478124"
- UIAlertController.alertPayTip(content,appStoreURL)
- }
- })
- } else {
- let bSucc = UIApplication.shared.openURL(toUrl)
- if !bSucc {
- let content = "当前手机暂未下载微信,是否前往 AppStore 下载"
- let appStoreURL = "https://itunes.apple.com/app/id414478124"
- UIAlertController.alertPayTip(content,appStoreURL)
- }
- }
-
- }
- webView.willRemoveSubview(payView)
- decisionHandler(WKNavigationActionPolicy.cancel)
- return
- }
- // 跳转到支付宝支付
- else if reqUrl.hasPrefix("alipays://") || reqUrl.hasPrefix("alipay://") {
- mmkv.removeValues(forKeys: ["__pay__url","__pay__type","__pay__form"])
- reqUrl = reqUrl.replacingOccurrences(of: "alipays", with: "main.pay.lancooedu.com")
- // 跳转支付宝App
- if let toUrl = URL(string: reqUrl) {
- if #available(iOS 10, *) {
- UIApplication.shared.open(toUrl, options: [:], completionHandler: {(success) in
- if (!success) {
- let content = "当前手机暂未下载支付宝,是否前往 AppStore 下载"
- let appStoreURL = "https://itunes.apple.com/cn/app/zhi-fu-bao-qian-bao-yu-e-bao/id333206289?mt=8"
- UIAlertController.alertPayTip(content,appStoreURL)
- }
- })
- } else {
- let bSucc = UIApplication.shared.openURL(toUrl)
- if !bSucc {
- let content = "当前手机暂未下载支付宝,是否前往 AppStore 下载"
- let appStoreURL = "https://itunes.apple.com/cn/app/zhi-fu-bao-qian-bao-yu-e-bao/id333206289?mt=8"
- UIAlertController.alertPayTip(content,appStoreURL)
- }
- }
- }
- webView.willRemoveSubview(payView)
- decisionHandler(WKNavigationActionPolicy.cancel)
- return
- }
- else if reqUrl.contains("lancooIosAppId") {
- let getIdString = "lancooIosAppId";
- let location:Int = reqUrl.positionOf(sub: getIdString)
- let jumpAppId = reqUrl.substring(from: location+getIdString.count+1)
- print("AppId:\(jumpAppId)")
- // 跳转第三方应用:lancoodemo://
- if let toUrl = URL(string: reqUrl) {
- if #available(iOS 10, *) {
- UIApplication.shared.open(toUrl, options: [:], completionHandler: {(success) in
- if (!success) {
- let content = "当前手机暂未下载该应用,是否前往 AppStore 下载"
- let appStoreURL = "https://itunes.apple.com/app/id\(jumpAppId)"
- UIAlertController.alertPayTip(content,appStoreURL)
- }
- })
- } else {
- let bSucc = UIApplication.shared.openURL(toUrl)
- if !bSucc {
- let content = "当前手机暂未下载该应用,是否前往 AppStore 下载"
- let appStoreURL = "https://itunes.apple.com/app/id\(jumpAppId)"
- UIAlertController.alertPayTip(content,appStoreURL)
- }
- }
- }
- }
- preUrl = reqUrl
- decisionHandler(WKNavigationActionPolicy.allow)
- }
-
- let keyWindow = UIApplication.shared.connectedScenes
- .map({ $0 as? UIWindowScene })
- .compactMap({ $0 })
- .first?.windows.first
- func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
- print("跳转页面中。。。")
- LoadingView.width = self.webView.bounds.width
- LoadingView.height = self.webView.bounds.height
- LoadingView.show()
-
- AppDelegate.initalTime = Int64(Date().timeIntervalSince1970)
- }
-
- // flag: true被t下线,false主动退出
- func logout(_ flag:Bool) {
- let cachePath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.cachesDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first
- let fileArr = FileManager.default.subpaths(atPath: cachePath!)
- for file in fileArr! {
- let path = (cachePath! as NSString).appending("/\(file)")
- if FileManager.default.fileExists(atPath: path) {
- do {
- try FileManager.default.removeItem(atPath: path)
- } catch {}
- }
- }
- let dataStore = WKWebsiteDataStore.default()
- dataStore.fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(), completionHandler: { (records) in
- for record in records{
- WKWebsiteDataStore.default().removeData(ofTypes: record.dataTypes, for: [record], completionHandler: {
- print("清除成功\(record)")
- })
- }
- })
- if (mmkv.contains(key: "userInfo") && mmkv.contains(key: "homeUrl") && mmkv.contains(key: "token")
- && mmkv.contains(key: "account")) {
- mmkv.removeValue(forKey: "userInfo")
- mmkv.removeValue(forKey: "token")
- mmkv.removeValue(forKey: "account")
- mmkv.removeValue(forKey: "homeUrl")
- mmkv.removeValue(forKey: "__APP_ONLY_LOG_SUCCESS_KEY__")
- let myURL = URL(string: mainUrl)!
- let myRequest = URLRequest(url: myURL)
- webView.load(myRequest)
- webView.backForwardList.perform(Selector(("_removeAllItems")))
- }
- }
-
- func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
- let name = message.name
- print("name:\(name)")
- if name == "IosDevices" {
- print("messageBody:\(message.body)")
-
- let body:[String:Optional] = message.body as! [String : Optional<Any>]
- let method:String = body["method"] as! String
-
- if method == "back" {
- print("back")
- if(webView.canGoBack) {
- webView.goBack()
- }else {
- self.navigationController?.popViewController(animated: true)
- }
- }
- else if method == "goHome" {
- if(mmkv.contains(key: "homeUrl")) {
- let homeUrl:String = mmkv.string(forKey: "homeUrl")!
- print("homeUrl:\(homeUrl)")
- if !homeUrl.isEmpty {
- let myURL = URL(string: homeUrl)!
- let myRequest = URLRequest(url: myURL)
- webView.load(myRequest)
- webView.backForwardList.perform(Selector(("_removeAllItems")))
- }
- }else {
- self.view.makeToast("无法跳转到主页")
- }
- }
- else if method == "logout" {
- // 删除智慧校园登录信息
- self.logout(false)
- }else if method == "openFileReader" {
- let path = body["path"] as! String
- MainController.preViewFilePath = path
- print("预览文件路径:\(MainController.preViewFilePath)")
- let manager = FileManager.default
- var isDirectory = ObjCBool(false)
- let isExist:Bool = manager.fileExists(atPath: MainController.preViewFilePath,isDirectory:&isDirectory)
- if isExist {
- // 方法1:
- //navigationController?.pushViewController(PreViewFileVc(), animated: true)
- //方法2:
- let preViewController = QLPreviewController.init()
- preViewController.delegate = self
- preViewController.dataSource = self
- self.present(preViewController, animated: true) {
- print("打开文件")
- }
- // 方法3:
- // let filePath: String = MainController.preViewFilePath
- //
- // let indexOfFileName = filePath.positionOf(sub: "/", backwards: true)
- // let fileName = filePath.suffix(filePath.count-1-indexOfFileName)
- //
- // let documents:String = NSHomeDirectory() + "/Documents/" + fileName;
- // print("documents:\(documents)")
- // let documentController = UIDocumentInteractionController.init(url: URL.init(fileURLWithPath: documents))
- // documentController.delegate = self
- // documentController.presentPreview(animated: true)
- // 最终方法:采用wkwebview
- // let myURL = URL(string: MainController.preViewFilePathUrl)!
- // let myRequest = URLRequest(url: myURL)
- // webView.load(myRequest)
- }else {
- self.view.makeToast("文件已损坏,请退出重新登录下载")
- }
- //navigationController?.pushViewController(PreViewFileVc(), animated: true)
- } else if method == "clearCache" {
- // 暂时不清除缓存
- } else if method == "gotoUpdate" {
- // 手动更新
- let hasNewVersion = MMKV.default()!.bool(forKey: ConstantVC.HAS_NEW_VERSION)
- if hasNewVersion {
- UIApplication.shared.open(URL.init(string: "https://itunes.apple.com/app/id\(appId)")!, options: [:], completionHandler: nil)
- }else {
- self.view.makeToast("当前已经是最新版本")
- }
- } else if method == "scanCode" {
- self.scanCodeTaskId = body["taskId"] as! Int
- codeScan()
- } else if method == "getLocation" {
- self.getLocationTaskId = body["taskId"] as! Int
- getLocation()
- }
- }else if name == "IosStorage" {
- let sentData = message.body as! Dictionary<String,Optional<Any>>
- let method = sentData["method"] as! String
- if method == "set" {
- let key = sentData["key"] as! String
- if (sentData["value"] != nil) {
- let value = try? (sentData["value"] as! String)
- if (value != nil) {
- mmkv.set(value!, forKey: key)
- print("存储用户存储缓存:\(key)--\(value)--\(Date())")
- }
- }
- }
- self.rtcLogin()
- self.rtcAuthLogin()
- }else if name == "IosNet" {
- let body:[String:Optional] = message.body as! [String : Optional<Any>]
- let method:String = body["method"] as! String
- if method == "downloadFile" {
- self.taskId = body["taskId"] as! Int
- let url:String = body["url"] as! String
- self.fileName = body["fileName"] as! String
- print("\(taskId)--\(url)--\(fileName)")
- sessionSeniorDownload(downLoadUrl: url)
- }else if method == "uploadFile" {
- self.uploadParam.taskId = body["taskId"] as! Int
- self.uploadParam.url = body["url"] as! String
- self.uploadParam.fileType = body["fileType"] as! [String]
- self.uploadParam.limit = body["limit"] as! Int
- self.uploadParam.header = stringValueDic(body["header"] as! String)
- self.uploadParam.count = body["count"] as! Int
- let fileType = self.uploadParam.fileType
- let imageType = ["png","jpge","jpg"]
- var flag = true
- for ft in fileType {
- if !imageType.contains(ft) {
- flag = false
- }
- }
- if flag {
- let picker = UIImagePickerController()
- picker.delegate = self
- present(picker, animated: true, completion: nil)
- }else {
- var documentTypes:[UTType] = []
- for type in fileType {
- let type:UTType = UTType.init(filenameExtension: type)!
- documentTypes.append(type)
- }
- let document = UIDocumentPickerViewController.init(forOpeningContentTypes: documentTypes)
- if self.uploadParam.count == 1 {
- document.allowsMultipleSelection = false
- }else {
- document.allowsMultipleSelection = true
- }
- document.delegate = self //UIDocumentPickerDelegate
- print("开始选择文件")
- self.present(document, animated:true, completion:nil)
- }
- }else if method == "startSpeechRecognition" {
- startSpeechMark()
- }else if method == "stopSpeechRecognition" {
- stopSpeechMark()
- }
- }
- }
-
- func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]){
- //获取选择的原图
- let pickedImage = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
- //将选择的图片保存到Document目录下
- let fileManager = FileManager.default
- let rootPath = NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask, true)[0] as String
- let filePath = "\(rootPath)/pickedimage.jpg"
- let imageData = pickedImage.jpegData(compressionQuality: 1.0)
- fileManager.createFile(atPath: filePath, contents: imageData, attributes: nil)
-
- //上传图片
- if (fileManager.fileExists(atPath: filePath)){
- //取得NSURL
- sessionUpload(filePath)
- }
-
- picker.dismiss(animated: true, completion: nil)
- }
-
- func sessionUpload(_ document:String){
- print("document:\(document)")
-
- //上传地址
- let url = URL(string: self.uploadParam.url)
- //请求
- let request = NSMutableURLRequest(url: url!)
-
- for e in self.uploadParam.header {
- request.addValue(e.value, forHTTPHeaderField: e.key)
- }
-
- let boundary = "Boundary-\(UUID().uuidString)"
- let body = NSMutableArray()
- var fileTmpStr = ""
- //设置为POST请求
- request.httpMethod = "POST"
- request.setValue("multipart/form-data; boundary=----\(boundary)", forHTTPHeaderField: "Content-Type")
-
- // 上传文件的文件名,按照需求起名字就好
- let imgPath:String = document.removingPercentEncoding!
- let indexOfPoint = imgPath.positionOf(sub: ".", backwards: true)
- let suffix = imgPath.suffix(imgPath.count-1-indexOfPoint)
- print(suffix)
- let indexOfFileName = imgPath.positionOf(sub: "/", backwards: true)
- let fileName = imgPath.suffix(imgPath.count-1-indexOfFileName)
- print(fileName)
-
- // 将文件名和boundary组装在一起
- fileTmpStr = "------\(boundary)\r\nContent-Disposition: form-data; name=\"file\"; filename=\"\(fileName)\"\r\n"
- body.add(fileTmpStr)
- // 文件类型是图片,png、jpeg随意
- fileTmpStr = "Content-Type: image/\(suffix)\r\n\r\n"
- body.add(fileTmpStr)
- // 将body里的内容转成字符串
- let parameterStr = body.componentsJoined(by: "")
- // UTF8转码,防止汉字符号引起的非法网址
- var parameterData = parameterStr.data(using: String.Encoding.utf8)!
- // 将图片追加进parameterData
- let imageData = try! Data(contentsOf: URL(fileURLWithPath: imgPath))
- parameterData.append(imageData)
- // 将boundary结束部分追加进parameterData
- parameterData.append("\r\n------\(boundary)--".data(using: String.Encoding.utf8)!)
- // 设置请求体
- request.httpBody = parameterData
-
- //发起请求
- let dataTask = session.dataTask(with: request as URLRequest) { (data, response, error) in
- //上传完毕后
- if error != nil{
- DispatchQueue.main.async {
- self.webView.evaluateJavaScript("onIosUploadError(\(self.uploadParam.taskId),'network')") { (data, err) in
- print("onIosUploadError|network")
- }
- }
- }else{
- let str = String(data: data!, encoding: String.Encoding.utf8)!
- print("上传完毕:\(str)")
- DispatchQueue.main.async {
- self.webView.evaluateJavaScript("onIosUploadSuccess(\(self.uploadParam.taskId),'\(str)')") { (data, err) in
- }
- }
- }
- }
- //请求开始
- dataTask.resume()
-
- }
-
- func sessionFileUpload(_ urlsAndData:[String:Data]){
- print("urlsAndData:\(urlsAndData)")
- //上传地址
- let url = URL(string: self.uploadParam.url)
- //请求
- let request = NSMutableURLRequest(url: url!)
-
- for e in self.uploadParam.header {
- print("header:\(e)")
- request.addValue(e.value, forHTTPHeaderField: e.key)
- }
-
- let boundary = "Boundary-\(UUID().uuidString)"
- let body = NSMutableArray()
- var fileTmpStr = ""
- //设置为POST请求
- request.httpMethod = "POST"
- request.setValue("multipart/form-data; boundary=----\(boundary)", forHTTPHeaderField: "Content-Type")
-
- var parameterData:Data = Data()
- for e in urlsAndData {
- if e.value.count == 0 {
- DispatchQueue.main.async {
- self.webView.evaluateJavaScript("onIosUploadError(\(self.uploadParam.taskId),'noSelect')") { (data, err) in
- print("onIosUploadError|noSelect")
- }
- }
- return
- }
- let filePath = e.key
- let indexOfFileName = filePath.positionOf(sub: "/", backwards: true)
- let fileName = filePath.suffix(filePath.count-1-indexOfFileName)
- print(fileName)
-
- // 将文件名和boundary组装在一起
- fileTmpStr = "\r\n------\(boundary)\r\nContent-Disposition: form-data; name=\"file\"; filename=\"\(fileName)\"\r\n"
- body.add(fileTmpStr)
- // 文件类型
- fileTmpStr = "Content-type:application/octet-stream\r\n\r\n"
- body.add(fileTmpStr)
- // 将body里的内容转成字符串
- let parameterStr = body.componentsJoined(by: "")
- // UTF8转码,防止汉字符号引起的非法网址
- parameterData = parameterStr.data(using: String.Encoding.utf8)!
- // 将文件追加进parameterData
- let data = e.value
- parameterData.append(data)
- parameterData.append("\r\n".data(using: String.Encoding.utf8)!)
- }
- // 将boundary结束部分追加进parameterData
- parameterData.append("\r\n------\(boundary)--".data(using: String.Encoding.utf8)!)
-
-
- // 设置请求体
- request.httpBody = parameterData
-
- //发起请求
- let dataTask = session.dataTask(with: request as URLRequest) { (data, response, error) in
- //上传完毕后
- if error != nil{
- DispatchQueue.main.async {
- self.webView.evaluateJavaScript("onIosUploadError(\(self.uploadParam.taskId),'network')") { (data, err) in
- print("onIosUploadError|network")
- }
- }
- }else{
- let str = String(data: data!, encoding: String.Encoding.utf8)!
- print("上传完毕:\(str)")
- DispatchQueue.main.async {
- self.webView.evaluateJavaScript("onIosUploadSuccess(\(self.uploadParam.taskId),'\(str)')") { (data, err) in
- }
- }
- }
- }
- print("dataTask:\(dataTask)")
- //请求开始
- dataTask.resume()
- }
-
-
- // 监听上传文件进度
- func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
- let written:CGFloat = (CGFloat)(totalBytesSent)
- let total:CGFloat = (CGFloat)(totalBytesExpectedToSend)
- let pro:CGFloat = written/total
- let process:Int = Int(pro * 100)
- print("上传进度:\(pro)")
- DispatchQueue.main.async {
- self.webView.evaluateJavaScript("onIosUploadProgress(\(self.uploadParam.taskId),\(process))") { (data, err) in
- print("onIosUploadProgress:\(self.uploadParam.taskId)--\(process)")
- }
- }
- }
-
- func buildFileData(_ url:String) -> Data {
- // 上传文件的文件名,按照需求起名字就好
- //let strToUtf8 = url.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) ?? ""
- let filePath:String = url.removingPercentEncoding!
- let indexOfPoint = filePath.positionOf(sub: ".", backwards: true)
- let suffix = filePath.suffix(filePath.count-1-indexOfPoint)
- print(suffix)
-
- // 校验文件类型
- print(self.uploadParam.fileType)
- print(self.uploadParam.fileType.contains(String(suffix).lowercased()))
- if !self.uploadParam.fileType.contains(String(suffix).lowercased()) {
- DispatchQueue.main.async {
- self.webView.evaluateJavaScript("onIosUploadError(\(self.uploadParam.taskId),'extendNameError')") { (data, err) in
- print("onIosUploadError|extendNameError")
- }
- }
- return Data.init()
- }
- let data = try! Data(contentsOf: URL(fileURLWithPath: filePath))
- if data.count > self.uploadParam.limit*1024*1024 {
- DispatchQueue.main.async {
- self.webView.evaluateJavaScript("onIosUploadError(\(self.uploadParam.taskId),'exceedLimit')") { (data, err) in
- print("onIosUploadError|exceedLimit")
- }
- }
- return Data.init()
- }
- return data
- }
-
- func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
- // 未选择
- if urls.count == 0 {
- DispatchQueue.main.async {
- self.webView.evaluateJavaScript("onIosUploadError(\(self.uploadParam.taskId),'noSelect')") { (data, err) in
- }
- }
- return
- }
- // 超过所需选择数量
- if urls.count > self.uploadParam.count {
- DispatchQueue.main.async {
- self.webView.evaluateJavaScript("onIosUploadError(\(self.uploadParam.taskId),'exceedCount')") { (data, err) in
- }
- }
- return
- }
- let fileUrlAuthorized:Bool = (urls.first?.startAccessingSecurityScopedResource())! as Bool
- if fileUrlAuthorized {
- let fileCoordinator = NSFileCoordinator.init()
- var error:NSError?
- // 需要上传的文件路径
- var newUrlsData:[String:Data] = [:]
- for url in urls {
- fileCoordinator.coordinate(readingItemAt: url, options: NSFileCoordinator.ReadingOptions.forUploading, error: &error) { (newURL:URL) in
- let tempUrl = String(newURL.absoluteString.suffix(newURL.absoluteString.count - 7))
- let data = buildFileData(tempUrl)
- newUrlsData[tempUrl] = data
- }
- }
- sessionFileUpload(newUrlsData)
- urls.first?.stopAccessingSecurityScopedResource()
- }
-
- }
-
- func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
- print("documentPickerWasCancelled")
- }
-
- func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
- }
-
- func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
- LoadingView.complete()
- YJSpeechManager.default().setMicrophoneAuthorization()
- }
-
- func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
- LoadingView.complete()
- }
-
- func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
- LoadingView.complete()
- }
-
- let refreshLabel = UILabel()
-
- func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
- // let response:HTTPURLResponse = navigationResponse.response as! HTTPURLResponse
- // print("跳转地址:\(response.url?.absoluteString)!")
- decisionHandler(.allow)
- }
-
- //MARK:WKUIDelegate
- //此方法作为js的alert方法接口的实现,默认弹出窗口应该只有提示消息,及一个确认按钮,当然可以添加更多按钮以及其他内容,但是并不会起到什么作用
- //点击确认按钮的相应事件,需要执行completionHandler,这样js才能继续执行
- //参数 message为 js 方法 alert(<message>) 中的<message>
- func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
- let alertViewController = UIAlertController(title: nil, message:message, preferredStyle: UIAlertController.Style.alert)
- alertViewController.addAction(UIAlertAction(title: "确认", style: UIAlertAction.Style.default, handler: { (action) in
- completionHandler()
- }))
- self.present(alertViewController, animated: true, completion: nil)
- }
-
- // confirm
- //作为js中confirm接口的实现,需要有提示信息以及两个相应事件, 确认及取消,并且在completionHandler中回传相应结果,确认返回YES, 取消返回NO
- //参数 message为 js 方法 confirm(<message>) 中的<message>
- func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
- let alertVicwController = UIAlertController(title: "提示", message: message, preferredStyle: UIAlertController.Style.alert)
- alertVicwController.addAction(UIAlertAction(title: "取消", style: UIAlertAction.Style.cancel, handler: { (alertAction) in
- completionHandler(false)
- }))
- alertVicwController.addAction(UIAlertAction(title: "确定", style: UIAlertAction.Style.default, handler: { (alertAction) in
- 3
-
- }))
- self.present(alertVicwController, animated: true, completion: nil)
- }
-
- // prompt
- //作为js中prompt接口的实现,默认需要有一个输入框一个按钮,点击确认按钮回传输入值
- //当然可以添加多个按钮以及多个输入框,不过completionHandler只有一个参数,如果有多个输入框,需要将多个输入框中的值通过某种方式拼接成一个字符串回传,js接收到之后再做处理
- //参数 prompt 为 prompt(<message>, <defaultValue>);中的<message>
- //参数defaultText 为 prompt(<message>, <defaultValue>);中的 <defaultValue>
- func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
-
- let body:String = prompt.description
-
- if(body.hasPrefix("IosStorageGet")) {
- let keys = body.components(separatedBy: "|")
- if keys.count >= 2 {
- let key = keys[1]
- if (mmkv.contains(key:key)) {
- let value = mmkv.string(forKey: key)
- print("获取用户存储缓存:\(key)--\(value!)")
- completionHandler(value)
- return
- }
- }
-
- completionHandler("")
- return
- }
-
- if(body.hasPrefix("EnvironmentVariable")) {
- let keys = body.components(separatedBy: "|")
- if keys.count >= 2 {
- let key = keys[1]
- switch key {
- case "iosEnv":
- completionHandler("iOS")
- return
- case "CameraPermission":
- let isOpenCamera = IsOpenCamera()
- let result = "\(isOpenCamera)"
- print("isOpenCamera:\(result)")
- completionHandler(result)
- return;
- default:
- completionHandler("")
- break;
- }
- }
-
- completionHandler("")
- return
- }
-
- switch body {
- case "getId":
- // 获取设备唯一标识
- print("getId...")
- // let deviceId = ASIdentifierManager.shared().advertisingIdentifier.uuidString
- let deviceId = UIDevice.current.identifierForVendor?.uuidString
- print("deviceId:\(deviceId!)")
- completionHandler("\(deviceId!)")
- break
- case "getIp":
- // 获取ip地址
- print("getIp...")
- completionHandler("192.168.2.90")
- break
- case "getStatusBarHeight":
- print("getStatusBarHeight...")
- // 状态栏高度
- let statusHeight = isIphoneX() ? "24" : "0";
- print("statusHeight:\(statusHeight)")
- completionHandler(statusHeight)
- break
- case "getFooterHeight":
- print("getFooterHeight...")
- // 底部横线高度
- let footerHeight = isIphoneX() ? "10" : "0";
- completionHandler(footerHeight)
- break
- case "cacheSize":
- completionHandler("1")
- break;
- case "getAppVersion":
- var appVersion = "5.0.0"
- if MMKV.default()!.contains(key: ConstantVC.APP_VERSION) {
- appVersion = MMKV.default()!.string(forKey: ConstantVC.APP_VERSION)!
- }
- completionHandler("\(appVersion)")
- break;
- case "hasNewVersion":
- completionHandler("\(MMKV.default()!.bool(forKey: ConstantVC.HAS_NEW_VERSION))")
- break
- case "hasScanCode":
- completionHandler("true")
- break
- default:
- completionHandler("")
- break
- }
-
- // let alertViewController = UIAlertController(title: prompt.description, message: "撒打算", preferredStyle: UIAlertController.Style.alert)
- // alertViewController.addTextField { (textField) in
- // textField.text = defaultText
- // }
- //
- // alertViewController.addAction(UIAlertAction(title: "完成", style: UIAlertAction.Style.default, handler: { (alertAction) in
- // completionHandler("当前设备ID")
- // }))
- // self.present(alertViewController, animated: true, completion: nil)
- }
-
- // 判断是否设备是iphonex系列
- func isIphoneX() -> (Bool) {
- // ========第一种判断方法=========
- // // iPhoneX,XS
- // if (UIScreen.main.bounds.size.width == 375 && UIScreen.main.bounds.size.height == 812) {
- // return true;
- // }
- //// // iPhoneXS Max,XR
- // if (UIScreen.main.bounds.size.width == 414 && UIScreen.main.bounds.size.height == 896) {
- // return true;
- // }
- // return false;
- // ========第二种判断方法=========
- if UIDevice.current.userInterfaceIdiom == .pad {
- return false
- }
- let size = UIScreen.main.bounds.size
- let notchValue = Int(size.width/size.height*100)
- if notchValue == 216 || notchValue == 46 {
- return true
- }
- return false
- // ========第三种判断方法=========
- // let screenHeight = UIScreen.main.nativeBounds.size.height
- // if screenHeight == 2436 || screenHeight == 1792 || screenHeight == 2688 || screenHeight == 1624 {
- // return true
- // }
- // return false
- }
- //下载文件
- func sessionSeniorDownload(downLoadUrl:String){
- var filePath:String = downLoadUrl.removingPercentEncoding!
-
- filePath = filePath.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
- //下载地址
- let url = URL(string: filePath)
-
- //请求
- let request = URLRequest(url: url!)
-
- //下载任务
- let downloadTask = session.downloadTask(with: request)
-
- //使用resume方法启动任务
- downloadTask.resume()
-
- let task = session.dataTask(with: request) { (data, response, error) in
- if error != nil {
- DispatchQueue.main.async {
- self.webView.evaluateJavaScript("onIosDownError(\(self.taskId),'network')") { (data, err) in
- print("onIosDownError")
- }
- }
- } else {
- print("NO ERROR")
- }
- }
- task.resume()
- }
-
- //下载代理方法,下载结束
- func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask,
- didFinishDownloadingTo location: URL) {
- //下载结束
- print("下载结束")
- //输出下载文件原来的存放目录
- print("location:\(location)")
- //location位置转换
- let locationPath = location.path
- //拷贝到用户目录
- let fileManager = FileManager.default
- //================获取文件下载地址
- // let homeDirectory = NSHomeDirectory()
- // print("\(homeDirectory)")
- // let indexOfVirgule = homeDirectory.lastIndex(of: "/") ?? homeDirectory.endIndex
- // let directory = homeDirectory[..<indexOfVirgule]
- // let documents:String = "\(directory)/\(self.fileName)"
- let documents:String = NSHomeDirectory() + "/Documents/" + self.fileName;
- // let documents:String = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true)[0] + "/" + self.fileName
- // let documents:String = NSHomeDirectory() + "/Documents/" + self.fileName;
- //创建文件管理器
-
- if fileManager.fileExists(atPath: documents) {
- do {
- try FileManager.init().removeItem(atPath: documents)
- debugPrint("已删除" + documents)
- } catch {
- DispatchQueue.main.async {
- self.webView.evaluateJavaScript("onIosDownError(\(self.taskId),'network')") { (data, err) in
- print("onIosDownError")
- }
- }
- print(error)
- }
- }
- try! fileManager.moveItem(atPath: locationPath, toPath: documents)
- print("new location:\(documents)")
- DispatchQueue.main.async {
- self.webView.evaluateJavaScript("onIosDownSuccess(\(self.taskId),'\(documents)')") { (data, err) in
- print("onIosDownSuccess")
- }
- }
- }
-
- //下载代理方法,监听下载进度
- func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask,
- didWriteData bytesWritten: Int64, totalBytesWritten: Int64,
- totalBytesExpectedToWrite: Int64) {
- //获取进度
- let written:CGFloat = (CGFloat)(totalBytesWritten)
- let total:CGFloat = (CGFloat)(totalBytesExpectedToWrite)
- let pro:CGFloat = written/total
- let process:Int = Int(pro * 100)
- print("下载进度:\(pro)")
- DispatchQueue.main.async {
- self.webView.evaluateJavaScript("onIosDownProgress(\(self.taskId),\(process))") { (data, err) in
- print("onIosDownProgress:\(self.taskId)--\(process)")
- }
- }
- }
-
- //下载代理方法,下载偏移
- func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask,
- didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64) {
- //下载偏移,主要用于暂停续传
- DispatchQueue.main.async {
- self.webView.evaluateJavaScript("onIosDownError(\(self.taskId),'network')") { (data, err) in
- print("onIosDownError")
- }
- }
- }
-
- override func didReceiveMemoryWarning() {
- super.didReceiveMemoryWarning()
- print("didReceiveMemoryWarning")
- }
-
- // MARK: 字符串转字典
- func stringValueDic(_ str: String) -> [String : String]{
- print("stringValueDic:\(str)")
- let data = str.data(using: String.Encoding.utf8)
- if let dict = try? JSONSerialization.jsonObject(with: data!,
- options: .mutableContainers) as? [String : String] {
- print("stringValueDic:dict:\(dict)")
- return dict
- }
- return [:]
- }
- }
- extension MainController: URLSessionDownloadDelegate,UIDocumentPickerDelegate,UIImagePickerControllerDelegate,V2TIMSignalingListener{
- func onReceiveNewInvitation(_ inviteID: String!, inviter: String!, groupID: String!, inviteeList: [String]!, data: String?) {
- print("inviteID:\(String(describing: inviteID))")
-
- }
-
- // 打开相机权限
- func openCamera() {
- let authStatus = AVCaptureDevice.authorizationStatus(for: .video)
- if authStatus == .notDetermined {
- AVCaptureDevice.requestAccess(for: .video) { (res) in
- //此处可以判断权限状态来做出相应的操作,如改变按钮状态
- if res{
- }else{
- }
- }
- }
- }
-
- //开启相册权限
- func openAlbum() {
- let authStatus = PHPhotoLibrary.authorizationStatus()
- if authStatus == .notDetermined {
- PHPhotoLibrary.requestAuthorization({ (status) in
- //此处可以判断权限状态来做出相应的操作,如改变按钮状态
- if status == .authorized {
- } else if status == .denied || status == .restricted{
- }
- })
- }
- }
-
- //是否开启相机权限
- func IsOpenCamera() -> Bool{
- let authStatus = AVCaptureDevice.authorizationStatus(for: .video)
- return authStatus != .restricted && authStatus != .denied
- }
-
- //是否开启相册权限
- func IsOpenAlbum() -> Bool{
- let authStatus = PHPhotoLibrary.authorizationStatus(for: .readWrite)
- return authStatus != .restricted && authStatus != .denied
- }
-
- }
- extension MainController:V2TIMSDKListener {
-
- func onKickedOffline() {
- print("被t下线了")
-
- if (mmkv.contains(key: "userInfo") && mmkv.contains(key: "homeUrl") && mmkv.contains(key: "token")
- && mmkv.contains(key: "account")) {
- mmkv.removeValue(forKey: "userInfo")
- mmkv.removeValue(forKey: "token")
- mmkv.removeValue(forKey: "account")
- mmkv.removeValue(forKey: "homeUrl")
- let myURL = URL(string: mainUrl)!
- let myRequest = URLRequest(url: myURL)
- webView.load(myRequest)
- webView.backForwardList.perform(Selector(("_removeAllItems")))
- }
- }
-
- func IMLogout() {
- ProfileManager.shared.removeLoginCache()
-
- V2TIMManager.sharedInstance()?.logout({
- }, fail: { (errCode, errMsg) in
- })
- self.view.makeToast("已退出")
- }
-
- func IMKickOff() {
- ProfileManager.shared.removeLoginCache()
- V2TIMManager.sharedInstance()?.logout({
- }, fail: { (errCode, errMsg) in
- })
- }
- // MARK: 字典转字符串
- func dicValueString(_ dic:[String : Any]) -> String?{
- let data = try? JSONSerialization.data(withJSONObject: dic, options: [])
- let str = String(data: data!, encoding: String.Encoding.utf8)
- return str
- }
- }
- // 在线推送
- extension MainController: V2TIMAdvancedMsgListener {
- //注册音频文件,获取SystemSoundID
- func getSoundId() -> SystemSoundID {
- var soundId: SystemSoundID = SystemSoundID()
- let path = Bundle.main.path(forResource: "phone_ringing", ofType: "caf")
- let url = URL.init(fileURLWithPath: path!)
- AudioServicesCreateSystemSoundID(url as CFURL, &soundId)
- return soundId
- }
-
- //播放自定义铃声和震动
- func playAlertSound() {
- if soundId == nil {
- soundId = self.getSoundId()
- }
- AudioServicesAddSystemSoundCompletion(soundId!, nil, nil, { (SystemSoundID, pointer: UnsafeMutableRawPointer?) in
- AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
- AudioServicesPlaySystemSound(SystemSoundID)
- }, nil)
- //kSystemSoundID_Vibrate是震动的id
- AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
- AudioServicesPlaySystemSound(soundId!)
- }
-
- //停止播放
- func stopAlertSoundWithSoundID() {
- if soundId != nil {
- AudioServicesDisposeSystemSoundID(soundId!)
- AudioServicesRemoveSystemSoundCompletion(soundId!)
- soundId = nil
- }
- AudioServicesDisposeSystemSoundID(kSystemSoundID_Vibrate)
- }
-
- func onRecvNewMessage(_ msg: V2TIMMessage!) {
- let curTimeStamp = Int64(Date().timeIntervalSince1970)
- if msg.customElem.desc != nil && msg.customElem.data != nil {
- if curTimeStamp - AppDelegate.initalTime >= 3 && !String(msg.customElem.description).isEmpty {
- if UIApplication.shared.applicationState == .active {
- let content = UNMutableNotificationContent()
- content.title = msg.customElem.desc!
- content.userInfo["ext"] = msg.customElem.extension
- content.body = String.init(data: msg.customElem.data, encoding: .utf8)!
- //content.userInfo = ["icon":"1","mutable-content":1]
- content.categoryIdentifier = "categoryIdentifier"
- let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
- let requestIdentifier = "imageLocal"
- let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)
- UNUserNotificationCenter.current().add(request, withCompletionHandler: { (error) in
- if (error != nil) {
- print("error: \(error.debugDescription)")
- }
- })
- }
- }
- }
- }
- }
- extension MainController: QLPreviewControllerDataSource,QLPreviewControllerDelegate {
- func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
- return 1
- }
- func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
- let filePath: String = MainController.preViewFilePath
-
- let indexOfFileName = filePath.positionOf(sub: "/", backwards: true)
- let fileName = filePath.suffix(filePath.count-1-indexOfFileName)
-
- let documents:String = NSHomeDirectory() + "/Documents/" + fileName;
- print("documents:\(documents)")
- return URL.init(fileURLWithPath: filePath) as QLPreviewItem
- }
- func previewControllerDidDismiss(_ controller: QLPreviewController) {
- print("用户界面已消失")
- }
-
- func previewController(_ controller: QLPreviewController, shouldOpen url: URL, for item: QLPreviewItem) -> Bool {
- return false
- }
- }
- //extension MainController:UIDocumentInteractionControllerDelegate {
- // func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
- // return self
- // }
- // func documentInteractionControllerViewForPreview(_ controller: UIDocumentInteractionController) -> UIView? {
- // return self.view
- // }
- // func documentInteractionControllerRectForPreview(_ controller: UIDocumentInteractionController) -> CGRect {
- // return self.view.frame
- // }
- //}
- extension MainController: NotificationBannerDelegate {
- func notificationBannerWillAppear(_ banner: BaseNotificationBanner) {
-
- }
-
- func notificationBannerDidAppear(_ banner: BaseNotificationBanner) {
-
- }
-
- func notificationBannerWillDisappear(_ banner: BaseNotificationBanner) {
-
- }
-
- func notificationBannerDidDisappear(_ banner: BaseNotificationBanner) {
-
- }
-
- internal func showAlert(title: String, message: String) {
- let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
- let action = UIAlertAction(title: "OK", style: .default, handler: nil)
- alertController.addAction(action)
- present(alertController, animated: true, completion: nil)
- }
-
- /**
- Convenience function to display banner with non .zero default edge insets
- */
- public func show(
- queuePosition: QueuePosition = .back,
- bannerPosition: BannerPosition = .top,
- queue: NotificationBannerQueue = NotificationBannerQueue.default,
- on viewController: UIViewController? = nil,
- edgeInsets: UIEdgeInsets = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8),
- cornerRadius: CGFloat? = nil,
- shadowColor: UIColor = .black,
- shadowOpacity: CGFloat = 1,
- shadowBlurRadius: CGFloat = 0,
- shadowCornerRadius: CGFloat = 0,
- shadowOffset: UIOffset = .zero,
- shadowEdgeInsets: UIEdgeInsets? = nil
- ) {
- show(
- queuePosition: queuePosition,
- bannerPosition: bannerPosition,
- queue: queue,
- on: viewController
- )
- }
- }
- extension MainController: CLLocationManagerDelegate {
- func getLocation() {
- //设置定位服务管理器代理
- locationManager.delegate = self
- //设置定位进度
- locationManager.desiredAccuracy = kCLLocationAccuracyBest
- //更新距离
- locationManager.distanceFilter = 0.1
- ////发送授权申请
- locationManager.requestAlwaysAuthorization()
- if CLLocationManager.locationServicesEnabled()
- {
- //允许使用定位服务的话,开启定位服务更新
- locationManager.startUpdatingLocation()
- print("定位开始")
- }
- }
- func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
- print("定位失败")
- DispatchQueue.main.async {
- self.webView.evaluateJavaScript("onIosLocationError(\(self.getLocationTaskId),\"\(error.localizedDescription)\")") { (data, err) in
- }
- }
- }
- func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
- //获取最新的坐标
- let currLocation:CLLocation = locations.last!
- var province:String = String.init()
- var city:String = String.init()
- let geocoder:CLGeocoder = CLGeocoder()
- geocoder.reverseGeocodeLocation(currLocation) { placemarksArray, error in
- if (error) == nil {
- if placemarksArray!.count > 0 {
- let placemark = placemarksArray?[0]
- province = placemark?.administrativeArea ?? ""
- city = placemark?.locality ?? ""
- let locationDic:Dictionary<String, String> = [
- "longitude":"\(currLocation.coordinate.longitude)",
- "latitude":"\(currLocation.coordinate.latitude)",
- "province":"\(province)",
- "city":"\(city)"
- ]
-
- let data = try? JSONSerialization.data(withJSONObject: locationDic, options: JSONSerialization.WritingOptions.init(rawValue:0))
- var result = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)! as String
- result = result.replacingOccurrences(of: "\"", with: "\\\"")
- print("定位成功:\(result)")
- DispatchQueue.main.async {
- self.webView.evaluateJavaScript("onIosLocationSuccess(\(self.getLocationTaskId),\"\(result)\")") { (data, err) in
-
- }
- }
- }
- }
-
- }
- locationManager.stopUpdatingLocation()
-
- }
- }
- extension MainController: LBXScanViewControllerDelegate {
-
- func scanFinished(scanResult: LBXScanResult, error: String?) {
- let scanInfo:String? = scanResult.strScanned
- if scanResult.strScanned != nil {
- DispatchQueue.main.async {
- do{
- let data = try? JSONEncoder().encode(scanInfo)
- let jsonArr = String(data: data!, encoding:String.Encoding.utf8)!
- self.webView.evaluateJavaScript("onIosScanCodeSuccess(\(self.scanCodeTaskId),\(jsonArr))") { (data, err) in
- print("将\(String(describing: scanInfo!))传回H5页面")
- }
- }
- }
- }else {
- DispatchQueue.main.async {
- self.webView.evaluateJavaScript("onIosScanCodeError(\(self.scanCodeTaskId))") { (data, err) in
- print("扫码错误")
- }
- }
- }
-
- }
-
- @objc func codeScan() {
- //设置扫码区域参数
- var style = LBXScanViewStyle()
- style.centerUpOffset = 44
- style.photoframeAngleStyle = LBXScanViewPhotoframeAngleStyle.On
- style.photoframeLineW = 6
- style.photoframeAngleW = 24
- style.photoframeAngleH = 24
- style.isNeedShowRetangle = true
- style.anmiationStyle = LBXScanViewAnimationStyle.NetGrid
-
- //使用的支付宝里面网格图片
- style.animationImage = UIImage(named: "CodeScan.bundle/qrcode_scan_part_net")
- let vc = LBXScanViewController()
- vc.scanStyle = style
- vc.scanResultDelegate = self
- DispatchQueue.main.async {
- self.navigationController?.navigationBar.isHidden = false
- self.navigationController?.pushViewController(vc, animated: true)
- }
-
- }
- }
- extension String {
- //返回第一次出现的指定子字符串在此字符串中的索引
- //(如果backwards参数设置为true,则返回最后出现的位置)
- func positionOf(sub:String, backwards:Bool = false)->Int {
- var pos = -1
- if let range = range(of:sub, options: backwards ? .backwards : .literal ) {
- if !range.isEmpty {
- pos = self.distance(from:startIndex, to:range.lowerBound)
- }
- }
- return pos
- }
-
- func toDictionary() -> [String : Any] {
-
- var result = [String : Any]()
- guard !self.isEmpty else { return result }
-
- guard let dataSelf = self.data(using: .utf8) else {
- return result
- }
-
- if let dic = try? JSONSerialization.jsonObject(with: dataSelf,
- options: .mutableContainers) as? [String : Any] {
- result = dic
- }
- return result
-
- }
-
- //将原始的url编码为合法的url
- func urlEncoded() -> String {
- let encodeUrlString = self.addingPercentEncoding(withAllowedCharacters:
- .urlQueryAllowed)
- return encodeUrlString ?? ""
- }
-
- //将编码后的url转换回原始的url
- func urlDecoded() -> String {
- return self.removingPercentEncoding ?? ""
- }
-
- /// String使用下标截取字符串
- /// string[index] 例如:"abcdefg"[3] // c
- subscript (i:Int)->String{
- let startIndex = self.index(self.startIndex, offsetBy: i)
- let endIndex = self.index(startIndex, offsetBy: 1)
- return String(self[startIndex..<endIndex])
- }
- /// String使用下标截取字符串
- /// string[index..<index] 例如:"abcdefg"[3..<4] // d
- subscript (r: Range<Int>) -> String {
- get {
- let startIndex = self.index(self.startIndex, offsetBy: r.lowerBound)
- let endIndex = self.index(self.startIndex, offsetBy: r.upperBound)
- return String(self[startIndex..<endIndex])
- }
- }
- /// String使用下标截取字符串
- /// string[index,length] 例如:"abcdefg"[3,2] // de
- subscript (index:Int , length:Int) -> String {
- get {
- let startIndex = self.index(self.startIndex, offsetBy: index)
- let endIndex = self.index(startIndex, offsetBy: length)
- return String(self[startIndex..<endIndex])
- }
- }
- // 截取 从头到i位置
- func substring(to:Int) -> String{
- return self[0..<to]
- }
- // 截取 从i到尾部
- func substring(from:Int) -> String{
- return self[from..<self.count]
- }
-
- }
|