Table of contents
(1) Introduction
- This article will take you step by step to implement a simple android express delivery applet to let you know better
- Creation of android project
- Use of github
- Parsing of JSON data
The following is a screenshot of the program (please don’t criticize me)
(2) Start the project
(1) Create your code base on github
Step 1: Create a project.
Enter the project name. Select the type and license
. Create a project with the same name in Android Studio.
Enter the created project directory in bit bash and enter:
git clone (the address of your newly created project on github).
For examplegit clone https://github.com/LQF-dev/DaydayExpress.git
Finally push to github
git add .
git commit -m "你的commit"
git push origin master
(2)Write layout file
Note: The layout code is a bit cumbersome, and I am not good enough at it. If you do not follow this layout file, you can choose to skip directly and view the implementation section of the code.
2.1 MainActivity
In the main activity we will place two EditText and a button and introduce ToolBar to replace the original ActionBar
- The following is the code of activity_main
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
/> >
<EditText
android:id="@+id/edit_expNu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:hint="请输入快递单号"/>
<EditText
android:id="@+id/edit_expCode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_below="@+id/edit_expNu"
android:hint="请输入快递公司名称"/>
<Button
android:id="@+id/submit"
android:layout_below="@+id/edit_expCode"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="查询"/>
</RelativeLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
app:menu="@menu/nav_menu"
app:headerLayout="@layout/nav_header">
</com.google.android.material.navigation.NavigationView>
</androidx.drawerlayout.widget.DrawerLayout>
2.2 TraceAcvitity
- In this activity, there is
toolbar to display the title bar
RelativeLayout to accommodate pictures and shipping information
LinearLayout to accommodate auxiliary information
RecycleView to display express tracking information
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar_trace"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
/> >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="20dp"
android:padding="20dp">
<ImageView
android:id="@+id/iv_companyImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:src="@drawable/ic_express_64" />
<TextView
android:id="@+id/text_state"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginLeft="44dp"
android:layout_marginTop="12dp"
android:layout_toRightOf="@+id/iv_companyImage"
android:text="正在运送" />
<TextView
android:id="@+id/text_showNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/text_state"
android:layout_marginLeft="44dp"
android:layout_toRightOf="@+id/iv_companyImage"
android:text="快递单号" />
</RelativeLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:text="快速详情"
android:layout_gravity="center"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:padding="10dp"/>
<TextView
android:id="@+id/tv_time_total"
android:layout_gravity="center"
android:text="耗时:"
android:padding="10dp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycle_view_trace"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
2.3 Use of ToolBar
ActionBar is displayed by default in the android project, so you must first modify the project's theme in the style.xml file before you can use Toobar.
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
</style>
</resources>
The following is a simple use of toobar. I only added a scan item to the toolbar. You can add different functions according to your needs.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/scan"
android:title="扫一扫"
app:showAsAction="never"
/>
</menu>
2.4 Introduction of dependencies
(3) Project code implementation
3.1 Overall understanding of the code
The idea of the current program is very simple
1. Call the Query Express API locally and send a query request.
2. Accept the parsed json data and extract the valid data using GSON or other methods.
3. Finally , display the data in the main thread (UITHread) .
3.2 Code implementation of MainActivity
- overall framework
3.2.1.onCreate
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//实例化各种控件
Button submit = (Button)findViewById(R.id.submit);
submit.setOnClickListener(this);
expCode = (EditText)findViewById(R.id.edit_expCode);
expNu = (EditText)findViewById(R.id.edit_expNu);
androidx.appcompat.widget.Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mdrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout) ;
//展示ActionBar
ActionBar actionBar = getSupportActionBar();
if(actionBar != null){
actionBar.setDisplayHomeAsUpEnabled(true);
//Todo change icon later
actionBar.setHomeAsUpIndicator(R.drawable.ic_menu);
}
}
3.2.2.Button onCLick event
- Store input data through SharedPreferences and pass it to TraceActivity
@Override
public void onClick(View v){
switch (v.getId()){
case R.id.submit:
final String code = expCode.getText().toString();
final String num = expNu.getText().toString();
Log.d(TAG, "code = "+ code);
Log.d(TAG, "num = " + num);
if(!(code.equals("STO") || code.equals("YTO")|| code.equals("ZTO")) ){
Toast.makeText(this, "仅支持 申通 圆通 中通", Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(this, "查询成功", Toast.LENGTH_SHORT).show();
}
// 打开另一个activity
SharedPreferences.Editor editor = getSharedPreferences("data",MODE_PRIVATE).edit();
editor.putString("code",code);
editor.putString("number",num);
editor.apply();
Intent intent = new Intent(this,TraceActivity.class);
startActivity(intent);
}
}
3.2.3 Loading Toolbar and TooBar’s click event
- I just added a scan menu
public boolean onCreateOptionsMenu(Menu menu){
getMenuInflater().inflate(R.menu.toolbar,menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item){
switch (item.getItemId()){
case R.id.scan:
Toast.makeText(this, "你点击了扫一扫按钮", Toast.LENGTH_SHORT).show();
break;
case android.R.id.home:
Log.d(TAG, "onOptionsItemSelected: open_drawer");
mdrawerLayout.openDrawer(GravityCompat.START);
break;
default:
break;
}
return true;
}
3.3 Code implementation of TraceActivity
- overall framework
3.3.1 What are the free express APIs? How to use the API?
You can use Express 100 Express Bird's API. Here I am using the free version of Express Bird (you can register directly with Express Bird, but Express 100 still needs to be reviewed). . . The free version of Express Bird only supports express delivery inquiries from ZTO, Yuantong and Shentong. For specific information, please log in to Express Bird's website for inquiries.
When you get your ID apikey, you can use the Express Bird API, but how to use it? Don’t worry, I will explain it clearly to you!
As shown in the figure below, open the demo provided by Express Bird
and copy the downloaded .java file to your project.
This interface KdniaoTrackQueryAPI is relatively complex. You don’t need to know the specific implementation. You only need to know that there is one. getOrderByJson method, this method requires you to pass in two parameters (company number) (courier number) to return JSON data
3.3.2 Json data parsing and implementation of onCreate method
- This is the json data obtained
Since I only need the parsed logistics track, I will not use the GSON parsing method here, but directly convert it to JSONObject for direct parsing.
new Thread(new Runnable() {
@Override
public void run() {
try {
//Log.d(TAG, "run: 进入run");
//这里的 respond 就是 待解析的Json数据
String respond = new KdniaoTrackQueryAPI().getOrderTracesByJson(code,num);
// Log.d(TAG, "respond: " + respond);
JSONObject jsonObject = new JSONObject(respond);
JSONArray array = jsonObject.getJSONArray("Traces");
for (int i = 0; i < array.length(); i++) {
JSONObject object = array.getJSONObject(i);
String AcceptStation = object.getString("AcceptStation");
stations.add(AcceptStation);
String AcceptTime = object.getString("AcceptTime");
times.add(AcceptTime);
// Log.d(TAG, "AcceptStation:" + stations.get(i));
// Log.d(TAG, "AcceptTime : " + times.get(i));
//Log.d(TAG, "AcceptTime size: " + times.size());
} try {
Reason = jsonObject.getString("Reason");
Log.d(TAG, "Reason: " + Reason);
} catch (Exception e) {
e.printStackTrace();
//Log.d(TAG, "Reason: 正常查询无Reason 现在Reason:" + Reason);
}
catch (Exception e) {
e.printStackTrace();
}
The data has been obtained and already exists in two lists. The next step is to update the data.
3.3.3 Update data in the main thread
if( Reason==null ){
runOnUiThread(new Runnable() {
@Override
public void run() {
//查询正确显示
showInfo();
}
});
}
else {
runOnUiThread(new Runnable() {
@Override
public void run() {
//查询不正确显示默认数据
showDefaultInfo();
}
});
}
}
}).start();//runable
Please see below for the logic of showInfo() and showDefaultInfo()
/**
* 初始化 list 给recycleView的Adapter提供数据
*/
public void initLoadTrace(){
for(int i =0;i < times.size();i++){
LoadTrace loadTraceItem = new LoadTrace(stations.get(i),times.get(i));
loadTraces.add(loadTraceItem);
}
}
/**
* 展示物流轨迹信息
*/
public void showTraceInfo(){
initLoadTrace();
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
LoadTraceAdapter adapter = new LoadTraceAdapter(loadTraces);
recyclerView.setLayoutManager(layoutManager);
recyclerView.addItemDecoration(new DividerItemDecoration(this,
DividerItemDecoration.VERTICAL));
recyclerView.setAdapter(adapter);
}
/**
*展示界面以及物流轨迹信息
*/
public void showInfo(){
showTraceInfo();
tv_showNumber.setText(LogisticCode);
}
/**
* 展示默认信息
*/
public void showDefaultInfo(){
tv_showNumber.setText("暂无");
Toast.makeText(this, "请输入正确信息", Toast.LENGTH_SHORT).show();
}
-At this point the overall logic is basically over.
3.3.4 Use of RecycleView
I will briefly skip this section. If you don’t understand, please download the use of RecycleView from Baidu.
public class LoadTrace {
private String traceInfo;
private String time;
public LoadTrace(String traceInfo,String time){
this.traceInfo = traceInfo;
this.time = time;
}
public String getTraceInfo() {
return traceInfo;
}
public String getTime() {
return time;
}
}
public class LoadTraceAdapter extends RecyclerView.Adapter<LoadTraceAdapter.ViewHolder> {
private List<LoadTrace>mLoadTraces;
static class ViewHolder extends RecyclerView.ViewHolder{
TextView traceInfo;
TextView time;
public ViewHolder(View view){
super(view);
traceInfo = (TextView)view.findViewById(R.id.tv_traceInfo);
time = (TextView)view.findViewById(R.id.tv_time_item);
}
}
public LoadTraceAdapter(List<LoadTrace>loadTraceList){
mLoadTraces = loadTraceList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent , int viewType){
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.loadtrace_item,parent,false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
//滚动到这里加载
@Override
public void onBindViewHolder(ViewHolder holder,int position){
LoadTrace loadTrace = mLoadTraces.get(position);
holder.traceInfo.setText(loadTrace.getTraceInfo());
holder.time.setText(loadTrace.getTime());
}
@Override
public int getItemCount(){
return mLoadTraces.size();
}
}
(3) Push the code to github
The project is finally completed! At this time, we can upload our project to github for management.
Tail:
Thank you for reading this, friends. This is my first time writing such a long blog. I hope you can gain something, and I hope we can work together to learn technology well!
If any friends don’t know what the final effect is, you can download my code in github. Here is my source code:
https://github.com/LQF-dev/DaydayExpress