ข้ามไปที่เนื้อหา

เตรียมหน้าเว็บเพื่อให้บริการแอป

การตั้งค่าเว็บเพจสำหรับบริการแอป

ผู้ใช้แอปจะต้องผ่านขั้นตอนต่อไปนี้เพื่อติดตั้งและเรียกใช้แอป:

 

  1. คลิกปุ่มเปิดแอปบนหน้าเว็บที่แอปกำลังให้บริการ และดาวน์โหลดและติดตั้ง Crossplay Launcher.
  2. เรียกใช้ Crossplay Launcher.
  3. Crossplay Launcher จะดาวน์โหลดและติดตั้งแอปโดยอัตโนมัติ.
  4. Crossplay Launcher จะอัปเดตและเรียกใช้แอปโดยอัตโนมัติ.

 

ต่อไปนี้คือกระบวนการทั้งหมดในการให้บริการแอปจากหน้าเว็บโดยใช้ Crossplay Launcher.

 

 

หน้าเว็บสำหรับบริการแอปสามารถจัดเตรียมได้ในสองวิธี:

  1. เกม (https://withhive.com/)
  2. หน้าเว็บที่สร้างโดยบริษัทที่พัฒนาแอปนี้.

คู่มือนี้ให้ตัวอย่างและคำแนะนำเกี่ยวกับสิ่งที่ต้องดำเนินการบนหน้าเว็บเมื่อใช้ Crossplay Launcher เพื่อให้บริการแอปจากหน้าเว็บ ที่สร้างโดยนักพัฒนาแอป

ตรวจสอบเงื่อนไขบริการแอป

เมื่อผู้ใช้เข้าถึงหน้าเว็บ ให้ตรวจสอบว่า PC ของผู้ใช้ เช่น เวอร์ชัน OS ได้รับการสนับสนุนหรือไม่

  • OS ที่ได้รับการสนับสนุน: Windows 10 หรือสูงกว่า

หลังจากตรวจสอบเงื่อนไข หากมีปัญหาใด ๆ จะต้องมีป๊อปอัพข้อผิดพลาดแสดงให้ผู้ใช้เห็น

การนำปุ่มเปิดแอปและป๊อปอัปดาวน์โหลด Crossplay Launcher มาใช้

นำปุ่มเปิดแอปไปใช้บนหน้าเว็บ

 

สร้างหน้าต่างป๊อปอัพสำหรับดาวน์โหลดไฟล์ติดตั้ง Crossplay Launcher หน้าต่างป๊อปอัพต้องรวมคำแนะนำสำหรับการติดตั้ง Crossplay Launcher

 

การคลิกปุ่มเปิดแอปบนหน้าเว็บจะแสดงหน้าต่างป๊อปอัป หน้าต่างป๊อปอัปควรมีปุ่มเพื่อดาวน์โหลดไฟล์ติดตั้ง Crossplay Launcher

ตรวจสอบการติดตั้ง Crossplay Launcher

เมื่อผู้ใช้คลิกปุ่มเปิดแอปบนหน้าเว็บ จำเป็นต้องตรวจสอบว่า Crossplay Launcher ได้รับการติดตั้งบน PC ของผู้ใช้หรือไม่ ให้ดำเนินการรหัส JavaScript ต่อไปนี้บนหน้าเว็บเพื่อตรวจสอบว่า Crossplay Launcher ได้รับการติดตั้งบน PC ของผู้ใช้หรือไม่

JavaScript Code
!function (b, a) {
"object" == typeof exports && "object" == typeof module
? module.exports = a()
: "function" == typeof define && define.amd
    ? define("customProtocolCheck", [], a)
    : "object" == typeof exports
        ? exports.customProtocolCheck = a()
        : b.customProtocolCheck = a()
}(window, function () {
return function (b) {
var c = {};
function a(d) {
    if (c[d]) 
        return c[d].exports;
    var e = c[d] = {
        i: d,
        l: !1,
        exports: {}
    };
    return b[d].call(e.exports, e, e.exports, a),
    e.l = !0,
    e.exports
}
return a.m = b,
a.c = c,
a.d = function (b, c, d) {
    a.o(b, c) || Object.defineProperty(b, c, {
        enumerable: !0,
        get: d
    })
},
a.r = function (a) {
    "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(
        a,
        Symbol.toStringTag,
        {value: "Module"}
    ),
    Object.defineProperty(a, "__esModule", {
        value: !0
    })
},
a.t = function (b, c) {
    if (
        1 & c && (b = a(b)),
        8 & c || 4 & c && "object" == typeof b && b && b.__esModule
    ) 
        return b;
    var d = Object.create(null);
    if (a.r(d), Object.defineProperty(d, "default", {
        enumerable: !0,
        value: b
    }), 2 & c && "string" != typeof b) 
        for (var e in b) 
            a.d(d, e, (function (a) {
                return b[a]
            }).bind(null, e));
return d
},
a.n = function (c) {
    var b = c && c.__esModule
        ? function () {
            return c.default
        }
        : function () {
            return c
        };
    return a.d(b, "a", b),
    b
},
a.o = function (a, b) {
    return Object
        .prototype
        .hasOwnProperty
        .call(a, b)
},
a.p = "",
a(a.s = 0)
}({
"./index.js": function (module, exports) {
    eval(
        'var browser = {\n  getUserAgent: function getUserAgent() {\n    return window.' +
        'navigator.userAgent;\n  },\n  userAgentContains: function userAgentContains(br' +
        'owserName) {\n    browserName = browserName.toLowerCase();\n    return this.ge' +
        'tUserAgent().toLowerCase().indexOf(browserName) > -1;\n  },\n  isOSX: function' +
        ' isOSX() {\n    return this.userAgentContains("Macintosh");\n  },\n  isFirefox' +
        ': function isFirefox() {\n    return this.userAgentContains("firefox");\n  },' +
        '\n  isInternetExplorer: function isInternetExplorer() {\n    return this.userA' +
        'gentContains("trident");\n  },\n\n  /**\r\n   * Detects IE 11 and older\r\n   ' +
        '* @return {Boolean} Returns true when IE 11 and older\r\n   */\n  isIE: functi' +
        'on isIE() {\n    var ua = this.getUserAgent().toLowerCase(); // Test values.\n' +
        '    // Uncomment to check result\n    // IE 10\n    // ua = \'Mozilla/5.0 (com' +
        'patible; MSIE 10.0; Windows NT 6.2; Trident/6.0)\';\n    // IE 11\n    // ua =' +
        ' \'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko/20100101 Fire' +
        'fox/12.0\';\n\n    var msie = ua.indexOf("msie");\n\n    if (msie > 0) {\n    ' +
        '  // IE 10 or older\n      return true;\n    }\n\n    var trident = ua.indexOf' +
        '("trident/");\n\n    if (trident > 0) {\n      // IE 11\n      return true;\n ' +
        '   } // other browser\n\n\n    return false;\n  },\n  isEdge: function isEdge(' +
        ') {\n    var ua = this.getUserAgent().toLowerCase(); // Test values.\n    // U' +
        'ncomment to check result\n    // Edge\n    // ua = \'Mozilla/5.0 (Windows NT 1' +
        '0.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 S' +
        'afari/537.36 Edge/12.10240\';\n\n    var edge = ua.indexOf("edge");\n\n    if ' +
        '(edge > 0) {\n      return true;\n    }\n\n    return false;\n  },\n  isChrome' +
        ': function isChrome() {\n    // IE11 returns undefined for window.chrome\n    ' +
        '// and new Opera 30 outputs true for window.chrome\n    // but needs to check ' +
        'if window.opr is not undefined\n    // and new IE Edge outputs to true for win' +
        'dow.chrome\n    // and if not iOS Chrome check\n    var isChromium = window.ch' +
        'rome;\n    var winNav = window.navigator;\n    var vendorName = winNav.vendor;' +
        '\n    var isOpera = typeof window.opr !== "undefined";\n    var isIEedge = win' +
        'Nav.userAgent.indexOf("Edge") > -1;\n    var isIOSChrome = winNav.userAgent.ma' +
        'tch("CriOS");\n    return isChromium !== null && typeof isChromium !== "undefi' +
        'ned" && vendorName === "Google Inc." && isOpera === false && isIEedge === fals' +
        'e || isIOSChrome;\n  },\n  isWhale: function isWhale() {\n    // IE11 returns ' +
        'undefined สำหร window.chrome\n    // และ Opera 30 ใหม่ให้ผลลัพธ์เป็น true สำหรับ window.c' +
        'hrome\n    // แต่ต้องตรวจสอบว่า window.opr ไม่ได้ undefined\n    // และ ne' +
        'w IE Edge ใหผลลพธเป true สำหร window.chrome\n    // และถ้าไม่ใช่ iOS Chrome chec' +
        'k\n    var isChromium = window.chrome;\n    var winNav = window.navigator;\n  ' +
        '  var vendorName = winNav.vendor;\n    var isOpera = typeof window.opr !== "un' +
        'defined";\n    var isIEedge = winNav.userAgent.indexOf("Edge") > -1;\n    var ' +
        'isIOSChrome = winNav.userAgent.match("CriOS");\n    return isChromium !== null' +
        ' && typeof isChromium !== "undefined" && vendorName === "NAVER Corp." && isOpe' +
        'ra === false && isIEedge === false || isIOSChrome;\n  },\n  isOpera: function ' +
        'isOpera() {\n    return this.userAgentContains(" OPR/");\n  }\n};\nvar DEFAULT' +
        '_CUSTOM_PROTOCOL_FAIL_CALLBACK_TIMEOUT;\n\nvar registerEvent = function regist' +
        'erEvent(target, eventType, cb) {\n  if (target.addEventListener) {\n    target' +
        '.addEventListener(eventType, cb);\n    return {\n      remove: function remove' +
        '() {\n        target.removeEventListener(eventType, cb);\n      }\n    };\n  }' +
        ' else {\n    target.attachEvent(eventType, cb);\n    return {\n      remove: f' +
        'unction remove() {\n        target.detachEvent(eventType, cb);\n      }\n    }' +
        ';\n  }\n};\n\nvar createHiddenIframe = function createHiddenIframe(target, uri' +
        ') {\n  var iframe = document.createElement("iframe");\n  iframe.src = uri;\n  ' +
        'iframe.id = "hiddenIframe";\n  iframe.style.display = "none";\n  target.append' +
        'Child(iframe);\n  return iframe;\n};\n\nvar openUriWithHiddenFrame = function ' +
        'openUriWithHiddenFrame(uri, failCb, successCb) {\n  var timeout = setTimeout(f' +
        'unction () {\n    failCb();\n    handler.remove();\n  }, DEFAULT_CUSTOM_PROTOC' +
        'OL_FAIL_CALLBACK_TIMEOUT);\n  var iframe = document.querySelector("#hiddenIfra' +
        'me");\n\n  if (!iframe) {\n    iframe = createHiddenIframe(document.body, "abo' +
        'ut:blank");\n  }\n\n  onBlur = function onBlur() {\n    clearTimeout(timeout);' +
        '\n    handler.remove();\n    successCb();\n  };\n\n  var handler = registerEve' +
        'nt(window, "blur", onBlur);\n  iframe.contentWindow.location.href = uri;\n};\n' +
        '\nvar openUriWithTimeoutHack = function openUriWithTimeoutHack(uri, failCb, su' +
        'ccessCb) {\n  var timeout = setTimeout(function () {\n    failCb();\n    handl' +
        'er.remove();\n  }, DEFAULT_CUSTOM_PROTOCOL_FAIL_CALLBACK_TIMEOUT); //handle pa' +
        'ge running in an iframe (blur must be registered with top level window)\n\n  v' +
        'ar target = window;\n\n  while (target.parent && target != target.parent) {\n ' +
        '   target = target.parent;\n  }\n\n  onBlur = function onBlur() {\n    clearTi' +
        'meout(timeout);\n    handler.remove();\n    successCb();\n  };\n\n  var handle' +
        'r = registerEvent(target, "blur", onBlur);\n  window.location = uri;\n};\n\nva' +
        'r openUriUsingFirefox = function openUriUsingFirefox(uri, failCb, successCb) {' +
        '\n  var iframe = document.querySelector("#hiddenIframe");\n\n  if (!iframe) {' +
        '\n    iframe = createHiddenIframe(document.body, "about:blank");\n  }\n\n  try' +
        ' {\n    iframe.contentWindow.location.href = uri;\n    successCb();\n  } catch' +
        ' (e) {\n    if (e.name == "NS_ERROR_UNKNOWN_PROTOCOL") {\n      failCb();\n   ' +
        ' }\n  }\n};\n\nvar openUriWithMsLaunchUri = function openUriWithMsLaunchUri(ur' +
        'i, failCb, successCb) {\n  navigator.msLaunchUri(uri, successCb, failCb);\n};' +
        '\n\nvar getBrowserVersion = function getBrowserVersion() {\n  var ua = window.' +
        'navigator.userAgent;\n  var tem,\n      M = ua.match(/(opera|chrome|safari|fir' +
        'efox|msie|trident(?=\\/))\\/?\\s*(\\d+)/i) || [];\n\n  if (/trident/i.test(M[1' +
        '])) {\n    tem = /\\brv[ :]+(\\d+)/g.exec(ua) || [];\n    return parseFloat(te' +
        'm[1]) || "";\n  }\n\n  if (M[1] === "Chrome") {\n    tem = ua.match(/\\b(OPR|E' +
        'dge)\\/(\\d+)/);\n\n    if (tem != null) {\n      return parseFloat(tem[2]);\n' +
        '    }\n  }\n\n  M = M[2] ? [M[1], M[2]] : [window.navigator.appName, window.na' +
        'vigator.appVersion, "-?"];\n  if ((tem = ua.match(/version\\/(\\d+)/i)) != nul' +
        'l) M.splice(1, 1, tem[1]);\n  return parseFloat(M[1]);\n};\n\nvar protocolChec' +
        'k = function protocolCheck(uri, failCb, successCb) {\n  var timeout = argument' +
        's.length > 3 && arguments[3] !== undefined ? arguments[3] : 2000;\n  var unsup' +
        'portedCb = arguments.length > 4 ? arguments[4] : undefined;\n\n  var failCallb' +
        'ack = function failCallback() {\n    failCb && failCb();\n  };\n\n  var succes' +
        'sCallback = function successCallback() {\n    successCb && successCb();\n  };' +
        '\n\n  var unsupportedCallback = function unsupportedCallback() {\n    unsuppor' +
        'tedCb && unsupportedCb();\n  };\n\n  var openUri = function openUri() {\n    i' +
        'f (browser.isFirefox()) {\n      var browserVersion = getBrowserVersion();\n\n' +
        '      if (browserVersion >= 64) {\n        openUriWithHiddenFrame(uri, failCal' +
        'lback, successCallback);\n      } else {\n        openUriUsingFirefox(uri, fai' +
        'lCallback, successCallback);\n      }\n    } else if (browser.isWhale()) {\n  ' +
        '    openUriWithTimeoutHack(uri, failCallback, successCallback);\n    } else if' +
        ' (browser.isChrome()) {\n      openUriWithTimeoutHack(uri, failCallback, succe' +
        'ssCallback);\n    } else if (browser.isOSX()) {\n      openUriWithHiddenFrame(' +
        'uri, failCallback, successCallback);\n    } else {\n      //not supported, imp' +
        'lement please\n      unsupportedCallback();\n    }\n  };\n\n  if (timeout) {\n' +
        '    DEFAULT_CUSTOM_PROTOCOL_FAIL_CALLBACK_TIMEOUT = timeout;\n  }\n\n  if (bro' +
        'wser.isEdge() || browser.isIE()) {\n    //for IE and Edge in Win 8 and Win 10' +
        '\n    openUriWithMsLaunchUri(uri, failCb, successCb);\n  } else {\n    if (doc' +
        'ument.hasFocus()) {\n      openUri();\n    } else {\n      var focusHandler = ' +
        'registerEvent(window, "focus", function () {\n        focusHandler.remove();\n' +
        '        openUri();\n      });\n    }\n  }\n};\n\nmodule.exports = protocolChec' +
        'k;\n\n//# sourceURL=webpack://customProtocolCheck/./index.js?'
    )
},
0: function (module, exports, __webpack_require__) {
    eval(
        'module.exports = __webpack_require__(/*! /Users/shahv/Viresh/work/rnd/custom-p' +
        'rotocol-check/index.js */"./index.js");\n\n\n//# sourceURL=webpack://customPro' +
        'tocolCheck/multi_./index.js?'
    )
}
})
})

