前言:

水平:自学Android十五天,以前有过混日子的编程经验。

目标: 《第一行代码》学完之后,总想写个APP,天气的APP写了个初版,后面再说,今天演示的是制作快递查询APP的整个经过。

适合人群:新手

工具:Android Studio 2.2.2

  • 新建一个工程,选择Empty Actvity即可,其他默认。

1.布局

actvity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.blade.kuaidisearch.MainActivity"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textSize="16sp"android:text="@string/input_postid" /><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="45dp"><EditTextandroid:id="@+id/postid"android:layout_width="0dp"android:layout_weight="1"android:background="@layout/edit_bg"android:hint="@string/input_your_courier_number"android:layout_height="35dp" /><!--android:entries="@array/kdcompany"--><Spinnerandroid:id="@+id/spinner"android:entries="@array/kdcompany"android:layout_width="wrap_content"android:layout_height="wrap_content"></Spinner>
</LinearLayout><Buttonandroid:id="@+id/query"android:text="@string/btn_query"android:layout_width="match_parent"android:layout_height="wrap_content" /><ListViewandroid:id="@android:id/list"android:layout_width="match_parent"android:layout_height="match_parent">
</ListView>
</LinearLayout>

涉及到的相应要修改的文件,res->value->strings.xml文件

<resources>
<string name="app_name">KuaiDISearch</string>
<string name="input_postid">请输入快递单号:</string>
<string name="btn_query">查询</string>
<string name="input_your_courier_number">input your Courier number</string>
</resources>

看默认的输入框不爽,OK,我们来修改一下样式。在layout文件下新建一个名为edit_bg.xml的文件。

然后天剑EditText的android:background=”@layout/edit_bg”

<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item><shapexmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle"><solidandroid:color="#EFEFEF"/><cornersandroid:radius="3dip"/><strokeandroid:width="0.5px"android:color="#505050"/></shape>
</item>
</layer-list>
  • 下拉框的数据绑定,本文是通过xml文件。

在values下新建一个名为arrays.xml的文件,

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="kdcompany"><item>申通</item><item>EMS</item><item>顺丰</item><item>圆通</item><item>中通</item><item>韵达</item><item>天天</item><item>汇通</item><item>全峰</item><item>德邦</item><item>宅急送</item>
</string-array>
</resources>
  • 我只找到十一家,其他的我暂时还没看。

  • 然后设置Spinner的entries属性。

    android:entries=”@array/kdcompany”

  • 最后我们还要设置每一个item的样式。

  • 在layout下新建一个名为item_list.xml文件。(csdn的markdown编辑器不知道为啥不显示我在markdownpad2里编辑内容,大家直接看源码吧。)

整体布局就是垂直方向线性布局,在第二层,嵌套一个水平方向的线性布局。

涉及到的控件:一个TextView,EditText,Spinner,Button,ListView

知识点:

  • LinearLayout,vertical,horizontal,layout_weight
  • 效果图:

2.ListView使用方法

听说ListView是安卓开发常用的控件,看起来好像是。
我们的第一版的需求不要太复杂,把快递查询的结果分成两列,一列显示时间,一列显示内容(快递到哪儿了)

  • 运行一下程序,结果报错了:

Your content must have a ListView whose id attribute is ‘android.R.id.list’

原来在layout_main.xml中ListView的id需要使用系统的。

这一步需要注意的问题是ListView 控件的id要使用Android系统内置的 android:id=”@android:id/list”

忘了说了,我们让我们的MainActivity继承ListActivity,即extends ListActivity。

3.接口数据

昨天夜里一点逛知乎,看到了一个快递的免费接口,这让我马上想到做出这个应用。

http://www.kuaidi100.com/query?type=快递公司代号&postid=快递单号

快递公司代号:申通=”shentong” EMS=”ems” 顺丰=”shunfeng” 圆通=”yuantong” 中通=”zhongtong” 韵达=”yunda” 天天=”tiantian” 汇通=”huitongkuaidi” 全峰=”quanfengkuaidi” 德邦=”debangwuliu” 宅急送=”zhaijisong”

示例:http://www.kuaidi100.com/query?type=tiantian&postid=XXXXXXXXXXX
  • 网站返回的是JSON数据,为了更好地阅读JSON数据,可以把返回的数据复制到以下网址,可以格式化JSON数据。

  • www.bejson.com,其他类似的网站也行,点我

导入了org.apache.http.legacy还是无效呢,因为有两个版本的。
还要设置targetSdkVersion与legacy包相匹配。

4.解析JSON数据

4.1 Button的点击事件

先声明:

private Button query;

在onCreate方法里赋值:

query = (Button)findViewById(R.id.query);

