python 全棧開發,Day127(app端內容播放,web端的玩具,app經過websocket遠程遙控玩具播放內容,玩具管理頁面)

昨日內容回顧

1. 小爬爬 內容採集
    XMLY 的 兒童頻道 requests 

2. 登錄 註冊 自動登錄 退出
    mui.post("請求地址",{數據},function(){})
    plus.storage.setItem(key,value)
    plus.storage.getItem(key)
    plus.storage.removeItem(key)
    
3. app 首頁內容部分
    document.createElement("div")
View Code

 

1、app端內容播放

下載代碼javascript

https://github.com/987334176/Intelligent_toy/archive/v1.0.zipcss

注意:因爲涉及到版權問題,此附件沒有圖片和音樂。請參考昨天的代碼,手動採集一下!html

請參考連接:前端

http://www.javashuo.com/article/p-splctlzd-t.htmlhtml5

 

播放頁面

點擊首頁的圖文列表,須要打開播放頁面!java

新建一個player.htmlgit

內容以下:github

<!doctype html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
            <h1 class="mui-title" id="title_text">正在播放</h1>
        </header>
        <div class="mui-content">
            <div class="mui-row">
                
            </div>
        </div>

    </body>
    <script src="js/mui.min.js"></script>
    <script type="text/javascript">
        mui.init()
    </script>

</html>
View Code

 

新建一個目錄avatar,用來存放頭像。從網上下載2個頭像,放到此目錄。web

MyApp目錄結構以下:數據庫

./
├── avatar
│   ├── boy.jpg
│   └── girl.jpg
├── css
│   ├── mui.css
│   └── mui.min.css
├── fonts
│   └── mui.ttf
├── index.html
├── js
│   ├── md5.min.js
│   ├── mui.js
│   └── mui.min.js
├── login.html
├── main.html
├── manifest.json
├── phone.html
├── player.html
├── reg.html
├── unpackage
└── user_info.html

 

修改player.html,引入圖片,將圖片設置爲圓的

<!doctype html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
            <h1 class="mui-title" id="title_text">正在播放</h1>
        </header>
        <div class="mui-content">
            <div class="mui-row" style="text-align: center;margin-top: 5px;">
                <img src="avatar/girl.jpg" style="width: 250px;height: 250px; border-radius: 50%;" id="avatar" />
            </div>
        </div>

    </body>
    <script src="js/mui.min.js"></script>
    <script type="text/javascript">
        mui.init()
    </script>

</html>
View Code

使用HBuilder訪問頁面,效果以下:

這個圖片應該要設置轉圈的,有興趣的人,能夠用cs3語法弄一下! 

獲取列表id

這個圖片,應該是音頻的圖片。昨天咱們已經把音頻相關的圖片下載下來了!

那麼首頁點擊的時候,應該要把當前內容的id傳遞給player.html

修改main.html,增長點擊事件,使用onclick,打印id

<!doctype html>
<html lang="en">

    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link rel="stylesheet" type="text/css" href="css/mui.css" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <h1 class="mui-title">首頁</h1>
        </header>
        <div class="mui-scroll-wrapper">
            <div class="mui-scroll">
                <div class="mui-content">
                    <div id="slider" class="mui-slider">
                        <div class="mui-slider-group mui-slider-loop">
                            <!-- 額外增長的一個節點(循環輪播:第一個節點是最後一張輪播) -->
                            <div class="mui-slider-item mui-slider-item-duplicate">
                                <a href="#">
                                    <img src="http://placehold.it/400x300">
                                </a>
                            </div>
                            <!-- 第一張 -->
                            <div class="mui-slider-item">
                                <a href="#">
                                    <img src="https://timgsa.baidu.com/timg?image&amp;quality=80&amp;size=b9999_10000&amp;sec=1537023056923&amp;di=e50b27f1a9d34e586e421b50ff5cc0b0&amp;imgtype=0&amp;src=http%3A%2F%2Fatt.bbs.duowan.com%2Fforum%2F201508%2F18%2F173910p7045xys71x4zfyh.jpg"
                                        width="300px" height="400px">
                                </a>
                            </div>
                            <!-- 第二張 -->
                            <div class="mui-slider-item">
                                <a href="#">
                                    <img src="http://placehold.it/400x300">
                                </a>
                            </div>
                            <!-- 第三張 -->
                            <div class="mui-slider-item">
                                <a href="#">
                                    <img src="http://placehold.it/400x300">
                                </a>
                            </div>
                            <!-- 第四張 -->
                            <div class="mui-slider-item">
                                <a href="#">
                                    <img src="http://placehold.it/400x300">
                                </a>
                            </div>
                            <!-- 額外增長的一個節點(循環輪播:最後一個節點是第一張輪播) -->
                            <div class="mui-slider-item mui-slider-item-duplicate">
                                <a href="#">
                                    <img src="http://placehold.it/400x300">
                                </a>
                            </div>
                        </div>
                        <div class="mui-slider-indicator">
                            <div class="mui-indicator mui-active"></div>
                            <div class="mui-indicator"></div>
                            <div class="mui-indicator"></div>
                            <div class="mui-indicator"></div>
                        </div>
                    </div>
                    <ul class="mui-table-view mui-grid-view mui-grid-9">
                        <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
                            <a href="#">
                                <span class="mui-icon mui-icon-home"></span>
                                <div class="mui-media-body">Home</div>
                            </a>
                        </li>
                        <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
                            <a href="#">
                                <span class="mui-icon mui-icon-email"><span class="mui-badge mui-badge-red">5</span></span>
                                <div class="mui-media-body">Email</div>
                            </a>
                        </li>
                        <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
                            <a href="#">
                                <span class="mui-icon mui-icon-chatbubble"></span>
                                <div class="mui-media-body">Chat</div>
                            </a>
                        </li>
                        <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
                            <a href="#">
                                <span class="mui-icon mui-icon-location"></span>
                                <div class="mui-media-body">Location</div>
                            </a>
                        </li>
                        <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
                            <a href="#">
                                <span class="mui-icon mui-icon-search"></span>
                                <div class="mui-media-body">Search</div>
                            </a>
                        </li>
                        <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
                            <a href="#">
                                <span class="mui-icon mui-icon-phone"></span>
                                <div class="mui-media-body">Phone</div>
                            </a>
                        </li>
                    </ul>
                    <ul class="mui-table-view" id="content_list">

                    </ul>
                </div>
            </div>

        </div>
    </body>

    <script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript">
        mui.init()
        mui('.mui-scroll-wrapper').scroll()
        mui.back = function() {
            mui.toast("不讓你點")
        };
        
        mui.plusReady(function(){
            mui.post(
                window.serv+"/content_list",
                {},
                function(data){
                    console.log(JSON.stringify(data));
                    
                    for (var i = 0; i < data.data.length; i++) {
                        create_content(data.data[i])
                    }
                }
            )
            
        })
        
        document.addEventListener("talk",function(data){
            mui.toast(data.detail.talk);
        })
        
        function create_content(content){    //建立圖文列表    
            var litag = document.createElement("li");
            litag.className = "mui-table-view-cell mui-media";
            var atag = document.createElement("a");
            atag.id = content._id;
            // 點擊事件
            atag.onclick = function(){
                console.log(this.id);
            }
            
            var imgtag = document.createElement("img");
            imgtag.className = "mui-media-object mui-pull-left";
            
            imgtag.src = window.serv_imge + content.avatar;
//            console.log(window.serv_imge + content.avatar);
            
            var divtag = document.createElement("div");
            divtag.className = "mui-media-body";
            divtag.innerText = content.title;
            var ptag = document.createElement("p");
            ptag.className = "mui-ellipsis";
            ptag.innerText = content.intro;
             
             litag.appendChild(atag);
             atag.appendChild(imgtag);
             atag.appendChild(divtag);
             divtag.appendChild(ptag);
             
             document.getElementById("content_list").appendChild(litag);
        
        }
        
    </script>

</html>
View Code

使用模擬器訪問,點擊圖文列表,HBuilder控制檯就會輸出id:

這些id是從MongoDB獲取,並渲染的!

 

修改main.html,新增一個方法openPlayer,用來打開播放頁面。傳遞id參數

點擊圖文列表時,就調用次方法。

