Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 亚洲视频三区,久久综合免费,免费**毛片

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          企業級UI自動化平臺—添加腳本

          企業級UI自動化平臺—添加腳本

          前章節我們講了部門部門管理,項目管理,這節我們繼續實現添加腳本。

          那么關聯關系就是,在部門對應的項目中添加多個腳本。實現這個模塊我們需要完成三步操作。

          1:完成數據表的創建及與部門表和項目表之間的關聯關系

          2:完成前端界面布局

          3:完成對應后端接口的開發

          首先完成第一步,數據表的創建,既然是添加腳本,那么我們能夠想到的字段就有:

          腳本名稱,上傳的圖片名稱,操作的類型(點擊、滑動、校驗...),執行的步驟,操作類型的次數,生成腳本的類型。

          對應如下:

          ui自動化平臺添加腳本管理模塊:

          SET NAMES utf8;

          SET FOREIGN_KEY_CHECKS=0;

          DROP TABLE IF EXISTS `script_images`;

          CREATE TABLE `script_images` (

          `id` int(11) NOT NULL AUTO_INCREMENT,

          `script_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,

          `image_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,

          `action_type` enum('click','assert','exist') CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,

          `step_number` int(11) NULL DEFAULT NULL,

          `ftp_path` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,

          `department_id` int(11) NULL DEFAULT NULL,

          `project_id` int(11) NULL DEFAULT NULL,

          `repeatCount` int(11) NULL DEFAULT NULL,

          `select_type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,

          PRIMARY KEY (`id`) USING BTREE,

          INDEX `department_id`(`department_id`) USING BTREE,

          INDEX `project_id`(`project_id`) USING BTREE,

          CONSTRAINT `script_images_ibfk_1` FOREIGN KEY (`department_id`) REFERENCES `department` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,

          CONSTRAINT `script_images_ibfk_2` FOREIGN KEY (`project_id`) REFERENCES `project` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT

          ) ENGINE=InnoDB AUTO_INCREMENT=24 CHARACTER SET=utf8 COLLATE=utf8_general_ci ROW_FORMAT=Compact;

          SET FOREIGN_KEY_CHECKS=1;

          各個字段看名字對應即可。里面定義了部門表和項目表的主外鍵關聯關系,之前章節詳細講過,這里不在啰嗦。

          接下來我們實現前端部分,直接看下前端需要的功能界面。


          完整邏輯為:

          1. 加載用戶界面,界面中包含選擇部門、選擇項目、腳本類型和腳本名稱的輸入項,輸入項選擇后,用戶可以上傳圖片。
          2. 上傳圖片后,根據這張圖片,可以選擇執行的動作:點擊、校驗或是否存在。這三種動作分別對應到按鈕:“點擊”,“校驗”,“是否存在”。
          3. 選擇動作后,圖片數據被保存,并且動作按鈕會被禁用,直到上傳下一張圖片。
          4. 當所有圖片上傳并選擇動作完成后,用戶可以點擊“生成測試腳本”按鈕生成腳本。
          5. 在生成腳本的過程中,顯示加載動畫和提示,完成后隱藏加載動畫,并提示測試腳本已經生成。

          在腳本的實現中使用了Ajax進行異步通信,主要進行了以下操作:

          • 保存圖片數據
          • 上傳圖片
          • 獲取部門信息和對應的項目信息
          • 生成測試腳本

          在獲取部門信息和項目信息時,使用GET方法接收服務器返回的數據,并更新選擇部門和項目的下拉列表;在保存圖片數據、上傳圖片和生成測試腳本時,使用POST方法將數據發送到服務器。

          完整實現為:

          <!DOCTYPE html>
          <html lang="en">
          
          <head>
            <meta charset="UTF-8">
            <title>測試腳本生成</title>
          <!--  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>-->
            <style>
              /*body {*/
              /*  font-family: Arial, sans-serif;*/
              /*  margin: 20px;*/
              /*}*/
          
              h1 {
                text-align: center;
                color: #3c3c44;
                font-weight: bold;
              }
          
              label {
                margin-top: 10px;
                display: block;
                color: #1c1c1d;
              }
          
              select,
              input[type=text],
              input[type=file] {
                width: 100%;
                padding: 12px;
                margin-top: 4px;
                display: inline-block;
                border: 1px solid #ccc;
              }
          
              input[type=file] {
                padding: 3px;
              }
          
              button {
                border: none;
                color: white;
                padding: 14px 28px;
                font-size: 16px;
                cursor: pointer;
                border-radius: 4px;
                margin-top: 16px;
              }
          
              #click_btn {
                background-color: #4CAF50;
              }
          
              #assert_btn {
                background-color: #FF9800;
              }
          
              #generate_script_btn {
                background-color: #2196F3;
              }
            </style>
          </head>
          <body>
          <h1>測試腳本生成</h1>
          <div id="whole-body">
          <label for="select-department">選擇部門:</label>
          <select id="select-department">
            <option value=""> -- 請選擇部門 -- </option>
          </select>
          
          <label for="select-project">選擇項目:</label>
          <select id="select-project">
            <option value=""> -- 請選擇項目 -- </option>
          </select>
          <label for="select_type">腳本類型:</label>
          <select id="select_type">
            <option value=""> -- 請選擇類型 -- </option>
            <option value="1">windows</option>
            <option value="2">unity</option>
            <option value="3">android</option>
          </select>
          <label for="script_name">腳本名稱:</label>
          <input type="text" id="script_name">
          
          <input type="file" id="image_upload">
          
          <br>
          
          <button id="click_btn">點擊</button>
          <button id="assert_btn">校驗</button>
          <button id="exist_btn" style="background-color: #9C27B0; color: white; padding: 14px 28px; font-size: 16px; cursor: pointer; border-radius: 4px; margin-top: 16px;">
            是否存在
          </button>
          <button id="generate_script_btn">生成測試腳本</button>
          
          <p id="action_prompt" style="color: red; font-weight: bold; margin-top: 10px;"></p>
          <div id="uploaded_images"></div>
          
          <script>
            var step_number=0;
            var selected_action='';
            // 添加 isImageUploaded 和 isActionPerformed 變量
            var isImageUploaded=false;
            var isActionPerformed=false;
            function save_image_data(image_name, action_type, step_number, script_name,ftp_path, department_id, project_id,repeatCount,select_type) {
              $.ajax({
                url: "/save-image-data", // 您的后端接口
                type: "POST",
                contentType: "application/json",
                data: JSON.stringify({
                  image_name: image_name,
                  action_type: action_type,
                  step_number: step_number,
                  script_name: script_name,
                  // ftp_path: `/bignoxData/bignoxData/software/qa/Mobile/uitest/${script_name}/${image_name}`, // 添加新字段
                  department_id: department_id,
                  project_id: project_id,
                  repeatCount:repeatCount,
                  select_type:select_type,
                  ftp_path: ftp_path, // 添加新字段
                }),
                success: function (res) {
                  console.log("Image data saved successfully");
                  console.log(repeatCount);
                  console.log(select_type);
                  console.log(res); // 添加這一行以查看響應內容
                },
                error: function (err) {
                  console.error("Image data save failed");
                  console.error(err); // 添加這一行以查看錯誤內容
                },
              });
            }
            function disableActionButtons() {
              $("#click_btn").attr("disabled", true);
              $("#assert_btn").attr("disabled", true);
            }
          
            function enableActionButtons() {
              $("#click_btn").attr("disabled", false);
              $("#assert_btn").attr("disabled", false);
            }
            disableActionButtons(); // 最初禁用按鈕,直到上傳第一張圖片
            $("#click_btn").on("click", function () {
              selected_action='click';
              var repeatCount=prompt("請輸入點擊次數", "1");
              repeatCount=parseInt(repeatCount);
              while(isNaN(repeatCount) || repeatCount<1) {
                alert("無效的輸入!至少點擊一次。")
                repeatCount=prompt("請輸入點擊次數", "1");
                repeatCount=parseInt(repeatCount);
              }
              $("#action_prompt").text("已選擇點擊操作");
          
              if (step_number > 0) {
                var imgCaption=`點擊第${step_number}步。`;
                $("#uploaded_images div:last-child p").text(imgCaption);
              }
          
              disableActionButtons(); // 選擇操作后重新禁用按鈕
              // 修改并添加以下兩行代碼到 #click_btn 的事件處理程序中
              const department_id=$('#select-department').val();
              const project_Id=$('#select-project').val();
              const imageUrl=$(this).attr("data-url");
              const select_type=$('#select_type').val();
              save_image_data(imgFile.name, selected_action, step_number, $("#script_name").val(), imageUrl,department_id, project_Id,repeatCount,select_type);
              isActionPerformed=true; // 將 isActionPerformed 設置為 true
              //save_image_data(imgFile.name, selected_action, step_number, $("#script_name").val(), `/uploads${res.image_url}`); // 傳遞 ftp_path 參數
            });
            //新函數
            $("#image_upload").on("click", function () {
              this.value=null;
            });
            //分割線
            $("#assert_btn").on("click", function () {
              selected_action='assert';
              var repeatCount=1; // 為assert操作設置repeatCount為1
              $("#action_prompt").text("已選擇校驗操作");
          
              if (step_number > 0) {
                var imgCaption=`校驗第${step_number}步。`;
                $("#uploaded_images div:last-child p").text(imgCaption);
              }
          
              disableActionButtons(); // 選擇操作后重新禁用按鈕
              // 修改并添加以下兩行代碼到 #click_btn 的事件處理程序中
              const department_id=$('#select-department').val();
              const project_Id=$('#select-project').val();
              const imageUrl=$(this).attr("data-url");
              save_image_data(imgFile.name, selected_action, step_number, $("#script_name").val(), imageUrl, department_id, project_Id,select_type,repeatCount);
              isActionPerformed=true; // 將 isActionPerformed 設置為 true
              //save_image_data(imgFile.name, selected_action, step_number, $("#script_name").val(), `/uploads${res.image_url}`); // 傳遞 ftp_path 參數
            });
            $("#exist_btn").on("click", function () {
              selected_action='exist';
              var repeatCount=prompt("請輸入循環點擊次數", "1");
              repeatCount=parseInt(repeatCount);
              while(isNaN(repeatCount) || repeatCount<1) {
                alert("無效的輸入!次數至少為一。")
                repeatCount=prompt("請輸入循環點擊次數", "1");
                repeatCount=parseInt(repeatCount);
              }
          
              $("#action_prompt").text("已選擇是否存在操作");
          
              if (step_number > 0) {
                var imgCaption=`是否存在第${step_number}步。`;
                $("#uploaded_images div:last-child p").text(imgCaption);
              }
          
              disableActionButtons();
              const department_id=$('#select-department').val();
              const project_Id=$('#select-project').val();
              const imageUrl=$(this).attr("data-url");
              save_image_data(imgFile.name, selected_action, step_number, $("#script_name").val(), imageUrl, department_id, project_Id,select_type, repeatCount);
              isActionPerformed=true;
            });
            var imgFile; // 將 imgFile 變量移到外面
            $("#image_upload").on("change", function () {
              var fileInput=this;
              imgFile=fileInput.files[0];
              var imgName=imgFile.name;
              var formData=new FormData();
              formData.append("image", imgFile);
              formData.append("script_name", $("#script_name").val());
              formData.append("department_id", $("#select-department").val()); // 新增加這行
              formData.append("project_id", $("#select-project").val());       // 新增加這行
              formData.append("select_type", $("#select_type").val());       // 新增加這行
              step_number++;
          
              $.ajax({
                url: "/upload-image", // 您的后端接口
                type: "POST",
                data: formData,
                processData: false,
                contentType: false,
                success: function (res) {
                  var newImg=document.createElement("img");
                  newImg.src=res.image_url; // 響應中的圖片 URL
                  newImg.style.maxWidth="200px";
                  newImg.alt=imgName;
          
                  var imageCaption=document.createElement("p");
          
                  var imageContainer=document.createElement("div");
                  imageContainer.appendChild(newImg);
                  imageContainer.appendChild(imageCaption);
                  $("#uploaded_images").append(imageContainer);
          
                  enableActionButtons(); // 上傳新圖片后啟用點擊和校驗按鈕
                  $("#click_btn").attr("data-url", res.image_url);
                  $("#assert_btn").attr("data-url", res.image_url);
                  $("#exist_btn").attr("data-url", res.image_url);
                  enableActionButtons(); // 添加這一行代碼
                  // 在這里設置 isImageUploaded 為 true
                  isImageUploaded=true;
                },
                error: function (err) {
                  console.error("圖片上傳失敗", err);
                }
              });
            });
            $("#generate_script_btn").on("click", function () {
              if (!isImageUploaded) {
                alert("未上傳任何文件!");
                return;
              }
              if (!isActionPerformed) {
                alert("請先選擇當前圖片要執行的動作!");
                return;
              }
          
              // 添加的部分: 點擊生成后隱藏主頁面,顯示加載動畫和提示
              $('#whole-body').hide();
              $('#loading').show();
              // 更新此部分,使用正確的 ID
              console.log("項目ID: " + $("#select-project").val());
              console.log("部門ID: " + $("#select-department").val());
              var postData=JSON.stringify({
                script_name: $("#script_name").val(),
                department_id: $("#select-department").val(),
                project_id: $("#select-project").val(),
                select_type: $("#select_type").val()
              });
              $.ajax({
                url: "/generate-test-script",
                type: "POST",
                contentType: "application/json",
                data: postData,
                success: function (res) {
                  //接收到返回數據后先延時3秒
                  setTimeout(function () {
                    //隱藏加載動畫和提示,顯示生成成功提示,并顯示主頁面
                    $('#loading').hide();
                    $('#script_gen_prompt').show(); //顯示生成成功提示
                    alert('測試腳本已生成!');
                    setTimeout(function(){
                      $('#script_gen_prompt').hide();
                      $('#whole-body').show();  //重新顯示主頁面
                    }, 2000);  //2000ms后隱藏成功提示,并重新顯示主界面
                  }, 3000);   // 延時 3000 ms 顯示生成完成提示
                },
                error: function (err) {
                  setTimeout(function() {
                    $('#loading').hide();
                    alert("生成測試腳本失敗");
                    $('#whole-body').show();  //重新顯示主頁面
                  }, 3000);   // 延時 3000 ms 顯示失敗提示
                  console.error(err)
                }
              });
            });
            <!-- 在現有的 <script> 標簽內添加以下代碼 -->
            $(document).ready(function () {
          
              // 獲取部門信息并填充到下拉框
              function loadDepartments() {
                $.get("/get-all-departments", function (data) {
                  var departments=data.departments;
                  $("#select-department").empty();
                  $("#select-department").append("<option value=''> -- 請選擇部門 -- </option>")
                  for (var i=0; i < departments.length; i++) {
                    var option=$("<option>").val(departments[i].id).text(departments[i].name);
                    $("#select-department").append(option);
                  }
                });
              }
          
              loadDepartments();
              $("#select-department, #select-project").on("change", function() {
                if ($("#select-department").val() && $("#select-project").val()) {
                  $("#script_name").prop("disabled", false);
                } else {
                  $("#script_name").prop("disabled", true);
                }
              });
              $("#select-department").on("change", function () {
                var departmentId=$(this).val();
                if (departmentId) {
                  // 發送請求獲取部門對應項目
                  $.get("/get-projects?department_id=" + departmentId, function (data) {
                    var projects=data.projects;
                    $("#select-project").empty();
                    $("#select-project").append("<option value=''> -- 請選擇項目 -- </option>");
                    for (var i=0; i < projects.length; i++) {
                      var option=$("<option>").val(projects[i].id).text(projects[i].name);
                      $("#select-project").append(option);
                    }
                  });
                } else {
                  $("#select-project").empty();
                  $("#select-project").append("<option value=''> -- 請先選擇部門 -- </option>");
                }
              });
          
            })
          </script>
          </div>
          </body>
          <div id="loading" style="display: none; text-align: center;">
            <img src="/uploads/static/Picture/gif/xz.gif" style="width: 200px; height: auto; margin: 0 auto;">
            <p style="margin-top: 20px; font-size: 20px; font-weight: bold;">正在生成腳本...</p>
          </div>
          
          </html>

          對應后端生成腳本的邏輯為:

          @app.route('/generate-test-script', methods=['POST'])
          def generate_test_script():
              try:
                  script_name=request.json.get('script_name')
                  script_nameair=request.json.get('script_name') + '.air'
                  department_id=int(request.json.get('department_id'))
                  select_type=request.json.get('select_type')
                  print(select_type)
                  repeatCount=request.json.get('repeatCount')
                  if request.json:
                      project_id=int(request.json.get('project_id'))
                      department_id=int(department_id)
                      project_id=int(project_id)
                      start_package='com.noxgroup.game.android.townsurvivor'
                      # mycursor.execute("SELECT image_name, action_type, step_number, ftp_path FROM script_images WHERE script_name=%s ORDER BY step_number", (script_name, ))
                      # images_data=mycursor.fetchall()
                      # mycursor.execute("SELECT name FROM department WHERE id=%s", (department_id, ))
                      # department_name=mycursor.fetchone()[0]
                      # mycursor.execute("SELECT name FROM project WHERE id=%s and status=1", (project_id, ))
                      # project_name=mycursor.fetchone()[0]
                      sql="SELECT image_name, action_type, step_number, ftp_path,repeatCount FROM script_images WHERE script_name='{}' ORDER BY step_number".format(
                          script_name, )
                      print(sql+'lx')
                      images_data=db.select_data(sql)
                      print('這里出現imagesdata數據')
                      print(images_data)
                      sql="SELECT name FROM department WHERE id={}".format(department_id, )
                      department_name=db.select_one_data(sql)[0]
                      sql="SELECT name FROM project WHERE id={} and status=1".format(project_id, )
                      project_name=db.select_one_data(sql)[0]
                      script_folder=os.path.join(os.getcwd(), 'uploads', department_name, project_name, script_nameair)
                      if not os.path.exists(script_folder):
                          os.makedirs(script_folder)
                      with open(os.path.join(script_folder, f"{script_name}.py"), "w") as f:
                          # startapkpath=os.path.join(os.getcwd(), 'uploads', department_name, project_name, "uploadfiles")
                          # try:
                          #     apk_files=glob.glob(f'{startapkpath}/*.apk')
                          #     if not apk_files:
                          #         print(f"No apk files in {startapkpath}")
                          #         return jsonify({"result": "error", "error_message": f"No apk files in {startapkpath}"})
                          #     else:
                          #         apk_file=apk_files[0]
                          # except Exception as e:
                          #     print(e)
                          # a=APK(apk_file)
                          # package=a.get_package()
                          # activity=a.get_main_activity()
                          if project_name=='TownSurvivor':
                              ipconnect='127.0.0.1:{}'.format(config.tsphoneip)
                              print(123)
                          elif project_name=='忍者貓':
                              ipconnect='127.0.0.1:{}'.format(config.maophoneip)
                          elif project_name=='Player':
                              ipconnect='127.0.0.1:{}'.format(config.maophoneip)
                          else:
                              return 'adb erro'
                          print(ipconnect)
                          f.write("from airtest.core.api import *\n")
                          f.write("from airtest.core.settings import Settings as ST \n")
                          f.write("ST.THRESHOLD_STRICT=0.7\n")
                          f.write("ST.THRESHOLD=0.7\n")
                          f.write("auto_setup(__file__)\n")
                          # f.write("import subprocess\n")
                          # # 先構造要寫入的子進程調用命令字符串
                          # subprocess_cmd=(
                          #     f"output=subprocess.check_output('adb -s {ipconnect} shell am start -n {package}/{activity}', "
                          #     "shell=True)"
                          # )
                          #
                          # # 然后寫入文件
                          # f.write(subprocess_cmd + "\n")
                          # # f.write("output=subprocess.check_output(f'adb -s {ipconnect} shell am start -n {package}/{activity}', shell=True)\n")
                          # f.write("time.sleep(8)\n")
                          # f.write("print(output.decode())\n")
                          for image_data in images_data:
                              print(image_data)
                              image_name, action_type, step_number, _, repeatCount=image_data  # 接收重復次數
                              if action_type=='click':
                                  if int(repeatCount) > 1:
                                      f.write(f"for _ in range({repeatCount}):")  # 添加循環語句用于重復點擊
                                      f.write(f"\n    if exists(Template(r'{image_name}')):\n")  # 添加循環語句用于重復點擊
                                      f.write(f"        sleep(1.0)\n")  # 添加循環語句用于重復點擊
                                      f.write(f"        touch(Template(r'{image_name}'))\n")
                                      f.write(f"    else:\n")
                                      f.write(f"        break\n")
                                  else:
                                      f.write(f"touch(Template(r'{image_name}'))\n")
                                      f.write(f"time.sleep(1)\n")
                              elif action_type=='assert':
                                  f.write(f"assert_exists(Template(r'{image_name}'))\n")
                                  f.write(f"time.sleep(1)\n")
                              elif action_type=='exist':  # 處理新的action
                                  f.write(f"for i in range({repeatCount}):\n")
                                  f.write(f"    if exists(Template(r'{image_name}')):\n")
                                  f.write(f"        touch(Template(r'{image_name}'))\n")
                                  f.write(f"    else:\n")
                                  f.write(f"        break\n")
          
                      # 添加保存腳本邏輯
                      save_generated_script_to_DB(department_name, project_name, script_name,select_type)
                      return jsonify({'result': 'success'}, script_folder)
                  else:
                      return jsonify({'error': 'No script name found.'}), 400
              except Exception as e:
                  print('Error:', e)
                  traceback.print_exc()
                  return jsonify({"result": "error", "error_message": str(e)})
          
          
          

          綜上:添加腳本的功能邏輯開發完畢。

          下一節:執行腳本邏輯開發。敬請期待

          in10手機版怎么運行安卓APP應用?微軟官方并沒有給出正規的方法,但民間破解組織已經成功讓Win10手機版安裝安卓APP應用。據外媒報道,一西班牙開發者Antonio de la Iglesia寫出了一個在電腦上使用的神器,只要連接Win10手機,就可以一鍵將安卓APP應用裝到Win10手機上。

          軟件名稱:Win10 Mobile APK Installer(Win10手機版裝安卓應用神器)
          軟件版本:1.1
          軟件大小:10

          能手機的應用開發也隨著手機的發展成為一個火熱的行業,有著不錯的收入。為了方便而有效的進行開發選擇一套合適的開發模式是十分重要的。智能手機APP的開發模式可以分為三類分別是Native APPWeb APP和Hybrid APP開發模式。


          1三種移動APP開發模式



          1. Native APP


          NativeAPP開發模式,即本地開發模式,又稱為傳統型開發模式。這種開發模式基于移動終端的操作系統進行開發,可以良好的利用系統的硬件資源。其缺點也是顯而易見的,其應用只能在一種移動終端的系統中安裝使用,而且由于APP對硬件的依賴,應用升級會比較麻煩。


          1.2 Web APP

          Web APP開發模式基本依靠網絡技術實現。其APP 是一個針對手機優化后的 Web站點,優點是實現了跨平臺,而且對硬件幾乎沒有依賴,開發周期短。缺點也很明顯,APP 對網絡的依賴很大,數據基本都來自服務器,因此網絡狀況會直接影響用戶體驗。在沒有網絡的情況下,APP的功能基本不能使用。而且APP無法調用手機的硬件API功能受到一定的限制。


          1.3 Hybrid APP


          HybridAPP開發模式即混合開發模式。這種開發模式使用第三方的跨平臺開發框架,將一種語言開發出應用兼容到不同的移動設備上。這樣開發者就可以用Java Web技術或另一種不針對某具體系統的第三方的開發技術,實現應用的功能。APP同時具有了跨平臺性和不錯的硬件資源調用能力。


          2三種開發模式的環境配置及APP運行



          2.1 Hybrid APP的PhoneGap開發框架


          Nitobi公司(現在已被Adobe公司收購)推出了基于Web技術的移動解決方案PhoneGap,這一方案在其官網上的定義是“可以使用Web技術編寫手機本地應用程序的Htm15應用程序平臺”。簡單來說PhoneGap是一套基于Htm15的移動應用開發框架6PhoneGap開發框架成功將Java Web開發技術應用到了移動設備的開發上。已經具備 Java Web開發能力的開發者們可以使用熟知的HTML、CSS和JavaScript來開發手機APP。


          PhoneGap 開發框架支持包括IOS、Android、Windows Phone在內的多種手機平臺。開發者通過PhoneGap 提供的插件可以調用API使用攝像頭聯系人、地理定位等功能。PhoneGap 的使用是免費的它的兼容性強而且開發成本低。但PhoneGap本身也有不少缺點,它的運行需要依靠移動設備具有內置的瀏覽器引擎WebKit,PhoneGap的APP運行速度較慢,硬件調用能力也不如Native APP。安卓手機使用 PhoneGap 框架開發的Hy-bridAPP的基本結構。


          2.2PhoneGapAPP開發環境搭建


          開發PhoneGap APP可以使用Dreamweaver工具來制作Java Web頁面,并使用 PhoneGap Build(PhoneGap的在線編譯云服務)生成安裝包。但如果想測試某一平臺的硬件功能,就必須配置對應的開發環境,再進行編譯和測試。例如安卓開發的SDK工具包提供了手機模擬器,可以在PC機上進行APP測試。

          下面介紹在配置好安卓開發環境后,如何使用PhoneGap框架開發應用。首先,下載好 PhoneGap的工具包,打開 Eclipse后,按照創建步驟,新建一個安卓應用項目。復制cordova-xxxjar 文件到項目中的lib 文件夾下,右擊該jar 文件添加引用。然后在項目的assets 目錄下新建文件,復制 PhoneGap 工具包內的cordovajs 文件到個文件夾下,并創建Ja-va Web運行的級聯樣式表,Html文件和其他is 文件。創建完成后的文件結構。


          另外,安卓的應用需要依靠Activity啟動。要讓Activity啟動后,加載html頁面并運行JavaScript代碼,需要對Activity進行修改。改動包括兩步,要將Activity 繼承的類改為 DroidGap,導人需要的cor-dova包。然后將 setContentView(R.layout.activi-ty-main)改為 super.loadUrl(“file://android-asset/www/indexhtml”)其中www是新建的文件夾的名字index.html是該文件夾下的html文件

          編寫好文件夾下的html和is代碼生成apk安裝到安卓手機上就可以運行了。


          2.3NativeAPP的開發環境配置及APP運行


          對于Native APP發模式,不同的手機系統都有套成熟的開發框架與對應的開發語言”。例如,蘋果手機的APP需要用Object-C 編寫,AndroidAPP主要用Java開發,而屬于微軟公司的Win-dows Phone應用主要使用C#語言開發。如圖4 所示是安卓手機的Native APP的基本結構。其中Activity可以理解為活動窗口或者是一個單獨的頁面,它是與用戶交互的最基本的成像單元。在XMI文件中記錄了手機頁面的組件信息,Activity啟動后加載XML文件顯示頁面。開發者在 Activity里編寫Java代碼綁定組件,給綁定的組件添加監聽事件,在監聽事件中實現功能和API的調用。


          Android手機的Native APP開發環境配置主要包括兩個方面,一方面是配置程序設計語言的運行環境,需要下載JDK工具包并安裝。另一方面是開發平臺的搭建,需要將安卓開發的ADT插件安裝到Eclipse 開發平臺上,并用SDK 工具配置好安卓虛擬機JDK工具包只需要點擊按照提示即可安裝,配置完環境變量成后在dos下輸人命令java - version,若顯示 java 的版本則安裝成功。ADT的安裝需要打開 Eclipse,選擇工具欄的安裝新軟件,輸入地址https://dl-ssl.google.com/android/eclipse/,進行在線安裝。最后是虛擬機的創建,要將下載好的SDK包解壓并將路徑配置到 Eclipse 上,隨后在 eclipse 的工具欄打開AVD Manager下載適合自己的手機系統鏡像并更新到對應的平臺工具。然后打開SDKManager 創建一臺虛擬機,環境配置工作就基本完成了。


          2.4WebAPP的環境配置及APP運行


          Web APP開發模式的環境搭建主要是服務器端的環境搭建,Web APP的使用一般是用手機自帶的瀏覽器訪問站點,不需要下載安裝。這里選擇Java Web的應用。Java Web的開發環境配置,需要下載Java EE 版的 Eclipse,安裝Tomcat服務器并配置Java運行環境。僅僅靠 Java Web 技術開發出的頁面并不適合手機顯示,界面往往太大,操作起來也不方便。開發者可以使用成熟的移動 Web 開發框架來解決這個問題。現在已經有了很多優秀的移動 Web開發框架,例如Sencha TouchjQuery Mobile、DHTMLXTouch等。這些框架對HTML5和CSS3都有不錯的支持。用JQuery Mobile界面奈材創建的 Web APP在安卓模擬器上運行的效果。


          出處 長春理工大學學報(自然科學版)

          原標題 移動APP開發模式研究

          作者 李莉 張超然 劉丹 李紀成


          主站蜘蛛池模板: 日本不卡一区二区三区视频| 精品国产免费一区二区三区| 精品视频在线观看一区二区| 久久亚洲中文字幕精品一区四| 日本欧洲视频一区| 国产伦精品一区二区三区免费迷| 国产午夜精品一区二区| 午夜一区二区在线观看| 呦系列视频一区二区三区| 青青青国产精品一区二区| 久久精品国产一区二区三| 国产在线精品一区二区三区直播| 成人精品一区二区电影| 亚洲国产日韩在线一区| 亚欧色一区W666天堂| 亚洲一区AV无码少妇电影☆| 琪琪see色原网一区二区| 尤物精品视频一区二区三区| 亚洲性无码一区二区三区| 亚洲福利电影一区二区?| 亚洲午夜在线一区| 乱精品一区字幕二区| 精品一区二区三区四区在线播放 | 国产一区二区三区高清在线观看| 成人精品视频一区二区三区尤物| 日本一道高清一区二区三区| 亚洲熟妇AV一区二区三区宅男| 97久久精品一区二区三区| 亚洲一区二区三区91| 在线观看一区二区三区视频| 日韩精品久久一区二区三区| 精品一区二区久久久久久久网精| 国产人妖视频一区二区破除| 一区二区国产在线观看| 天堂Aⅴ无码一区二区三区| 国产在线精品一区二区在线观看| 成人精品一区二区不卡视频| 亚洲字幕AV一区二区三区四区| 国产成人精品一区二三区熟女 | 在线观看免费视频一区| 色妞色视频一区二区三区四区|