Android快递单号查询快递状态信息

本文介绍了一个简单的快递查询APP开发过程,使用了OkHttp3进行HTTP请求,并利用Gson解析JSON数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

辛苦堆砌,转载请注明出处,谢谢!

今天介绍一个自己做的快递单号查询的简单APP,供大家参考。由于需要使用http和json,本文在build.gradle(module:app)添加了okhttp3依赖和gson依赖。

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.1.1'
    testCompile 'junit:junit:4.12'
    compile 'com.squareup.okhttp3:okhttp:3.6.0'
    compile 'com.google.code.gson:gson:2.2.4'
}
看一下布局文件

<?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: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.yjp.deliverynoquerydemo.MainActivity">

    <Spinner
        android:id="@+id/delivery_company_spinner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:entries="@array/delivery_company"/>

    <EditText
        android:id="@+id/delivery_no_edit_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:hint="@string/please_enter_delivery_no"
        android:inputType="number"/>

    <Button
        android:id="@+id/query_button"
        android:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:text="@string/query"/>

    <ListView
        android:id="@+id/messages_list_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:listSelector="@android:color/transparent"/>
</LinearLayout>

ListView使用的item的布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/time_text_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textStyle="bold"
        android:textAppearance="?android:textAppearanceMedium"
        android:typeface="monospace"/>

    <TextView
        android:id="@+id/context_text_view"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:textAppearance="?android:textAppearanceSmall"
        android:typeface="monospace"/>

</LinearLayout>
资源文件,首先是strings.xml

<resources>
    <string name="app_name">快递查询</string>
    <string name="please_enter_delivery_no">请输入快递单号</string>
    <string name="query">查询</string>
    <string name="query_url">http://www.kuaidi100.com/query</string>
</resources>
这里我们使用了快递100的接口,然后看看arrays.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="delivery_company">
        <item>顺丰</item>
        <item>EMS</item>
        <item>快捷</item>
    </string-array>

    <string-array name="delivery_company_id">
        <item>shunfeng</item>
        <item>ems</item>
        <item>kuaijiesudi</item>
    </string-array>
</resources>
只做了3个快递公司的查询,还有很多其他的支持,界面如图所示

下面看看代码,我们自定义一个Application类,主要通过资源,使用表驱动法动态构建一个快递公司中文名与请求时候的公司编码的映射表。

package com.yjp.deliverynoquerydemo.global;

import android.app.Application;

import com.yjp.deliverynoquerydemo.R;

import java.util.HashMap;
import java.util.Map;

public class MyApplication extends Application {

    private Map<String, String> mDeliveryCompanyTable = new HashMap<>();

    public String getDeliveryCompanyNo(String deliveryCompanyName) throws RuntimeException {

        if (mDeliveryCompanyTable.isEmpty()) {
            String[] names = getResources().getStringArray(R.array.delivery_company);
            String[] ids = getResources().getStringArray(R.array.delivery_company_id);

            if (names.length != ids.length) {
                throw new RuntimeException();
            }

            for (int i = 0; i < names.length; i++) {
                mDeliveryCompanyTable.put(names[i], ids[i]);
            }
        }

        return mDeliveryCompanyTable.get(deliveryCompanyName);
    }
}
然后是模型,用来记录获取回来的快递状态信息

package com.yjp.deliverynoquerydemo.modal;

import java.util.List;

public class DeliveryMessages {

    //派送单号
    private String nu;

    //快递公司名称
    private String com;

    //快递信息
    private List<Message> data;

    //消息类
    public static class Message {

        //时间,格式为年-月-日 时:分:秒
        private String time;

        //详细信息内容
        private String context;

        public String getTime() {
            return time;
        }

        public void setTime(String time) {
            this.time = time;
        }

        public String getContext() {
            return context;
        }

        public void setContext(String context) {
            this.context = context;
        }
    }

    public String getNu() {
        return nu;
    }

    public void setNu(String nu) {
        this.nu = nu;
    }

    public String getCom() {
        return com;
    }

    public void setCom(String com) {
        this.com = com;
    }

    public List<Message> getData() {
        return data;
    }

    public void setData(List<Message> data) {
        this.data = data;
    }
}
一个用来通过http获取快递信息的工具类,这里我们使用了okHttp3和gson

package com.yjp.deliverynoquerydemo.tools;

