From 4bee99bfcb800c2ddc8f27e0bb7feb78f7fe1ded Mon Sep 17 00:00:00 2001 From: JianMiau Date: Thu, 25 Aug 2022 14:25:48 +0800 Subject: [PATCH] [add] iOS TTS --- assets/Script/Manager.ts | 194 +++++++++--------- assets/Script/NativeClass.ts | 194 ++++++++++++++++++ ..._to_Speech.ts.meta => NativeClass.ts.meta} | 2 +- assets/Script/Text_to_Speech.ts | 41 ---- 4 files changed, 294 insertions(+), 137 deletions(-) create mode 100644 assets/Script/NativeClass.ts rename assets/Script/{Text_to_Speech.ts.meta => NativeClass.ts.meta} (74%) delete mode 100644 assets/Script/Text_to_Speech.ts diff --git a/assets/Script/Manager.ts b/assets/Script/Manager.ts index b5d51b6..632151d 100644 --- a/assets/Script/Manager.ts +++ b/assets/Script/Manager.ts @@ -1,119 +1,123 @@ -import Text_to_Speech from "./Text_to_Speech"; +import NativeClass from "./NativeClass"; const { ccclass, property } = cc._decorator; @ccclass export default class Manager extends cc.Component { - //#region 外調參數 + //#region 外調參數 - @property({ type: cc.WebView }) - public webview: cc.WebView = null; + @property({ type: cc.WebView }) + public webview: cc.WebView = null; - @property({ type: cc.Node }) - public BG: cc.Node = null; + @property({ type: cc.Node }) + public BG: cc.Node = null; - //#endregion + //#endregion - //#region private + //#region private - private _text_to_Speech: Text_to_Speech; + // private _text_to_Speech: Text_to_Speech; - //#endregion + //#endregion - //#region Lifecycle + //#region Lifecycle - protected onLoad(): void { - if (CC_DEBUG) { - console.log("Debug"); - } - let self: this = this; - this._text_to_Speech = new Text_to_Speech(); - window.addEventListener("message", function (e: MessageEvent): void { - let data: any = e.data; - let method: string = data.method; - let value: any = data.value; - self.Birdge(method, ...value); - }, false); + protected onLoad(): void { + if (CC_DEBUG) { + console.log("Debug"); + } - if (!window["Bridge"]) { - window["Bridge"] = function (method: string = "", value: string = ""): void { - self.Birdge(method, value); - }; - } - let href: string = window.location.href; + new NativeClass(); - // let url: string = `https://karolchang.github.io/jm-expense-vue-ts/?host=${href}&ignore=${Date.now()}`; - // let url: string = `http://220.134.195.1/public/bonus_casino/html5/jianmiau/BJ_Casino_Rank/?v=${Date.now()}`; - // let url: string = `http://karol.jianmiau.cf/jm-expense-vue-ts/?v=${Date.now()}`; - let url: string = `https://jm-expense-2022.firebaseapp.com/login?v=${Date.now()}`; - this.webview.url = url; - // this.webview.url = `http://localhost:8080/jm-expense-vue-ts/?host=${href}&ignore=${Date.now()}`; - this.webview.node.active = true; + let self: this = this; + // this._text_to_Speech = new Text_to_Speech(); + window.addEventListener("message", function (e: MessageEvent): void { + let data: any = e.data; + let method: string = data.method; + let value: any = data.value; + self.Birdge(method, ...value); + }, false); - cc.view.setResizeCallback(this._resize.bind(this)); - this._resize(); - } + if (!window["Bridge"]) { + window["Bridge"] = function (method: string = "", value: string = ""): void { + self.Birdge(method, value); + }; + } + let href: string = window.location.href; - /** 跨版本溝通 - * @example - * CallParent('Speak', '我愛豬涵') - */ - public Birdge(method: string, value: string = ""): void { - let self: this = this; - if (method && self[method]) { - if (value) { - self[method](value); - return; - } else if (self[method]) { - self[method](); - return; - } - } - console.log(`not function: ${method}, value: ${value}`); - } + // let url: string = `https://karolchang.github.io/jm-expense-vue-ts/?host=${href}&ignore=${Date.now()}`; + // let url: string = `http://220.134.195.1/public/bonus_casino/html5/jianmiau/BJ_Casino_Rank/?v=${Date.now()}`; + // let url: string = `http://karol.jianmiau.cf/jm-expense-vue-ts/?v=${Date.now()}`; + let url: string = `https://jm-expense-2022.firebaseapp.com/login?v=${Date.now()}`; + this.webview.url = url; + // this.webview.url = `http://localhost:8080/jm-expense-vue-ts/?host=${href}&ignore=${Date.now()}`; + this.webview.node.active = true; - public CloseBG(): void { - this.BG.destroy(); - } + cc.view.setResizeCallback(this._resize.bind(this)); + this._resize(); + } - public Log(msg: string): void { - console.log(msg); - } + /** 跨版本溝通 + * @example + * CallParent('Speak', '我愛豬涵') + */ + public Birdge(method: string, value: string = ""): void { + let self: this = this; + if (method && self[method]) { + if (value) { + self[method](value); + return; + } else if (self[method]) { + self[method](); + return; + } + } + console.log(`not function: ${method}, value: ${value}`); + } - public Speak(msg: string): void { - this._text_to_Speech.speak(msg); - } + public CloseBG(): void { + this.BG.destroy(); + } - public Alert(msg: string): void { - alert(msg); - } + public Log(msg: string): void { + console.log(msg); + } - private _resize(): void { - let Canvas: cc.Canvas = cc.Canvas.instance; - let rect: DOMRect = cc.game.canvas.getBoundingClientRect(); - /** 判断是否是横屏 */ - let landscape: boolean = false; - if (rect.width > rect.height) { - landscape = true; - } - // 根据横竖屏调整节点的位置适配等 - let frameSize: cc.Size = cc.view.getFrameSize(); - if (landscape) { - // 横屏 - cc.view.setOrientation(cc.macro.ORIENTATION_LANDSCAPE); - if (frameSize.height > frameSize.width) { - cc.view.setFrameSize(frameSize.height, frameSize.width); - } - Canvas.designResolution = cc.size(1920, 1080); - } else { - // 竖屏 - cc.view.setOrientation(cc.macro.ORIENTATION_PORTRAIT); - if (frameSize.width > frameSize.height) { - cc.view.setFrameSize(frameSize.height, frameSize.width); - } - Canvas.designResolution = cc.size(1080, 1920); - } - } + public Speak(msg: string): void { + // this._text_to_Speech.speak(msg); + NativeClass.Instance.TTS_Play(msg); + } - //#endregion + public Alert(msg: string): void { + alert(msg); + } + + private _resize(): void { + let Canvas: cc.Canvas = cc.Canvas.instance; + let rect: DOMRect = cc.game.canvas.getBoundingClientRect(); + /** 判断是否是横屏 */ + let landscape: boolean = false; + if (rect.width > rect.height) { + landscape = true; + } + // 根据横竖屏调整节点的位置适配等 + let frameSize: cc.Size = cc.view.getFrameSize(); + if (landscape) { + // 横屏 + cc.view.setOrientation(cc.macro.ORIENTATION_LANDSCAPE); + if (frameSize.height > frameSize.width) { + cc.view.setFrameSize(frameSize.height, frameSize.width); + } + Canvas.designResolution = cc.size(1920, 1080); + } else { + // 竖屏 + cc.view.setOrientation(cc.macro.ORIENTATION_PORTRAIT); + if (frameSize.width > frameSize.height) { + cc.view.setFrameSize(frameSize.height, frameSize.width); + } + Canvas.designResolution = cc.size(1080, 1920); + } + } + + //#endregion } diff --git a/assets/Script/NativeClass.ts b/assets/Script/NativeClass.ts new file mode 100644 index 0000000..baba1d8 --- /dev/null +++ b/assets/Script/NativeClass.ts @@ -0,0 +1,194 @@ +const { ccclass } = cc._decorator; + +@ccclass +export default class NativeClass extends cc.Component { + //#region static 屬性 + + private static _instance: NativeClass = null; + public static get Instance(): NativeClass { return NativeClass._instance; } + + //#endregion + + //#region public 屬性 + + public URLscheme: Object = {}; + + public URLschemeFlags: number = 0; + + //#endregion + + //#region Lifecycle + + constructor() { + super(); + NativeClass._instance = this; + this.init(); + } + + private init(): void { + let self: this = this; + let HttpData: any[] = []; + // let HttpParmData: any[] = []; + // 註冊要被Java、OC呼叫的事件 + if (!window["JSBridge"]) { + window["JSBridge"] = function (method: string = "", value: string = ""): void { + if (method || self[method]) { + if (value) { + self[method](value); + } else if (self[method]) { + self[method](); + } else { + console.log(`not function: ${method}, value: ${value}`); + } + } else { + console.log(`not function: ${method}, value: ${value}`); + } + }; + } + if (cc.sys.isBrowser) { + let url: string = window.location.search; + // let request: object = []; + if (url.indexOf("?") !== -1) { + let str: string = url.substring(1); + let strs: string[] = str.split("&"); + for (let i: number = 0; i < strs.length; i++) { + this.URLscheme[strs[i].split("=")[0]] = decodeURI(strs[i].split("=")[1]); + } + } + } else { + switch (cc.sys.os) { + case cc.sys.OS_WINDOWS: { + // cc.sys.platform = 101(DESKTOP_BROWSER) + break; + } + case cc.sys.OS_ANDROID: { + // cc.sys.platform = 3(Android) + + // 呼叫Java取得由URL打開時的網址(呼叫getIntent 無帶入參數(null) 回傳字串((Ljava/lang/String;)Ljava/lang/String;)) + /** 取得由URL打開時的網址(內容是自己取得後用特殊符號拼成字串) */ + let scheme: any = jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "getURLData", "(Ljava/lang/String;)Ljava/lang/String;", null); + if (scheme && scheme !== "null") { + let _Get_Arr: string[] = scheme.split("?"); + let Get_Arr: string[] = _Get_Arr[1].split("#"); + for (let i: number = 0; i < Get_Arr.length; i++) { + let Get: string[] = Get_Arr[i].split("$"); + HttpData[Get[0]] = Get[1]; + } + let Query: string = HttpData["Query"]; + if (Query) { + Get_Arr = Query.split("&"); + for (let i: number = 0; i < Get_Arr.length; i++) { + let Get: string[] = Get_Arr[i].split("="); + this.URLscheme[Get[0]] = Get[1]; + } + } + } + // cc.log("getIntent OK, " + getIntent); + break; + } + + case cc.sys.OS_IOS: { + // cc.sys.platform = 4(iPhone) + + // 呼叫OC取得由URL打開時的網址(呼叫getIntent 無帶入參數 回傳字串)(開發中功能,預計要取得由URL打開時的網址) + /** 取得由URL打開時的網址(內容是自己取得後用特殊符號拼成字串) */ + let scheme: any = jsb.reflection.callStaticMethod("AppController", "getIntent"); + if (scheme && scheme !== "null") { + let Get_Arr: string[] = scheme.split("#"); + for (let i: number = 0; i < Get_Arr.length; i++) { + let Get: string[] = Get_Arr[i].split("$"); + HttpData[Get[0]] = Get[1]; + } + let Query: string = HttpData["Query"]; + if (Query) { + Get_Arr = Query.split("&"); + for (let i: number = 0; i < Get_Arr.length; i++) { + let Get: string[] = Get_Arr[i].split("="); + this.URLscheme[Get[0]] = Get[1]; + } + } + } + // cc.log("getIntent OK, " + getIntent); + break; + } + + default: { + break; + } + } + } + } + + //#endregion + + //#region Custom Function + + /** + * TTS_Play + * @param {string} msg msg + */ + public TTS_Play(msg: string): void { + switch (cc.sys.os) { + case cc.sys.OS_WINDOWS: { + // // 網頁端 + break; + } + case cc.sys.OS_ANDROID: { + jsb.reflection.callStaticMethod("org/cocos2dx/javascript/AppActivity", "TTS_Play", "(Ljava/lang/String;)V", msg); + break; + } + + case cc.sys.OS_IOS: { + jsb.reflection.callStaticMethod("AppController", "TTS_Play:", msg); + break; + } + + default: { + break; + } + } + } + + public HideNativeSplash(): void { + if (CC_JSB) { + if (cc.sys.os === cc.sys.OS_ANDROID) { + // 反射调用原生的隐藏方法 + jsb.reflection.callStaticMethod( + "org/cocos2dx/javascript/AppActivity", + "hideSplash", + "()V" + ); + } + } + } + + public CCLOG(msg: String): void { + console.log(msg); + } + + public DispatchCallback(msg: string): void { + let data: string[] = msg.split("="); + let data1: string[] = data[1] ? data[1].split("#") : []; + + let scenename: string = cc.director.getScene().name; + // cc.director.on(cc.Director.EVENT_AFTER_SCENE_LAUNCH, callback, this); + // this.NativeCallback.DispatchCallback(data[0], data1); + } + + public ClearAllCache(): void { + cc.sys.localStorage.clear(); + cc.assetManager.bundles.clear(); + cc.assetManager.cacheManager.clearCache(); + cc.game.restart(); + } + + //#endregion +} + +//#region Enum + +export enum DeepLink { + ClearAllCache = "ClearAllCache", +} + +//#endregion \ No newline at end of file diff --git a/assets/Script/Text_to_Speech.ts.meta b/assets/Script/NativeClass.ts.meta similarity index 74% rename from assets/Script/Text_to_Speech.ts.meta rename to assets/Script/NativeClass.ts.meta index 490c585..83b965d 100644 --- a/assets/Script/Text_to_Speech.ts.meta +++ b/assets/Script/NativeClass.ts.meta @@ -1,6 +1,6 @@ { "ver": "1.0.8", - "uuid": "99fa9c05-c449-4a27-b629-42f77916556a", + "uuid": "5558f747-ed9e-4040-9a01-3b89b99ac37a", "isPlugin": false, "loadPluginInWeb": true, "loadPluginInNative": true, diff --git a/assets/Script/Text_to_Speech.ts b/assets/Script/Text_to_Speech.ts deleted file mode 100644 index 836d6a0..0000000 --- a/assets/Script/Text_to_Speech.ts +++ /dev/null @@ -1,41 +0,0 @@ -const responsiveVoice = window["responsiveVoice"]; - -export default class Text_to_Speech { - //#region 外調參數 - - private voice: string = null; - - //#endregion - - //#region Custom - - constructor() { - let self: this = this; - responsiveVoice.init(); - var voicelist = responsiveVoice.getVoices(); - this.setDefaultVoice(voicelist[14].name); - } - - public setDefaultVoice(voice: string): void { - this.voice = voice; - responsiveVoice.setDefaultVoice(voice); - } - - public speak(msg: string): void { - let self: this = this; - if (responsiveVoice.voiceSupport()) { - responsiveVoice.speak(msg, this.voice, { - onstart: function (Callback: any): void { - console.log(`onstart msg: ${msg}`); - }, - onend: function (Callback: any): void { - console.log(`onstart msg: ${msg}`); - }, - }); - } else { - console.error(`!responsiveVoice.voiceSupport`); - } - } - - //#endregion -}