หากCrossplay Launcherยังไม่ได้ติดตั้งบนPCของผู้ใช้ ให้ดำเนินการฟีเจอร์เพื่อติดตั้งCrossplay Launcherและแอปพร้อมกัน หากCrossplay Launcherถูกติดตั้งแล้ว ให้ดำเนินการฟีเจอร์เพื่อเรียกใช้Crossplay Launcher

ติดตั้งทั้ง Crossplay Launcher และแอปพร้อมกัน

ในระหว่างกระบวนการติดตั้ง Crossplay Launcher แอปสามารถติดตั้งและรันโดยอัตโนมัติได้เช่นกัน.

Implement event for downloading Crossplay Launcher installation file: download the installation file

หลังจากที่ได้ทำการติดตั้ง คู่มือข้างต้น เพื่อสร้างปุ่มเปิดแอปและป๊อปอัพแล้ว ให้ทำการพัฒนาฟีเจอร์สำหรับผู้ใช้ในการดาวน์โหลดไฟล์ติดตั้ง Crossplay Launcher ไฟล์ติดตั้ง hivecrossplay-fn.qpyou.cn/hivecrossplay/p/w/Installer.exe เมื่อพวกเขาคลิกที่ปุ่มดาวน์โหลดในป๊อปอัพ

ดำเนินการเหตุการณ์สำหรับการดาวน์โหลดไฟล์ติดตั้ง Crossplay Launcher: การติดตั้งแอปอัตโนมัติ

