[Huawei Developers] John Wo:
You are probably a shipping and logistics company and your services require you to manage the flow of product delivery. You are trying your best to make sure that the products you handle, are transported from the purpose of origin to destination safely. You are trying to find ways to reinforce your services to cater to your customers better. QR Codes are the need of time as QR Codes store information which is easily scan-able with a smartphone and don't need you to put in any cost-intensive set-QR Codes store information. In fact, a QR Code can store up to 7,089 numeric or 2,953 alphanumeric characters.

Being a Shipping & Logistics Service, you need to keep an eye on goods at various stages during transit for which you do not need to regularly call the fellow operators or track the goods information and delivery status. QR Codes help both shipping and logistics do it easily. Once you place them on the packaging, operators can scan them at various stages of the transit from the warehouse to the delivery destination.

With Scan & Map Kit in your Business App, you can easily keep a track of the delivery packages. From scanning to get information, delivery status, delivery destination, and the directions to guide the Deliveryman to the destination.

Huawei Scan Kit:

HUAWEI Scan Kit scans and parses all major 1D and 2D barcodes and generates QR codes, helping you quickly build barcode scanning functions into your apps. Scan Kit automatically detects, magnifies, and recognizes barcodes from a distance, and is also able to scan a very small barcode in the same way.

Huawei Map Kit:

Huawei Map kit allows can easily integrate map-based functions into your apps and make location-based services work better for you.

Pre-Requisites

1. Integrate HMS Core in project

2. Enable Scan and Map Kit from AGC Console

3. Add agconnet-service.json file in the app level directory

1. Add Dependencies & Permission:

1.1: Add the following dependencies in the app level build.gradle file:

dependencies {
//Map
implementation 'com.huawei.hms:maps:5.0.3.302'
//Scan
implementation 'com.huawei.hms:scan:1.2.2.300'
}

1.2: Add the following permissions in the AndroidManifest.xml:

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

<!--Camera permission-->
<uses-permission android:name="android.permission.CAMERA" />
<!--File reading permission-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />

2. Add Layout Files:

2.1: Add the activity_main.xml layout file in the layout folder of the res. This is the layout view of the Main Activity of the in the application, contains a Recyclerview to display the arraylist.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview_parcels"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/_5sdp"
android:stackFromBottom="true" />

</RelativeLayout>

2.2: Add the activity_details.xml layout file in the layout folder of the res. This is the layout view of the Details Activity of the in the application, which contains the Textviews and a Mapview.

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

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/parcel_details"
android:textStyle="bold"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:gravity="center"
android:textColor="@color/teal_200"
android:textSize="@dimen/_14sdp"/>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
android:id="@+id/parcelid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="@dimen/_14sdp"/>

<TextView
android:id="@+id/parcelname"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="@dimen/_14sdp"/>

<TextView
android:id="@+id/parcelcontact"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="@dimen/_14sdp"/>

<TextView
android:id="@+id/parcellocation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="@dimen/_14sdp"/>

<TextView
android:id="@+id/parcelstatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="@dimen/_14sdp"
android:layout_marginBottom="@dimen/_20sdp"/>

<com.huawei.hms.maps.MapView
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
map:cameraTargetLat="51"
map:cameraTargetLng="10"
map:cameraZoom="8.5"
map:mapType="normal"
map:uiCompass="true"
map:uiZoomControls="true" />

</LinearLayout>
</LinearLayout>

2.3: Add the activity_scan.xml layout file in the layout folder of the res. This is the layout view of the Details Activity of the in the application, which contains the Surfaceview for the camera preview and an ImageView for a customize scanning rectangular area.

<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:my_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">

<!-- customize view for camera preview -->
<FrameLayout
android:id="@+id/rim"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#C0C0C0">

<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>

<!-- customize scanning rectangle -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:layout_centerHorizontal="true"
android:background="#FF000000"
android:alpha="0.1" />

<ImageView
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_centerInParent="true"
android:layout_centerHorizontal="true"
android:background="@drawable/scanningframe" />
</RelativeLayout>

</RelativeLayout>

2.4: Add the cardview_parcel.xml layout file in the layout folder of the res. This is the layout view for the items of Recyclerview in the Main Activity of the application, which contains the Cardview to display Textviews & Imageviews.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:card_view="http://schemas.android.com/tools"
android:padding="@dimen/_3sdp">

<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:orientation="horizontal"
android:background="@color/white"
card_view:cardCornerRadius="5dp"
card_view:cardElevation="4dp"
card_view:cardUseCompatPadding="true">

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">

