一、app端内容播放

下载代码

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

注意:由于涉及到版权问题,此附件没有图片和音乐。请参考昨天的代码,手动采集一下!

请参考链接:

https://www.cnblogs.com/xiao987334176/p/9647993.html#autoid-3-4-0

播放页面

点击首页的图文列表,需要打开播放页面!

新建一个player.html

内容如下:

  1. <!doctype html>
  2. <html>
  3.  
  4. <head>
  5. <meta charset="UTF-8">
  6. <title></title>
  7. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  8. <link href="css/mui.min.css" rel="stylesheet" />
  9. </head>
  10.  
  11. <body>
  12. <header class="mui-bar mui-bar-nav">
  13. <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
  14. <h1 class="mui-title" id="title_text">正在播放</h1>
  15. </header>
  16. <div class="mui-content">
  17. <div class="mui-row">
  18.  
  19. </div>
  20. </div>
  21.  
  22. </body>
  23. <script src="js/mui.min.js"></script>
  24. <script type="text/javascript">
  25. mui.init()
  26. </script>
  27.  
  28. </html>

新建一个目录avatar,用来存放头像。从网上下载2个头像,放到此目录。

MyApp目录结构如下:

  1. ./
  2. ├── avatar
  3.    ├── boy.jpg
  4.    └── girl.jpg
  5. ├── css
  6.    ├── mui.css
  7.    └── mui.min.css
  8. ├── fonts
  9.    └── mui.ttf
  10. ├── index.html
  11. ├── js
  12.    ├── md5.min.js
  13.    ├── mui.js
  14.    └── mui.min.js
  15. ├── login.html
  16. ├── main.html
  17. ├── manifest.json
  18. ├── phone.html
  19. ├── player.html
  20. ├── reg.html
  21. ├── unpackage
  22. └── user_info.html

修改player.html,引入图片,将图片设置为圆的

  1. <!doctype html>
  2. <html>
  3.  
  4. <head>
  5. <meta charset="UTF-8">
  6. <title></title>
  7. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  8. <link href="css/mui.min.css" rel="stylesheet" />
  9. </head>
  10.  
  11. <body>
  12. <header class="mui-bar mui-bar-nav">
  13. <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
  14. <h1 class="mui-title" id="title_text">正在播放</h1>
  15. </header>
  16. <div class="mui-content">
  17. <div class="mui-row" style="text-align: center;margin-top: 5px;">
  18. <img src="avatar/girl.jpg" style="width: 250px;height: 250px; border-radius: 50%;" id="avatar" />
  19. </div>
  20. </div>
  21.  
  22. </body>
  23. <script src="js/mui.min.js"></script>
  24. <script type="text/javascript">
  25. mui.init()
  26. </script>
  27.  
  28. </html>

使用HBuilder访问页面,效果如下:

这个图片应该要设置转圈的,有兴趣的人,可以用cs3语法弄一下!

获取列表id

这个图片,应该是音频的图片。昨天我们已经把音频相关的图片下载下来了!

那么首页点击的时候,应该要把当前内容的id传递给player.html

修改main.html,增加点击事件,使用onclick,打印id

  1. <!doctype html>
  2. <html lang="en">
  3.  
  4. <head>
  5. <meta charset="UTF-8" />
  6. <title>Document</title>
  7. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  8. <link rel="stylesheet" type="text/css" href="css/mui.css" />
  9. </head>
  10.  
  11. <body>
  12. <header class="mui-bar mui-bar-nav">
  13. <h1 class="mui-title">首页</h1>
  14. </header>
  15. <div class="mui-scroll-wrapper">
  16. <div class="mui-scroll">
  17. <div class="mui-content">
  18. <div id="slider" class="mui-slider">
  19. <div class="mui-slider-group mui-slider-loop">
  20. <!-- 额外增加的一个节点(循环轮播:第一个节点是最后一张轮播) -->
  21. <div class="mui-slider-item mui-slider-item-duplicate">
  22. <a href="#">
  23. <img src="http://placehold.it/400x300">
  24. </a>
  25. </div>
  26. <!-- 第一张 -->
  27. <div class="mui-slider-item">
  28. <a href="#">
  29. <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"
  30. width="300px" height="400px">
  31. </a>
  32. </div>
  33. <!-- 第二张 -->
  34. <div class="mui-slider-item">
  35. <a href="#">
  36. <img src="http://placehold.it/400x300">
  37. </a>
  38. </div>
  39. <!-- 第三张 -->
  40. <div class="mui-slider-item">
  41. <a href="#">
  42. <img src="http://placehold.it/400x300">
  43. </a>
  44. </div>
  45. <!-- 第四张 -->
  46. <div class="mui-slider-item">
  47. <a href="#">
  48. <img src="http://placehold.it/400x300">
  49. </a>
  50. </div>
  51. <!-- 额外增加的一个节点(循环轮播:最后一个节点是第一张轮播) -->
  52. <div class="mui-slider-item mui-slider-item-duplicate">
  53. <a href="#">
  54. <img src="http://placehold.it/400x300">
  55. </a>
  56. </div>
  57. </div>
  58. <div class="mui-slider-indicator">
  59. <div class="mui-indicator mui-active"></div>
  60. <div class="mui-indicator"></div>
  61. <div class="mui-indicator"></div>
  62. <div class="mui-indicator"></div>
  63. </div>
  64. </div>
  65. <ul class="mui-table-view mui-grid-view mui-grid-9">
  66. <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
  67. <a href="#">
  68. <span class="mui-icon mui-icon-home"></span>
  69. <div class="mui-media-body">Home</div>
  70. </a>
  71. </li>
  72. <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
  73. <a href="#">
  74. <span class="mui-icon mui-icon-email"><span class="mui-badge mui-badge-red">5</span></span>
  75. <div class="mui-media-body">Email</div>
  76. </a>
  77. </li>
  78. <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
  79. <a href="#">
  80. <span class="mui-icon mui-icon-chatbubble"></span>
  81. <div class="mui-media-body">Chat</div>
  82. </a>
  83. </li>
  84. <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
  85. <a href="#">
  86. <span class="mui-icon mui-icon-location"></span>
  87. <div class="mui-media-body">Location</div>
  88. </a>
  89. </li>
  90. <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
  91. <a href="#">
  92. <span class="mui-icon mui-icon-search"></span>
  93. <div class="mui-media-body">Search</div>
  94. </a>
  95. </li>
  96. <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
  97. <a href="#">
  98. <span class="mui-icon mui-icon-phone"></span>
  99. <div class="mui-media-body">Phone</div>
  100. </a>
  101. </li>
  102. </ul>
  103. <ul class="mui-table-view" id="content_list">
  104.  
  105. </ul>
  106. </div>
  107. </div>
  108.  
  109. </div>
  110. </body>
  111.  
  112. <script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
  113. <script type="text/javascript">
  114. mui.init()
  115. mui('.mui-scroll-wrapper').scroll()
  116. mui.back = function() {
  117. mui.toast("不让你点")
  118. };
  119.  
  120. mui.plusReady(function(){
  121. mui.post(
  122. window.serv+"/content_list",
  123. {},
  124. function(data){
  125. console.log(JSON.stringify(data));
  126.  
  127. for (var i = 0; i < data.data.length; i++) {
  128. create_content(data.data[i])
  129. }
  130. }
  131. )
  132.  
  133. })
  134.  
  135. document.addEventListener("talk",function(data){
  136. mui.toast(data.detail.talk);
  137. })
  138.  
  139. function create_content(content){ //创建图文列表
  140. var litag = document.createElement("li");
  141. litag.className = "mui-table-view-cell mui-media";
  142. var atag = document.createElement("a");
  143. atag.id = content._id;
  144. // 点击事件
  145. atag.onclick = function(){
  146. console.log(this.id);
  147. }
  148.  
  149. var imgtag = document.createElement("img");
  150. imgtag.className = "mui-media-object mui-pull-left";
  151.  
  152. imgtag.src = window.serv_imge + content.avatar;
  153. // console.log(window.serv_imge + content.avatar);
  154.  
  155. var divtag = document.createElement("div");
  156. divtag.className = "mui-media-body";
  157. divtag.innerText = content.title;
  158. var ptag = document.createElement("p");
  159. ptag.className = "mui-ellipsis";
  160. ptag.innerText = content.intro;
  161.  
  162. litag.appendChild(atag);
  163. atag.appendChild(imgtag);
  164. atag.appendChild(divtag);
  165. divtag.appendChild(ptag);
  166.  
  167. document.getElementById("content_list").appendChild(litag);
  168.  
  169. }
  170.  
  171. </script>
  172.  
  173. </html>

使用模拟器访问,点击图文列表,HBuilder控制台就会输出id:

这些id是从MongoDB获取,并渲染的!

修改main.html,新增一个方法openPlayer,用来打开播放页面。传递id参数