<!doctype html>
<html lang="en">

    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link rel="stylesheet" type="text/css" href="css/mui.css" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <h1 class="mui-title">首頁</h1>
        </header>
        <div class="mui-scroll-wrapper">
            <div class="mui-scroll">
                <div class="mui-content">
                    <div id="slider" class="mui-slider">
                        <div class="mui-slider-group mui-slider-loop">
                            <!-- 額外增長的一個節點(循環輪播:第一個節點是最後一張輪播) -->
                            <div class="mui-slider-item mui-slider-item-duplicate">
                                <a href="#">
                                    <img src="http://placehold.it/400x300">
                                </a>
                            </div>
                            <!-- 第一張 -->
                            <div class="mui-slider-item">
                                <a href="#">
                                    <img src="https://timgsa.baidu.com/timg?image&amp;quality=80&amp;size=b9999_10000&amp;sec=1537023056923&amp;di=e50b27f1a9d34e586e421b50ff5cc0b0&amp;imgtype=0&amp;src=http%3A%2F%2Fatt.bbs.duowan.com%2Fforum%2F201508%2F18%2F173910p7045xys71x4zfyh.jpg"
                                        width="300px" height="400px">
                                </a>
                            </div>
                            <!-- 第二張 -->
                            <div class="mui-slider-item">
                                <a href="#">
                                    <img src="http://placehold.it/400x300">
                                </a>
                            </div>
                            <!-- 第三張 -->
                            <div class="mui-slider-item">
                                <a href="#">
                                    <img src="http://placehold.it/400x300">
                                </a>
                            </div>
                            <!-- 第四張 -->
                            <div class="mui-slider-item">
                                <a href="#">
                                    <img src="http://placehold.it/400x300">
                                </a>
                            </div>
                            <!-- 額外增長的一個節點(循環輪播:最後一個節點是第一張輪播) -->
                            <div class="mui-slider-item mui-slider-item-duplicate">
                                <a href="#">
                                    <img src="http://placehold.it/400x300">
                                </a>
                            </div>
                        </div>
                        <div class="mui-slider-indicator">
                            <div class="mui-indicator mui-active"></div>
                            <div class="mui-indicator"></div>
                            <div class="mui-indicator"></div>
                            <div class="mui-indicator"></div>
                        </div>
                    </div>
                    <ul class="mui-table-view mui-grid-view mui-grid-9">
                        <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
                            <a href="#">
                                <span class="mui-icon mui-icon-home"></span>
                                <div class="mui-media-body">Home</div>
                            </a>
                        </li>
                        <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
                            <a href="#">
                                <span class="mui-icon mui-icon-email"><span class="mui-badge mui-badge-red">5</span></span>
                                <div class="mui-media-body">Email</div>
                            </a>
                        </li>
                        <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
                            <a href="#">
                                <span class="mui-icon mui-icon-chatbubble"></span>
                                <div class="mui-media-body">Chat</div>
                            </a>
                        </li>
                        <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
                            <a href="#">
                                <span class="mui-icon mui-icon-location"></span>
                                <div class="mui-media-body">Location</div>
                            </a>
                        </li>
                        <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
                            <a href="#">
                                <span class="mui-icon mui-icon-search"></span>
                                <div class="mui-media-body">Search</div>
                            </a>
                        </li>
                        <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
                            <a href="#">
                                <span class="mui-icon mui-icon-phone"></span>
                                <div class="mui-media-body">Phone</div>
                            </a>
                        </li>
                    </ul>
                    <ul class="mui-table-view" id="content_list">

                    </ul>
                </div>
            </div>

        </div>
    </body>

    <script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript">
        mui.init()
        mui('.mui-scroll-wrapper').scroll()
        mui.back = function() {
            mui.toast("不讓你點")
        };
        
        mui.plusReady(function(){
            mui.post(
                window.serv+"/content_list",
                {},
                function(data){
                    console.log(JSON.stringify(data));
                    
                    for (var i = 0; i < data.data.length; i++) {
                        create_content(data.data[i])
                    }
                }
            )
            
        })
        
        document.addEventListener("talk",function(data){
            mui.toast(data.detail.talk);
        })
        
        function create_content(content){    //建立圖文列表    
            var litag = document.createElement("li");
            litag.className = "mui-table-view-cell mui-media";
            var atag = document.createElement("a");
            atag.id = content._id;
            // 點擊事件
            atag.onclick = function(){
                console.log(this.id);
                openPlayer(this.id);  //調用openPlayer方法
            }
            
            var imgtag = document.createElement("img");
            imgtag.className = "mui-media-object mui-pull-left";
            
            imgtag.src = window.serv_imge + content.avatar;
//            console.log(window.serv_imge + content.avatar);
            
            var divtag = document.createElement("div");
            divtag.className = "mui-media-body";
            divtag.innerText = content.title;
            var ptag = document.createElement("p");
            ptag.className = "mui-ellipsis";
            ptag.innerText = content.intro;
             
             litag.appendChild(atag);
             atag.appendChild(imgtag);
             atag.appendChild(divtag);
             divtag.appendChild(ptag);
             
             document.getElementById("content_list").appendChild(litag);
        
        }
        
        function openPlayer(content_id){  //打開播放頁面
            mui.openWindow({
                url:"player.html",
                id:"player.html",
                // 傳遞參數content_id
                extras:{content_id:content_id}
            })
        }
        
    </script>

</html>
View Code

 

修改player.html,接收id

<!doctype html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
            <h1 class="mui-title" id="title_text">正在播放</h1>
        </header>
        <div class="mui-content">
            <div class="mui-row" style="text-align: center;margin-top: 5px;">
                <img src="avatar/girl.jpg" style="width: 250px;height: 250px; border-radius: 50%;" id="avatar" />
            </div>
            <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id='play' >播放</button>
        </div>

    </body>
    <script src="js/mui.js"></script>
    <script type="text/javascript">
        mui.init();
        var Sdata = null;
        mui.plusReady(function() {
            Sdata = plus.webview.currentWebview();  // 當前web頁面
            mui.toast(Sdata.content_id);  // 彈窗顯示由main.html傳遞的content_id
        })
    </script>

</html>
View Code

 

使用模擬器訪問,底部會彈出id,效果以下:

 

發送POST請求

修改player.html,注意js代碼部分,是mui.js。由於它依賴mui.js的一個全局變量!

<!doctype html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
            <h1 class="mui-title" id="title_text">正在播放</h1>
        </header>
        <div class="mui-content">
            <div class="mui-row" style="text-align: center;margin-top: 5px;">
                <img src="avatar/girl.jpg" style="width: 250px;height: 250px; border-radius: 50%;" id="avatar" />
            </div>
        </div>

    </body>
    <script src="js/mui.min.js"></script>
    <script type="text/javascript">
        mui.init();
        var Sdata = null;
        mui.plusReady(function() {
            Sdata = plus.webview.currentWebview();  // 當前web頁面
            mui.toast(Sdata.content_id);  // 彈窗顯示由main.html傳遞的content_id
            //發送post請求
            mui.post(
                window.serv + "/content_one", {
                    // 參數爲content_id
                    content_id: Sdata.content_id
                },
                function(data) {
                    // 打印響應數據
                    console.log(JSON.stringify(data));
                    
                }
            )
        })
    </script>

</html>
View Code

 

打開flask項目,修改 serv-->content.py,增長視圖函數content_one

from flask import Blueprint, jsonify,request
from setting import MONGO_DB
from setting import RET
from bson import ObjectId

cont = Blueprint("cont", __name__)


@cont.route("/content_list", methods=["POST"])
def content_list():  # 內容列表
    res_list = list(MONGO_DB.sources.find({}))  # 字典轉換列表

    for index, item in enumerate(res_list):  #返回 enumerate(枚舉)對象
        # 因爲_id是ObjectId對象,轉換爲字符串
        res_list[index]["_id"] = str(item.get("_id"))

    RET["code"] = 0
    RET["msg"] = ""
    RET["data"] = res_list

    return jsonify(RET)  # 返回json數據


@cont.route("/content_one", methods=["POST"])
def content_one():
    """
    獲取一條內容
    :return: settings-->RET
    """
    content_id = request.form.get("content_id")
    # 根據_id獲取一條數據
    res = MONGO_DB.sources.find_one({"_id":ObjectId(content_id)})

    res["_id"] = str(res["_id"])  # 轉換爲str

    RET["code"] = 0
    RET["msg"] = ""
    RET["data"] = res

    return jsonify(RET)