เมื่อผู้ใช้คลิกปุ่มดาวน์โหลด ให้ดำเนินการฟีเจอร์ในการคัดลอก Auto Installation URI ไปยังคลิปบอร์ดของ PC ของผู้ใช้ หลังจากติดตั้ง Crossplay Launcher แล้ว Crossplay Launcher จะค้นหาคลิปบอร์ดโดยอัตโนมัติสำหรับ URI การติดตั้งเกม หากพบ จะติดตั้งแอปที่สอดคล้องกับ URI หากไม่พบ URI การติดตั้งเกมในคลิปบอร์ด จะติดตั้งเฉพาะ Crossplay Launcher บน PC ของผู้ใช้เท่านั้น เพื่อที่จะติดตั้งแอป ผู้ใช้ต้องกลับไปที่หน้าเว็บและคลิกปุ่มเริ่มแอปอีกครั้ง ดูรายละเอียดเพิ่มเติมที่ เรียกใช้ Crossplay Launcher สำหรับรายละเอียดเพิ่มเติม.

การรับ URI การติดตั้งอัตโนมัติ

รับ URI การติดตั้งอัตโนมัติจาก Hive Console (Sandbox หรือ Commercial) > Crossplay Launcher > App Management > Download Setting > Launcher Installation/Launch URI.