点击图文列表时,就调用次方法。

  1. <!doctype html>
  2. <html lang="en">
  3.  
  4. <head>
  5. <meta charset="UTF-8" />
  6. <title>Document</title>
  7. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  8. <link rel="stylesheet" type="text/css" href="css/mui.css" />
  9. </head>
  10.  
  11. <body>
  12. <header class="mui-bar mui-bar-nav">
  13. <h1 class="mui-title">首页</h1>
  14. </header>
  15. <div class="mui-scroll-wrapper">
  16. <div class="mui-scroll">
  17. <div class="mui-content">
  18. <div id="slider" class="mui-slider">
  19. <div class="mui-slider-group mui-slider-loop">
  20. <!-- 额外增加的一个节点(循环轮播:第一个节点是最后一张轮播) -->
  21. <div class="mui-slider-item mui-slider-item-duplicate">
  22. <a href="#">
  23. <img src="http://placehold.it/400x300">
  24. </a>
  25. </div>
  26. <!-- 第一张 -->
  27. <div class="mui-slider-item">
  28. <a href="#">
  29. <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"
  30. width="300px" height="400px">
  31. </a>
  32. </div>
  33. <!-- 第二张 -->
  34. <div class="mui-slider-item">
  35. <a href="#">
  36. <img src="http://placehold.it/400x300">
  37. </a>
  38. </div>
  39. <!-- 第三张 -->
  40. <div class="mui-slider-item">
  41. <a href="#">
  42. <img src="http://placehold.it/400x300">
  43. </a>
  44. </div>
  45. <!-- 第四张 -->
  46. <div class="mui-slider-item">
  47. <a href="#">
  48. <img src="http://placehold.it/400x300">
  49. </a>
  50. </div>
  51. <!-- 额外增加的一个节点(循环轮播:最后一个节点是第一张轮播) -->
  52. <div class="mui-slider-item mui-slider-item-duplicate">
  53. <a href="#">
  54. <img src="http://placehold.it/400x300">
  55. </a>
  56. </div>
  57. </div>
  58. <div class="mui-slider-indicator">
  59. <div class="mui-indicator mui-active"></div>
  60. <div class="mui-indicator"></div>
  61. <div class="mui-indicator"></div>
  62. <div class="mui-indicator"></div>
  63. </div>
  64. </div>
  65. <ul class="mui-table-view mui-grid-view mui-grid-9">
  66. <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
  67. <a href="#">
  68. <span class="mui-icon mui-icon-home"></span>
  69. <div class="mui-media-body">Home</div>
  70. </a>
  71. </li>
  72. <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
  73. <a href="#">
  74. <span class="mui-icon mui-icon-email"><span class="mui-badge mui-badge-red">5</span></span>
  75. <div class="mui-media-body">Email</div>
  76. </a>
  77. </li>
  78. <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
  79. <a href="#">
  80. <span class="mui-icon mui-icon-chatbubble"></span>
  81. <div class="mui-media-body">Chat</div>
  82. </a>
  83. </li>
  84. <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
  85. <a href="#">
  86. <span class="mui-icon mui-icon-location"></span>
  87. <div class="mui-media-body">Location</div>
  88. </a>
  89. </li>
  90. <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
  91. <a href="#">
  92. <span class="mui-icon mui-icon-search"></span>
  93. <div class="mui-media-body">Search</div>
  94. </a>
  95. </li>
  96. <li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
  97. <a href="#">
  98. <span class="mui-icon mui-icon-phone"></span>
  99. <div class="mui-media-body">Phone</div>
  100. </a>
  101. </li>
  102. </ul>
  103. <ul class="mui-table-view" id="content_list">
  104.  
  105. </ul>
  106. </div>
  107. </div>
  108.  
  109. </div>
  110. </body>
  111.  
  112. <script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
  113. <script type="text/javascript">
  114. mui.init()
  115. mui('.mui-scroll-wrapper').scroll()
  116. mui.back = function() {
  117. mui.toast("不让你点")
  118. };
  119.  
  120. mui.plusReady(function(){
  121. mui.post(
  122. window.serv+"/content_list",
  123. {},
  124. function(data){
  125. console.log(JSON.stringify(data));
  126.  
  127. for (var i = 0; i < data.data.length; i++) {
  128. create_content(data.data[i])
  129. }
  130. }
  131. )
  132.  
  133. })
  134.  
  135. document.addEventListener("talk",function(data){
  136. mui.toast(data.detail.talk);
  137. })
  138.  
  139. function create_content(content){ //创建图文列表
  140. var litag = document.createElement("li");
  141. litag.className = "mui-table-view-cell mui-media";
  142. var atag = document.createElement("a");
  143. atag.id = content._id;
  144. // 点击事件
  145. atag.onclick = function(){
  146. console.log(this.id);
  147. openPlayer(this.id); //调用openPlayer方法
  148. }
  149.  
  150. var imgtag = document.createElement("img");
  151. imgtag.className = "mui-media-object mui-pull-left";
  152.  
  153. imgtag.src = window.serv_imge + content.avatar;
  154. // console.log(window.serv_imge + content.avatar);
  155.  
  156. var divtag = document.createElement("div");
  157. divtag.className = "mui-media-body";
  158. divtag.innerText = content.title;
  159. var ptag = document.createElement("p");
  160. ptag.className = "mui-ellipsis";
  161. ptag.innerText = content.intro;
  162.  
  163. litag.appendChild(atag);
  164. atag.appendChild(imgtag);
  165. atag.appendChild(divtag);
  166. divtag.appendChild(ptag);
  167.  
  168. document.getElementById("content_list").appendChild(litag);
  169.  
  170. }
  171.  
  172. function openPlayer(content_id){ //打开播放页面
  173. mui.openWindow({
  174. url:"player.html",
  175. id:"player.html",
  176. // 传递参数content_id
  177. extras:{content_id:content_id}
  178. })
  179. }
  180.  
  181. </script>
  182.  
  183. </html>

修改player.html,接收id

  1. <!doctype html>
  2. <html>
  3.  
  4. <head>
  5. <meta charset="UTF-8">
  6. <title></title>
  7. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  8. <link href="css/mui.min.css" rel="stylesheet" />
  9. </head>
  10.  
  11. <body>
  12. <header class="mui-bar mui-bar-nav">
  13. <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
  14. <h1 class="mui-title" id="title_text">正在播放</h1>
  15. </header>
  16. <div class="mui-content">
  17. <div class="mui-row" style="text-align: center;margin-top: 5px;">
  18. <img src="avatar/girl.jpg" style="width: 250px;height: 250px; border-radius: 50%;" id="avatar" />
  19. </div>
  20. <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id='play' >播放</button>
  21. </div>
  22.  
  23. </body>
  24. <script src="js/mui.js"></script>
  25. <script type="text/javascript">
  26. mui.init();
  27. var Sdata = null;
  28. mui.plusReady(function() {
  29. Sdata = plus.webview.currentWebview(); // 当前web页面
  30. mui.toast(Sdata.content_id); // 弹窗显示由main.html传递的content_id
  31. })
  32. </script>
  33.  
  34. </html>

使用模拟器访问,底部会弹出id,效果如下:

发送POST请求

修改player.html,注意js代码部分,是mui.js。因为它依赖mui.js的一个全局变量!

  1. <!doctype html>
  2. <html>
  3.  
  4. <head>
  5. <meta charset="UTF-8">
  6. <title></title>
  7. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  8. <link href="css/mui.min.css" rel="stylesheet" />
  9. </head>
  10.  
  11. <body>
  12. <header class="mui-bar mui-bar-nav">
  13. <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
  14. <h1 class="mui-title" id="title_text">正在播放</h1>
  15. </header>
  16. <div class="mui-content">
  17. <div class="mui-row" style="text-align: center;margin-top: 5px;">
  18. <img src="avatar/girl.jpg" style="width: 250px;height: 250px; border-radius: 50%;" id="avatar" />
  19. </div>
  20. </div>
  21.  
  22. </body>
  23. <script src="js/mui.min.js"></script>
  24. <script type="text/javascript">
  25. mui.init();
  26. var Sdata = null;
  27. mui.plusReady(function() {
  28. Sdata = plus.webview.currentWebview(); // 当前web页面
  29. mui.toast(Sdata.content_id); // 弹窗显示由main.html传递的content_id
  30. //发送post请求
  31. mui.post(
  32. window.serv + "/content_one", {
  33. // 参数为content_id
  34. content_id: Sdata.content_id
  35. },
  36. function(data) {
  37. // 打印响应数据
  38. console.log(JSON.stringify(data));
  39.  
  40. }
  41. )
  42. })
  43. </script>
  44.  
  45. </html>

打开flask项目,修改 serv-->content.py,增加视图函数content_one

  1. from flask import Blueprint, jsonify,request
  2. from setting import MONGO_DB
  3. from setting import RET
  4. from bson import ObjectId
  5.  
  6. cont = Blueprint("cont", __name__)
  7.  
  8. @cont.route("/content_list", methods=["POST"])
  9. def content_list(): # 内容列表
  10. res_list = list(MONGO_DB.sources.find({})) # 字典转换列表
  11.  
  12. for index, item in enumerate(res_list): #返回 enumerate(枚举)对象
  13. # 由于_id是ObjectId对象,转换为字符串
  14. res_list[index]["_id"] = str(item.get("_id"))
  15.  
  16. RET["code"] = 0
  17. RET["msg"] = ""
  18. RET["data"] = res_list
  19.  
  20. return jsonify(RET) # 返回json数据
  21.  
  22. @cont.route("/content_one", methods=["POST"])
  23. def content_one():
  24. """
  25. 获取一条内容
  26. :return: settings-->RET
  27. """
  28. content_id = request.form.get("content_id")
  29. # 根据_id获取一条数据
  30. res = MONGO_DB.sources.find_one({"_id":ObjectId(content_id)})
  31.  
  32. res["_id"] = str(res["_id"]) # 转换为str
  33.  
  34. RET["code"] = 0
  35. RET["msg"] = ""
  36. RET["data"] = res
  37.  
  38. return jsonify(RET)