View Code

 

使用模擬器,從新點擊一次,查看HBuilder控制檯輸出:

 {"code":0,"data":{"_id":"5b9cd309e125320580da5b94","audio":"a6d680fe-fa80-4a54-82b8-b203f5a9c7b4.mp3","avatar":"a6d680fe-fa80-4a54-82b8-b203f5a9c7b4.jpg","category":"erge","intro":"【一千零一晚上】經典兒歌","nickname":"一千零一晚上頻道","play_count":0,"title":"新年偏偏"},"msg":""} at player.html:39

 

既然數據有了,就能夠渲染頁面了!

修改player.html

<!doctype html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
            <h1 class="mui-title" id="title_text">正在播放</h1>
        </header>
        <div class="mui-content">
            <div class="mui-row" style="text-align: center;margin-top: 5px;">
                <img src="avatar/girl.jpg" style="width: 250px;height: 250px; border-radius: 50%;" id="avatar" />
            </div>
        </div>

    </body>
    <script src="js/mui.js"></script>
    <script type="text/javascript">
        mui.init();
        var Sdata = null;
        mui.plusReady(function() {
            Sdata = plus.webview.currentWebview();  // 當前web頁面
            mui.toast(Sdata.content_id);  // 彈窗顯示由main.html傳遞的content_id

            //發送post請求
            mui.post(
                window.serv + "/content_one", {
                    // 參數爲content_id
                    content_id: Sdata.content_id
                },
                function(data) {
                    // 打印響應數據
                    console.log(JSON.stringify(data));
                    // 修改標題
                    document.getElementById("title_text").innerText = "正在播放 : " + data.data.title;
                    // 修改圖片地址
                    document.getElementById("avatar").src = window.serv_imge + data.data.avatar;
                }
            )
        })
    </script>

</html>
View Code

 

使用模擬器,從新點擊。播放以下:

 

如今須要播放這首歌曲,如何實現呢?

聽歌是一個新的接口,使用Audio模塊

 

Audio模塊

Audio模塊用於提供音頻的錄製和播放功能,可調用系統的麥克風設備進行錄音操做,也可調用系統的揚聲器設備播放音頻文件。經過plus.audio獲取音頻管理對象。

參考連接:

http://www.html5plus.org/doc/zh_cn/audio.html

 

AudioPlayer

音頻播放對象

interface AudioPlayer {
    function void play( successCB, errorCB );
    function void pause();
    function void resume();
    function void stop();
    function void seekTo( position );
    function Number getDuration();
    function Number getPosition();
    function void setRoute( route );
}

說明:

音頻播放對象,用於音頻文件的播放。不能經過new方法直接建立,只能經過audio.createPlayer方法建立。

方法:

 

參考連接:

http://www.html5plus.org/doc/zh_cn/audio.html#plus.audio.AudioPlayer

 

因爲音頻在後端,前端播放時,獲取的是一個遠程音頻。能播放嗎?

先測試一下本地播放

測試本地播放

使用HBuilder 新建一個文件夾audiotest,

在此目錄,放一個音頻文件123.mp3

 

修改player.html,增長一個button按鈕。設置點擊事件,播放123.mp3

<!doctype html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
            <h1 class="mui-title" id="title_text">正在播放</h1>
        </header>
        <div class="mui-content">
            <div class="mui-row" style="text-align: center;margin-top: 5px;">
                <img src="avatar/girl.jpg" style="width: 250px;height: 250px; border-radius: 50%;" id="avatar" />
            </div>
            <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id="play">播放</button>
        </div>

    </body>
    <script src="js/mui.js"></script>
    <script type="text/javascript">
        mui.init();
        var Sdata = null;
        mui.plusReady(function() {
            Sdata = plus.webview.currentWebview();  // 當前web頁面
            mui.toast(Sdata.content_id);  // 彈窗顯示由main.html傳遞的content_id

            //發送post請求
            mui.post(
                window.serv + "/content_one", {
                    // 參數爲content_id
                    content_id: Sdata.content_id
                },
                function(data) {
                    // 打印響應數據
                    console.log(JSON.stringify(data));
                    // 修改標題
                    document.getElementById("title_text").innerText = "正在播放 : " + data.data.title;
                    // 修改圖片地址
                    document.getElementById("avatar").src = window.serv_imge + data.data.avatar;
                    
                }
            );
            
            function play_anything(content) {  //播放音頻
                // 建立播放對象
                player = plus.audio.createPlayer(content);
                player.play();  // 播放音頻
            }
            
            document.getElementById("play").addEventListener("tap", function() {
                // 播放指定音樂
                play_anything("audiotest/123.mp3");
            });
        })
    </script>

</html>
View Code

 

打開模擬器,點擊任意的圖文列表。跳轉到播放頁面,點擊播放,就會有聲音了!

 

若是沒有聲音,打開音量合成器。將模擬器的音量設置和系統同樣

 

參考連接:

https://www.yeshen.com/faqs/HyentzDUZ

 

若是仍是沒有聲音,重啓夜神模擬器。再次播放,就有聲音了!

我就是這麼解決的!

 

播放遠程音頻

既然本地的解決了,刪除目錄audiotest目錄!

下面來測試一下播放遠程音頻。

 

修改mui.js,增長全局變量serv_audio

...
window.serv = "http://192.168.11.86:9527"
window.serv_imge = window.serv+"/get_image/";
window.serv_audio = window.serv+"/get_audio/";
...

 

修改 player.html,設置爲遠程地址

<!doctype html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
            <h1 class="mui-title" id="title_text">正在播放</h1>
        </header>
        <div class="mui-content">
            <div class="mui-row" style="text-align: center;margin-top: 5px;">
                <img src="avatar/girl.jpg" style="width: 250px;height: 250px; border-radius: 50%;" id="avatar" />
            </div>
            <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id="play">播放</button>
        </div>

    </body>
    <script src="js/mui.js"></script>
    <script type="text/javascript">
        mui.init();
        var Sdata = null;
        mui.plusReady(function() {
            Sdata = plus.webview.currentWebview();  // 當前web頁面
            mui.toast(Sdata.content_id);  // 彈窗顯示由main.html傳遞的content_id

            //發送post請求
            mui.post(
                window.serv + "/content_one", {
                    // 參數爲content_id
                    content_id: Sdata.content_id
                },
                function(data) {
                    // 打印響應數據
                    console.log(JSON.stringify(data));
                    // 修改標題
                    document.getElementById("title_text").innerText = "正在播放 : " + data.data.title;
                    // 修改圖片地址
                    document.getElementById("avatar").src = window.serv_imge + data.data.avatar;
                    // 調用自定義方法,播放音頻
                    // data是後端返回的數據,data.audio是音頻文件名
                    play_anything(data.data.audio);
                }
            );
            
            function play_anything(content) {  //播放音頻
                // 建立播放對象,拼接路徑
                player = plus.audio.createPlayer(window.serv_audio + content);
                console.log(window.serv_audio + content);  //打印路徑
                //  http://192.168.11.86:9527/get_audio/a6d680fe-fa80-4a54-82b8-b203f5a9c7b4.mp3
                player.play();  // 播放音頻
            }
            
            document.getElementById("play").addEventListener("tap", function() {
                // 播放指定音樂
//                play_anything("audiotest/123.mp3");
            });
        })
    </script>

</html>
View Code

 

使用模擬器訪問,點擊一個列表,就會自動播放

 

 若是要其餘功能,好比暫停,繼續,中止。

修改player.html,增長按鈕,並增長3個方法。

