CertiScan Android SDK Tutorial
Overview
In this tutorial, we will guide you through writing a basic Android app using the CertiScan SDK. This app will be able to retrieve data from a Med-ic package or eCAP.
Create a new Android Studio project
- Launch Android Studio.
- Click Start a new Android Studio project.
- Select the Phone and Tablet tab, then Empty Activity, then click Next.
- Enter GetTagMessage in the Name field.
- Select Java from the Language dropdown menu.
- Select API 23 from the Minimum SDK dropdown menu, then click Finish.
Configuration
Copy the
CertiScanSDK.aar
to the libs directory.In
build.gradle
, setcompileSdkVersion
to the level 31 or higher. AndminSdkVersion
must be the level 23 or higher.// build.gradle (:app)
android {
compileSdk 31
defaultConfig {
minSdk 23
targetSdk 31
}
}Modify
implementation fileTree
inbuild.gradle
of the Module app as below, then Sync the project.// build.gradle (:app)
dependencies {
// implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
}
Add NFC permission to AndroidManifest.xml (
GetTagMessage/app/src/main/AndroidManifest.xml
).<manifest>
<uses-permission android:name="android.permission.NFC" />
<!-- optional-->
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
</manifest>Set
required
astrue
for theuses-feature
element "android.hardware.nfc" so that your application shows up in Google Play only for devices that have NFC hardware. If your application uses NFC functionality, but that functionality is not crucial to your application, you can omit the uses-feature element and check for NFC availability at runtime by checking to see ifgetDefaultAdapter()
isnull
.Create a new directory xml to the
GetTagMessage/app/src/main/res/
if it doesn't exist, then create filter_nfc.xml file to xml directory. And add the following to it.<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.IsoDep</tech>
</tech-list>
</resources>
Add NFCReaderActivity to AndroidManifest.xml, and also add “android.nfc.action.TECH_DISCOVERED” intent-filter and meta-data for MainActivity. If your app targets Android 12 and contains activities, services, or broadcast receivers that use intent filters, you must explicitly declare the
android:exported
attribute for these app components.<manifest>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/filter_nfc" />
</activity>
<activity
android:name="CertiScanSDK.NFCReaderActivity"
android:launchMode="singleTask"
android:theme="@style/Theme.Transparent"
android:exported="false">
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/filter_nfc" />
</activity>
</application>
</manifest>The complete AndroidManifest.xml is:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.informationmediary.app.android.gettagmessage">
<uses-permission android:name="android.permission.NFC" />
<!-- optional-->
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/filter_nfc" />
</activity>
<activity
android:name="CertiScanSDK.NFCReaderActivity"
android:launchMode="singleTask"
android:theme="@style/Theme.Transparent"
android:exported="false">
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/filter_nfc" />
</activity>
</application>
</manifest>
Implementing Get Tag Message (Java)
Open activity_main.xml (
GetTagMessage/app/src/main/res/layout/activity_main.xml
), then add a button.<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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">
<Button
android:id="@+id/btn_get_tag_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:minWidth="200dp"
android:text="Get Tag Message"
android:textAllCaps="false"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Open MainActivity.java and set OnClickListener to the button btn_get_tag_message. Then implement Get Tag Message.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnGetTagMessage = findViewById(R.id.btn_get_tag_message);
btnGetTagMessage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
NFCAPIManager.getTagMessage(MainActivity.this, new NFCAPIManager.Callback() {
@Override
public void OnComplete(String output) {
Log.i("MainActivity", "output=" + output);
}
@Override
public void onNFCReaderStatusChanged(NFCReaderStatus status) {
Log.i("MainActivity", "status=" + status);
}
});
}
});
}Now the complete code of MainActivity.java is:
package com.informationmediary.app.android.gettagmessage;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
import CertiScanSDK.NFCAPIManager;
import CertiScanSDK.NFCReaderStatus;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnGetTagMessage = findViewById(R.id.btn_get_tag_message);
btnGetTagMessage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
NFCAPIManager.getTagMessage(MainActivity.this, new NFCAPIManager.Callback() {
@Override
public void OnComplete(String output) {
Log.i("MainActivity", "output=" + output);
}
@Override
public void onNFCReaderStatusChanged(NFCReaderStatus status) {
Log.i("MainActivity", "status=" + status);
}
});
}
});
}
}
Implementing Get Tag Message (Kotlin)
Create a new Empty Activity.
- Enter “MainActivity2” in the Activity Name field.
- Uncheck the Generate a Layout File. We are going to reuse the activity_main.xml.
- Check Launcher Activity.
- Enter your Package Name.
- Select Kotlin from the Source Language dropdown menu, then click Finish.
In AndroidManifest.xml, comment out the Launcher intent-filter of MainActivity. And add “android.nfc.action.TECH_DISCOVERED” intent-filter and meta-data for MainActivity2. The complete code is:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.informationmediary.app.android.gettagmessage">
<uses-permission android:name="android.permission.NFC" /> <!-- optional -->
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity2"
android:label="CertiScan SDK"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/filter_nfc" />
</activity>
<activity
android:name=".MainActivity"
android:label="CertiScan SDK"
android:exported="true">
<!-- <intent-filter> -->
<!-- <action android:name="android.intent.action.MAIN" /> -->
<!-- <category android:name="android.intent.category.LAUNCHER" /> -->
<!-- </intent-filter> -->
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/filter_nfc" />
</activity>
<activity
android:name="CertiScanSDK.NFCReaderActivity"
android:launchMode="singleTask"
android:theme="@style/Theme.Transparent"
android:exported="false">
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/filter_nfc" />
</activity>
</application>
</manifest>
Open MainActivity2.kt and set activity_main as the content view.
class MainActivity2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
Set OnClickListener and implement Get Tag Message.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val btnGetTagMessage = findViewById<Button>(R.id.btn_get_tag_message)
btnGetTagMessage.setOnClickListener {
val callback = object : NFCAPIManager.Callback {
override fun OnComplete(responseJsonString: String?) {
Log.i("CertiScan", "output=$responseJsonString")
}
override fun onNFCReaderStatusChanged(status: NFCReaderStatus?) {
Log.i("CertiScan", "status=$status")
}
}
NFCAPIManager.getTagMessage(this, callback)
}
}Now the complete code of MainActivity2.kt is:
package com.informationmediary.app.android.gettagmessage
import android.os.Bundle
import android.util.Log
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import CertiScanSDK.NFCAPIManager
import CertiScanSDK.NFCReaderStatus
class MainActivity2 : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val btnGetTagMessage = findViewById<Button>(R.id.btn_get_tag_message)
btnGetTagMessage.setOnClickListener {
val callback = object : NFCAPIManager.Callback {
override fun OnComplete(responseJsonString: String?) {
Log.i("CertiScan", "output=$responseJsonString")
}
override fun onNFCReaderStatusChanged(status: NFCReaderStatus?) {
Log.i("CertiScan", "status=$status")
}
}
NFCAPIManager.getTagMessage(this, callback)
}
}
}
Run and Test
Run app on your device. Tapping the Get Tag Message button will start the NFC Scan Activity (CertiScanSDK.NFCReaderActivity
).
Scan a Medic or eCAP package and you will see the output in the Logcat.
output={
"tag_message":{
"tag_id":"500465364-PR2",
"scan_time":1626893242,
"event_count":3,
"package_id":"My Package ID",
"patient_id":"Patient_1",
"custom_data_1":"My Custom Data A",
"started" : true,
"clock_coefficient_correction" : true,
"tag_events":[
{
"timestamp":1623862993,
"type":1
},
{
"timestamp":1623862993,
"type":2
},
{
"timestamp":1623862993,
"type":6
}
],
"versioning" : {
"hardware_version" : "1.0.1",
"firmware_version" : "1.1.1.0.0.4.1",
"model" : "Med-ic"
}
},
"command_code":1,
"success":true
}