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")
下載代碼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>
新建一個目錄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>
使用HBuilder訪問頁面,效果以下:
這個圖片應該要設置轉圈的,有興趣的人,能夠用cs3語法弄一下!
這個圖片,應該是音頻的圖片。昨天咱們已經把音頻相關的圖片下載下來了!
那麼首頁點擊的時候,應該要把當前內容的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&quality=80&size=b9999_10000&sec=1537023056923&di=e50b27f1a9d34e586e421b50ff5cc0b0&imgtype=0&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>
使用模擬器訪問,點擊圖文列表,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&quality=80&size=b9999_10000&sec=1537023056923&di=e50b27f1a9d34e586e421b50ff5cc0b0&imgtype=0&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>
修改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>
使用模擬器訪問,底部會彈出id,效果以下:
修改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>
打開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)
使用模擬器,從新點擊一次,查看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>
使用模擬器,從新點擊。播放以下:
如今須要播放這首歌曲,如何實現呢?
聽歌是一個新的接口,使用Audio模塊
Audio模塊用於提供音頻的錄製和播放功能,可調用系統的麥克風設備進行錄音操做,也可調用系統的揚聲器設備播放音頻文件。經過plus.audio獲取音頻管理對象。
參考連接:
http://www.html5plus.org/doc/zh_cn/audio.html
音頻播放對象
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>
打開模擬器,點擊任意的圖文列表。跳轉到播放頁面,點擊播放,就會有聲音了!
若是沒有聲音,打開音量合成器。將模擬器的音量設置和系統同樣
參考連接:
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>
使用模擬器訪問,點擊一個列表,就會自動播放
若是要其餘功能,好比暫停,繼續,中止。
修改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>
使用模擬器訪問,點擊一首歌。會自動播放!
點擊暫停-->繼續,暫停-->繼續,再點擊中止。最後點擊播放,就沒有聲音了!
注意:中止,是直接清空player中的對象。
先來說一個小故事:前期開發時,因爲軟件部須要測試。可是硬件部暫時沒法拿出板子給軟件部測試!
爲了解決這個問題,硬件部使用了工程版的面板作了low版的樣品,給軟件部測試。第一天測試了幾個小時,到了中午時間,同事都去吃飯了!
回來時,發現板子燒了!桌子燒一個大洞!鍵盤沒了一半,顯示器...
爲啥呢?由於芯片程序,沒有寫任何保護措施。觸發了一個死循環,致使板子過熱!
爲了不重蹈覆轍,不容許使用工程版!
軟件部爲了測試,作了一個web版玩具頁面!使用websocket
以前後端寫的 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()
在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>
將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)
此時目錄結構以下:
./
├── 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()
重啓im_serv.py
再次訪問首頁,錄一段音。查看flask項目,會生成一個123.wav文件
直接播放這個文件,是有聲音的!
注意:這個頁面,就代指了玩具!
如今手機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()
修改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>
使用模擬器訪問,效果以下:
須要在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>
注意:必須寫在 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>
修改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>
刷新web玩具頁面,此時有2個websocket鏈接
{'5b9bb768e1253281608e96eb': <geventwebsocket.websocket.WebSocket object at 0x0000027DC1FE1F50>, '123456': <geventwebsocket.websocket.WebSocket object at 0x0000027DC20001E8>}
使用模擬器訪問首頁,隨便點擊一首歌。它會自動播放,點擊暫停,再點擊發送給玩具
此時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()
重啓 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屬性。那麼頁面點擊播放,就能夠播放音樂了!
默認登陸以後,會跳轉到用戶信息頁面,這裏須要展現用戶頭像。
可是數據庫少了頭像字段。
使用客戶端工具訪問用戶表
默認的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)
進入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>
使用模擬器從新登陸,效果以下:
修改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>
新建文件 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
修改 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>
從新登陸,效果以下:
總結:
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({}))
完整代碼,請參考github:
https://github.com/987334176/Intelligent_toy/archive/v1.1.zip