<!doctype html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
            <h1 class="mui-title" id="title_text">正在播放</h1>
        </header>
        <div class="mui-content">
            <div class="mui-row" style="text-align: center;margin-top: 5px;">
                <img src="avatar/girl.jpg" style="width: 250px;height: 250px; border-radius: 50%;" id="avatar" />
            </div>
            <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id="play">播放</button>
            <button type="button" class="mui-btn mui-btn-yellow mui-btn-block" id="pause">暫停</button>
            <button type="button" class="mui-btn mui-btn-green mui-btn-block" id="resume">繼續</button>
            <button type="button" class="mui-btn mui-btn-red mui-btn-block" id="stop">中止</button>
        </div>

    </body>
    <script src="js/mui.js"></script>
    <script type="text/javascript">
        mui.init();
        var Sdata = null;  //當前web頁面
        var player = null;  //播放對象
        mui.plusReady(function() {
            Sdata = plus.webview.currentWebview();  // 當前web頁面
            mui.toast(Sdata.content_id);  // 彈窗顯示由main.html傳遞的content_id

            //發送post請求
            mui.post(
                window.serv + "/content_one", {
                    // 參數爲content_id
                    content_id: Sdata.content_id
                },
                function(data) {
                    // 打印響應數據
                    console.log(JSON.stringify(data));
                    // 修改標題
                    document.getElementById("title_text").innerText = "正在播放 : " + data.data.title;
                    // 修改圖片地址
                    document.getElementById("avatar").src = window.serv_imge + data.data.avatar;
                    // 調用自定義方法,播放音頻
                    // data是後端返回的數據,data.audio是音頻文件名
                    play_anything(data.data.audio);
                }
            );
            
            function play_anything(content) {  //播放音頻
                // 建立播放對象,拼接路徑
                player = plus.audio.createPlayer(window.serv_audio + content);
                console.log(window.serv_audio + content);  //打印路徑
                //  http://192.168.11.86:9527/get_audio/a6d680fe-fa80-4a54-82b8-b203f5a9c7b4.mp3
                player.play();  // 播放音頻
            }
            
            document.getElementById("play").addEventListener("tap", function() {
                player.play();
            });
    
            document.getElementById("pause").addEventListener("tap", function() {
                player.pause();  //暫停
            });
            
            document.getElementById("resume").addEventListener("tap", function() {
                player.resume();  //繼續
            });
            
            document.getElementById("stop").addEventListener("tap", function() {
                player.stop(); // 中止,直接清空player中的對象
            });
            
        })
    </script>

</html>
View Code

 

使用模擬器訪問,點擊一首歌。會自動播放!

點擊暫停-->繼續,暫停-->繼續,再點擊中止。最後點擊播放,就沒有聲音了!

注意:中止,是直接清空player中的對象

 

2、web端的玩具

小故事

先來說一個小故事:前期開發時,因爲軟件部須要測試。可是硬件部暫時沒法拿出板子給軟件部測試!

爲了解決這個問題,硬件部使用了工程版的面板作了low版的樣品,給軟件部測試。第一天測試了幾個小時,到了中午時間,同事都去吃飯了!

回來時,發現板子燒了!桌子燒一個大洞!鍵盤沒了一半,顯示器...

爲啥呢?由於芯片程序,沒有寫任何保護措施。觸發了一個死循環,致使板子過熱!

爲了不重蹈覆轍,不容許使用工程版!

軟件部爲了測試,作了一個web版玩具頁面!使用websocket

 

web版玩具頁面

以前後端寫的 manager.py,是用來提供資源服務的。

如今和玩具交互,使用websocket,它是通信類服務。須要單獨起一個進程,和資源進程分開!

錄音

新建文件 im_serv.py

from flask import Flask, request
from geventwebsocket.websocket import WebSocket
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
import json


app = Flask(__name__)

user_socket_dict = {}  # 空字典,用來存放用戶名和發送消息


@app.route("/toy/<tid>")
def toy(tid):
    # 獲取請求的WebSocket對象
    user_socket = request.environ.get("wsgi.websocket")  # type:WebSocket
    if user_socket:
        # 設置鍵值對
        user_socket_dict[tid] = user_socket
        print(user_socket_dict)
        # {'123456': <geventwebsocket.websocket.WebSocket object at 0x00000176ABD92E18>}

    # 循環,接收消息
    while True:
        # 接收消息
        msg = user_socket.receive()
        print(msg)  # 打印


if __name__ == '__main__':
    # 建立一個WebSocket服務器
    http_serv = WSGIServer(("0.0.0.0", 9528), app, handler_class=WebSocketHandler)
    # 開始監聽HTTP請求
    http_serv.serve_forever()
View Code

 

在templates 目錄建立文件index.html,將以前的單聊的頁面拿過來

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>
<audio src="" autoplay controls id="player"></audio>
<br>
<button onclick="start_reco()">開始廢話</button>
<br>
<button onclick="stop_reco()">發送語音</button>
</body>
<script src="/static/recorder.js"></script>
<script type="application/javascript">
    // 獲取音頻文件
    var get_file = "http://192.168.11.86:9527/get_audio/";
    // 建立 WebSocket 對象
    var ws = new WebSocket("ws://192.168.11.86:9528/toy/123456");
    var reco = null;
    // 建立AudioContext對象
    var audio_context = new AudioContext();
    //要獲取音頻和視頻
    navigator.getUserMedia = (navigator.getUserMedia ||
        navigator.webkitGetUserMedia ||
        navigator.mozGetUserMedia ||
        navigator.msGetUserMedia);

    // 拿到媒體對象,容許音頻對象
    navigator.getUserMedia({audio: true}, create_stream, function (err) {
        console.log(err)
    });

    //建立媒體流容器
    function create_stream(user_media) {
        var stream_input = audio_context.createMediaStreamSource(user_media);
        // 給Recoder 建立一個空間,麥克風說的話,均可以錄入。是一個流
        reco = new Recorder(stream_input);

    }

    function start_reco() {  //開始錄音
        reco.record();  //往裏面寫流
    }

    function stop_reco() {  //中止錄音
        reco.stop();  //中止寫入流
        get_audio();  //調用自定義方法
        reco.clear();  //清空容器
    }

    function get_audio() {  // 獲取音頻
        reco.exportWAV(function (wav_file) {
            ws.send(wav_file);  //使用websocket鏈接發送數據給後端
        })
    }

    ws.onmessage = function (data) {  // 客戶端接收服務端數據時觸發
        // console.log(get_file + data.data);
        var content = JSON.parse(data.data);
        // 修改id爲player的src屬性,實現自動播放
        document.getElementById("player").src = get_file + content.data;
        console.log(content.from_user + "給你點了一首歌");
    }


</script>
</html>
View Code

 

將recorder.js,放到static目錄。

github下載地址爲:

https://github.com/mattdiamond/Recorderjs

 

修改 manager.py,渲染index.html頁面

from flask import Flask, request,jsonify,render_template
from setting import MONGO_DB
from setting import RET
from bson import ObjectId
from serv import get_file
from serv import content

app = Flask(__name__)

app.register_blueprint(get_file.getfile)
app.register_blueprint(content.cont)

@app.route('/')
def hello_world():
    return render_template("index.html")


@app.route('/login',methods=["POST"])
def login():
    """
    登錄驗證
    :return: settings -> RET
    """
    try:
        RET["code"] = 1
        RET["msg"] = "用戶名或密碼錯誤"
        RET["data"] = {}

        username = request.form.get("username")
        password = request.form.get("password")

        user = MONGO_DB.users.find_one({"username": username, "password": password})

        if user:
            # 因爲user中的_id是ObjectId對象,須要轉化爲字符串
            user["_id"] = str(user.get("_id"))
            RET["code"] = 0
            RET["msg"] = "歡迎登錄"
            RET["data"] = {"user_id": user.get("_id")}

    except Exception as e:
        RET["code"] = 1
        RET["msg"] = "登錄失敗"

    return jsonify(RET)


@app.route('/reg',methods=["POST"])
def reg():
    """
    註冊
    :return: {"code":0,"msg":"","data":""}
    """
    try:
        username = request.form.get("username")
        password = request.form.get("password")
        age = request.form.get("age")
        nickname = request.form.get("nickname")
        gender = request.form.get("gender")
        phone = request.form.get("phone")

        user_info = {
            "username": username,
            "password": password,
            "age": age,
            "nickname": nickname,
            "gender": gender,
            "phone": phone
        }

        res = MONGO_DB.users.insert_one(user_info)
        user_id = str(res.inserted_id)

        RET["code"] = 0
        RET["msg"] = "註冊成功"
        RET["data"] = user_id
    except Exception as e:
        RET["code"] = 1
        RET["msg"] = "註冊失敗"

    return jsonify(RET)


@app.route('/user_info', methods=["POST"])
def user_info():
    user_id = request.form.get("user_id")

    # "password": 0 表示忽略密碼字段
    res = MONGO_DB.users.find_one({"_id": ObjectId(user_id)}, {"password": 0})
    if res:
        res["_id"] = str(res.get("_id"))

    RET["code"] = 0
    RET["msg"] = ""
    RET["data"] = res

    return jsonify(res)

