1. 程式人生 > >在微信及支付寶下的音訊自動播放

在微信及支付寶下的音訊自動播放

廢話不多說,直接上程式碼。

// 微信、支付寶音訊Hack方案
; void function (win, doc, undefined) {
    // 原理:呼叫鏈中的某個事件被標識為使用者事件而非系統事件
    // 進而導致瀏覽器以為是使用者觸發播放而允許播放
    Audio.prototype._play = Audio.prototype.play;
    HTMLAudioElement.prototype._play = HTMLAudioElement.prototype.play;

    function wxPlay(audio) {
        /// <summary>
        /// 微信播放Hack
        /// </summary>
        /// <param name="audio" type="Audio">音訊物件</param>

        WeixinJSBridge.invoke('getNetworkType', {}, function (e) {
            audio._play();
        });
    }

    function alipayPlay(audio) {
        /// <summary>
        /// 支付寶播放Hack
        /// </summary>
        /// <param name="audio" type="Audio">音訊物件</param>

        AlipayJSBridge.call('getNetworkType', function (result) {
            audio._play();
        });
    }

    function play() {
        var self = this;

        self._play();

        try {
            wxPlay(self);
        } catch (ex) {
            document.addEventListener("WeixinJSBridgeReady", function evt() {
                wxPlay(self);
                document.removeEventListener("WeixinJSBridgeReady", evt, false);
            }, false);
        }

        try {
            alipayPlay(self);
        } catch (ex) {
            document.addEventListener('AlipayJSBridgeReady', function evt() {
                alipayPlay(self);
                document.removeEventListener("AlipayJSBridgeReady", evt, false);
            }, false);
        }
    }

    Audio.prototype.play = play;
    HTMLAudioElement.prototype.play = play;
}(window, document);

起因:

        在IOS及Android中無法自動播放音訊(出於流量和使用者體驗的考慮,所以用JS直接呼叫play是無效的)。

        但是產品狗們卻要求必須開啟頁面就播放聲音,這可難倒了很多人。

        那麼我們首先要知道什麼情況下呼叫play函式是有效的,什麼時候是無效的。

var audio = new Audio("xxx.mp3");

audio.play(); // 無效

document.body.onclick = function(){
    audio.play(); // 有效
};
        從上面的程式碼中可以看出,只有使用者事件中觸發play函式才有效。

        什麼是使用者事件?click事件、touch事件、mouse事件以及keyboard事件等必須使用者手動觸發的事件為使用者事件。

解決原理:

        既然是使用者事件才會觸發,那我們有沒有辦法模擬一個使用者事件?

        答案是肯定的,由於微信、支付寶有擴充套件API,而此類API是直接內嵌入Js中的,這時Js會把這些內容當成是使用者手動觸發的內容。

        所以我們就可以利用這個來達到效果。

        首先將原生的play函式儲存下來,然後重寫Audio以及HTMLAudioElement原型中的play函式。

        接下來是重點,我們要呼叫一個不會產生任何影響的應用擴充套件函式,並在回撥函式中觸發play。

        仔細看了一下微信以及支付寶中的介面,發現獲取網路資訊的介面最符合,因為即使失敗了也會呼叫回撥,而且沒有任何不良影響。

總結:

       有時候解決問題的方法有很多,只要能解決問題的方法就是好方法。