用匿名内部类来写点击事件(其他写法,可以参考我的博文Button点击事件的四种写法)

    query.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {sendRequest();}});

点击按钮之后,我们想服务器(接口所在的)发送请求,sendRequest方法就是干这个的。

//发送Http请求
private void sendRequest(){new Thread(new Runnable() {@Overridepublic void run() {try{HttpClient httpClient = new DefaultHttpClient();//处理快递单号HttpGet httpGet = new HttpGet(http://www.kuaidi100.com/query?type=shunfeng&postid=XXXXXXX);//XXXXXX处填写快递单号HttpResponse httpResponse = httpClient.execute(httpGet);if(httpResponse.getStatusLine().getStatusCode() == 200){//请求和响应都成功了HttpEntity entity = httpResponse.getEntity();String response = EntityUtils.toString(entity,"utf-8");parseJSON(response);}}catch (Exception e){e.printStackTrace();}}}).start();
}

在这里补一句,HttpClient需要自己在libs添加一个jar包。自己通过在windows上搜索,找到org.apache.http.legacy.jar 还要注意一个版本的问题,你的build.gradle(Module:app)里的targetSdkVersion是24,那么你就在例如D:\Android\sdk\platforms\android-24\optional文件夹下找。

android-24,我之前找了个android-23的,出不来

接受到的JSON数据如下:

"message": "ok",
"nu": "XXXXXXXXXXX",
"ischeck": "0",
"condition": "00",
"com": "tiantian",
"status": "200",
"state": "0",
"data": [{"time": "2016-12-18 18:57:54","ftime": "2016-12-18 18:57:54","context": "快件已签收,签收人是乡镇代理点,签收网点是XXXXXX","location": ""},
  • 先声明一个list和一个HashMap,哈希表是按照键值对来储存数据了。

ArrayList

4.2 到了关键部分了,就是解析JSON数据,有很多种方式,其他方式可以上网搜一搜。

//解析JSON数据
private void parseJSON(String jsonData){try{//我们需要解析数组data的数据,其中time和context就是需要的字段JSONArray jsonArray = new JSONObject(jsonData).getJSONArray("data");for (int i = 0;i<jsonArray.length();i++){JSONObject jsonObject = jsonArray.getJSONObject(i);String time = jsonObject.getString("time");String context = jsonObject.getString("context");Log.d("data","time is " + time);Log.d("context","context is " + context);map = new HashMap<String,String>();map.put("time",time);map.put("context",context);list.add(map);}//在子线程向ListView里添加数据new Thread(){public void run(){runOnUiThread(new Runnable() {@Overridepublic void run() {SimpleAdapter simpleAdapter = new SimpleAdapter(MainActivity.this,list,R.layout.item_list,form,to);setListAdapter(simpleAdapter);//假如没有数据,提醒用户if(lv.getCount() == 0){Toast.makeText(MainActivity.this,"还没有数据",Toast.LENGTH_LONG).show();}}});}}.start();}catch (Exception e){e.printStackTrace();}
}
  • 假如没有在子线程更新view,就会报错,如下:

Only the original thread that created a view hierarchy can touch its views.

5.下拉框

到这里,应该可以查询到单条数据了,

回到上面的sendRequest方法。可以看到我们刚才发送请求的地址是:

//处理快递单号HttpGet httpGet = new HttpGet(http://www.kuaidi100.com/query?type=shunfeng&postid=XXXXXXX);//XXXXXX处填写快递单号
  • 现在我们要实现输入框和下拉框的功能,为了能让大家看得更直观,我就先只传了一个具体的链接。
  • 需要发送的链接里包含两个参数,一个是快递公司的代号,我们可以获得下拉框选中的值得到,另一个是快递单号,可以通过获取输入框的值得到。

声明:

private EditText postid;
private Spinner spinner;

赋值

    postid = (EditText)findViewById(R.id.postid);spinner = (Spinner)findViewById(R.id.spinner);

需要修改一下sendRequest方法。

//发送Http请求
private void sendRequest(){new Thread(new Runnable() {@Overridepublic void run() {try{HttpClient httpClient = new DefaultHttpClient();//处理快递单号String queryString = checkPostid();HttpGet httpGet = new HttpGet(queryString);HttpResponse httpResponse = httpClient.execute(httpGet);if(httpResponse.getStatusLine().getStatusCode() == 200){//请求和响应都成功了HttpEntity entity = httpResponse.getEntity();String response = EntityUtils.toString(entity,"utf-8");parseJSON(response);}}catch (Exception e){e.printStackTrace();}}}).start();
}

checkPostid方法就是通过识别快递单号是哪家的快递,给服务器传递响应的请求

//识别快递单号是哪家的快递,给服务器传递响应的请求
private String checkPostid(){//基础链接String baseStr = "http://www.kuaidi100.com/query?type=";String type= "";String postidNumber = postid.getText().toString().trim();String kuaidiCompany = spinner.getSelectedItem().toString().trim();Log.d("post id",postidNumber);Log.d("kuaidiCompany id",kuaidiCompany);if(kuaidiCompany.equals("申通")){type = "shentong";}else if(kuaidiCompany.equals("EMS")){type = "ems";}else if(kuaidiCompany.equals("顺丰")){type = "shunfeng";}else if(kuaidiCompany.equals("圆通")){type = "yuantong";}else if(kuaidiCompany.equals("中通")){type = "zhongtong";}else if (kuaidiCompany.equals("韵达")){type = "yunda";}else if (kuaidiCompany.equals("天天")){type = "tiantian";}else if (kuaidiCompany.equals("汇通")){type = "huitongkuaidi";}else if (kuaidiCompany.equals("全峰")){type = "quanfengkuaidi";}else if (kuaidiCompany.equals("德邦")){type = "debangwuliu";}else if(kuaidiCompany.equals("宅急送")){type = "zhaijisong";}Log.d("url",baseStr + type + "&postid=" + postidNumber);return baseStr + type + "&postid=" + postidNumber;
}
  • 不要吐槽我的英文,想半天也不知道怎么取个合适的方法名。连工程名也写错了意思。/(ㄒoㄒ)/~~

6.测试

天天,顺丰,中通,韵达都测试过,没有问题。

  • 为了有更好的用户体验,在没有数据的时候,给一个Toast提示一下用户。

    用listview的getCount方法,假如是0,说明没有数据。

                        //假如没有数据,提醒用户if(lv.getCount() == 0){Toast.makeText(MainActivity.this,"还没有数据",Toast.LENGTH_LONG).show();}
    

有时候出现这种情况,那么要去了解status为201是什么意思。今天就算了,都凌晨了。

{“message”:”快递公司参数异常:单号不存在或者已经过期”,”nu”:”“,”ischeck”:”0”,”condition”:”“,”com”:”“,”status”:”201”,”state”:”0”,”data”:[]}

其他的查询快递的APP都是直接输快递单号的,为啥这个不行,因为我在网上找不到快递公司单号的规则啊,就是怎么通过快递单号码来知道它是哪家公司的,这个不像身份证一样那么有规律。

7.问题

  • android没有标题栏
  • 清空android ListView控件的内容

8.后期版本

  • 扫二维码(不过,还是多看看接口的文档,快递单号的问题没解决,扫码暂时也没啥用)
  • 输入单号自动识别快递公司
  • 美化控件和界面
  • 标题栏的问题
  • 菜单栏(先解决标题栏的问题)

9.参考资料以及扩展

  • 接口文档

https://www.kuaidi100.com/openapi/api_post.shtml

  • 美化界面

http://blog.sina.com.cn/s/blog_7256fe8f0101ddmd.html

http://blog.csdn.net/badboy007/article/details/19034609

  • 给EditText设置边框

http://www.cnblogs.com/johnsonwei/p/5785055.html

http://www.jb51.net/article/46652.htm

  • EditText自定义样式

http://blog.csdn.net/jdsjlzx/article/details/25063169

  • layout的五大布局

http://www.tuicool.com/articles/3uUZbmu

  • android开发教程之listview使用方法

http://www.jb51.net/article/46652.htm

  • Android采用ListView实现数据列表显示

http://blog.csdn.net/furongkang/article/details/6819247

  • Android适配器之ArrayAdapter、SimpleAdapter和BaseAdapter的简单用法与有用代码片段

http://blog.csdn.net/shakespeare001/article/details/7926783

  • android Json解析详解(详细代码)

http://blog.csdn.net/onlyonecoder/article/details/8490924

  • Android子线程中更新UI的3种方法

http://gqdy365.iteye.com/blog/2112471

  • Android子线程真的不能更新UI么

http://www.cnblogs.com/lao-liang/p/5108745.html

  • ListView之SimpleAdapter的使用

http://blog.csdn.net/abc5382334/article/details/13503475/

  • 免费实用的API接口

https://zhuanlan.zhihu.com/p/21320392?refer=passer

10.结束语

感谢以上文章的作者,给了我做出第一款APP的资源。

时间已经到了00:43,我还是睡不着。

代码写的烂,需要改进的地方很多。

基础不扎实,还得好好搞搞java。

需要做的事很多,再也没有接口说不会了,说很难了。因为你可以做到的。

一个曾经写过程序又没写了,现在又写了的菜鸟程序员实在是有点啰嗦。

程序的源码我整理一下再上传,方便大家参考,我怕自己没写清楚。
地址(设置了1分的鼓励分):http://download.csdn.net/detail/a1b2c300/9724067

一步一步教你写一个快递查询APP(适合新手)相关推荐

  1. 用jaxa写一个快递查询

    用jaxa写一个快递查询 jquery-3.3.1.js <!DOCTYPE html><html lang="en"> <head> < ...

  2. thinkphp 助手函数url不生成https_如何用ThinkPHP框架写一个快递查询接口

    ThinkPHP是php程序员们经常使用的框架之一,运用框架来开发网站无疑减轻了我们代码量,加快了我们的开发速度,框架底层封装的方法和函数使用起来简直不能太爽.今天给大家总结一个小案例,如何实现一个快 ...

  3. 手把手教你写一个spring IOC容器

    本文分享自华为云社区<手把手教你写一个spring IOC容器>,原文作者:技术火炬手. spring框架的基础核心和起点毫无疑问就是IOC,IOC作为spring容器提供的核心技术,成功 ...

  4. 手把手教你写一个串口调试助手

    硬件攻城狮 2022-05-20 14:05 发表于广东 果果小师弟. 电子信息工程硕士在读,分享单片机.嵌入式linux.物联网等知识,致力于打造最硬核的嵌入式技术公众号. 摘要:前段时间发布了一个 ...

  5. 【vps】教你写一个自己的随机图API

    [vps]教你写一个自己的随机图API 前言 刚刚开始使用halo博客的时候,我就发现halo博客系统是可以使用随机图当背景的,所以也是使用了网上一些比较火的随机图API. 在上次发现了各种图片API ...

  6. 手把手教你写一个中文聊天机器人

    本文来自作者 赵英俊(Enjoy) 在 GitChat 上分享 「手把手教你写一个中文聊天机器人」,「阅读原文」查看交流实录. 「文末高能」 编辑 | 哈比 一.前言 发布这篇 Chat 的初衷是想和 ...

  7. 手把手教你写一个安卓app

    最近有很多小伙伴在后台留言:Android Studio.我想大家是想写一个手机app,前面已经分享了在QT上如何写一个安卓蓝牙app,虽然qt可以做app,但是比起Android Studio还是差 ...

  8. 手把手教你写一个生成对抗网络

    成对抗网络代码全解析, 详细代码解析(TensorFlow, numpy, matplotlib, scipy) 那么,什么是 GANs? 用 Ian Goodfellow 自己的话来说: " ...

  9. python k线合成_手把手教你写一个Python版的K线合成函数

    手把手教你写一个Python版的K线合成函数 在编写.使用策略时,经常会使用一些不常用的K线周期数据.然而交易所.数据源又没有提供这些周期的数据.只能通过使用已有周期的数据进行合成.合成算法已经有一个 ...

最新文章

  1. C# .NET Web API 如何自訂 ModelBinder
  2. 问题:二进制数中1的个数。
  3. Tomcat Filter 自己动手实现
  4. 从双11看技术趋势:金融行业总动员之阿里金融云
  5. Android之解决AppBarLayout 下面一道阴影
  6. win10创建c语言文件,c – 如何在Windows中创建扩展(自定义)文件属性?
  7. DButils工具使用笔记以及常见问题总结
  8. Kafka-consumer(消费者)
  9. es search delete
  10. js+css 实现遮罩居中弹出层(随浏览器窗口滚动条滚动)
  11. am 启动 activity 流程分析
  12. MRI T1加权结构
  13. 常见的非线性回归模型
  14. 解决浏览器下载文件时中文文件名乱码的问题
  15. Cisco Packet Tracer 网络系统工程实训大作业【附网络拓扑图】
  16. 裸板 nand flash K9F2G08U0C --- 读取ID
  17. [英语语法]词法之动词:时态语态
  18. 01-Intellij IDEA搭建SSM(SpringMVC+Spring+Mybatis+Maven)框架(下)
  19. 八进制在计算机系统中的应用场景,二进制、八进制、十进制、十六进制都能干什么? 十六进制计算器使用场景...
  20. DS1302数码管显示时--分--秒(按键可修改时间)

热门文章

  1. error execution phase preflight: couldn‘t validate the identity of the API Server: abort connecting
  2. Android 热修复 Tinker接入及源码浅析最精彩没有之一
  3. Android手机root,查看sqllite数据库文件
  4. 彻底删除迅雷影音(2022年12月16-17日)
  5. Tushare筛选成交量大于五日一倍的股票
  6. 希尔伯特曲线 java_《算法心得:高效算法的奥秘》PDF 下载
  7. java 抓图_用JAVA实现屏幕抓图的简单实例
  8. PyTorch3D 立体隐式形状渲染:教你构建场景 3D 结构
  9. 拓扑排序和关键路径的图形化显示
  10. 《游戏人工智能》学习笔记