if __name__ == '__main__':
    app.run("0.0.0.0", 9527, debug=True)
View Code

 

此時目錄結構以下:

./
├── audio
├── audio_img
├── im_serv.py
├── manager.py
├── serv
│   ├── content.py
│   └── get_file.py
├── setting.py
├── static
│   └── recorder.js
├── templates
│   └── index.html
└── xiaopapa.py

 

訪問首頁:

http://127.0.0.1:9527/

注意:千萬不要用IP訪問,不然點擊開始廢話時,console會報錯!

DOMException: Only secure origins are allowed (see: https://goo.gl/Y0ZkNV).
(index):44 Uncaught TypeError: Cannot read property 'record' of null

提示 只有安全的來源是容許的。什麼意思呢?就是說,這個連接,必須使用HTTPS鏈接。涉及HTTPS,必然就要買證書了!

固然了,證書又很貴!這裏推薦bootcdn使用的免費證書,參考連接:

https://blog.bootcdn.cn/only-https/

 

訪問首頁以後,Pycharm控制檯就會輸出:

{'123456': <geventwebsocket.websocket.WebSocket object at 0x0000016DFC2BBE18>}

這個123456是從哪裏來的呢?是用index.html來的,看這一行代碼

var ws = new WebSocket("ws://192.168.11.86:9528/toy/123456");

這裏,我指定的id爲123456,後端接收後,以id爲鍵。那麼打印出一個字典!

 

點擊頁面的開始廢話,再點擊中止

 

查看Pycharm控制檯輸出:

bytearray(b'RIFF$@\x03\x00WAVEfmt...)

 輸出了bytearray數據類型,它能夠直接保存爲音頻文件!

 

修改im_serv.py,判斷類型,保存文件

from flask import Flask, request
from geventwebsocket.websocket import WebSocket
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
import json


app = Flask(__name__)

user_socket_dict = {}  # 空字典,用來存放用戶名和發送消息


@app.route("/toy/<tid>")
def toy(tid):
    # 獲取請求的WebSocket對象
    user_socket = request.environ.get("wsgi.websocket")  # type:WebSocket
    if user_socket:
        # 設置鍵值對
        user_socket_dict[tid] = user_socket
        print(user_socket_dict)
        # {'123456': <geventwebsocket.websocket.WebSocket object at 0x00000176ABD92E18>}

    # 循環,接收消息
    while True:
        # 接收消息
        msg = user_socket.receive()
        print(msg)  # 打印
        if type(msg) == bytearray:
            with open('123.wav','wb') as f:
                f.write(msg)  # 寫入文件


if __name__ == '__main__':
    # 建立一個WebSocket服務器
    http_serv = WSGIServer(("0.0.0.0", 9528), app, handler_class=WebSocketHandler)
    # 開始監聽HTTP請求
    http_serv.serve_forever()
View Code

重啓im_serv.py

 

再次訪問首頁,錄一段音。查看flask項目,會生成一個123.wav文件

直接播放這個文件,是有聲音的!

 

注意:這個頁面,就代指了玩具!

 

3、app經過websocket遠程遙控玩具播放內容

如今手機APP,也須要經過websocket鏈接服務器。那麼手機能不能也鏈接 ws://192.168.11.86:9528/toy/123456 

呢?能夠的!可是我不想讓手機鏈接它。由於手機發送的數據,不必定是bytearray,也有多是字符串。

須要從新寫一個接口

修改im_serv.py,增長視圖函數user_app

from flask import Flask, request
from geventwebsocket.websocket import WebSocket
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
import json


app = Flask(__name__)

user_socket_dict = {}  # 空字典,用來存放用戶名和發送消息


@app.route("/toy/<tid>")
def toy(tid):  # 玩具鏈接
    # 獲取請求的WebSocket對象
    user_socket = request.environ.get("wsgi.websocket")  # type:WebSocket
    if user_socket:
        # 設置鍵值對
        user_socket_dict[tid] = user_socket
        print(user_socket_dict)
        # {'123456': <geventwebsocket.websocket.WebSocket object at 0x00000176ABD92E18>}

    # 循環,接收消息
    while True:
        # 接收消息
        msg = user_socket.receive()
        print(msg)  # 打印
        if type(msg) == bytearray:
            print(11)
            with open('123.wav','wb') as f:
                f.write(msg)  # 寫入文件


@app.route("/app/<uid>")
def user_app(uid):  # 手機app鏈接
    user_socket = request.environ.get("wsgi.websocket")  # type:WebSocket
    if user_socket:
        user_socket_dict[uid] = user_socket
        # { uid : websocket}
        print(user_socket_dict)
    while True:  # 手機聽歌 把歌曲發送給 玩具 1.將文件直接發送給玩具 2.將當前聽的歌曲名稱或ID發送到玩具
        msg = user_socket.receive()
        print(msg)


if __name__ == '__main__':
    # 建立一個WebSocket服務器
    http_serv = WSGIServer(("0.0.0.0", 9528), app, handler_class=WebSocketHandler)
    # 開始監聽HTTP請求
    http_serv.serve_forever()
View Code

 

修改MyApp裏面的player.html,增長按鈕,發送給玩具

<!doctype html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
            <h1 class="mui-title" id="title_text">正在播放</h1>
        </header>
        <div class="mui-content">
            <div class="mui-row" style="text-align: center;margin-top: 5px;">
                <img src="avatar/girl.jpg" style="width: 250px;height: 250px; border-radius: 50%;" id="avatar" />
            </div>
            <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id="play">播放</button>
            <button type="button" class="mui-btn mui-btn-yellow mui-btn-block" id="pause">暫停</button>
            <button type="button" class="mui-btn mui-btn-green mui-btn-block" id="resume">繼續</button>
            <button type="button" class="mui-btn mui-btn-red mui-btn-block" id="stop">中止</button>
            <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id="send2toy">發送給玩具</button>
        </div>

    </body>
    <script src="js/mui.js"></script>
    <script type="text/javascript">
        mui.init();
        var Sdata = null;  //當前web頁面
        var player = null;  //播放對象
        mui.plusReady(function() {
            Sdata = plus.webview.currentWebview();  // 當前web頁面
            mui.toast(Sdata.content_id);  // 彈窗顯示由main.html傳遞的content_id

            //發送post請求
            mui.post(
                window.serv + "/content_one", {
                    // 參數爲content_id
                    content_id: Sdata.content_id
                },
                function(data) {
                    // 打印響應數據
                    console.log(JSON.stringify(data));
                    // 修改標題
                    document.getElementById("title_text").innerText = "正在播放 : " + data.data.title;
                    // 修改圖片地址
                    document.getElementById("avatar").src = window.serv_imge + data.data.avatar;
                    // 調用自定義方法,播放音頻
                    // data是後端返回的數據,data.audio是音頻文件名
                    play_anything(data.data.audio);
                }
            );
            
            function play_anything(content) {  //播放音頻
                // 建立播放對象,拼接路徑
                player = plus.audio.createPlayer(window.serv_audio + content);
                console.log(window.serv_audio + content);  //打印路徑
                //  http://192.168.11.86:9527/get_audio/a6d680fe-fa80-4a54-82b8-b203f5a9c7b4.mp3
                player.play();  // 播放音頻
            }
            
            document.getElementById("play").addEventListener("tap", function() {
                player.play();
            });
    
            document.getElementById("pause").addEventListener("tap", function() {
                player.pause();  //暫停
            });
            
            document.getElementById("resume").addEventListener("tap", function() {
                player.resume();  //繼續
            });
            
            document.getElementById("stop").addEventListener("tap", function() {
                player.stop(); // 中止,直接清空player中的對象
            });
            
        })
    </script>

</html>
View Code

 

使用模擬器訪問,效果以下:

 

創建鏈接

須要在APP中使用websocket,那麼在何時,創建鏈接呢?

應該是在用戶登陸以後,點擊首頁時,創建websocket鏈接

 

修改mui.js,增長全局變量 ws_serv

...
window.ws_serv = "192.168.11.86:9528";
window.serv = "http://192.168.11.86:9527";
window.serv_imge = window.serv+"/get_image/";
window.serv_audio = window.serv+"/get_audio/";
...

 

修改index.html,判斷登陸狀態,創建鏈接

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <title></title>
        <script src="js/mui.js"></script>
        <link href="css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <nav class="mui-bar mui-bar-tab">
            <a class="mui-tab-item mui-active" id="index">
                <span class="mui-icon mui-icon-home"></span>
                <span class="mui-tab-label">首頁</span>
            </a>
            <a class="mui-tab-item" id="phone">
                <span class="mui-icon mui-icon-phone"></span>
                <span class="mui-tab-label">電話</span>
            </a>
            <a class="mui-tab-item">
                <span class="mui-icon mui-icon-email"></span>
                <span class="mui-tab-label">郵件</span>
            </a>
            <a class="mui-tab-item" id="login">
                <span class="mui-icon mui-icon-gear"></span>
                <span class="mui-tab-label">設置</span>
            </a>
        </nav>
    </body>
    <script type="text/javascript" charset="utf-8">
        var ws = null;  // websocket對象
        mui.init({
            subpages: [{
                url: "main.html",
                id: "main.html",
                styles: window.styles
            }]
        });
        mui.plusReady(function() {
//            console.log(JSON.stringify(plus.webview.currentWebview()))
            if(plus.storage.getItem("user")) {  // 判斷是否登陸
                console.log('已結登陸了!');
                //鏈接websocket鏈接
                ws = new WebSocket("ws://"+window.ws_serv+"/app/"+plus.storage.getItem("user"))
                // 客戶端接收服務端數據時觸發
                ws.onmessage = function() {};
            } 
        });

        document.getElementById("phone").addEventListener("tap", function() {
            mui.toast("你點擊了電話按鈕");

            mui.openWindow({
                url: "phone.html",
                id: "phone.html",
                styles: window.styles,
                extras: {
                    user_id: 123456
                }
            })
        })

        document.getElementById("index").addEventListener("tap", function() {
            mui.openWindow({
                url: "main.html",
                id: "main.html",
                styles: window.styles
            })
        })

        document.getElementById("login").addEventListener("tap", function() {
            mui.openWindow({
                url: "login.html",
                id: "login.html",
                styles: window.styles
            })
        })
        
        document.addEventListener("login",function(data){
            // fire事件接收消息,使用data.detail
            // index是爲作顯示區分
            mui.toast("index"+data.detail.msg)
        })
    </script>

</html>
View Code

注意:必須寫在 mui.plusReady 裏面

 

使用模擬器打開登陸頁面

登陸成功以後,點擊首頁

查看Pycharm控制檯輸出

{'5b9bb768e1253281608e96eb': <geventwebsocket.websocket.WebSocket object at 0x0000027DC1F0BE18>}

這個時候,創建了一個鏈接!

前面的 5b9bb768e1253281608e96eb是MongoDB用戶表記錄的_id字段!

 

那麼在後端flask裏面的im_sevr.py中。user_socket_dict保存了全部的websocket鏈接!它們之間,就能夠進行一對一通信了!

 

一對一通信

需求:播放頁面的歌曲,經過websocket,將歌曲名發給web玩具進行播放!

 

修改player.html,須要將歌曲名發送給index.html頁面。爲何呢?由於index.html創建了websocket鏈接。注意:index.html的webview的視圖id爲HBuilder

使用fire傳值

<!doctype html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link href="css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
            <h1 class="mui-title" id="title_text">正在播放</h1>
        </header>
        <div class="mui-content">
            <div class="mui-row" style="text-align: center;margin-top: 5px;">
                <img src="avatar/girl.jpg" style="width: 250px;height: 250px; border-radius: 50%;" id="avatar" />
            </div>
            <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id="play">播放</button>
            <button type="button" class="mui-btn mui-btn-yellow mui-btn-block" id="pause">暫停</button>
            <button type="button" class="mui-btn mui-btn-green mui-btn-block" id="resume">繼續</button>
            <button type="button" class="mui-btn mui-btn-red mui-btn-block" id="stop">中止</button>
            <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id="send2toy">發送給玩具</button>
        </div>

    </body>
    <script src="js/mui.js"></script>
    <script type="text/javascript">
        mui.init();
        var Sdata = null;  //當前web頁面
        var music_name = null;  //歌曲名
        var player = null;  //播放對象
        mui.plusReady(function() {
            Sdata = plus.webview.currentWebview();  // 當前web頁面
            mui.toast(Sdata.content_id);  // 彈窗顯示由main.html傳遞的content_id

            //發送post請求
            mui.post(
                window.serv + "/content_one", {
                    // 參數爲content_id
                    content_id: Sdata.content_id
                },
                function(data) {
                    // 打印響應數據
                    console.log(JSON.stringify(data));
                    // 修改標題
                    document.getElementById("title_text").innerText = "正在播放 : " + data.data.title;
                    // 修改圖片地址
                    document.getElementById("avatar").src = window.serv_imge + data.data.avatar;
                    // 調用自定義方法,播放音頻
                    // data是後端返回的數據,data.audio是音頻文件名
                    music_name = data.data.audio;  // 歌曲名
                    play_anything(music_name);  //播放歌曲
                }
            );
            
            function play_anything(content) {  //播放音頻
                // 建立播放對象,拼接路徑
                player = plus.audio.createPlayer(window.serv_audio + content);
                console.log(window.serv_audio + content);  //打印路徑
                //  http://192.168.11.86:9527/get_audio/a6d680fe-fa80-4a54-82b8-b203f5a9c7b4.mp3
                player.play();  // 播放音頻
            }
            
            document.getElementById("play").addEventListener("tap", function() {
                player.play();
            });
    
            document.getElementById("pause").addEventListener("tap", function() {
                player.pause();  //暫停
            });
            
            document.getElementById("resume").addEventListener("tap", function() {
                player.resume();  //繼續
            });
            
            document.getElementById("stop").addEventListener("tap", function() {
                player.stop(); // 中止,直接清空player中的對象
            });
            
            //發送給玩具
            document.getElementById("send2toy").addEventListener("tap", function() {
                var index = plus.webview.getWebviewById("HBuilder");  //index.html頁面
                mui.fire(index, "send_music", {  //發送音樂
                    music_name: music_name,  //歌曲名
                    toy_id:"123456"  // 發給玩具id爲12345
                })
            });
            
        })
    </script>

</html>
View Code

 

修改index.html,監聽send_music事件

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <title></title>
        <script src="js/mui.js"></script>
        <link href="css/mui.min.css" rel="stylesheet" />
    </head>

    <body>
        <nav class="mui-bar mui-bar-tab">
            <a class="mui-tab-item mui-active" id="index">
                <span class="mui-icon mui-icon-home"></span>
                <span class="mui-tab-label">首頁</span>
            </a>
            <a class="mui-tab-item" id="phone">
                <span class="mui-icon mui-icon-phone"></span>
                <span class="mui-tab-label">電話</span>
            </a>
            <a class="mui-tab-item">
                <span class="mui-icon mui-icon-email"></span>
                <span class="mui-tab-label">郵件</span>
            </a>
            <a class="mui-tab-item" id="login">
                <span class="mui-icon mui-icon-gear"></span>
                <span class="mui-tab-label">設置</span>
            </a>
        </nav>
    </body>
    <script type="text/javascript" charset="utf-8">
        var ws = null;  // websocket對象
        mui.init({
            subpages: [{
                url: "main.html",
                id: "main.html",
                styles: window.styles
            }]
        });
        mui.plusReady(function() {
//            console.log(JSON.stringify(plus.webview.currentWebview()))
            if(plus.storage.getItem("user")) {  // 判斷是否登陸
                console.log('已結登陸了!');
                //鏈接websocket鏈接
                ws = new WebSocket("ws://"+window.ws_serv+"/app/"+plus.storage.getItem("user"))
                // 客戶端接收服務端數據時觸發
                ws.onmessage = function() {};
            } 
        });

        document.getElementById("phone").addEventListener("tap", function() {
            mui.toast("你點擊了電話按鈕");

            mui.openWindow({
                url: "phone.html",
                id: "phone.html",
                styles: window.styles,
                extras: {
                    user_id: 123456
                }
            })
        })

        document.getElementById("index").addEventListener("tap", function() {
            mui.openWindow({
                url: "main.html",
                id: "main.html",
                styles: window.styles
            })
        })

        document.getElementById("login").addEventListener("tap", function() {
            mui.openWindow({
                url: "login.html",
                id: "login.html",
                styles: window.styles
            })
        })
        
        document.addEventListener("login",function(data){
            // fire事件接收消息,使用data.detail
            // index是爲作顯示區分
            mui.toast("index"+data.detail.msg)
        });
        
        document.addEventListener("send_music", function(data) {  //監聽send_music事件
            var music_name = data.detail.music_name;  //獲取player.html使用fire發送的music_name值
            var toy_id = data.detail.toy_id;  //獲取發送的玩具id
            
            send_str = {  //構造數據
                music_name:music_name,
                toy_id:toy_id
            }  
            // 發送數據給後端,注意要json序列化
            ws.send(JSON.stringify(send_str));
        });
        
    </script>

</html>
View Code

 

刷新web玩具頁面,此時有2個websocket鏈接

{'5b9bb768e1253281608e96eb': <geventwebsocket.websocket.WebSocket object at 0x0000027DC1FE1F50>, '123456': <geventwebsocket.websocket.WebSocket object at 0x0000027DC20001E8>}
View Code

 

使用模擬器訪問首頁,隨便點擊一首歌。它會自動播放,點擊暫停,再點擊發送給玩具

此時Pycharm輸出一條信息:

{"music_name":"a6d680fe-fa80-4a54-82b8-b203f5a9c7b4.mp3","toy_id":"123456"}

歌曲名,獲取到了。這裏面的123456,是有player.html發送給index.html的!

 

網頁播放音樂

這個時候,須要後端接收消息並處理了

修改im_serv.py

from flask import Flask, request
from geventwebsocket.websocket import WebSocket
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
import json


app = Flask(__name__)

user_socket_dict = {}  # 空字典,用來存放用戶名和發送消息


@app.route("/toy/<tid>")
def toy(tid):  # 玩具鏈接
    # 獲取請求的WebSocket對象
    user_socket = request.environ.get("wsgi.websocket")  # type:WebSocket
    if user_socket:
        # 設置鍵值對
        user_socket_dict[tid] = user_socket
        print(user_socket_dict)
        # {'123456': <geventwebsocket.websocket.WebSocket object at 0x00000176ABD92E18>}

    # 循環,接收消息
    while True:
        # 接收消息
        msg = user_socket.receive()
        print(msg)  # 打印
        if type(msg) == bytearray:
            print(11)
            with open('123.wav','wb') as f:
                f.write(msg)  # 寫入文件


@app.route("/app/<uid>")
def user_app(uid):  # 手機app鏈接
    user_socket = request.environ.get("wsgi.websocket")  # type:WebSocket
    if user_socket:
        user_socket_dict[uid] = user_socket
        # { uid : websocket}
        print(user_socket_dict)
    while True:  # 手機聽歌 把歌曲發送給 玩具 1.將文件直接發送給玩具 2.將當前聽的歌曲名稱或ID發送到玩具
        msg = user_socket.receive()
        msg_dict = json.loads(msg)  # 接收值,因爲APP發送的是json,須要反序列化
        # {"music_name": "a6d680fe-fa80-4a54-82b8-b203f5a9c7b4.mp3", "toy_id": "123456"}
        user_id = msg_dict.get("toy_id")  # 獲取toy_id
        music_name = msg_dict.get("music_name")  # 獲取歌曲名
        # 從user_socket_dict這個大字典中獲取
        other_user_socket = user_socket_dict.get(user_id)  # 獲取APP用戶的websocket對象
        # 構造數據
        send_str = {
            "code": 0,
            "from_user": uid,  # APP用戶id
            "data": music_name  # 歌曲名
        }
        
        # 發送給web玩具頁面,注意:不能是jsonify,它是針對於HTTP請求,會設置響應頭
        # 這裏是websocket鏈接,只能用json.dumps
        other_user_socket.send(json.dumps(send_str))

if __name__ == '__main__':
    # 建立一個WebSocket服務器
    http_serv = WSGIServer(("0.0.0.0", 9528), app, handler_class=WebSocketHandler)
    # 開始監聽HTTP請求
    http_serv.serve_forever()
View Code

重啓 im_serv.py

 

重啓以後,websocket鏈接就丟失了!

先訪問web玩具頁面

http://127.0.0.1:9527/

 

將模擬器中的HBuilder進程關閉,重啓開啓,並登錄。

點擊一首歌曲,點擊暫停,再點擊一次發送給玩具!

此時,播放按鈕,會播放音樂。

效果以下:

 

爲何,點擊網頁的播放按鈕,就能播放指定的音樂呢?

查看flask中的templates-->index.html,這一段代碼

ws.onmessage = function (data) {  // 客戶端接收服務端數據時觸發
        // console.log(get_file + data.data);
        var content = JSON.parse(data.data);
        // 修改id爲player的src屬性,實現自動播放
        document.getElementById("player").src = get_file + content.data;
        console.log(content.from_user + "給你點了一首歌");
    }

注意:ws.onmessage是接收到數據時,會自動觸發!

那麼它接收到什麼數據了呢?接收了一個json數據。序列化以後,應該是這個樣子

{code: 0, from_user: "5b9bb768e1253281608e96eb", data: "4ed490e8-aded-4f23-8a7c-c845e48ec778.mp3"}

 

那麼它就會修改頁面的src屬性。那麼頁面點擊播放,就能夠播放音樂了!

 

4、玩具管理頁面

默認登陸以後,會跳轉到用戶信息頁面,這裏須要展現用戶頭像。

可是數據庫少了頭像字段。

 

使用客戶端工具訪問用戶表

默認的ORM語句爲:

db.users.find({})

目前只有一個用戶

 

增長一個字段avatar,這個表示頭像

db.users.updateMany({"username":"xiao"},{$set:{"avatar":"boy.jpg"}})

 

修改flask後端的 的註冊函數,增長avatar字段

from flask import Flask, request,jsonify,render_template
from setting import MONGO_DB
from setting import RET
from bson import ObjectId
from serv import get_file
from serv import content

app = Flask(__name__)

app.register_blueprint(get_file.getfile)
app.register_blueprint(content.cont)

@app.route('/')
def hello_world():
    return render_template("index.html")


@app.route('/login',methods=["POST"])
def login():
    """
    登錄驗證
    :return: settings -> RET
    """
    try:
        RET["code"] = 1
        RET["msg"] = "用戶名或密碼錯誤"
        RET["data"] = {}

        username = request.form.get("username")
        password = request.form.get("password")

        user = MONGO_DB.users.find_one({"username": username, "password": password})

        if user:
            # 因爲user中的_id是ObjectId對象,須要轉化爲字符串
            user["_id"] = str(user.get("_id"))
            RET["code"] = 0
            RET["msg"] = "歡迎登錄"
            RET["data"] = {"user_id": user.get("_id")}

    except Exception as e:
        RET["code"] = 1
        RET["msg"] = "登錄失敗"

    return jsonify(RET)


@app.route('/reg',methods=["POST"])
def reg():
    """
    註冊
    :return: {"code":0,"msg":"","data":""}
    """
    try:
        username = request.form.get("username")
        password = request.form.get("password")
        age = request.form.get("age")
        nickname = request.form.get("nickname")
        gender = request.form.get("gender")
        phone = request.form.get("phone")

        user_info = {
            "username": username,
            "password": password,
            "age": age,
            "nickname": nickname,
            # 判斷gender==2,成立時爲girl.jpg,不然爲boy.jpg
            "avatar": "girl.jpg" if gender == 2 else "boy.jpg",
            "gender": gender,
            "phone": phone
        }

        res = MONGO_DB.users.insert_one(user_info)
        user_id = str(res.inserted_id)

        RET["code"] = 0
        RET["msg"] = "註冊成功"
        RET["data"] = user_id
    except Exception as e:
        RET["code"] = 1
        RET["msg"] = "註冊失敗"

    return jsonify(RET)


@app.route('/user_info', methods=["POST"])
def user_info():
    user_id = request.form.get("user_id")

    # "password": 0 表示忽略密碼字段
    res = MONGO_DB.users.find_one({"_id": ObjectId(user_id)}, {"password": 0})
    if res:
        res["_id"] = str(res.get("_id"))

    RET["code"] = 0
    RET["msg"] = ""
    RET["data"] = res

    return jsonify(res)

if __name__ == '__main__':
    app.run("0.0.0.0", 9527, debug=True)
View Code

 

進入HBuilder的項目MyApp,修改user_info.html,增長頭像

<!doctype html>
<html lang="en">

    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link rel="stylesheet" type="text/css" href="css/mui.css" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <h1 class="mui-title">用戶信息</h1>
        </header>
        <div class="mui-content">
            <ul class="mui-table-view">
                <div class="mui-row" style="text-align: center;">
                    <img src="" id="avatar" style="width: 250px;height: 250px; border-radius: 100%;"/>
                </div>
                <li class="mui-table-view-cell"><span>用戶名</span><span id="username" class="mui-pull-right">111</span></li>
                <li class="mui-table-view-cell"><span>暱稱</span><span id="nickname" class="mui-pull-right">22</span></li>
            </ul>

            <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id="logout">退出登錄</button>
        </div>

    </body>
    <script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript">
        mui.init()
        mui.back = function() {};
        mui.plusReady(function() {
            var Sdata = plus.webview.currentWebview();
            mui.post(
                window.serv + "/user_info", {
                    user_id: Sdata.user_id
                },
                function(data) {
                    console.log(JSON.stringify(data));
                    console.log("wfdsfdsafdsafas");
                    document.getElementById("username").innerText = data.username;
                    document.getElementById("nickname").innerText = data.nickname;
                    // 修改頭像地址
                    document.getElementById("avatar").src = "avatar/" + data.avatar;
//                    console.log("avatar/" + data.avatar);
                }
            )
        })

        document.getElementById("logout").addEventListener("tap", function() {
            plus.storage.removeItem("user")
            mui.openWindow({
                url: "login.html",
                id: "login.html",
                styles: window.styles
            })
        });
        

    </script>

</html>
View Code

 

使用模擬器從新登陸,效果以下:

 

修改user_info.html,增長一行,用來管理玩具。並增長點擊事件

<!doctype html>
<html lang="en">

    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link rel="stylesheet" type="text/css" href="css/mui.css" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <h1 class="mui-title">用戶信息</h1>
        </header>
        <div class="mui-content">
            <ul class="mui-table-view">
                <div class="mui-row" style="text-align: center;">
                    <img src="" id="avatar" / style="width: 250px;height: 250px; border-radius: 100%;">
                </div>
                <li class="mui-table-view-cell"><span>用戶名</span><span id="username" class="mui-pull-right">111</span></li>
                <li class="mui-table-view-cell"><span>暱稱</span><span id="nickname" class="mui-pull-right">22</span></li>
            </ul>
            <ul class="mui-table-view">
                <li class="mui-table-view-cell" id="toy_manager"><i class="mui-icon mui-icon-qq"></i>管理個人玩具</li>

            </ul>

            <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id="logout">退出登錄</button>
        </div>

    </body>
    <script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript">
        mui.init()
        mui.back = function() {};
        mui.plusReady(function() {
            var Sdata = plus.webview.currentWebview();
            mui.post(
                window.serv + "/user_info", {
                    user_id: Sdata.user_id
                },
                function(data) {
                    console.log(JSON.stringify(data));
                    console.log("wfdsfdsafdsafas");
                    document.getElementById("username").innerText = data.username;
                    document.getElementById("nickname").innerText = data.nickname;
                    // 修改頭像地址
                    document.getElementById("avatar").src = "avatar/" + data.avatar;
//                    console.log("avatar/" + data.avatar);
                }
            )
        })

        document.getElementById("logout").addEventListener("tap", function() {
            plus.storage.removeItem("user")
            mui.openWindow({
                url: "login.html",
                id: "login.html",
                styles: window.styles
            })
        });
        
        // 管理玩具頁面
        document.getElementById("toy_manager").addEventListener("tap", function() {
            mui.openWindow({
                url: "toy_manager.html",
                id: "toy_manager.html",
            })
        });
        

    </script>

</html>
View Code

 

新建文件 toy_manager.html

 

新建目錄image,用來保存添加按鈕的圖片

從網絡上面,搜索一個添加按鈕圖片,放到此目錄!

此時,目錄結構以下:

./
└── MyApp
    ├── avatar
    │   ├── boy.jpg
    │   └── girl.jpg
    ├── css
    │   ├── mui.css
    │   └── mui.min.css
    ├── fonts
    │   └── mui.ttf
    ├── images
    │   └── add.png
    ├── index.html
    ├── js
    │   ├── md5.min.js
    │   ├── mui.js
    │   └── mui.min.js
    ├── login.html
    ├── main.html
    ├── manifest.json
    ├── phone.html
    ├── player.html
    ├── reg.html
    ├── toy_manager.html
    ├── unpackage
    └── user_info.html
View Code

 

修改 toy_manager.html

<!doctype html>
<html lang="en">

    <head>
        <meta charset="UTF-8" />
        <title>Document</title>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link rel="stylesheet" type="text/css" href="css/mui.css" />
    </head>

    <body>
        <header class="mui-bar mui-bar-nav">
            <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
            <h1 class="mui-title">管理個人玩具</h1>
        </header>
        <div class="mui-content">
            <ul class="mui-table-view" id="toy_list">
                <li class="mui-table-view-cell mui-media">
                    <a id="add_toy">
                        <img class="mui-media-object mui-pull-left" src="images/add.png">
                        <div class="mui-media-body">
                            你尚未玩具
                            <p class="mui-ellipsis">點擊此處掃描二維碼添加玩具</p>
                        </div>
                    </a>
                </li>
            </ul>
        </div>
    </body>
    <script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript">
        mui.init()

        function create_content(content) {
            var litag = document.createElement("li");
            litag.className = "mui-table-view-cell mui-media";
            var atag = document.createElement("a");
            atag.id = content._id;
            // 點擊事件 週一把這兒寫了 綁定事件
            atag.onclick = function() {
                console.log(this.id);
                openPlayer(this.id);
            }

            var imgtag = document.createElement("img");
            imgtag.className = "mui-media-object mui-pull-left";

            imgtag.src = window.serv_imge + content.avatar;

            var divtag = document.createElement("div");
            divtag.className = "mui-media-body";
            divtag.innerText = content.title;
            var ptag = document.createElement("p");
            ptag.className = "mui-ellipsis";
            ptag.innerText = content.intro;

            litag.appendChild(atag);
            atag.appendChild(imgtag);
            atag.appendChild(divtag);
            divtag.appendChild(ptag);

            document.getElementById("toy_list").appendChild(litag);

        }

        document.getElementById("add_toy").addEventListener("tap", function() {
            mui.openWindow({
                url: "掃描二維碼.html",
                id: "掃描二維碼.html",
            })
        })
    </script>

</html>
View Code

 

從新登陸,效果以下:

 

總結:

1. app端內容播放
    聽歌:plus.audio
    建立:var player = plus.audio.createPlay(內容的URL路徑) //蘋果暫時不支持HTTP
    開始播放 : player.play()
    暫停播放 :player.pause()
    繼續播放 :player.resume()
    中止播放 :player.stop() 清空player中對象
    

2. 手動寫一個web端的玩具(小劇情)
    硬件須要時間,我們先寫一個協議,而後開發一個初級硬件暫時先頂上,用了一週的事件作了一個LowB的硬件
    事件:    中午吃飯忘了關閉硬件,結果芯片過熱,形成芯片燒燬,燒燬了一個桌面,燙壞了一個顯示器,鍵盤沒了一半兒
            老張呵斥硬件部:工程開發板不容許再次使用,全部壓力所有在軟件部,本身寫一個Web模擬玩具收發消息
        
    

3. app經過websocket 事件遠程遙控玩具播放內容
websocket 在整個app中只能存在一個
app 端 :
    mui.fire(ws頁面,"事件",{data})
ws頁面:
    document.addEventListener("事件",function(data){
        data.detail
    })

開啓websocket服務 - 
兩個接口 app toy - 
兩個前端 鏈接 websocket - 
{user:websocket,toy:websocket}
appuser 發送了一個字符串給服務端 {toy_id:123456,content_id:tyuiop123r234}
經過字符串中的toy_id 拿到 websocket_dict 中的 toy websocket
能夠給 toy 中的websocket 發送消息了
toy.send(json.dumps({}))
View Code

 

完整代碼,請參考github:

https://github.com/987334176/Intelligent_toy/archive/v1.1.zip

相關文章
相關標籤/搜索