Android 杂记 - 存货盘点用的客户端
最近有个盘点用的东西,要放到移动设备,本来用 .Net Compact Framework,CAB 部署在 CE 系统的移动条码设备。技术太旧,我用了这个周末两天时间,把这东西在试试实现在安卓上面,给用户看看效果。
很多很多的意外,大量 Gotcha… 分享一下我的惨痛经历。以下有错误、或各位大哥有更好做法,请留言赐教。
1. IIS 上面用 ASMX,返回 JSON,原来在客户端 POST 时候是必须注明 Content-type 为 json,否则 ASMX 返回 XML。POST 没有标识为 json,即使你自己序列化,它也是返回 XML 包裹着 JSON。
ASP.NET CODE:
namespace Stocktake {
/// <summary>
/// Summary description for RecordService
/// </summary>
[WebService(Namespace = "http://xxx.com/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
[System.Web.Script.Services.ScriptService]
public class RecordService : System.Web.Services.WebService { [WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public StocktakeCode getStocktakeCode() { var result = new StocktakeCode() {
Code = "Testing",
Remark = "Some Remark"
};
return result;
}
} public class StocktakeCode {
public string Code {
get;
set;
}
public string Remark {
get;
set;
}
}
}
这段服务器端代码,我拼了命找错处,StackOverflow、Google、百度,原来,是没有错的。TMD x 10000。问题是下面客户端的,之前没 addHeader()。
ANDROID CODE:
public class DataAccess {
public static String getStocktakeCode(StocktakeActivity activity)
throws IOException {
HttpHost target = new HttpHost(getHostName(activity), getServerPort(activity));
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(getStockCodeWsPath(activity));
post.addHeader("Content-type", "application/json; charset=utf-8"); // THIS IS IMPORTANT
HttpEntity results = null;
try{
HttpResponse response=client.execute(target, post);
results = response.getEntity();
return EntityUtils.toString(results);
} catch (Exception e){
throw new IOException("Web Service failed.");
} finally{
if(results!=null){
try{
results.consumeContent();
} catch (IOException e){ }
}
}
}
}
2. web.config 要加 protocol … 我忘记了加。
ASP.NET web.config XML:
<webServices>
<protocols>
<add name="HttpPost"/>
</protocols>
</webServices>
不熟悉 web 开发的我,这个也很要人命。
3. MS 自动序列化为 JSON 时,多了个莫名其妙的 d:。客户端那边,必须用 getString 方式过滤掉。里面的字符才是我们要的。
ANDROID CODE:
JSONObject raw = new JSONObject(HttpPost_result);
String text = raw.getString("d");
4. Android 内,JSONObject 要取节点内的值用getString,遇上null 会抛JSONException异常。必须检查。
ANDROID CODE:
JSONObject raw = new JSONObject(HttpPost_result);
if(!raw.isNull("d")){
String text = raw.getString("d");
JSONObject newObj = new JSONObject(text);
TextView tv = (TextView)activity.findViewById(R.id.textViewStocktakeCode);
tv.setText(newObj.getString("Code"));
TextView tv2 = (TextView)activity.findViewById(R.id.textViewStocktakeRemark);
tv2.setText(newObj.getString("Remark"));
activity.setIsStocktakeAllowed(true);
} else {
//...
}
我这设计是,服务器可能返回对象(序列化为 JSON),也可能返回 null。返回 null 时候,服务器发出的响应 JSON 是 {d:null}。
5. Android 内,启动 AsyncTask 必须用 execute()。可能各位安卓的大哥觉得理所当然吧,我没怎么看 documentation 就动手,结果我直接 doInBackground,在 onPreExecute 打断点不到。就这问题,查了 TMD 四小时…。
ANDROID CODE:
错误:
String result = new StocktakeCodeWorker(StocktakeActivity.this).doInBackground((String[])null);
正确:
new StocktakeCodeWorker(StocktakeActivity.this).execute((String[])null);
Execute 是 void 没返回值,要干就要在 Override onPostExecute 内。
6. Android 内,用 intent 打开另一个程序等返回值,要指定 app 的话必须 setPackage。
ANDROID CODE:
Intent intent = new Intent("com.google.zxing.client.android.SCAN");
intent.setPackage("com.google.zxing.client.android"); // THIS IS IMPORTANT
intent.putExtra("SCAN_MODE","ONE_D_MODE");
intent.putExtra("SCAN_FORMAT", "CODE_128");
startActivityForResult(intent, SCAN_BARCODE_REQUEST);
否则,有多个程序供应比如 com.google.zxing.client.android.SCAN 的话,画面会出现 app chooser 让用户选。我测试用的手机上,刚好就有(淘宝、和 ZXING 本身)。我在好几个 QQ 群上问为何,也问为何淘宝出现在 app chooser,无回复。我猜,应该是淘宝用了 ZXING 的代码,而且连开放 INTENT 的也拿了过来的原因。
加上 setPackage 后,问题消失,app chooser 没有出现而直接运行了 ZXING。
7. Android 的 Preferences 内,用 EditTextPreferences 即使指明 input type 是 number,保存的依然是 String。除非你一直直接用代码来保存 preferences 和读取 preferences,否则,SharedPreferences.getInteger 是废的。要自己 parse。
ANDROID Preference XML:
<EditTextPreference
android:key="server_port"
android:title="@string/preference_serverPort"
android:summary="@string/preference_serverPortRemark"
android:dialogTitle="@string/preference_serverPort"
android:inputType="number"
android:defaultValue="80" />
ANDROID CODE:
public static int getServerPort(StocktakeActivity activity){
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(activity);
String textResult = sp.getString("server_port", "").trim();
return Integer.parseInt(textResult);
}
8. 用 Eclipse 图形化界面添加 Permission ,android.permission.INTERNET,加完依然无法连。搜了一下 StackOverflow,试试手工直接修改 XML,把它删了再手写一次,又可以了… 原因不明。
ANDROID Manifest XML:
<uses-permission android:name="android.permission.INTERNET"/>
真心不知道什么回事。
这完全是为了做个 protocol 出来给用户试试看而已。已能用,不美观,代码不公开。其实最关键部分,已经在上面全都写了。过程没有乐趣,只有痛苦。被采纳的话,接下去给下面的人改。
Android 杂记 - 存货盘点用的客户端的更多相关文章
- [Android] Android 手机下 仿 微信 客户端 界面 -- 微聊
Android 手机下 仿 微信 客户端 界面 -- 微聊 (包括聊天列表 + 聊天对话页 + 朋友圈列表页 + 我的/发现 列表页) 项目演示: 功能说明: 1)底部标签切换 (TabHost + ...
- 基于Android的小巫新闻客户端开发系列教程
<ignore_js_op> 141224c6n6x7wmu1aacap7.jpg (27.51 KB, 下载次数: 0) 下载附件 保存到相册 23 秒前 上传 <ignor ...
- Xamarin.Forms读取并展示Android和iOS通讯录 - TerminalMACS客户端
Xamarin.Forms读取并展示Android和iOS通讯录 - TerminalMACS客户端 本文同步更新地址: https://dotnet9.com/11520.html https:// ...
- Android SlidingMenu 仿网易新闻客户端布局
前面两篇文章中的SlidingMenu都出现在左侧,今天来模仿一下网易新闻客户端左右两边都有SlidingMenu的效果,以下是网易新闻客户端效果: 不扯闲话了,直接进入正题吧 frame_conte ...
- Android中FTP服务器、客户端搭建以及SwiFTP、ftp4j介绍
本文主要内容: 1.FTP服务端部署---- 基于Android中SwiFTP开源软件介绍: 2.FTP客户端部署 --- 基于ftp4j开源jar包的客户端开发 : 3.使用步骤 --- 如何测试我 ...
- 【Android】又一个Gank客户端来啦
介绍 Gank平台的移动端又来了,非常感谢Gank平台开放接口,让我们这些小白有机会练手.学习. 本项目在架构方面有稍微花点心思,虽然还是最简单的MVC模式,但基本参考MVP的思想,Activity只 ...
- android 启动默认的邮件客户端,多附件的问题
目前开发的app中需要发送邮件,所以需要调用android默认的邮件客户端,并需要添加多个邮件附件,我该通过哪个组件调用默认的客户端?用什么组件来支持多个附件的电子邮件? 是通过下面的哪一个?(Int ...
- android物理动画、Kotlin客户端、架构组件、菜单效果、应用选择器等源码
Android精选源码 Android一个有趣的Android动画交互设计 android可伸缩日历效果源码 关于界面,全新的卡片风格,支持夜晚模式 Android 用 Kotlin 实现的基于物理的 ...
- android应用市场、社区客户端、漫画App、TensorFlow Demo、歌词显示、动画效果等源码
Android精选源码 MVP架构Android应用市场项目 android刻度盘控件源码 Android实现一个社区客户端 android商品详情页上拉查看详情 基于RxJava+Retrofit2 ...
随机推荐
- MapReduce之Mapper类,Reducer类中的函数(转载)
Mapper类4个函数的解析 Mapper有setup(),map(),cleanup()和run()四个方法.其中setup()一般是用来进行一些map()前的准备工作,map()则一般承担主要的处 ...
- ASP.NET MVC的TempData(转载)
本文章基于ASP.NET MVC Preview5. ASP.NET MVC的TempData用于传输一些临时的数据,例如在各个控制器Action间传递临时的数据或者给View传递一些临时的数据,相信 ...
- 菜鸟,大牛和教主三者的区别(转自hzwer)
菜鸟,大牛和教主,三者的区别 对菜鸟来说题目有三种:会算法且能AC的,会算法但不能AC的,不会做的 对大牛来说题目有两种:会做的,不会做的 对教主来说题目有两种:能AC的,数据有错的 菜鸟提交WA了, ...
- 《HTML5高级程序设计》知识点概要(不涉及详细语法)
不断更新. 说明:主要记录html5中的一些注意点或知识点,尽量不涉及具体语法信息. 一.CANVAS: 检测: try{ document.createElement("canvas&qu ...
- 关于undefined reference to `WSASocketA@24'问题的解决
关于 Eclipse 开发C++ Socket ,在开发的过程中 用WinGW 平台编译, 示例server端: #include <winsock2.h> #include <m ...
- MongoDB C# / .NET Driver
MongoDB C# Driver是官方提供的.NET C#驱动. Getting Started with the C# Driver C# Driver Tutorial C# Driver LI ...
- Docker Centos安装Openssh
环境介绍: Docker版本:1.5.0 镜像:docker.io:centos latest 操作步骤: 1.启动镜像 docker run -ti centos /bin/bash 2.安装pas ...
- 判断listview是上滑还是下滑的方法
方法一: 用setOnScrollListener(new AbsListView.OnScrollListener())来实现,判断滑动后显示的第一个条目 ,与滑动前的第一个条目的大小来判断, 这种 ...
- javaWEB小练习:在数据库中查找相同的username和password
/*练习题: * 在Mysql数据库中创建一个person数据表,添加三个字段,id,user,password,并录入几条记录 * *练习题:定义一个login.html,里面定义了两个请求字段:u ...
- CI框架 QQ接口(第三方登录接口PHP版)
本帖内容较多,大部分都是源码,要修改的地方只有一个,其他只要复制过去,就可以完美运行.本帖主要针对CI框架,不用下载SDK,按我下面的步骤,建文件,复制代码就可以了.10分钟不要,接口就可完成.第一步 ...