使用模拟器,重新点击一次,查看HBuilder控制台输出:

  1. {"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

  1. <!doctype html>
  2. <html>
  3.  
  4. <head>
  5. <meta charset="UTF-8">
  6. <title></title>
  7. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  8. <link href="css/mui.min.css" rel="stylesheet" />
  9. </head>
  10.  
  11. <body>
  12. <header class="mui-bar mui-bar-nav">
  13. <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
  14. <h1 class="mui-title" id="title_text">正在播放</h1>
  15. </header>
  16. <div class="mui-content">
  17. <div class="mui-row" style="text-align: center;margin-top: 5px;">
  18. <img src="avatar/girl.jpg" style="width: 250px;height: 250px; border-radius: 50%;" id="avatar" />
  19. </div>
  20. </div>
  21.  
  22. </body>
  23. <script src="js/mui.js"></script>
  24. <script type="text/javascript">
  25. mui.init();
  26. var Sdata = null;
  27. mui.plusReady(function() {
  28. Sdata = plus.webview.currentWebview(); // 当前web页面
  29. mui.toast(Sdata.content_id); // 弹窗显示由main.html传递的content_id
  30.  
  31. //发送post请求
  32. mui.post(
  33. window.serv + "/content_one", {
  34. // 参数为content_id
  35. content_id: Sdata.content_id
  36. },
  37. function(data) {
  38. // 打印响应数据
  39. console.log(JSON.stringify(data));
  40. // 修改标题
  41. document.getElementById("title_text").innerText = "正在播放 : " + data.data.title;
  42. // 修改图片地址
  43. document.getElementById("avatar").src = window.serv_imge + data.data.avatar;
  44. }
  45. )
  46. })
  47. </script>
  48.  
  49. </html>

使用模拟器,重新点击。播放如下:

现在需要播放这首歌曲,如何实现呢?

听歌是一个新的接口,使用Audio模块

Audio模块

Audio模块用于提供音频的录制和播放功能,可调用系统的麦克风设备进行录音操作,也可调用系统的扬声器设备播放音频文件。通过plus.audio获取音频管理对象。

参考链接:

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

AudioPlayer

音频播放对象

  1. interface AudioPlayer {
  2. function void play( successCB, errorCB );
  3. function void pause();
  4. function void resume();
  5. function void stop();
  6. function void seekTo( position );
  7. function Number getDuration();
  8. function Number getPosition();
  9. function void setRoute( route );
  10. }

说明:

音频播放对象,用于音频文件的播放。不能通过new方法直接创建,只能通过audio.createPlayer方法创建。

方法:

参考链接:

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

由于音频在后端,前端播放时,获取的是一个远程音频。能播放吗?

先测试一下本地播放

测试本地播放

使用HBuilder 新建一个文件夹audiotest,

在此目录,放一个音频文件123.mp3

修改player.html,增加一个button按钮。设置点击事件,播放123.mp3

  1. <!doctype html>
  2. <html>
  3.  
  4. <head>
  5. <meta charset="UTF-8">
  6. <title></title>
  7. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  8. <link href="css/mui.min.css" rel="stylesheet" />
  9. </head>
  10.  
  11. <body>
  12. <header class="mui-bar mui-bar-nav">
  13. <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
  14. <h1 class="mui-title" id="title_text">正在播放</h1>
  15. </header>
  16. <div class="mui-content">
  17. <div class="mui-row" style="text-align: center;margin-top: 5px;">
  18. <img src="avatar/girl.jpg" style="width: 250px;height: 250px; border-radius: 50%;" id="avatar" />
  19. </div>
  20. <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id="play">播放</button>
  21. </div>
  22.  
  23. </body>
  24. <script src="js/mui.js"></script>
  25. <script type="text/javascript">
  26. mui.init();
  27. var Sdata = null;
  28. mui.plusReady(function() {
  29. Sdata = plus.webview.currentWebview(); // 当前web页面
  30. mui.toast(Sdata.content_id); // 弹窗显示由main.html传递的content_id
  31.  
  32. //发送post请求
  33. mui.post(
  34. window.serv + "/content_one", {
  35. // 参数为content_id
  36. content_id: Sdata.content_id
  37. },
  38. function(data) {
  39. // 打印响应数据
  40. console.log(JSON.stringify(data));
  41. // 修改标题
  42. document.getElementById("title_text").innerText = "正在播放 : " + data.data.title;
  43. // 修改图片地址
  44. document.getElementById("avatar").src = window.serv_imge + data.data.avatar;
  45.  
  46. }
  47. );
  48.  
  49. function play_anything(content) { //播放音频
  50. // 创建播放对象
  51. player = plus.audio.createPlayer(content);
  52. player.play(); // 播放音频
  53. }
  54.  
  55. document.getElementById("play").addEventListener("tap", function() {
  56. // 播放指定音乐
  57. play_anything("audiotest/123.mp3");
  58. });
  59. })
  60. </script>
  61.  
  62. </html>

打开模拟器,点击任意的图文列表。跳转到播放页面,点击播放,就会有声音了!

如果没有声音,打开音量合成器。将模拟器的音量设置和系统一样

参考链接:

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

如果还是没有声音,重启夜神模拟器。再次播放,就有声音了!

我就是这么解决的!

播放远程音频

既然本地的解决了,删除目录audiotest目录!

下面来测试一下播放远程音频。

修改mui.js,增加全局变量serv_audio

  1. ...
  2. window.serv = "http://192.168.11.86:9527"
  3. window.serv_imge = window.serv+"/get_image/";
  4. window.serv_audio = window.serv+"/get_audio/";
  5. ...

修改 player.html,设置为远程地址

  1. <!doctype html>
  2. <html>
  3.  
  4. <head>
  5. <meta charset="UTF-8">
  6. <title></title>
  7. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  8. <link href="css/mui.min.css" rel="stylesheet" />
  9. </head>
  10.  
  11. <body>
  12. <header class="mui-bar mui-bar-nav">
  13. <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
  14. <h1 class="mui-title" id="title_text">正在播放</h1>
  15. </header>
  16. <div class="mui-content">
  17. <div class="mui-row" style="text-align: center;margin-top: 5px;">
  18. <img src="avatar/girl.jpg" style="width: 250px;height: 250px; border-radius: 50%;" id="avatar" />
  19. </div>
  20. <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id="play">播放</button>
  21. </div>
  22.  
  23. </body>
  24. <script src="js/mui.js"></script>
  25. <script type="text/javascript">
  26. mui.init();
  27. var Sdata = null;
  28. mui.plusReady(function() {
  29. Sdata = plus.webview.currentWebview(); // 当前web页面
  30. mui.toast(Sdata.content_id); // 弹窗显示由main.html传递的content_id
  31.  
  32. //发送post请求
  33. mui.post(
  34. window.serv + "/content_one", {
  35. // 参数为content_id
  36. content_id: Sdata.content_id
  37. },
  38. function(data) {
  39. // 打印响应数据
  40. console.log(JSON.stringify(data));
  41. // 修改标题
  42. document.getElementById("title_text").innerText = "正在播放 : " + data.data.title;
  43. // 修改图片地址
  44. document.getElementById("avatar").src = window.serv_imge + data.data.avatar;
  45. // 调用自定义方法,播放音频
  46. // data是后端返回的数据,data.audio是音频文件名
  47. play_anything(data.data.audio);
  48. }
  49. );
  50.  
  51. function play_anything(content) { //播放音频
  52. // 创建播放对象,拼接路径
  53. player = plus.audio.createPlayer(window.serv_audio + content);
  54. console.log(window.serv_audio + content); //打印路径
  55. // http://192.168.11.86:9527/get_audio/a6d680fe-fa80-4a54-82b8-b203f5a9c7b4.mp3
  56. player.play(); // 播放音频
  57. }
  58.  
  59. document.getElementById("play").addEventListener("tap", function() {
  60. // 播放指定音乐
  61. // play_anything("audiotest/123.mp3");
  62. });
  63. })
  64. </script>
  65.  
  66. </html>

使用模拟器访问,点击一个列表,就会自动播放

如果要其他功能,比如暂停,继续,停止。

修改player.html,增加按钮,并增加3个方法。

  1. <!doctype html>
  2. <html>
  3.  
  4. <head>
  5. <meta charset="UTF-8">
  6. <title></title>
  7. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  8. <link href="css/mui.min.css" rel="stylesheet" />
  9. </head>
  10.  
  11. <body>
  12. <header class="mui-bar mui-bar-nav">
  13. <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
  14. <h1 class="mui-title" id="title_text">正在播放</h1>
  15. </header>
  16. <div class="mui-content">
  17. <div class="mui-row" style="text-align: center;margin-top: 5px;">
  18. <img src="avatar/girl.jpg" style="width: 250px;height: 250px; border-radius: 50%;" id="avatar" />
  19. </div>
  20. <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id="play">播放</button>
  21. <button type="button" class="mui-btn mui-btn-yellow mui-btn-block" id="pause">暂停</button>
  22. <button type="button" class="mui-btn mui-btn-green mui-btn-block" id="resume">继续</button>
  23. <button type="button" class="mui-btn mui-btn-red mui-btn-block" id="stop">停止</button>
  24. </div>
  25.  
  26. </body>
  27. <script src="js/mui.js"></script>
  28. <script type="text/javascript">
  29. mui.init();
  30. var Sdata = null; //当前web页面
  31. var player = null; //播放对象
  32. mui.plusReady(function() {
  33. Sdata = plus.webview.currentWebview(); // 当前web页面
  34. mui.toast(Sdata.content_id); // 弹窗显示由main.html传递的content_id
  35.  
  36. //发送post请求
  37. mui.post(
  38. window.serv + "/content_one", {
  39. // 参数为content_id
  40. content_id: Sdata.content_id
  41. },
  42. function(data) {
  43. // 打印响应数据
  44. console.log(JSON.stringify(data));
  45. // 修改标题
  46. document.getElementById("title_text").innerText = "正在播放 : " + data.data.title;
  47. // 修改图片地址
  48. document.getElementById("avatar").src = window.serv_imge + data.data.avatar;
  49. // 调用自定义方法,播放音频
  50. // data是后端返回的数据,data.audio是音频文件名
  51. play_anything(data.data.audio);
  52. }
  53. );
  54.  
  55. function play_anything(content) { //播放音频
  56. // 创建播放对象,拼接路径
  57. player = plus.audio.createPlayer(window.serv_audio + content);
  58. console.log(window.serv_audio + content); //打印路径
  59. // http://192.168.11.86:9527/get_audio/a6d680fe-fa80-4a54-82b8-b203f5a9c7b4.mp3
  60. player.play(); // 播放音频
  61. }
  62.  
  63. document.getElementById("play").addEventListener("tap", function() {
  64. player.play();
  65. });
  66.  
  67. document.getElementById("pause").addEventListener("tap", function() {
  68. player.pause(); //暂停
  69. });
  70.  
  71. document.getElementById("resume").addEventListener("tap", function() {
  72. player.resume(); //继续
  73. });
  74.  
  75. document.getElementById("stop").addEventListener("tap", function() {
  76. player.stop(); // 停止,直接清空player中的对象
  77. });
  78.  
  79. })
  80. </script>
  81.  
  82. </html>

使用模拟器访问,点击一首歌。会自动播放!

点击暂停-->继续,暂停-->继续,再点击停止。最后点击播放,就没有声音了!

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

二、web端的玩具

小故事

先来讲一个小故事:前期开发时,由于软件部需要测试。但是硬件部暂时无法拿出板子给软件部测试!

为了解决这个问题,硬件部使用了工程版的面板做了low版的样品,给软件部测试。第一天测试了几个小时,到了中午时间,同事都去吃饭了!

回来时,发现板子烧了!桌子烧一个大洞!键盘没了一半,显示器...

为啥呢?因为芯片程序,没有写任何保护措施。触发了一个死循环,导致板子过热!

为了避免重蹈覆辙,不允许使用工程版!

软件部为了测试,做了一个web版玩具页面!使用websocket

web版玩具页面

之前后端写的 manager.py,是用来提供资源服务的。

现在和玩具交互,使用websocket,它是通讯类服务。需要单独起一个进程,和资源进程分开!

录音

新建文件 im_serv.py

  1. from flask import Flask, request
  2. from geventwebsocket.websocket import WebSocket
  3. from geventwebsocket.handler import WebSocketHandler
  4. from gevent.pywsgi import WSGIServer
  5. import json
  6.  
  7. app = Flask(__name__)
  8.  
  9. user_socket_dict = {} # 空字典,用来存放用户名和发送消息
  10.  
  11. @app.route("/toy/<tid>")
  12. def toy(tid):
  13. # 获取请求的WebSocket对象
  14. user_socket = request.environ.get("wsgi.websocket") # type:WebSocket
  15. if user_socket:
  16. # 设置键值对
  17. user_socket_dict[tid] = user_socket
  18. print(user_socket_dict)
  19. # {'123456': <geventwebsocket.websocket.WebSocket object at 0x00000176ABD92E18>}
  20.  
  21. # 循环,接收消息
  22. while True:
  23. # 接收消息
  24. msg = user_socket.receive()
  25. print(msg) # 打印
  26.  
  27. if __name__ == '__main__':
  28. # 创建一个WebSocket服务器
  29. http_serv = WSGIServer(("0.0.0.0", 9528), app, handler_class=WebSocketHandler)
  30. # 开始监听HTTP请求
  31. http_serv.serve_forever()

在templates 目录创建文件index.html,将之前的单聊的页面拿过来

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6.  
  7. </head>
  8. <body>
  9. <audio src="" autoplay controls id="player"></audio>
  10. <br>
  11. <button onclick="start_reco()">开始废话</button>
  12. <br>
  13. <button onclick="stop_reco()">发送语音</button>
  14. </body>
  15. <script src="/static/recorder.js"></script>
  16. <script type="application/javascript">
  17. // 获取音频文件
  18. var get_file = "http://192.168.11.86:9527/get_audio/";
  19. // 创建 WebSocket 对象
  20. var ws = new WebSocket("ws://192.168.11.86:9528/toy/123456");
  21. var reco = null;
  22. // 创建AudioContext对象
  23. var audio_context = new AudioContext();
  24. //要获取音频和视频
  25. navigator.getUserMedia = (navigator.getUserMedia ||
  26. navigator.webkitGetUserMedia ||
  27. navigator.mozGetUserMedia ||
  28. navigator.msGetUserMedia);
  29.  
  30. // 拿到媒体对象,允许音频对象
  31. navigator.getUserMedia({audio: true}, create_stream, function (err) {
  32. console.log(err)
  33. });
  34.  
  35. //创建媒体流容器
  36. function create_stream(user_media) {
  37. var stream_input = audio_context.createMediaStreamSource(user_media);
  38. // 给Recoder 创建一个空间,麦克风说的话,都可以录入。是一个流
  39. reco = new Recorder(stream_input);
  40.  
  41. }
  42.  
  43. function start_reco() { //开始录音
  44. reco.record(); //往里面写流
  45. }
  46.  
  47. function stop_reco() { //停止录音
  48. reco.stop(); //停止写入流
  49. get_audio(); //调用自定义方法
  50. reco.clear(); //清空容器
  51. }
  52.  
  53. function get_audio() { // 获取音频
  54. reco.exportWAV(function (wav_file) {
  55. ws.send(wav_file); //使用websocket连接发送数据给后端
  56. })
  57. }
  58.  
  59. ws.onmessage = function (data) { // 客户端接收服务端数据时触发
  60. // console.log(get_file + data.data);
  61. var content = JSON.parse(data.data);
  62. // 修改id为player的src属性,实现自动播放
  63. document.getElementById("player").src = get_file + content.data;
  64. console.log(content.from_user + "给你点了一首歌");
  65. }
  66.  
  67. </script>
  68. </html>

将recorder.js,放到static目录。

github下载地址为:

https://github.com/mattdiamond/Recorderjs

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

  1. from flask import Flask, request,jsonify,render_template
  2. from setting import MONGO_DB
  3. from setting import RET
  4. from bson import ObjectId
  5. from serv import get_file
  6. from serv import content
  7.  
  8. app = Flask(__name__)
  9.  
  10. app.register_blueprint(get_file.getfile)
  11. app.register_blueprint(content.cont)
  12.  
  13. @app.route('/')
  14. def hello_world():
  15. return render_template("index.html")
  16.  
  17. @app.route('/login',methods=["POST"])
  18. def login():
  19. """
  20. 登陆验证
  21. :return: settings -> RET
  22. """
  23. try:
  24. RET["code"] = 1
  25. RET["msg"] = "用户名或密码错误"
  26. RET["data"] = {}
  27.  
  28. username = request.form.get("username")
  29. password = request.form.get("password")
  30.  
  31. user = MONGO_DB.users.find_one({"username": username, "password": password})
  32.  
  33. if user:
  34. # 由于user中的_id是ObjectId对象,需要转化为字符串
  35. user["_id"] = str(user.get("_id"))
  36. RET["code"] = 0
  37. RET["msg"] = "欢迎登陆"
  38. RET["data"] = {"user_id": user.get("_id")}
  39.  
  40. except Exception as e:
  41. RET["code"] = 1
  42. RET["msg"] = "登陆失败"
  43.  
  44. return jsonify(RET)
  45.  
  46. @app.route('/reg',methods=["POST"])
  47. def reg():
  48. """
  49. 注册
  50. :return: {"code":0,"msg":"","data":""}
  51. """
  52. try:
  53. username = request.form.get("username")
  54. password = request.form.get("password")
  55. age = request.form.get("age")
  56. nickname = request.form.get("nickname")
  57. gender = request.form.get("gender")
  58. phone = request.form.get("phone")
  59.  
  60. user_info = {
  61. "username": username,
  62. "password": password,
  63. "age": age,
  64. "nickname": nickname,
  65. "gender": gender,
  66. "phone": phone
  67. }
  68.  
  69. res = MONGO_DB.users.insert_one(user_info)
  70. user_id = str(res.inserted_id)
  71.  
  72. RET["code"] = 0
  73. RET["msg"] = "注册成功"
  74. RET["data"] = user_id
  75. except Exception as e:
  76. RET["code"] = 1
  77. RET["msg"] = "注册失败"
  78.  
  79. return jsonify(RET)
  80.  
  81. @app.route('/user_info', methods=["POST"])
  82. def user_info():
  83. user_id = request.form.get("user_id")
  84.  
  85. # "password": 0 表示忽略密码字段
  86. res = MONGO_DB.users.find_one({"_id": ObjectId(user_id)}, {"password": 0})
  87. if res:
  88. res["_id"] = str(res.get("_id"))
  89.  
  90. RET["code"] = 0
  91. RET["msg"] = ""
  92. RET["data"] = res
  93.  
  94. return jsonify(res)
  95.  
  96. if __name__ == '__main__':
  97. app.run("0.0.0.0", 9527, debug=True)

此时目录结构如下:

  1. ./
  2. ├── audio
  3. ├── audio_img
  4. ├── im_serv.py
  5. ├── manager.py
  6. ├── serv
  7.    ├── content.py
  8.    └── get_file.py
  9. ├── setting.py
  10. ├── static
  11.    └── recorder.js
  12. ├── templates
  13.    └── index.html
  14. └── xiaopapa.py

访问首页:

http://127.0.0.1:9527/

注意:千万不要用IP访问,否则点击开始废话时,console会报错!

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

提示 只有安全的来源是允许的。什么意思呢?就是说,这个链接,必须使用HTTPS连接。涉及HTTPS,必然就要买证书了!

当然了,证书又很贵!这里推荐bootcdn使用的免费证书,参考链接:

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

访问首页之后,Pycharm控制台就会输出:

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

这个123456是从哪里来的呢?是用index.html来的,看这一行代码

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

这里,我指定的id为123456,后端接收后,以id为键。那么打印出一个字典!

点击页面的开始废话,再点击停止

查看Pycharm控制台输出:

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

输出了bytearray数据类型,它可以直接保存为音频文件!

修改im_serv.py,判断类型,保存文件

  1. from flask import Flask, request
  2. from geventwebsocket.websocket import WebSocket
  3. from geventwebsocket.handler import WebSocketHandler
  4. from gevent.pywsgi import WSGIServer
  5. import json
  6.  
  7. app = Flask(__name__)
  8.  
  9. user_socket_dict = {} # 空字典,用来存放用户名和发送消息
  10.  
  11. @app.route("/toy/<tid>")
  12. def toy(tid):
  13. # 获取请求的WebSocket对象
  14. user_socket = request.environ.get("wsgi.websocket") # type:WebSocket
  15. if user_socket:
  16. # 设置键值对
  17. user_socket_dict[tid] = user_socket
  18. print(user_socket_dict)
  19. # {'123456': <geventwebsocket.websocket.WebSocket object at 0x00000176ABD92E18>}
  20.  
  21. # 循环,接收消息
  22. while True:
  23. # 接收消息
  24. msg = user_socket.receive()
  25. print(msg) # 打印
  26. if type(msg) == bytearray:
  27. with open('123.wav','wb') as f:
  28. f.write(msg) # 写入文件
  29.  
  30. if __name__ == '__main__':
  31. # 创建一个WebSocket服务器
  32. http_serv = WSGIServer(("0.0.0.0", 9528), app, handler_class=WebSocketHandler)
  33. # 开始监听HTTP请求
  34. http_serv.serve_forever()

重启im_serv.py

再次访问首页,录一段音。查看flask项目,会生成一个123.wav文件

直接播放这个文件,是有声音的!

注意:这个页面,就代指了玩具!

三、app通过websocket远程遥控玩具播放内容

现在手机APP,也需要通过websocket连接服务器。那么手机能不能也连接 ws://192.168.11.86:9528/toy/123456

呢?可以的!但是我不想让手机连接它。因为手机发送的数据,不一定是bytearray,也有可能是字符串。

需要重新写一个接口

修改im_serv.py,增加视图函数user_app

  1. from flask import Flask, request
  2. from geventwebsocket.websocket import WebSocket
  3. from geventwebsocket.handler import WebSocketHandler
  4. from gevent.pywsgi import WSGIServer
  5. import json
  6.  
  7. app = Flask(__name__)
  8.  
  9. user_socket_dict = {} # 空字典,用来存放用户名和发送消息
  10.  
  11. @app.route("/toy/<tid>")
  12. def toy(tid): # 玩具连接
  13. # 获取请求的WebSocket对象
  14. user_socket = request.environ.get("wsgi.websocket") # type:WebSocket
  15. if user_socket:
  16. # 设置键值对
  17. user_socket_dict[tid] = user_socket
  18. print(user_socket_dict)
  19. # {'123456': <geventwebsocket.websocket.WebSocket object at 0x00000176ABD92E18>}
  20.  
  21. # 循环,接收消息
  22. while True:
  23. # 接收消息
  24. msg = user_socket.receive()
  25. print(msg) # 打印
  26. if type(msg) == bytearray:
  27. print(11)
  28. with open('123.wav','wb') as f:
  29. f.write(msg) # 写入文件
  30.  
  31. @app.route("/app/<uid>")
  32. def user_app(uid): # 手机app连接
  33. user_socket = request.environ.get("wsgi.websocket") # type:WebSocket
  34. if user_socket:
  35. user_socket_dict[uid] = user_socket
  36. # { uid : websocket}
  37. print(user_socket_dict)
  38. while True: # 手机听歌 把歌曲发送给 玩具 1.将文件直接发送给玩具 2.将当前听的歌曲名称或ID发送到玩具
  39. msg = user_socket.receive()
  40. print(msg)
  41.  
  42. if __name__ == '__main__':
  43. # 创建一个WebSocket服务器
  44. http_serv = WSGIServer(("0.0.0.0", 9528), app, handler_class=WebSocketHandler)
  45. # 开始监听HTTP请求
  46. http_serv.serve_forever()

修改MyApp里面的player.html,增加按钮,发送给玩具

  1. <!doctype html>
  2. <html>
  3.  
  4. <head>
  5. <meta charset="UTF-8">
  6. <title></title>
  7. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  8. <link href="css/mui.min.css" rel="stylesheet" />
  9. </head>
  10.  
  11. <body>
  12. <header class="mui-bar mui-bar-nav">
  13. <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
  14. <h1 class="mui-title" id="title_text">正在播放</h1>
  15. </header>
  16. <div class="mui-content">
  17. <div class="mui-row" style="text-align: center;margin-top: 5px;">
  18. <img src="avatar/girl.jpg" style="width: 250px;height: 250px; border-radius: 50%;" id="avatar" />
  19. </div>
  20. <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id="play">播放</button>
  21. <button type="button" class="mui-btn mui-btn-yellow mui-btn-block" id="pause">暂停</button>
  22. <button type="button" class="mui-btn mui-btn-green mui-btn-block" id="resume">继续</button>
  23. <button type="button" class="mui-btn mui-btn-red mui-btn-block" id="stop">停止</button>
  24. <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id="send2toy">发送给玩具</button>
  25. </div>
  26.  
  27. </body>
  28. <script src="js/mui.js"></script>
  29. <script type="text/javascript">
  30. mui.init();
  31. var Sdata = null; //当前web页面
  32. var player = null; //播放对象
  33. mui.plusReady(function() {
  34. Sdata = plus.webview.currentWebview(); // 当前web页面
  35. mui.toast(Sdata.content_id); // 弹窗显示由main.html传递的content_id
  36.  
  37. //发送post请求
  38. mui.post(
  39. window.serv + "/content_one", {
  40. // 参数为content_id
  41. content_id: Sdata.content_id
  42. },
  43. function(data) {
  44. // 打印响应数据
  45. console.log(JSON.stringify(data));
  46. // 修改标题
  47. document.getElementById("title_text").innerText = "正在播放 : " + data.data.title;
  48. // 修改图片地址
  49. document.getElementById("avatar").src = window.serv_imge + data.data.avatar;
  50. // 调用自定义方法,播放音频
  51. // data是后端返回的数据,data.audio是音频文件名
  52. play_anything(data.data.audio);
  53. }
  54. );
  55.  
  56. function play_anything(content) { //播放音频
  57. // 创建播放对象,拼接路径
  58. player = plus.audio.createPlayer(window.serv_audio + content);
  59. console.log(window.serv_audio + content); //打印路径
  60. // http://192.168.11.86:9527/get_audio/a6d680fe-fa80-4a54-82b8-b203f5a9c7b4.mp3
  61. player.play(); // 播放音频
  62. }
  63.  
  64. document.getElementById("play").addEventListener("tap", function() {
  65. player.play();
  66. });
  67.  
  68. document.getElementById("pause").addEventListener("tap", function() {
  69. player.pause(); //暂停
  70. });
  71.  
  72. document.getElementById("resume").addEventListener("tap", function() {
  73. player.resume(); //继续
  74. });
  75.  
  76. document.getElementById("stop").addEventListener("tap", function() {
  77. player.stop(); // 停止,直接清空player中的对象
  78. });
  79.  
  80. })
  81. </script>
  82.  
  83. </html>

使用模拟器访问,效果如下:

建立连接

需要在APP中使用websocket,那么在什么时候,建立连接呢?

应该是在用户登录之后,点击首页时,建立websocket连接

修改mui.js,增加全局变量 ws_serv

  1. ...
  2. window.ws_serv = "192.168.11.86:9528";
  3. window.serv = "http://192.168.11.86:9527";
  4. window.serv_imge = window.serv+"/get_image/";
  5. window.serv_audio = window.serv+"/get_audio/";
  6. ...

修改index.html,判断登录状态,建立连接

  1. <!DOCTYPE html>
  2. <html>
  3.  
  4. <head>
  5. <meta charset="utf-8">
  6. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  7. <title></title>
  8. <script src="js/mui.js"></script>
  9. <link href="css/mui.min.css" rel="stylesheet" />
  10. </head>
  11.  
  12. <body>
  13. <nav class="mui-bar mui-bar-tab">
  14. <a class="mui-tab-item mui-active" id="index">
  15. <span class="mui-icon mui-icon-home"></span>
  16. <span class="mui-tab-label">首页</span>
  17. </a>
  18. <a class="mui-tab-item" id="phone">
  19. <span class="mui-icon mui-icon-phone"></span>
  20. <span class="mui-tab-label">电话</span>
  21. </a>
  22. <a class="mui-tab-item">
  23. <span class="mui-icon mui-icon-email"></span>
  24. <span class="mui-tab-label">邮件</span>
  25. </a>
  26. <a class="mui-tab-item" id="login">
  27. <span class="mui-icon mui-icon-gear"></span>
  28. <span class="mui-tab-label">设置</span>
  29. </a>
  30. </nav>
  31. </body>
  32. <script type="text/javascript" charset="utf-8">
  33. var ws = null; // websocket对象
  34. mui.init({
  35. subpages: [{
  36. url: "main.html",
  37. id: "main.html",
  38. styles: window.styles
  39. }]
  40. });
  41. mui.plusReady(function() {
  42. // console.log(JSON.stringify(plus.webview.currentWebview()))
  43. if(plus.storage.getItem("user")) { // 判断是否登录
  44. console.log('已结登录了!');
  45. //连接websocket连接
  46. ws = new WebSocket("ws://"+window.ws_serv+"/app/"+plus.storage.getItem("user"))
  47. // 客户端接收服务端数据时触发
  48. ws.onmessage = function() {};
  49. }
  50. });
  51.  
  52. document.getElementById("phone").addEventListener("tap", function() {
  53. mui.toast("你點擊了電話按鈕");
  54.  
  55. mui.openWindow({
  56. url: "phone.html",
  57. id: "phone.html",
  58. styles: window.styles,
  59. extras: {
  60. user_id: 123456
  61. }
  62. })
  63. })
  64.  
  65. document.getElementById("index").addEventListener("tap", function() {
  66. mui.openWindow({
  67. url: "main.html",
  68. id: "main.html",
  69. styles: window.styles
  70. })
  71. })
  72.  
  73. document.getElementById("login").addEventListener("tap", function() {
  74. mui.openWindow({
  75. url: "login.html",
  76. id: "login.html",
  77. styles: window.styles
  78. })
  79. })
  80.  
  81. document.addEventListener("login",function(data){
  82. // fire事件接收消息,使用data.detail
  83. // index是为做显示区分
  84. mui.toast("index"+data.detail.msg)
  85. })
  86. </script>
  87.  
  88. </html>

注意:必须写在 mui.plusReady 里面

使用模拟器打开登录页面

登录成功之后,点击首页

查看Pycharm控制台输出

  1. {'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传值

  1. <!doctype html>
  2. <html>
  3.  
  4. <head>
  5. <meta charset="UTF-8">
  6. <title></title>
  7. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  8. <link href="css/mui.min.css" rel="stylesheet" />
  9. </head>
  10.  
  11. <body>
  12. <header class="mui-bar mui-bar-nav">
  13. <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
  14. <h1 class="mui-title" id="title_text">正在播放</h1>
  15. </header>
  16. <div class="mui-content">
  17. <div class="mui-row" style="text-align: center;margin-top: 5px;">
  18. <img src="avatar/girl.jpg" style="width: 250px;height: 250px; border-radius: 50%;" id="avatar" />
  19. </div>
  20. <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id="play">播放</button>
  21. <button type="button" class="mui-btn mui-btn-yellow mui-btn-block" id="pause">暂停</button>
  22. <button type="button" class="mui-btn mui-btn-green mui-btn-block" id="resume">继续</button>
  23. <button type="button" class="mui-btn mui-btn-red mui-btn-block" id="stop">停止</button>
  24. <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id="send2toy">发送给玩具</button>
  25. </div>
  26.  
  27. </body>
  28. <script src="js/mui.js"></script>
  29. <script type="text/javascript">
  30. mui.init();
  31. var Sdata = null; //当前web页面
  32. var music_name = null; //歌曲名
  33. var player = null; //播放对象
  34. mui.plusReady(function() {
  35. Sdata = plus.webview.currentWebview(); // 当前web页面
  36. mui.toast(Sdata.content_id); // 弹窗显示由main.html传递的content_id
  37.  
  38. //发送post请求
  39. mui.post(
  40. window.serv + "/content_one", {
  41. // 参数为content_id
  42. content_id: Sdata.content_id
  43. },
  44. function(data) {
  45. // 打印响应数据
  46. console.log(JSON.stringify(data));
  47. // 修改标题
  48. document.getElementById("title_text").innerText = "正在播放 : " + data.data.title;
  49. // 修改图片地址
  50. document.getElementById("avatar").src = window.serv_imge + data.data.avatar;
  51. // 调用自定义方法,播放音频
  52. // data是后端返回的数据,data.audio是音频文件名
  53. music_name = data.data.audio; // 歌曲名
  54. play_anything(music_name); //播放歌曲
  55. }
  56. );
  57.  
  58. function play_anything(content) { //播放音频
  59. // 创建播放对象,拼接路径
  60. player = plus.audio.createPlayer(window.serv_audio + content);
  61. console.log(window.serv_audio + content); //打印路径
  62. // http://192.168.11.86:9527/get_audio/a6d680fe-fa80-4a54-82b8-b203f5a9c7b4.mp3
  63. player.play(); // 播放音频
  64. }
  65.  
  66. document.getElementById("play").addEventListener("tap", function() {
  67. player.play();
  68. });
  69.  
  70. document.getElementById("pause").addEventListener("tap", function() {
  71. player.pause(); //暂停
  72. });
  73.  
  74. document.getElementById("resume").addEventListener("tap", function() {
  75. player.resume(); //继续
  76. });
  77.  
  78. document.getElementById("stop").addEventListener("tap", function() {
  79. player.stop(); // 停止,直接清空player中的对象
  80. });
  81.  
  82. //发送给玩具
  83. document.getElementById("send2toy").addEventListener("tap", function() {
  84. var index = plus.webview.getWebviewById("HBuilder"); //index.html页面
  85. mui.fire(index, "send_music", { //发送音乐
  86. music_name: music_name, //歌曲名
  87. toy_id:"" // 发给玩具id为12345
  88. })
  89. });
  90.  
  91. })
  92. </script>
  93.  
  94. </html>

修改index.html,监听send_music事件

  1. <!DOCTYPE html>
  2. <html>
  3.  
  4. <head>
  5. <meta charset="utf-8">
  6. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  7. <title></title>
  8. <script src="js/mui.js"></script>
  9. <link href="css/mui.min.css" rel="stylesheet" />
  10. </head>
  11.  
  12. <body>
  13. <nav class="mui-bar mui-bar-tab">
  14. <a class="mui-tab-item mui-active" id="index">
  15. <span class="mui-icon mui-icon-home"></span>
  16. <span class="mui-tab-label">首页</span>
  17. </a>
  18. <a class="mui-tab-item" id="phone">
  19. <span class="mui-icon mui-icon-phone"></span>
  20. <span class="mui-tab-label">电话</span>
  21. </a>
  22. <a class="mui-tab-item">
  23. <span class="mui-icon mui-icon-email"></span>
  24. <span class="mui-tab-label">邮件</span>
  25. </a>
  26. <a class="mui-tab-item" id="login">
  27. <span class="mui-icon mui-icon-gear"></span>
  28. <span class="mui-tab-label">设置</span>
  29. </a>
  30. </nav>
  31. </body>
  32. <script type="text/javascript" charset="utf-8">
  33. var ws = null; // websocket对象
  34. mui.init({
  35. subpages: [{
  36. url: "main.html",
  37. id: "main.html",
  38. styles: window.styles
  39. }]
  40. });
  41. mui.plusReady(function() {
  42. // console.log(JSON.stringify(plus.webview.currentWebview()))
  43. if(plus.storage.getItem("user")) { // 判断是否登录
  44. console.log('已结登录了!');
  45. //连接websocket连接
  46. ws = new WebSocket("ws://"+window.ws_serv+"/app/"+plus.storage.getItem("user"))
  47. // 客户端接收服务端数据时触发
  48. ws.onmessage = function() {};
  49. }
  50. });
  51.  
  52. document.getElementById("phone").addEventListener("tap", function() {
  53. mui.toast("你點擊了電話按鈕");
  54.  
  55. mui.openWindow({
  56. url: "phone.html",
  57. id: "phone.html",
  58. styles: window.styles,
  59. extras: {
  60. user_id: 123456
  61. }
  62. })
  63. })
  64.  
  65. document.getElementById("index").addEventListener("tap", function() {
  66. mui.openWindow({
  67. url: "main.html",
  68. id: "main.html",
  69. styles: window.styles
  70. })
  71. })
  72.  
  73. document.getElementById("login").addEventListener("tap", function() {
  74. mui.openWindow({
  75. url: "login.html",
  76. id: "login.html",
  77. styles: window.styles
  78. })
  79. })
  80.  
  81. document.addEventListener("login",function(data){
  82. // fire事件接收消息,使用data.detail
  83. // index是为做显示区分
  84. mui.toast("index"+data.detail.msg)
  85. });
  86.  
  87. document.addEventListener("send_music", function(data) { //监听send_music事件
  88. var music_name = data.detail.music_name; //获取player.html使用fire发送的music_name值
  89. var toy_id = data.detail.toy_id; //获取发送的玩具id
  90.  
  91. send_str = { //构造数据
  92. music_name:music_name,
  93. toy_id:toy_id
  94. }
  95. // 发送数据给后端,注意要json序列化
  96. ws.send(JSON.stringify(send_str));
  97. });
  98.  
  99. </script>
  100.  
  101. </html>

刷新web玩具页面,此时有2个websocket连接

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

使用模拟器访问首页,随便点击一首歌。它会自动播放,点击暂停,再点击发送给玩具

此时Pycharm输出一条信息:

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

歌曲名,获取到了。这里面的123456,是有player.html发送给index.html的!

网页播放音乐

这个时候,需要后端接收消息并处理了

修改im_serv.py

  1. from flask import Flask, request
  2. from geventwebsocket.websocket import WebSocket
  3. from geventwebsocket.handler import WebSocketHandler
  4. from gevent.pywsgi import WSGIServer
  5. import json
  6.  
  7. app = Flask(__name__)
  8.  
  9. user_socket_dict = {} # 空字典,用来存放用户名和发送消息
  10.  
  11. @app.route("/toy/<tid>")
  12. def toy(tid): # 玩具连接
  13. # 获取请求的WebSocket对象
  14. user_socket = request.environ.get("wsgi.websocket") # type:WebSocket
  15. if user_socket:
  16. # 设置键值对
  17. user_socket_dict[tid] = user_socket
  18. print(user_socket_dict)
  19. # {'123456': <geventwebsocket.websocket.WebSocket object at 0x00000176ABD92E18>}
  20.  
  21. # 循环,接收消息
  22. while True:
  23. # 接收消息
  24. msg = user_socket.receive()
  25. print(msg) # 打印
  26. if type(msg) == bytearray:
  27. print(11)
  28. with open('123.wav','wb') as f:
  29. f.write(msg) # 写入文件
  30.  
  31. @app.route("/app/<uid>")
  32. def user_app(uid): # 手机app连接
  33. user_socket = request.environ.get("wsgi.websocket") # type:WebSocket
  34. if user_socket:
  35. user_socket_dict[uid] = user_socket
  36. # { uid : websocket}
  37. print(user_socket_dict)
  38. while True: # 手机听歌 把歌曲发送给 玩具 1.将文件直接发送给玩具 2.将当前听的歌曲名称或ID发送到玩具
  39. msg = user_socket.receive()
  40. msg_dict = json.loads(msg) # 接收值,由于APP发送的是json,需要反序列化
  41. # {"music_name": "a6d680fe-fa80-4a54-82b8-b203f5a9c7b4.mp3", "toy_id": "123456"}
  42. user_id = msg_dict.get("toy_id") # 获取toy_id
  43. music_name = msg_dict.get("music_name") # 获取歌曲名
  44. # 从user_socket_dict这个大字典中获取
  45. other_user_socket = user_socket_dict.get(user_id) # 获取APP用户的websocket对象
  46. # 构造数据
  47. send_str = {
  48. "code": 0,
  49. "from_user": uid, # APP用户id
  50. "data": music_name # 歌曲名
  51. }
  52.  
  53. # 发送给web玩具页面,注意:不能是jsonify,它是针对于HTTP请求,会设置响应头
  54. # 这里是websocket连接,只能用json.dumps
  55. other_user_socket.send(json.dumps(send_str))
  56.  
  57. if __name__ == '__main__':
  58. # 创建一个WebSocket服务器
  59. http_serv = WSGIServer(("0.0.0.0", 9528), app, handler_class=WebSocketHandler)
  60. # 开始监听HTTP请求
  61. http_serv.serve_forever()

重启 im_serv.py

重启之后,websocket连接就丢失了!

先访问web玩具页面

http://127.0.0.1:9527/

将模拟器中的HBuilder进程关闭,重启开启,并登陆。

点击一首歌曲,点击暂停,再点击一次发送给玩具!

此时,播放按钮,会播放音乐。

效果如下:

为什么,点击网页的播放按钮,就能播放指定的音乐呢?

查看flask中的templates-->index.html,这一段代码

  1. ws.onmessage = function (data) { // 客户端接收服务端数据时触发
  2. // console.log(get_file + data.data);
  3. var content = JSON.parse(data.data);
  4. // 修改id为player的src属性,实现自动播放
  5. document.getElementById("player").src = get_file + content.data;
  6. console.log(content.from_user + "给你点了一首歌");
  7. }

注意:ws.onmessage是接收到数据时,会自动触发!

那么它接收到什么数据了呢?接收了一个json数据。序列化之后,应该是这个样子

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

那么它就会修改页面的src属性。那么页面点击播放,就可以播放音乐了!

四、玩具管理页面

默认登录之后,会跳转到用户信息页面,这里需要展示用户头像。

但是数据库少了头像字段。

使用客户端工具访问用户表

默认的ORM语句为:

  1. db.users.find({})

目前只有一个用户

增加一个字段avatar,这个表示头像

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

修改flask后端的 的注册函数,增加avatar字段

  1. from flask import Flask, request,jsonify,render_template
  2. from setting import MONGO_DB
  3. from setting import RET
  4. from bson import ObjectId
  5. from serv import get_file
  6. from serv import content
  7.  
  8. app = Flask(__name__)
  9.  
  10. app.register_blueprint(get_file.getfile)
  11. app.register_blueprint(content.cont)
  12.  
  13. @app.route('/')
  14. def hello_world():
  15. return render_template("index.html")
  16.  
  17. @app.route('/login',methods=["POST"])
  18. def login():
  19. """
  20. 登陆验证
  21. :return: settings -> RET
  22. """
  23. try:
  24. RET["code"] = 1
  25. RET["msg"] = "用户名或密码错误"
  26. RET["data"] = {}
  27.  
  28. username = request.form.get("username")
  29. password = request.form.get("password")
  30.  
  31. user = MONGO_DB.users.find_one({"username": username, "password": password})
  32.  
  33. if user:
  34. # 由于user中的_id是ObjectId对象,需要转化为字符串
  35. user["_id"] = str(user.get("_id"))
  36. RET["code"] = 0
  37. RET["msg"] = "欢迎登陆"
  38. RET["data"] = {"user_id": user.get("_id")}
  39.  
  40. except Exception as e:
  41. RET["code"] = 1
  42. RET["msg"] = "登陆失败"
  43.  
  44. return jsonify(RET)
  45.  
  46. @app.route('/reg',methods=["POST"])
  47. def reg():
  48. """
  49. 注册
  50. :return: {"code":0,"msg":"","data":""}
  51. """
  52. try:
  53. username = request.form.get("username")
  54. password = request.form.get("password")
  55. age = request.form.get("age")
  56. nickname = request.form.get("nickname")
  57. gender = request.form.get("gender")
  58. phone = request.form.get("phone")
  59.  
  60. user_info = {
  61. "username": username,
  62. "password": password,
  63. "age": age,
  64. "nickname": nickname,
  65. # 判断gender==2,成立时为girl.jpg,否则为boy.jpg
  66. "avatar": "girl.jpg" if gender == 2 else "boy.jpg",
  67. "gender": gender,
  68. "phone": phone
  69. }
  70.  
  71. res = MONGO_DB.users.insert_one(user_info)
  72. user_id = str(res.inserted_id)
  73.  
  74. RET["code"] = 0
  75. RET["msg"] = "注册成功"
  76. RET["data"] = user_id
  77. except Exception as e:
  78. RET["code"] = 1
  79. RET["msg"] = "注册失败"
  80.  
  81. return jsonify(RET)
  82.  
  83. @app.route('/user_info', methods=["POST"])
  84. def user_info():
  85. user_id = request.form.get("user_id")
  86.  
  87. # "password": 0 表示忽略密码字段
  88. res = MONGO_DB.users.find_one({"_id": ObjectId(user_id)}, {"password": 0})
  89. if res:
  90. res["_id"] = str(res.get("_id"))
  91.  
  92. RET["code"] = 0
  93. RET["msg"] = ""
  94. RET["data"] = res
  95.  
  96. return jsonify(res)
  97.  
  98. if __name__ == '__main__':
  99. app.run("0.0.0.0", 9527, debug=True)

进入HBuilder的项目MyApp,修改user_info.html,增加头像

  1. <!doctype html>
  2. <html lang="en">
  3.  
  4. <head>
  5. <meta charset="UTF-8" />
  6. <title>Document</title>
  7. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  8. <link rel="stylesheet" type="text/css" href="css/mui.css" />
  9. </head>
  10.  
  11. <body>
  12. <header class="mui-bar mui-bar-nav">
  13. <h1 class="mui-title">用户信息</h1>
  14. </header>
  15. <div class="mui-content">
  16. <ul class="mui-table-view">
  17. <div class="mui-row" style="text-align: center;">
  18. <img src="" id="avatar" style="width: 250px;height: 250px; border-radius: 100%;"/>
  19. </div>
  20. <li class="mui-table-view-cell"><span>用户名</span><span id="username" class="mui-pull-right">111</span></li>
  21. <li class="mui-table-view-cell"><span>昵称</span><span id="nickname" class="mui-pull-right">22</span></li>
  22. </ul>
  23.  
  24. <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id="logout">退出登陆</button>
  25. </div>
  26.  
  27. </body>
  28. <script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
  29. <script type="text/javascript">
  30. mui.init()
  31. mui.back = function() {};
  32. mui.plusReady(function() {
  33. var Sdata = plus.webview.currentWebview();
  34. mui.post(
  35. window.serv + "/user_info", {
  36. user_id: Sdata.user_id
  37. },
  38. function(data) {
  39. console.log(JSON.stringify(data));
  40. console.log("wfdsfdsafdsafas");
  41. document.getElementById("username").innerText = data.username;
  42. document.getElementById("nickname").innerText = data.nickname;
  43. // 修改头像地址
  44. document.getElementById("avatar").src = "avatar/" + data.avatar;
  45. // console.log("avatar/" + data.avatar);
  46. }
  47. )
  48. })
  49.  
  50. document.getElementById("logout").addEventListener("tap", function() {
  51. plus.storage.removeItem("user")
  52. mui.openWindow({
  53. url: "login.html",
  54. id: "login.html",
  55. styles: window.styles
  56. })
  57. });
  58.  
  59. </script>
  60.  
  61. </html>

使用模拟器重新登录,效果如下:

修改user_info.html,增加一行,用来管理玩具。并增加点击事件

  1. <!doctype html>
  2. <html lang="en">
  3.  
  4. <head>
  5. <meta charset="UTF-8" />
  6. <title>Document</title>
  7. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  8. <link rel="stylesheet" type="text/css" href="css/mui.css" />
  9. </head>
  10.  
  11. <body>
  12. <header class="mui-bar mui-bar-nav">
  13. <h1 class="mui-title">用户信息</h1>
  14. </header>
  15. <div class="mui-content">
  16. <ul class="mui-table-view">
  17. <div class="mui-row" style="text-align: center;">
  18. <img src="" id="avatar" / style="width: 250px;height: 250px; border-radius: 100%;">
  19. </div>
  20. <li class="mui-table-view-cell"><span>用户名</span><span id="username" class="mui-pull-right">111</span></li>
  21. <li class="mui-table-view-cell"><span>昵称</span><span id="nickname" class="mui-pull-right">22</span></li>
  22. </ul>
  23. <ul class="mui-table-view">
  24. <li class="mui-table-view-cell" id="toy_manager"><i class="mui-icon mui-icon-qq"></i>管理我的玩具</li>
  25.  
  26. </ul>
  27.  
  28. <button type="button" class="mui-btn mui-btn-blue mui-btn-block" id="logout">退出登陆</button>
  29. </div>
  30.  
  31. </body>
  32. <script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
  33. <script type="text/javascript">
  34. mui.init()
  35. mui.back = function() {};
  36. mui.plusReady(function() {
  37. var Sdata = plus.webview.currentWebview();
  38. mui.post(
  39. window.serv + "/user_info", {
  40. user_id: Sdata.user_id
  41. },
  42. function(data) {
  43. console.log(JSON.stringify(data));
  44. console.log("wfdsfdsafdsafas");
  45. document.getElementById("username").innerText = data.username;
  46. document.getElementById("nickname").innerText = data.nickname;
  47. // 修改头像地址
  48. document.getElementById("avatar").src = "avatar/" + data.avatar;
  49. // console.log("avatar/" + data.avatar);
  50. }
  51. )
  52. })
  53.  
  54. document.getElementById("logout").addEventListener("tap", function() {
  55. plus.storage.removeItem("user")
  56. mui.openWindow({
  57. url: "login.html",
  58. id: "login.html",
  59. styles: window.styles
  60. })
  61. });
  62.  
  63. // 管理玩具页面
  64. document.getElementById("toy_manager").addEventListener("tap", function() {
  65. mui.openWindow({
  66. url: "toy_manager.html",
  67. id: "toy_manager.html",
  68. })
  69. });
  70.  
  71. </script>
  72.  
  73. </html>

新建文件 toy_manager.html

新建目录image,用来保存添加按钮的图片

从网络上面,搜索一个添加按钮图片,放到此目录!

此时,目录结构如下:

  1. ./
  2. └── MyApp
  3. ├── avatar
  4.    ├── boy.jpg
  5.    └── girl.jpg
  6. ├── css
  7.    ├── mui.css
  8.    └── mui.min.css
  9. ├── fonts
  10.    └── mui.ttf
  11. ├── images
  12.    └── add.png
  13. ├── index.html
  14. ├── js
  15.    ├── md5.min.js
  16.    ├── mui.js
  17.    └── mui.min.js
  18. ├── login.html
  19. ├── main.html
  20. ├── manifest.json
  21. ├── phone.html
  22. ├── player.html
  23. ├── reg.html
  24. ├── toy_manager.html
  25. ├── unpackage
  26. └── user_info.html

修改 toy_manager.html

  1. <!doctype html>
  2. <html lang="en">
  3.  
  4. <head>
  5. <meta charset="UTF-8" />
  6. <title>Document</title>
  7. <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  8. <link rel="stylesheet" type="text/css" href="css/mui.css" />
  9. </head>
  10.  
  11. <body>
  12. <header class="mui-bar mui-bar-nav">
  13. <a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
  14. <h1 class="mui-title">管理我的玩具</h1>
  15. </header>
  16. <div class="mui-content">
  17. <ul class="mui-table-view" id="toy_list">
  18. <li class="mui-table-view-cell mui-media">
  19. <a id="add_toy">
  20. <img class="mui-media-object mui-pull-left" src="data:images/add.png">
  21. <div class="mui-media-body">
  22. 你还没有玩具
  23. <p class="mui-ellipsis">点击此处扫描二维码添加玩具</p>
  24. </div>
  25. </a>
  26. </li>
  27. </ul>
  28. </div>
  29. </body>
  30. <script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
  31. <script type="text/javascript">
  32. mui.init()
  33.  
  34. function create_content(content) {
  35. var litag = document.createElement("li");
  36. litag.className = "mui-table-view-cell mui-media";
  37. var atag = document.createElement("a");
  38. atag.id = content._id;
  39. // 点击事件 周一把这儿写了 绑定事件
  40. atag.onclick = function() {
  41. console.log(this.id);
  42. openPlayer(this.id);
  43. }
  44.  
  45. var imgtag = document.createElement("img");
  46. imgtag.className = "mui-media-object mui-pull-left";
  47.  
  48. imgtag.src = window.serv_imge + content.avatar;
  49.  
  50. var divtag = document.createElement("div");
  51. divtag.className = "mui-media-body";
  52. divtag.innerText = content.title;
  53. var ptag = document.createElement("p");
  54. ptag.className = "mui-ellipsis";
  55. ptag.innerText = content.intro;
  56.  
  57. litag.appendChild(atag);
  58. atag.appendChild(imgtag);
  59. atag.appendChild(divtag);
  60. divtag.appendChild(ptag);
  61.  
  62. document.getElementById("toy_list").appendChild(litag);
  63.  
  64. }
  65.  
  66. document.getElementById("add_toy").addEventListener("tap", function() {
  67. mui.openWindow({
  68. url: "扫描二维码.html",
  69. id: "扫描二维码.html",
  70. })
  71. })
  72. </script>
  73.  
  74. </html>

重新登录,效果如下:

总结:

  1. 1. app端内容播放
  2. 听歌:plus.audio
  3. 创建:var player = plus.audio.createPlay(内容的URL路径) //苹果暂时不支持HTTP
  4. 开始播放 : player.play()
  5. 暂停播放 player.pause()
  6. 继续播放 player.resume()
  7. 停止播放 player.stop() 清空player中对象
  8.  
  9. 2. 手动写一个web端的玩具(小剧情)
  10. 硬件需要时间,咱们先写一个协议,然后开发一个初级硬件暂时先顶上,用了一周的事件做了一个LowB的硬件
  11. 事件: 中午吃饭忘了关闭硬件,结果芯片过热,造成芯片烧毁,烧毁了一个桌面,烫坏了一个显示器,键盘没了一半儿
  12. 老张呵斥硬件部:工程开发板不允许再次使用,所有压力全部在软件部,自己写一个Web模拟玩具收发消息
  13.  
  14. 3. app通过websocket 事件远程遥控玩具播放内容
  15. websocket 在整个app中只能存在一个
  16. app
  17. mui.fire(ws页面,"事件",{data})
  18. ws页面:
  19. document.addEventListener("事件",function(data){
  20. data.detail
  21. })
  22.  
  23. 开启websocket服务 -
  24. 两个接口 app toy -
  25. 两个前端 连接 websocket -
  26. {user:websocket,toy:websocket}
  27. appuser 发送了一个字符串给服务端 {toy_id:123456,content_id:tyuiop123r234}
  28. 通过字符串中的toy_id 拿到 websocket_dict 中的 toy websocket
  29. 可以给 toy 中的websocket 发送消息了
  30. toy.send(json.dumps({}))

完整代码,请参考github:

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

https://www.cnblogs.com/xiao987334176/p/9662372.html

 
 

app端内容播放,web端的玩具,app通过websocket远程遥控玩具播放内容,玩具管理页面的更多相关文章

  1. python 全栈开发,Day127(app端内容播放,web端的玩具,app通过websocket远程遥控玩具播放内容,玩具管理页面)

    昨日内容回顾 1. 小爬爬 内容采集 XMLY 的 儿童频道 requests 2. 登陆 注册 自动登陆 退出 mui.post("请求地址",{数据},function(){} ...

  2. APP端测试与web端测试的区别

    想要知道APP端测试与web端测试的区别 ,那么我们就要先来了解,web和app的区别. web项目,一般都是b/s架构,基于浏览器的,而app则是c/s的,必须要有客户端.那么在系统测试测试的时候就 ...

  3. 关于emoji表情,支持在app端发送web端显示,web端发送给app端显示,web与wap端互相显示。

    要用到emoji.js和emoji.jquery.js两个插件配合实现三端互通. 1.app端发送的emoji表情----到服务器---服务器存储的是‘问号’,无法显示如图所示: 后台的同学也试验了网 ...

  4. 移动测(APP)试与web端测试的区别

    1.操作环境不同 移动端的测试环境是安卓操作环境或者iOS操作系统: web端操作环境一般是windows(如果你用的是MC电脑,那就是iOS操作系统). 2.页面的显示尺寸不同 移动端的尺寸比较多, ...

  5. 移动端与Web端疫情数据展示

    1.题目要求 2.整体思想 首先是在前两阶段已经完成的echarts可视化.利用Jsoup爬取疫情数据基础上来进行调用与完善.大致思想是在Android Studio上完成交互去调用ecplise中的 ...

  6. web端 第一天认识基础

    .NET 分为两大类 一.客户端应用程序   C/S 技术: Winform WPF MFC   MVVM 二.外部端应用程序  B/S(网页端应用程序/WEB端/WEB端应用程序) 目前学的技术是A ...

  7. Web程序员开发App系列 - 调试Android和IOS手机代码(补图)

    Web程序员开发App系列 Web程序员开发App系列 - 认识HBuilder Web程序员开发App系列 - 申请苹果开发者账号 Web程序员开发App系列 - 调试Android和iOS手机代码 ...

  8. Web程序员开发App系列 - 申请苹果开发者账号

    Web程序员开发App系列 Web程序员开发App系列 - 认识HBuilder Web程序员开发App系列 - 申请苹果开发者账号 Web程序员开发App系列 - 调试Android和iOS手机代码 ...

  9. Web程序员开发App系列 - 开发我的第一个App,源码下载

    Web程序员开发App系列 Web程序员开发App系列 - 认识HBuilder Web程序员开发App系列 - 申请苹果开发者账号 Web程序员开发App系列 - 调试Android和iOS手机代码 ...

随机推荐

  1. Ceph配置项动态变更机制浅析

    转自:https://www.ustack.com/blog/ceph%e9%85%8d%e7%bd%ae%e9%a1%b9%e5%8a%a8%e6%80%81%e5%8f%98%e6%9b%b4%e ...

  2. django model_fields_validators 前端页面编辑自定义验证

    # model_field_validators.py import re from django.core.exceptions import ValidationError from django ...

  3. LeetCode OJ:Longest Common Prefix(最长公共前缀)

    Write a function to find the longest common prefix string amongst an array of strings. 求很多string的公共前 ...

  4. LeetCode OJ:Add Binary(二进制相加)

    Given two binary strings, return their sum (also a binary string). For example,a = "11"b = ...

  5. [置顶] 长谈:关于 View Measure 测量机制,让我一次把话说完

    <倚天屠龙记中>有这么一处:张三丰示范自创的太极剑演示给张无忌看,然后问他记住招式没有.张无忌说记住了一半.张三丰又慢吞吞使了一遍,问他记住多少,张无忌说只记得几招了.张三丰最后又示范了一 ...

  6. net core集成CAP

    net core集成CAP https://www.cnblogs.com/guolianyu/p/9756941.html 一.前言 感谢杨晓东大佬为社区贡献的CAP开源项目,传送门在此:.NET ...

  7. SMMS 2016 啟用深色主題

    1.用文本類編輯器 打開C:\Program Files (x86)\Microsoft SQL Server\130\Tools\Binn\ManagementStudio目錄下的 ssms.pkg ...

  8. lvs之 lvs+nginx+tomcat_1、tomcat_2+redis(lvs dr 模式)

    前提:已经安装好 lvs+nginx+tomcat_1.tomcat_2+redis环境 ,可参考 (略有改动,比如tomcat_1.tomcat_2安装在两台机器上,而不是单机多实例 ,自行稍稍变动 ...

  9. Dobbo问题及解决方案:forbid-consumer

    本地运行Dubbo经常出现以下情况: com.alibaba.dubbo.rpc.RpcException: Forbid consumer 10.0.53.69 access service com ...

  10. Windows2008 R2上完全卸载Oracle操作步骤(转)

    最近现场项目,碰到了好几次oracle数据库被损坏,而且无法恢复的问题,没办法,只好卸载重装了.oracle卸载确实麻烦,都是从网上查的方法, 为了方便以后查询,在此就做一下记录. Windows20 ...