import com.google.gson.Gson;
import com.yjp.deliverynoquerydemo.modal.DeliveryMessages;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class DeliveryMessageGetter {

    //异步请求监听接口
    public interface DeliveryMessageGetterListener {
        void onSuccess(DeliveryMessages deliveryMessages);
        void onFailure(String errorStr);
    }

    //okHttp
    private OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
            .readTimeout(10, TimeUnit.SECONDS)
            .writeTimeout(10, TimeUnit.SECONDS)
            .connectTimeout(10, TimeUnit.SECONDS)
            .build();

    //异步GET请求
    public void getAsync(final String url,
                         final Map<String, String> params,
                         final DeliveryMessageGetterListener listener) {

        //构建请求URL
        String requestString = url;
        if (!params.isEmpty()) {
            requestString += "?";
            for (Map.Entry<String, String> entry : params.entrySet()) {
                requestString += entry.getKey() + "=" + entry.getValue() + "&";
            }
            requestString = requestString.substring(0, requestString.length() - 1);
        }

        //创建一个Request
        final Request request = new Request.Builder()
                .url(requestString)
                .build();

        //请求加入调度
        Call call = mOkHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                if(e.getCause().equals(SocketTimeoutException.class)) {
                    listener.onFailure("查询超时");
                } else {
                    listener.onFailure("查询失败");
                }
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String messages = response.body().string();
                Gson gson = new Gson();
                DeliveryMessages deliveryMessages = gson.fromJson(messages, DeliveryMessages.class);

                if (deliveryMessages != null) {
                    listener.onSuccess(deliveryMessages);
                } else {
                    listener.onFailure("查询失败");
                }
            }
        });
    }

}
最后是我们的MainActivity

package com.yjp.deliverynoquerydemo;

import android.app.ProgressDialog;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Spinner;
import android.widget.Toast;

import com.yjp.deliverynoquerydemo.global.MyApplication;
import com.yjp.deliverynoquerydemo.modal.DeliveryMessages;
import com.yjp.deliverynoquerydemo.tools.DeliveryMessageGetter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.yjp.deliverynoquerydemo.modal.DeliveryMessages.Message;

public class MainActivity extends AppCompatActivity implements DeliveryMessageGetter.DeliveryMessageGetterListener {

    private List<Map<String, String>> mQueryData = new ArrayList<>();
    private SimpleAdapter mQueryAdapter;

    private Spinner mDeliveryCompanySpinner;
    private EditText mDeliveryNoEditText;

    private ProgressDialog mQueryWaitDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mDeliveryCompanySpinner = (Spinner) findViewById(R.id.delivery_company_spinner);
        mDeliveryNoEditText = (EditText) findViewById(R.id.delivery_no_edit_text);
        Button queryButton = (Button) findViewById(R.id.query_button);
        ListView messagesListView = (ListView) findViewById(R.id.messages_list_view);

        queryButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                //没有输入快递单号
                if (0 == mDeliveryNoEditText.getText().length()) {
                    Toast.makeText(MainActivity.this, "请输入快递单号", Toast.LENGTH_SHORT).show();
                    return;
                }

                //创建ProgressDialog对象
                mQueryWaitDialog = new ProgressDialog(MainActivity.this);
                mQueryWaitDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
                mQueryWaitDialog.setMessage("正在查询...");
                mQueryWaitDialog.show();

                //准备请求参数
                int selectedPosition = mDeliveryCompanySpinner.getSelectedItemPosition();
                String deliveryCompanyName =
                        getResources().getStringArray(R.array.delivery_company)[selectedPosition];
                Map<String, String> params = new HashMap<>();
                params.put("type",
                        ((MyApplication)getApplication()).getDeliveryCompanyNo(deliveryCompanyName));
                params.put("postid", mDeliveryNoEditText.getText().toString());

                //清空数据
                mQueryData.clear();

                //发送请求
                DeliveryMessageGetter getter = new DeliveryMessageGetter();
                getter.getAsync(getResources().getString(R.string.query_url),
                        params, MainActivity.this);
            }
        });

        mQueryAdapter = new SimpleAdapter(this,
                mQueryData,
                R.layout.query_list_item_layout,
                new String[] {"time", "context"},
                new int[] {R.id.time_text_view, R.id.context_text_view});
        messagesListView.setAdapter(mQueryAdapter);
    }

    @Override
    public void onSuccess(DeliveryMessages deliveryMessages) {
        List<Message> messages = deliveryMessages.getData();

        for (Message message : messages) {
            Map<String, String> map = new HashMap<>();
            map.put("time", message.getTime());
            map.put("context", message.getContext());
            mQueryData.add(map);
        }

        queryComplete("查询完成");
    }

    @Override
    public void onFailure(String errorStr) {
        final String hint = errorStr;
        queryComplete("查询失败");
    }

    private void queryComplete(final String toast) {
        MainActivity.this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mQueryAdapter.notifyDataSetChanged();
                mQueryWaitDialog.dismiss();
                Toast.makeText(MainActivity.this, toast, Toast.LENGTH_SHORT).show();
            }
        });
    }
}
主要是调用接口,实现功能,代码比较好理解,不再赘述。最后给出Manifest文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.yjp.deliverynoquerydemo">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:name=".global.MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
            android:windowSoftInputMode="stateHidden">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

主要是替换了默认的Application类,然后让MainActivity默认不弹出软键盘。








评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值