一步一步教你写一个快递查询APP(适合新手)
前言:
水平:自學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(适合新手)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Vscode——开发常用插件分享
- 下一篇: Flying Saucer实现html转