# Example
hivelauncher:?app_id=com.com2us.hivesdk.windows.microsoftstore.global.normal&start_point=9 f387268b8ea6c3e0016c8fd41562ed53d4c38338

คัดลอก URI ไปยังคลิปบอร์ด

ดำเนินการคัดลอก URI การติดตั้งอัตโนมัติที่ได้รับไปยังพื้นที่คลิปบอร์ดของผู้ใช้ PC .

เรียกใช้ Crossplay Launcher

เมื่อ Crossplay Launcher ถูกติดตั้งบน PC ของผู้ใช้ ให้ดำเนินการตาม JavaScript โค้ดต่อไปนี้เมื่อเกิดเหตุการณ์ที่ผู้ใช้คลิกปุ่มเริ่มแอปบนหน้าเว็บ โค้ด JavaScript จะเรียกใช้ Crossplay Launcher ด้วย URI ที่เริ่มต้น และ Crossplay Launcher จะติดตั้งและเรียกใช้แอปโดยอัตโนมัติ.

รับ URI การเปิดตัว

รับ URI การเปิดตัวจาก Hive Console (Sandbox หรือ Live) > Crossplay Launcher > การจัดการแอป > การตั้งค่าการดาวน์โหลด > การติดตั้ง/URI การเปิดตัว.