<LinearLayout
android:id="@+id/linearclick_category"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:background="@color/white"
android:orientation="horizontal"
android:weightSum="10">

<TextView
android:id="@+id/serial_no"
android:layout_width="0dp"
android:layout_height="match_parent"
android:gravity="center"
android:layout_weight="1.5"
android:padding="@dimen/_5sdp"
android:background="@color/purple_200"
android:textColor="@color/black"
android:textSize="@dimen/_11sdp"/>

<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="7.5"
android:padding="@dimen/_5sdp"
android:gravity="center"
android:id="@+id/linearmid"
android:orientation="vertical"
android:weightSum="10">

<TextView
android:id="@+id/parcelid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:textColor="@color/black" />

<TextView
android:id="@+id/parcelname"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/black" />

<TextView
android:id="@+id/parcelcontact"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/black" />

<TextView
android:id="@+id/parcellocation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/black" />

<TextView
android:id="@+id/parcelstatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/black"/>

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end">

<ImageView
android:layout_marginEnd="@dimen/_10sdp"
android:layout_width="@dimen/_20sdp"
android:layout_height="@dimen/_20sdp"
android:scaleType="centerCrop"
android:id="@+id/cameraBtn"
android:visibility="invisible"
android:background="@drawable/ic_camera"/>

<ImageView
android:layout_width="@dimen/_20sdp"
android:layout_height="@dimen/_20sdp"
android:layout_toEndOf="@id/cameraBtn"
android:scaleType="centerCrop"
android:id="@+id/locationBtn"
android:background="@drawable/ic_location"/>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
</androidx.cardview.widget.CardView>
</RelativeLayout>

3. Add Classes

3.1: Add the MainActivity.java file in the App. This class extends AppCompatActivity and implements the Callback Interface of Parcel Adapter to handle views inside the adapter.

public class MainActivity extends AppCompatActivity implements ParcelsAdapter.CallbackInterface {

List<ParcelsModal> parcelsModalList;
RecyclerView mRecyclerView;
ParcelsAdapter parcelsAdapter;
public static final int SCAN_START_CODE = 001;
private static final int SCAN_CODE = 002;

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

parcelsModalList = new ArrayList<ParcelsModal>();
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview_parcels);
mRecyclerView.setLayoutManager(layoutManager);

// Add Data to list
parcelsModalList.add(new ParcelsModal("00001", "John Atkinson", "123456789", "40.716124, -74.001884","Delivered"));
parcelsModalList.add(new ParcelsModal("00002", "Mark Bennett", "123456789", "40.712188, -73.997378","Delivered"));
parcelsModalList.add(new ParcelsModal("00003", "Jack Brooks", "123456789", "40.717588, -74.010403","Not Delivered"));
parcelsModalList.add(new ParcelsModal("00004", "Alice John", "123456789", "40.715188, -73.995078","Not Delivered"));
parcelsModalList.add(new ParcelsModal("00005", "Julie Berk", "123456789", "40.713588, -74.013303","Not Delivered"));

parcelsAdapter = new ParcelsAdapter(MainActivity.this, (ArrayList<ParcelsModal>) parcelsModalList);
mRecyclerView.setAdapter(parcelsAdapter);
parcelsAdapter.notifyDataSetChanged();
}

//To Handle Callback
@Override
public void onHandleSelection(String text) {
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE},
SCAN_START_CODE);
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (permissions == null || grantResults == null || grantResults.length < 2 || grantResults[0] != PackageManager.PERMISSION_GRANTED || grantResults[1] != PackageManager.PERMISSION_GRANTED) {
return;
}

if (requestCode == SCAN_START_CODE) {
//start your activity for scanning barcode
Intent newIntent = new Intent(this, ScanActivity.class);
this.startActivityForResult(newIntent, SCAN_CODE);
}
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//receive result after your activity finished scanning
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK || data == null) {
return;
}
//Get Code from QR
if (requestCode == SCAN_CODE) {
HmsScan hmsScan = data.getParcelableExtra(ScanActivity.SCAN_RESULT);
if (hmsScan != null && !TextUtils.isEmpty(hmsScan.getOriginalValue())) {
processData(hmsScan.getOriginalValue());
}
}
}

//To Handle Adapter callback data in Activity
private void processData(String value){
for (ParcelsModal modal : parcelsAdapter.getDataAdapterList()) {
//Update date at your Server Here
if(modal.getParcel_id().equals(value)){
modal.setParcel_dilvery_status("Delivered");
Toast.makeText(this, "Parcel Delivered", Toast.LENGTH_SHORT).show();
break; // No need to run the remaining loop
}
}
parcelsAdapter.notifyDataSetChanged();
}
}