欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

android studio+webapi+easyui混合开发

发布时间:2024/3/24 编程问答 38 豆豆
生活随笔 收集整理的这篇文章主要介绍了 android studio+webapi+easyui混合开发 小编觉得挺不错的,现在分享给大家,帮大家做个参考.
近日做了个android小例子,我是个初学者,新手上路,请多多指教。

一. 创建一个H5页面,UI使用easyui

    创建assets目录,用来存放前端资源

 下载easyui资源包,复制CSS、资源和js文件。

 把easyui文件直接复制到目录下

  这个路径就是 easyuif/……,下面这一步可以查看路径

这就是要引用的路径

参考easyui demo创建h5网页

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" type="text/css" href="easyuif/themes/default/easyui.css" /><link rel="stylesheet" type="text/css" href="easyuif/themes/mobile.css" /><link rel="stylesheet" type="text/css" href="easyuif/themes/icon.css" /><link rel="stylesheet" type="text/css" href="easyuif/themes/color.css" /><script type="text/javascript" src="easyuif/jquery.min.js"></script><script type="text/javascript" src="easyuif/jquery.easyui.min.js"></script><script type="text/javascript" src="easyuif/locale/easyui-lang-zh_CN.js"></script><style>.nihong{/* 要把阴影与大小配合好,一般来说大小都是偏大时采用 */font-family: "Arial Rounded MT Bold", "Helvetica Rounded", Arial, sans-serif;text-transform: uppercase;/* 全开大写 */font-size: 24px;color: orangered;text-shadow: 0 8px 9px #c4b59d, 0px -2px 1px #fff;font-weight: bold;letter-spacing: -4px;/*background: linear-gradient(to bottom, #ece4d9 0%,#e9dfd1 100%);*/}</style> </head> <body onload="iniatialize()"> <div style="margin:20px 0;"><a class="nihong" style="">RCS参数下发_测试用例</a> </div> <div><ul class="m-list"><li><span style="font-size:12px;color:gray">请求编号(RequestCode:string):</span><br><input id="RequestCode" class="easyui-textbox" prompt="...(选填)" style="width:100%;height:30px"></li><li><span style="font-size:12px;color:gray">任务类型(taskType:string):</span><br><select id="state" class="easyui-combobox" name="state" style="width:100%;height:30px"><option value="AL">产线上线</option><option value="AK">立库出库</option><option value="AZ">产线下线</option></select></li><li><span style="font-size:12px;color:gray">任务号(taskNo:string):</span><br><input id="taskNo" class="easyui-textbox" prompt="..." style="width:100%;height:30px"></li><li><span style="font-size:12px;color:gray">状态(taskState:string):</span><br><input id="taskState" class="easyui-textbox" prompt="..." style="width:100%;height:30px"></li><li><span style="font-size:12px;color:gray">接收位置(begin_location:string):</span><br><input id="beginlocation"  class="easyui-textbox" prompt="例如301-101" style="width:100%;height:30px"></li><li><span style="font-size:12px;color:gray">送达位置(target_location:string):</span><br><input id="targetlocation"  class="easyui-textbox" prompt="例如301-103" style="width:100%;height:30px"></li><li><span style="font-size:12px;color:gray">下一工序产线编码(To_Line_Code:string):</span><br><input id="ToLineCode"  class="easyui-textbox" prompt="..." style="width:100%;height:30px"></li><li><span style="font-size:12px;color:gray">请求操作时间(RequestTime:string)</span><br><input id="RequestTime"  class="easyui-textbox" prompt="..." style="width:100%;height:30px"></li><li><span style="font-size:12px;color:gray">托盘号(PalletCode:string):</span><br><input id="PalletCode"  class="easyui-textbox" prompt="例如:P2100056" style="width:100%;height:30px"></li><li><span style="font-size:12px;color:gray">部件总数量(TotalQuantity:int):</span><br><input id="TotalQuantity"  class="easyui-textbox" prompt="请输入正整数" style="width:100%;height:30px"></li><li><span style="font-size:12px;color:gray">部件集合(PartSets:集合):(PartSets:ArrayList):</span><br><input id="PartSets" class="easyui-searchbox" data-options="prompt:'null(选填)',searcher:doSearch" style="width:100%;height:30px"></li></ul><a href="javascript:quest();" class="easyui-linkbutton c3" style="width:100%;height:40px">提交</a> </div> <!--弹窗 --> <div id="win" class="easyui-window" title="部件编辑" closed="true" style="top:40%;width:90%;height:40%;"><form id="frm" style= "padding:1px 1px 1px 1px;"><table id="dg" class="easyui-datagrid" style="width:100%;height:auto"data-options="iconCls: 'icon-edit',singleSelect: true,toolbar: '#tb',onClickCell: onClickCell,onEndEdit: onEndEdit"><thead><tr><th data-options="field:'SequenceNumber',width:40,align:'center',editor:'textbox'">顺序</th><th data-options="field:'ProductionBatchCode',width:80,align:'center',editor:'textbox'">批次号</th><th data-options="field:'PartSerialNumber',width:80,align:'center',editor:'textbox'">条码号</th><th data-options="field:'TaskNumber',width:80,align:'center',editor:'textbox'">任务单</th><th data-options="field:'PartMaterialCode',width:80,align:'center',editor:'textbox'">物料号</th><th data-options="field:'status',align:'middle',width:40,align:'center',editor:{type:'checkbox',options:{on:'P',off:''}}">状态</th></tr></thead></table><div id="tb" style="height:auto"><a href="javascript:void(0)" class="easyui-linkbutton" data-options="iconCls:'icon-add',plain:true" onclick="append()">添加</a><a href="javascript:void(0)" class="easyui-linkbutton" data-options="iconCls:'icon-remove',plain:true" onclick="removeit()">删除</a><a href="javascript:void(0)" class="easyui-linkbutton" data-options="iconCls:'icon-clear',plain:true" onclick="removeall()">清空</a><a href="javascript:void(0)" class="easyui-linkbutton" data-options="iconCls:'icon-cancel',plain:true" onclick="closewin2()">关闭</a></div></form> </div> <!--弹窗 --> <div id="win2" class="easyui-window" title="系统消息" closed="true" style="top:60%;width:90%;height:30%;"><form id="frm2" style= "padding:10px 10px 10px 10px;"><div style="width:100%;height:90%"><div style="width:100%;height:5%"><p style="font-size:14px"><label id="typename">sdfsdfsdfsdg</label></p></div><div style="width:100%;height:95%"><p style="font-size:12px;color:darkgray;padding:5px 5px 5px 5px;"><label id="msgtxt" style="word-break:break-all;">asdasdasd</label></p></div></div><div style="width:100%;top:90%;height:5%"><p><a href="javascript:closewin()" class="easyui-linkbutton c4" style="left:60%;width:20%;height:40px">确定</a></p></div></form> </div> <script type="text/javascript">function quest(){var RequestCode_ =$("#RequestCode").textbox('getText');var taskType_ =$("#state").combobox('getText');var taskNo_ = $("#taskNo").textbox('getText');var taskState_ = $("#taskState").textbox('getText');var beginlocation_ = $("#beginlocation").textbox('getText');var targetlocation_ = $("#targetlocation").textbox('getText');var ToLineCode_ = $("#ToLineCode").textbox('getText');var date = new Date();var datm=dateTimeToString(date).toLocaleString();$('#RequestTime').textbox('setValue', datm);var RequestTime_ = $("#RequestTime").textbox('getText');var PalletCode_ = $("#PalletCode").textbox('getText');var TotalQuantity_ = parseInt($("#TotalQuantity").textbox('getText'));var msginfo=getTable();var PartSets_;if(msginfo==''){PartSets_ = null;$('#PartSets').textbox('setValue', 'null');}else{PartSets_ = getTable();var numcou=PartSets_.length;$('#PartSets').textbox('setValue', 'data['+String(numcou)+']');}var datax={                       RequestCode:RequestCode_,taskType:taskType_,taskNo:taskNo_,taskState:taskState_,begin_location:beginlocation_,                    target_location:targetlocation_,To_Line_Code:ToLineCode_,RequestTime:RequestTime_,PalletCode:PalletCode_,TotalQuantity:TotalQuantity_,PartSets:PartSets_};android.showToast(JSON.stringify(datax));}function ShowMsg(str,datx){document.getElementById('typename').innerHTML =datx;document.getElementById('msgtxt').innerHTML = JSON.stringify(str);openmsg();}function iniatialize(){$('#RequestCode').textbox('setValue', 'testRCS_001');$('#taskState').textbox('setValue', '下发');$('#taskNo').textbox('setValue', 'Task001');var date = new Date();var datm=dateTimeToString(date).toLocaleString();$('#RequestTime').textbox('setValue', datm);$('#ToLineCode').textbox('setValue', '8A27A001004');$('#TotalQuantity').textbox('setValue', '0');$('#PartSets').textbox('setValue', 'null');}function dateTimeToString(date) {var y = date.getFullYear();var M = date.getMonth() + 1;var d = date.getDate();var H = date.getHours();var m = date.getMinutes();var s = date.getSeconds();return y + '-' + (M < 10 ? ('0' + M) : M) + '-' + (d < 10 ? ('0' + d) : d) + " " + (H < 10 ? ('0' + H) : H) + ":" + (m < 10 ? ('0' + m) : m) + ":" + (s < 10 ? ('0' + s) : s);}function getTable(){var list= [];var checkedItems = $('#dg').datagrid('getRows');$.each(checkedItems, function(index, item){var _SequenceNumber=parseInt(item.SequenceNumber);var _ProductionBatchCode=item.ProductionBatchCode==null?'':item.ProductionBatchCode;var _PartSerialNumber=item.PartSerialNumber==null?'':item.PartSerialNumber;var _TaskNumber=item.TaskNumber==null?'':item.TaskNumber;var _PartMaterialCode=item.PartMaterialCode==null?'':item.PartMaterialCode;var datax={SequenceNumber:_SequenceNumber,ProductionBatchCode:_ProductionBatchCode,PartSerialNumber:_PartSerialNumber,TaskNumber:_TaskNumber,PartMaterialCode:_PartMaterialCode};list.push(datax);});return list;}function doSearch(value){openlogin();}var editIndex = undefined;function endEditing(){if (editIndex == undefined){return true}if ($('#dg').datagrid('validateRow', editIndex)){$('#dg').datagrid('endEdit', editIndex);editIndex = undefined;return true;} else {return false;}}function onClickCell(index, field){if (editIndex != index){if (endEditing()){$('#dg').datagrid('selectRow', index).datagrid('beginEdit', index);var ed = $('#dg').datagrid('getEditor', {index:index,field:field});if (ed){($(ed.target).data('textbox') ? $(ed.target).textbox('textbox') : $(ed.target)).focus();}editIndex = index;} else {setTimeout(function(){$('#dg').datagrid('selectRow', editIndex);},0);}}}function onEndEdit(index, row){var ed = $(this).datagrid('getEditor', {index: index,field: 'ProductionBatchCode'});row.ProductionBatchCode = $(ed.target).combobox('getText');}function append(){if (endEditing()){$('#dg').datagrid('appendRow',{status:'P'});editIndex = $('#dg').datagrid('getRows').length-1;$('#dg').datagrid('selectRow', editIndex).datagrid('beginEdit', editIndex);}}function removeit(){if (editIndex == undefined){return}$('#dg').datagrid('cancelEdit', editIndex).datagrid('deleteRow', editIndex);editIndex = undefined;}function removeall(){$('#dg').datagrid('loadData',[]);}function accept(){if (endEditing()){$('#dg').datagrid('acceptChanges');}}function reject(){$('#dg').datagrid('rejectChanges');editIndex = undefined;}function getChanges(){var rows = $('#dg').datagrid('getChanges');alert(rows.length+' rows are changed!');}function openlogin(){$('#win').window('open');}function openmsg(){$('#win2').window('open');}(function($){function getParentMenu(rootMenu, menu){return findParent(rootMenu);function findParent(pmenu){var p = undefined;$(pmenu).find('.menu-item').each(function(){if (!p && this.submenu){if ($(this.submenu)[0] == $(menu)[0]){p = pmenu;} else {p = findParent(this.submenu);}}});return p;}}$.extend($.fn.menubutton.methods, {enableNav: function(enabled){var curr;$(document).unbind('.menubutton');if (enabled == undefined){enabled = true;}if (enabled){$(document).bind('keydown.menubutton', function(e){var currButton = $(this).find('.m-btn-active,.m-btn-plain-active,.l-btn:focus');if (!currButton.length){return;}if (!curr || curr.button != currButton[0]){curr = {menu: currButton.data('menubutton') ? $(currButton.menubutton('options').menu) : $(),button: currButton[0]};}var item = curr.menu.find('.menu-active');switch(e.keyCode){case 13:  // enteritem.trigger('click');break;case 27:  // esccurrButton.trigger('mouseleave');break;case 38:  // upvar prev = !item.length ? curr.menu.find('.menu-item:last') : item.prevAll('.menu-item:first');prev.trigger('mouseenter');return false;case 40:  // downvar next = !item.length ? curr.menu.find('.menu-item:first') : item.nextAll('.menu-item:first');next.trigger('mouseenter');return false;case 37:  // leftvar pmenu = getParentMenu(currButton.data('menubutton') ? $(currButton.menubutton('options').menu) : $(), curr.menu);if (pmenu){curr.menu = pmenu;item.triggerHandler('mouseleave');} else {var prev = currButton.prevAll('.l-btn:first');if (prev.length){currButton.trigger('mouseleave');prev.focus();}}return false;case 39:  // rightif (item.length && item[0].submenu){curr.menu = $(item[0].submenu);curr.button = currButton[0];curr.menu.find('.menu-item:first').trigger('mouseenter');} else {var next = currButton.nextAll('.l-btn:first');if (next.length){currButton.trigger('mouseleave');next.focus();}}return false;}});}}});})(jQuery);$(function(){$.fn.menubutton.methods.enableNav();$(document).keydown(function(e){if (e.altKey && e.keyCode == 87){$('#btn-home').focus();}})});//显示消息let timer;var inter=0;function clock() {if(inter<3) {$("#msginfo").css("visibility","visible");$("#msginfo").css("display","block");inter++;}else{endclock();$("#msginfo").css("visibility","hidden");$("#msginfo").css("display","none");}}function endclock() {clearInterval(timer);}function closewin() {$(".panel-tool-close").click();}function closewin2() {$(".panel-tool-close").click();var PartSets_ = getTable();var numcou=PartSets_.length;if(numcou==0){$('#PartSets').textbox('setValue', 'null');}else{$('#PartSets').textbox('setValue', 'data['+String(numcou)+']');}} </script> </body> </html> 前端网站至此创建完毕,我们继续配置android端后台。二. 配置网络权限设置Layout布局 AnddoirdManifest文件里必须开通网络权限。 <!-- 开启网络访问权限 --> <uses-permission android:name="android.permission.INTERNET"></uses-permission> <!-- 允许访问网络状态的权限 --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 允许访问wifi状态的权限 --> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- 允许修改网络状态的权限 --> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"></uses-permission> <!-- 允许修改wifi状态的权限 --> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> 在布局文件里修改手机UI布局。 拖放webview,给他一个id,布局需要设置Margin还需要指定布局大小。 我们做的是一个混合开发的APP,结合webview互操作前台与后台,原理与HbuilderX的nui和mui是一样的,也是现在开发的主流,网络api请求不指定平台,一般有idea和.net,soap+。前端其实一般前端制作工具编辑好设计好,再迁移到android studio,我用的是intellij idea,很方便测试。 编辑前端的时候我们再前端预留了2个js函数,方便android互操作。 前端按钮按下调用前端quest()。

        操作android原生后台函数android.showToast(参数)。