# Example
hivelauncher:?app_id=com.com2us.hivesdk.windows.microsoftstore.global.normal&start_point=9

(ไม่บังคับ) ใช้พารามิเตอร์ที่กำหนดเองใน execution uri

หากนักพัฒนาต้องการ พวกเขาสามารถเพิ่มพารามิเตอร์ที่กำหนดเองลงใน URI การเปิดเกมที่ได้รับจาก Hive คอนโซล ด้านล่างนี้คือตัวอย่างของ URI การเปิดที่มีพารามิเตอร์ที่กำหนดเองเพิ่มเข้าไป

# Example
hivelauncher:?app_id=com.com2us.hivesdk.windows.microsoftstore.global.normal&start_point=9&custom_param1=value1&custom_param2=value2 


URI การติดตั้งเกมอัตโนมัติ game auto-installation URI สามารถได้รับจากคอนโซล Hive ในตอนแรก อย่างไรก็ตาม หากคุณได้เพิ่มพารามิเตอร์ที่กำหนดเองไปยัง URI การดำเนินการเกม คุณจะต้องสร้างและใช้ URI การติดตั้งอัตโนมัติ ด้วยตัวเอง ด้านล่างนี้ ให้แฮช URI การดำเนินการด้วย SHA1 และจากนั้นแนบค่าแฮชนี้ไปยัง URI การดำเนินการเอง หลังจากนั้น ให้ใช้สตริงทั้งหมดรวมถึงค่าแฮชเป็น URI การติดตั้งอัตโนมัติ

# Hash the execution URI with custom parameters.
hivelauncher:?app_id=com.com2us.hivesdk.windows.microsoftstore.global.normal&start_point=9&custom_param1=value1&custom_param2=value2 

# The hashed value is as follows:
CFF1F0C2FC15E4CF3C06A81A41E1E079B2BD7A9D

# Append the hash value to the execution URI as shown below. Use the entire string as the auto-installation URI.
hivelauncher:?app_id=com.com2us.hivesdk.windows.microsoftstore.global.normal&start_point=9&custom_param1=value1&custom_param2=value2 CFF1F0C2FC15E4CF3C06A81A41E1E079B2BD7A9D
Note

คุณสามารถตรวจสอบ ค่าพารามิเตอร์ที่กำหนดเองที่ป้อนใน URI การดำเนินการ ในไคลเอนต์เกม

นำไปใช้และรันโค้ด Javascript

เมื่อ Crossplay Launcher ถูกติดตั้งบน PC ของผู้ใช้ ให้ดำเนินการเรียกใช้ JavaScript เมื่อผู้ใช้คลิกปุ่มเปิดแอปบนหน้าเว็บ

    event.preventDefault
        ? event.preventDefault()
        : (event.returnValue = false);
    window.customProtocolCheck({
        # Implement executing the launch URI.
        # The launch URI launches the Crossplay Launcher. The Crossplay Launcher automatically installs and runs the app.
    }, function (e) {
        console.log("FAIL");
        {
            # Handling Crossplay Launcher Execution Failure
        }
    }, function (e) {
        console.log("SUCCESS");
    }, 2500, function (e) {
        console.log("Not Supported");
        {
            # Handling No Response After 2500ms from Crossplay Launcher Execution Request
        }
    });

 

ด้านล่างนี้คือตัวอย่างของผลลัพธ์เมื่อกดปุ่ม "เล่นบน PC" ซึ่งจะกระตุ้นการทำงานของโค้ด JavaScript ขณะที่ Crossplay Launcher ทำงาน จะมีการแจ้งเตือนในเบราว์เซอร์ถามว่าต้องการให้ดำเนินการ Crossplay Updater หรือไม่ ซึ่งจะทำการอัปเดต Crossplay Launcher เอง

Note

เนื่องจากความแตกต่างระหว่าง JAVA's URLEncoder.encode() และ JavaScript's encodeURIComponent() เมื่อทำการดำเนินการของแอปใน JAVA จะต้องมีการดำเนินการ replaceAll("\+", "%20")