ShowMsg是显示一个弹窗,当后台请求数据成功后,H5显示弹窗UI就没有违和感。

当提交按钮提交时,后台请求webapi,返回消息,后台控制webview加载弹窗,提示一个消息。

 

三. 后台代码

程序写三个类,MainActivity是主线程首先创建一个webapi请求的类requestApi,我们一直在纠结为什么要这么复杂使用后台,而不直接使用前台操作,js能一步到位。这个其实就是一个水很深的领域,是现存最大问题,前端有他的局限性,他会考虑跨域问题、内置浏览器端口限制问题,为了修复这个问题,需要配置浏览器还要配置API服务器支持浏览器,往往我们API来自不通领域,不仅仅是java开发的,浏览器访问需要考虑跨域问题,但是api是网络协议,不该有过多的限制,所以我们还是用后端做一些数据处理比较恰当。 package com.example.productlinetest;import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class requestApi {public String getSapData(String ptd) throws JSONException {URL wsUrl;int errCode=0;JSONObject resultJson=new JSONObject();String result="";try {wsUrl = new URL("http://xxx.xxx.xxx.xxx:6000/Mes/IssueTask?requestCommand=1");HttpURLConnection conn = (HttpURLConnection) wsUrl.openConnection();conn.setDoInput(true);conn.setDoOutput(true);conn.setRequestMethod("POST");conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");conn.setConnectTimeout(50000);conn.setReadTimeout(50000);OutputStream os = conn.getOutputStream();//请求体String soap = ptd.trim();os.write(soap.getBytes());InputStream is = conn.getInputStream();byte[] b = new byte[1024];int len = 0;String s = "";while((len = is.read(b)) != -1){String ss = new String(b,0,len,"UTF-8");s += ss+"\r\n";}result=s;is.close();os.close();conn.disconnect();} catch (MalformedURLException e) {// TODO Auto-generated catch blockSystem.out.println(e.toString());errCode=1;} catch (IOException e) {// TODO Auto-generated catch blockSystem.out.println(e.toString());errCode=2;}resultJson.put("errCode", errCode);resultJson.put("data", result);return resultJson.toString();} } 从上面就不难看出6000端口,那是Google限制端口,跟他内部冲突。主线程MainActivity添加代码。 package com.example.productlinetest; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Toast; public class MainActivity extends AppCompatActivity{public static Handler mHandler;public WebView webview;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//实例化webviewwebview=this.findViewById(R.id.webviewa);//设置WebView属性,能够执行Javascript脚本webview.getSettings().setJavaScriptEnabled(true);//添加与js的交互接口,起的名称与js代码中的接口名称要一致webview.addJavascriptInterface(new JavaScriptinterface(this), "android");// 使WebView的网页跳转在WebView中进行,而非跳到浏览器webview.setWebViewClient(new WebViewClient() {public boolean shouldOverrideUrlLoading(WebView view, String url) {view.loadUrl(url);return true;}});//加载页面try {//设置打开的页面地址webview.loadUrl("file:///android_asset/mhx.html");} catch(Exception ex) {ex.printStackTrace();Toast toast=Toast.makeText(this,"加载服务器失败",Toast.LENGTH_SHORT);toast.show();}//订阅静态传值对象mHandler = new Handler(){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);//msg.what对应子线程中msg的标签,在子线程中进行赋值if(msg.what==1){//操作js方法,显示消息String datax=msg.obj.toString();String[] datm=datax.split("》");webview.loadUrl("javascript:ShowMsg('"+datm[1]+"','"+datm[0]+"');");}}};} } 从上面代码来看,我们给webview注入了一个接口类变量。

 

  给主窗口写了一个传值跨线程对象。

 

他是个静态对象,这里只是为了图方便,当然不建议用这种静态方法。

 

JavaScriptinterface这个类继承自主线程MainAcgtivity要调用静态handler传值。内部要写一个@JavascriptInterface需要接收前端传值。 package com.example.productlinetest; import android.content.Context; import android.os.Message; import android.webkit.JavascriptInterface; import org.json.JSONException; public class JavaScriptinterface extends MainActivity{Context context;public JavaScriptinterface(Context contextpara) {context= contextpara;}@JavascriptInterfacepublic void showToast(String ssss) {requestApi req=new requestApi();try {String str=req.getSapData(ssss);runOnUiThread(() -> {Message msg = new Message();msg.what = 1;msg.obj="接口调用成功》"+str;mHandler.sendMessage(msg);});} catch (JSONException e) {runOnUiThread(() -> {Message msg = new Message();msg.what = 1;msg.obj="接口请求异常:》erro unlinked";mHandler.sendMessage(msg);});}} } @JavascriptInterface是不能互操作后端的,需要写一个线程单独去刷新。 Android操作js也是要通过webview的。

        webview是主线程控件,子线程访问需要刷新handler。

总结

以上是生活随笔为你收集整理的android studio+webapi+easyui混合开发的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。