More information like this, you can visit HUAWEI Developer Forum
Original link: https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0201258006396920241&fid=0101187876626530001
Foreword
The previous articles have introduced the function development of using HMS ML Kit SDK to implement Smile Capture Snapshot, ID photo DIY and photo translation,this time I will introduce to you the use of HMS Machine Learning Service (ML Kit) bank card recognition SDK, quickly bind credit cards.
Application scenarios of bank card recognition
Before introducing the development steps, let ’s talk about the specific application scenarios of bank card recognition,For banking apps, mobile payments app, e-commerce apps, or other apps with payment functions, during the use process, we often encounter the following common application scenarios:
· Card payment
Commonly used in payment apps, or apps with payment functions,used to bind credit cards, UnionPay debit cards, and provide online payment functions
· transfer money
Commonly used in bank or payment apps to transfer funds to users of our bank or other banks.
· Real-name authentication, identity verification
For example, social APP,Complete quick real-name authentication through the identity information associated with the bank card.
Whether it is card tying, money transfer or identity verification,will encounter a critical step,enter bank card information,such as bank card number, validity period, etc.;Since bank card numbers tend to be longer,manual entry is very error-prone,poor user experience;With the help of the HMS ML Kit bank card specific recognition capability,Can easily deal with the above scenarios, quickly and accurately enter bank card information, improve user experience.
How to use Huawei bank card identification service
Bank card recognition service can input bank card information through video streaming,obtain the important text information such as the card number and expiration date of the bank card in the image.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Bank card identification provides processing plug-ins. Developers can integrate a bank card recognition plug-in without the need to process camera video stream data, thereby achieving rapid integration of bank card recognition capabilities.
Key process of integrated bank card identification service
Since Huawei provides a bank card identification plug-in, developers can directly call the bank card plug-in, so the development steps are simpler, and only need to pull up the interface to obtain the result to complete the identification of the card number.
publishing ur app on Huawei AppGallery can refer to:https://forums.developer.huawei.com...d=0201253492001500241&fid=0101187876626530001
Development steps
1 Development preparation
1.1 Add Huawei maven address in project-level gradle
Code:
buildscript {
repositories {
maven {url 'http://developer.huawei.com/repo/'}
} }allprojects {
repositories {
maven { url 'http://developer.huawei.com/repo/'}
}}
1.2 Add SDK dependencies to the application-level build.gradle
Code:
dependencies{
// Introduce the basic SDK,please use the newest version according to the development
implementation 'com.huawei.hms:ml-computer-vision-bcr:1.0.3.303'
// Introduce bank card identification plugin package ,please use the newest version according to the development
implementation 'com.huawei.hms:ml-computer-card-bcr-plugin:1.0.3.300'
// Introduce bank card recognition model package ,please use the newest version according to the development
implementation 'com.huawei.hms:ml-computer-card-bcr-model:1.0.3.300' }
1.3Automatically download the incremental incremental model in the AndroidManifest.xml file
To enable the application to automatically update the latest machine learning model to the user device after the user installs your application from the Huawei application market, add the following statement to the AndroidManifest.xml file of the application:
Code:
<manifest
...
<meta-data
android:name="com.huawei.hms.ml.DEPENDENCY"
android:value= "bcr"/>
<!--If multiple models are required,set the parameter as follows:
android:value="object,ocr,face,label,icr,bcr,imgseg"-->
... </manifest>
1.4 Apply for camera and storage permissions in the AndroidManifest.xml file
Code:
<!--Camera permissions--> <uses-permission android:name="android.permission.CAMERA" />
<!--Use storage permissions--><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2 Key steps in code development
2.1 Create a recognition result callback function
Overload onSuccess, onCanceled, onFailure, onDenied four methods; onSuccess means recognition success, MLBcrCaptureResult is recognition return result, onCanceled means user cancel, onFailure means recognition failure, onDenied means camera is unavailable
Code:
private MLBcrCapture.Callback callback = new MLBcrCapture.Callback() {
@Override
public void onSuccess(MLBcrCaptureResult bankCardResult){
// Identify successful processing。
}
@Override
public void onCanceled(){
// User cancel processing
}
// Callback method where no text information can be recognized or a system exception occurs during the recognition process。
// retCode:error code。
// bitmap:Card picture of failed test
@Override
public void onFailure(int retCode, Bitmap bitmap){
// Identify exception handling。
}
@Override
public void onDenied(){
// The camera does not support such scene processing。
} };
2.2 Set the identification parameters, call the captureFrame interface of the recognizer for recognition, and the recognition result will be returned through the callback function in step 2.1
Code:
private void startCaptureActivity(MLBcrCapture.Callback callback) {
MLBcrCaptureConfig config = new MLBcrCaptureConfig.Factory()
// Set the identification interface horizontal and vertical screen, support three modes:
// MLBcrCaptureConfig.ORIENTATION_AUTO: Adaptive mode, the physical sensor determines the display direction。
// MLBcrCaptureConfig.ORIENTATION_LANDSCAPE: Landscape mode。
// MLBcrCaptureConfig.ORIENTATION_PORTRAIT: Portrait mode。
.setOrientation(MLBcrCaptureConfig.ORIENTATION_AUTO)
.create();
MLBcrCapture bankCapture = MLBcrCaptureFactory.getInstance().getBcrCapture(config);
bankCapture.captureFrame(this, callback); }
2.3 In the callback of the detection button, the method defined in step 2.2 is called to realize bank card recognition
Code:
@Override
public void onClick(View v) {
switch (v.getId()) {
// detect button
case R.id.detect:
startCaptureActivity(callback);
break;
default:
break;
} }
Demo effect
github source
The source code has been uploaded to github, you can also improve this function together on github。
github source address:https://github.com/HMS-Core/hms-ml-demo
Bank card identification demo code path:MLKit-Sample\module-text\src\main\java\com\mlkit\sample\activity\BankCardRecognitionActivity.java
For more detailed development guide, refer to the official website of Huawei Developer
Related
Introduction
Huawei provides various services for developers to come up with the solution for the problems which we are facing in our everyday life.
Problem: We have researched and found out that some people do have sight problems due to age and because of that they cannot read the text on the screen clearly, but they love to read news every day. Keeping that in mind we come up with a solution.
Solution: Using Huawei Mobile Service (HMS) core kits, we have tried to integrate as many kits as possible and created a smart but very effective news application.
In this News Application user can login, read or listen to the latest news and also user can change the default app language to their own native language. User will also receive notification messages based on the topic they subscribed on regular basis.
Let’s look into the Kits we have integrated in our Smart News App:
1. Account Kit
2. Ads Kit
3. ML Kit
4. Push Kit
5. Crash Service
This application will be explained in two parts:
1. In part one, I will explain how to integrate Account Kit and Ads Kit.
2. In part two, I will explain how to integrate ML Kit and Push Kit.
Demo
We will be focusing only on Account Kit and Ads Kit demo in this part.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Prerequisites
1. Must have a Huawei Developer Account.
2. Must have a Huawei phone with HMS 4.0.0.300 or later
3. Must have a laptop or desktop with Android Studio, Jdk 1.8, SDK platform 26 and Gradle 4.6 installed.
Integration Preparations
1. First we need to create a project in android studio.
2. Generate a SHA-256 certificate fingerprint. To generate SHA-256 certificate fingerprint use below command.
Code:
keytool -list -v -keystore
D:\SmartNewsApp\file_name.keystore
-alias alias_name.
3. Create a project in AppGallery Connect.
4. Enable Account kit and Ads Kit in Manage APIs section.
5. Provide the SHA Key in App Information Section.
6. Provide storage location.
7. Download the agconnect-services.json, copy and paste the Json file in the app folder.
8. Copy and paste the below maven URL inside the repositories of buildscript and allprojects (project build.gradle file).
Java:
maven { url 'http://developer.huawei.com/repo/' }
9. Copy and paste the below plugin in the app build.gradle file.
Java:
apply plugin: 'com.huawei.agconnect'
10. After that, we need to add dependencies into build.gradle files.
Java:
implementation 'com.huawei.hms:hwid:5.0.3.301' //Account Kit
implementation 'com.huawei.hms:ads-lite:13.4.34.301' //Ads Kit
Now, we need to sync our build.gradle files.
Account Kit Overview
HUAWEI Account Kit provides developers with simple, secure, and quick sign-in and authorization functions. Instead of entering accounts and passwords and waiting for authorization, users can just tap the Sign In with HUAWEI ID button to quickly and securely sign in to the app.
We will implement authorization code sign in use case for login scenario in this application.
Let’s start the coding!
Signing with Authorization Code
Add the below code in activity_main.xml.
XML:
<com.huawei.hms.support.hwid.ui.HuaweiIdAuthButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/hwi_sign_in"
android:layout_gravity="center_horizontal|center_vertical"
android:visibility="visible"
android:paddingTop="2dp"
android:paddingBottom="2dp"
android:background="#3b5998"
app:hwid_button_theme="hwid_button_theme_full_title"
app:hwid_corner_radius="hwid_corner_radius_small"/>
Huawei id auth button component is used here. Please check for getting more information about usage of Huawei ID signing in button.
Add the below code in LoginActivity.java
Java:
HuaweiIdAuthParams authParams = new HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM).setAuthorizationCode().setEmail().createParams();
HuaweiIdAuthService service = HuaweiIdAuthManager.getService(MainActivity.this, authParams);
startActivityForResult(service.getSignInIntent(), Constants.HUAWEI_SIGNIN);
When we click the Huawei ID signing in button, it needs the HuaweiIdAuthParams and create a service with authParams. Then, we call startActivityForResult() method in Huawei ID signing in button click with service and HUAWEI_SIGNIN constant. The constant (HUAWEI_SIGNIN) uses for handling the requestCode in onActivityResult() method. When the user clicks login with Huawei ID button, the app needs to authorize and login operations from the user.
Java:
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
// Process the authorization result and obtain the authorization code from AuthHuaweiId.
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == Constants.REQUEST_CODE) {
Task<AuthHuaweiId> authHuaweiIdTask = HuaweiIdAuthManager.parseAuthResultFromIntent(data);
if (authHuaweiIdTask.isSuccessful()) {
// The sign-in is successful, and the user's HUAWEI ID information and authorization code are obtained.
AuthHuaweiId huaweiAccount = authHuaweiIdTask.getResult();
String name = huaweiAccount.getDisplayName();
String email = huaweiAccount.getEmail();
SharedPreferences.Editor editor = getSharedPreferences(Constants.MY_PREFS_NAME, MODE_PRIVATE).edit();
editor.putBoolean("login", true);
editor.putString("name", name);
editor.putString("email", email);
editor.apply();
editor.commit();
Intent intent = new Intent(MainActivity.this, NewsActivity.class);
startActivity(intent);
} else {
// The sign-in failed.
Log.e(TAG, getApplication().getResources().getString(R.string.sigin_failed));
Toast.makeText(this, getApplicationContext().getResources().getString(R.string.unable_to_login), Toast.LENGTH_LONG).show();
}
}
}
When the user is signed in successfully and we could able to get users name and profile picture, email address and etc. It is displayed in the user profile.
Add the below code in UserProfile.java class.
Java:
signout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
HuaweiIdAuthParams authParams = new HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM).setIdToken().createParams();
HuaweiIdAuthService service= HuaweiIdAuthManager.getService(About.this, authParams) ;
Task<Void> signOutTask = service.signOut();
signOutTask.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(Task<Void> task) {
// Processing after the sign-out.
finishAndRemoveTask();
}
});
}
});
Ads Kits Overview
The most common method used by mobile developers is to generate revenue from their application is to create advertising spaces for advertisers. Advertisers prefer to place their ads through mobile media rather than printed publications.In this sense, Huawei Ads meets the requirement of both advertisers and mobile developers.
HMS Ads Kit is a mobile service that helps us to create high quality and personalized ads in our application.
Currently, HMS contains 7 kind of ads kits. In this application we will be integrating Banner ads.
Adding a Banner Ad
Add the following lines to your app level build.gradle file.
Java:
implementation 'com.huawei.hms:ads-lite:13.4.34.301'
Add BannerView to the XML layout file. Set the hwads:adId for the ad slot ID and hwads:bannerSize for the ad size.
XML:
<com.huawei.hms.ads.banner.BannerView android:layout_height="wrap_content"
android:layout_width="match_parent" android:id="@+id/hw_banner_view"
app:bannerSize="BANNER_SIZE_360_57" app:adId="testw6vs28auh3"
android:layout_alignParentBottom="true"/>
Note: Various banner size is available.
After creating the BannerView in XML file, call it from your class and load the banner ad. In this application we are displaying banner ads after every news in the newslist. So we have added in NewsListAdapter class.
Add the below code in NewsListAdapter class.
Java:
BannerView bottomBannerView = itemView.findViewById(R.id.hw_banner_view);
rootView = itemView.findViewById(R.id.root_view);
AdParam adParam = new AdParam.Builder().build();
RelativeLayout bottomBannerView.loadAd(adParam);
// Call new BannerView(Context context) to create a BannerView class.
BannerView topBannerView = new BannerView(context);
topBannerView.setBannerAdSize(BannerAdSize.BANNER_SIZE_360_57);
topBannerView.loadAd(adParam);
rootView.addView(topBannerView);
Tips and Tricks
1. Add agconnect-services.json file without fail.
2. Add SHA-256 fingerprint without fail.
3. Make sure dependencies added in build files.
4. Banner ads be can also added programmatically.
Conclusion
You may find some problems in your surroundings and I hope you can come up with a solution for those problems using HMS core kits.
Thanks for reading the article, please do like and comment your queries or suggestions.
References
HMS Account Kit
HMS Ads Kit
Read In Forum
1. Background
Cordova is an open-source cross-platform development framework that allows you to use HTML and JavaScript to develop apps across multiple platforms, such as Android and iOS. So how exactly does Cordova enable apps to run on different platforms and implement the functions? The abundant plugins in Cordova are the main reason, and free you to focus solely on app functions, without having to interact with the APIs at the OS level.
HMS Core provides a set of Cordova-related plugins, which enable you to integrate kits with greater ease and efficiency.
2. Introduction
Here, I'll use the Cordova plugin in HUAWEI Push Kit as an example to demonstrate how to call Java APIs in JavaScript through JavaScript-Java messaging.
The following implementation principles can be applied to all other kits, except for Map Kit and Ads Kit (which will be detailed later), and help you master troubleshooting solutions.
3. Basic Structure of Cordova
When you call loadUrl in MainActivity, CordovaWebView will be initialized and Cordova starts up. In this case, CordovaWebView will create PluginManager, NativeToJsMessageQueue, as well as ExposedJsApi of JavascriptInterface. ExposedJsApi and NativeToJsMessageQueue will play a role in the subsequent communication.
During the plugin loading, all plugins in the configuration file will be read when the PluginManager object is created, and plugin mappings will be created. When the plugin is called for the first time, instantiation is conducted and related functions are executed.
A message can be returned from Java to JavaScript in synchronous or asynchronous mode. In Cordova, set async in the method to distinguish the two modes.
In synchronous mode, Cordova obtains data from the header of the NativeToJsMessageQueue queue, finds the message request based on callbackID, and returns the data to the success method of the request.
In asynchronous mode, Cordova calls the loop method to continuously obtain data from the NativeToJsMessageQueue queue, finds the message request, and returns the data to the success method of the request.
In the Cordova plugin of Push Kit, the synchronization mode is used.
4. Plugin CallYou may still be unclear on how the process works, based on the description above, so I've provided the following procedure:
1. Install the plugin.
Run the cordova plugin add u/hmscore/cordova-plugin-hms-push command to install the latest plugin. After the command is executed, the plugin information is added to the plugins directory.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
The plugin.xml file records all information to be used, such as JavaScript and Android classes. During the plugin initialization, the classes will be loaded to Cordova. If a method or API is not configured in the file, it is unable to be used.
2. Create a message mapping.
The plugin provides the methods for creating mappings for the following messages:
1) HmsMessaging
In the HmsPush.js file, call the runHmsMessaging API in asynchronous mode to transfer the message to the Android platform. The Android platform returns the result through Promise.
The message will be transferred to the HmsPushMessaging class. The execute method in HmsPushMessaging can transfer the message to a method for processing based on the action type in the message.
Code:
public void execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException { hmsLogger.startMethodExecutionTimer(action); switch (action) { case "isAutoInitEnabled": isAutoInitEnabled(callbackContext); break; case "setAutoInitEnabled": setAutoInitEnabled(args.getBoolean(1), callbackContext); break; case "turnOffPush": turnOffPush(callbackContext); break; case "turnOnPush": turnOnPush(callbackContext); break; case "subscribe": subscribe(args.getString(1), callbackContext); break;
The processing method returns the result to JavaScript. The result will be written to the nativeToJsMessageQueue queue.
Code:
callBack.sendPluginResult(new PluginResult(PluginResult.Status.OK,autoInit));
2) HmsInstanceId
In the HmsPush.js file, call the runHmsInstance API in asynchronous mode to transfer the message to the Android platform. The Android platform returns the result through Promise.
The message will be transferred to the HmsPushInstanceId class. The execute method in HmsPushInstanceId can transfer the message to a method for processing based on the action type in the message.
Code:
public void execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException { if (!action.equals("init")) hmsLogger.startMethodExecutionTimer(action);
switch (action) { case "init": Log.i("HMSPush", "HMSPush initialized "); break; case "enableLogger": enableLogger(callbackContext); break; case "disableLogger": disableLogger(callbackContext); break; case "getToken": getToken(args.length() > 1 ? args.getString(1) : Core.HCM, callbackContext); break; case "getAAID": getAAID(callbackContext); break; case "getCreationTime": getCreationTime(callbackContext); break;
Similarly, the processing method returns the result to JavaScript. The result will be written to the nativeToJsMessageQueue queue.
Code:
callBack.sendPluginResult(new PluginResult(PluginResult.Status.OK,autoInit));
This process is similar to that for HmsPushMessaging. The main difference is that HmsInstanceId is used for HmsPushInstanceId-related APIs, and HmsMessaging is used for HmsPushMessaging-related APIs.
3) localNotification
In the HmsLocalNotification.js file, call the run API in asynchronous mode to transfer the message to the Android platform. The Android platform returns the result through Promise.
The message will be transferred to the HmsLocalNotification class. The execute method in HmsLocalNotification can transfer the message to a method for processing based on the action type in the message.
Code:
public void execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException { switch (action) { case "localNotification": localNotification(args, callbackContext); break; case "localNotificationSchedule": localNotificationSchedule(args.getJSONObject(1), callbackContext); break; case "cancelAllNotifications": cancelAllNotifications(callbackContext); break; case "cancelNotifications": cancelNotifications(callbackContext); break; case "cancelScheduledNotifications": cancelScheduledNotifications(callbackContext); break; case "cancelNotificationsWithId": cancelNotificationsWithId(args.getJSONArray(1), callbackContext); break;
Call sendPluginResult to return the result. However, for localNotification, the result will be returned after the notification is sent.
3. Perform message push event callback.
In addition to the method calling, message push involves listening for many events, for example, receiving common messages, data messages, and tokens.
The callback process starts from Android.
In Android, the callback method is defined in HmsPushMessageService.java.
Based on the SDK requirements, you can opt to redefine certain callback methods, such as onMessageReceived, onDeletedMessages, and onNewToken.
When an event is triggered, an event notification is sent to JavaScript.
Code:
public static void runJS(final CordovaPlugin plugin, final String jsCode) { if (plugin == null) return; Log.d(TAG, "runJS()");
plugin.cordova.getActivity().runOnUiThread(() -> { CordovaWebViewEngine engine = plugin.webView.getEngine(); if (engine == null) { plugin.webView.loadUrl("javascript:" + jsCode);
} else { engine.evaluateJavascript(jsCode, (result) -> {
}); } }); }
Each event is defined and registered in HmsPushEvent.js.
exports.REMOTE_DATA_MESSAGE_RECEIVED = "REMOTE_DATA_MESSAGE_RECEIVED"; exports.TOKEN_RECEIVED_EVENT = "TOKEN_RECEIVED_EVENT"; exports.ON_TOKEN_ERROR_EVENT = "ON_TOKEN_ERROR_EVENT"; exports.NOTIFICATION_OPENED_EVENT = "NOTIFICATION_OPENED_EVENT"; exports.LOCAL_NOTIFICATION_ACTION_EVENT = "LOCAL_NOTIFICATION_ACTION_EVENT"; exports.ON_PUSH_MESSAGE_SENT = "ON_PUSH_MESSAGE_SENT"; exports.ON_PUSH_MESSAGE_SENT_ERROR = "ON_PUSH_MESSAGE_SENT_ERROR"; exports.ON_PUSH_MESSAGE_SENT_DELIVERED = "ON_PUSH_MESSAGE_SENT_DELIVERED";
Java:
function onPushMessageSentDelivered(result) { window.registerHMSEvent(exports.ON_PUSH_MESSAGE_SENT_DELIVERED, result); } exports.onPushMessageSentDelivered = onPushMessageSentDelivered;
Please note that the event initialization needs to be performed during app development. Otherwise, the event listening will fail. For more details, please refer to eventListeners.js in the demo.
If the callback has been triggered in Java, but is not received in JavaScript, check whether the event initialization is performed.
In doing so, when an event is triggered in Android, JavaScript will be able to receive and process the message. You can also refer to this process to add an event.
5. Summary
The description above illustrates how the plugin implements the JavaScript-Java communications. The methods of most kits can be called in a similar manner. However, Map Kit, Ads Kit, and other kits that need to display images or videos (such as maps and native ads) require a different method, which will be introduced in a later article.
To learn more, please visit:
HUAWEI Developers official website
Development Guide
Reddit to join developer discussions
GitHub or Gitee to download the demo and sample code
Stack Overflow to solve integration problems
Follow our official account for the latest HMS Core-related news and updates.
Original Source
These days, the smart watch market is highly competitive. Watches no longer just tell us the time, rather they can allow us to take and make calls, scan barcodes, check our location, and perform a variety of other functions. They are particularly useful for vulnerable groups such as children and elderly people, which has opened new doors for businesses. Huawei's HarmonyOS-powered watch is one such device that aims to create an intelligent user experience. It does this by leveraging the capabilities of HMS Core Location Kit, which are: fused location, activity identification, and geofence. In this article, I'll show you how the location function on HarmonyOS watches works, through several simple steps.
Advantages and Restrictions of Location Kit1. It implements the geofence function based on chips, saving power.
2. It improves roadside location accuracy in urban canyons, and implements location accurate to less than a meter in open areas based on the Real-time Kinematic (RTK) technology.
3. The latest Location SDK can be used only on devices running HMS Core (APK) 6.0.0 or later. If HMS Core (APK) is not installed or its version is earlier than 6.0.0, the SDK functions properly but cannot be automatically updated.
4. To ensure app integrity, HarmonyOS uses a digital certificate and a profile to ensure that only packages with signed HarmonyOS Ability Package (HAP) files can be installed on devices.
Demo IntroductionI have provided a simple demo here. You can use the demo to experience how to implement location on HarmonyOS watches. The demo includes requesting location updates, obtaining the cached location, checking whether the location is available, and checking and setting the location permissions.
Integration ProcedureI'll now show you how to run the demo using source code, so that you can understand how it is implemented.
Preparations1. Preparing Tools
Test device: a Huawei smart watch running HarmonyOS 2.0 or later
Development tool: DevEco Studio 2.1.0.201 or later
2. Preparing for the Development
(1) Register as a Huawei developer and create an app. Refer to the Location Kit Development Preparations to create an app in AppGallery Connect.
(2) Generate a digital certificate and profile. This requires you to apply for an app debugging certificate, register a debugging device, apply for a debugging profile, and configure signature information.
(3) Generate a signing certificate fingerprint and configure it.
(4) Integrate the Location SDK.
Download the agconnect-services.json file from AppGallery Connect, and place it in the entry\src\main\resources\rawfile directory.
Add apply plugin: 'com.huawei.agconnect' as a line under the file header declaration, and add the Maven repository address and a dependency on the AppGallery Connect service in the project-level build.gradle file.
Java:
buildscript {
repositories {
maven {url 'https://repo.huaweicloud.com/repository/maven/'}
// Configure the Maven repository address for the HMS Core SDK.
maven {url 'https://developer.huawei.com/repo/'}
jcenter()
}
dependencies {
classpath 'com.huawei.ohos:hap:2.4.4.2'
// Add a dependency on the AppGallery Connect service.
classpath 'com.huawei.agconnect:agcp-harmony:1.1.0.300'
classpath 'com.huawei.ohos:decctest:1.2.4.0'
}
}
allprojects {
repositories {
maven {url 'https://repo.huaweicloud.com/repository/maven/'}
// Configure the Maven repository address for the HMS Core SDK.
maven {url 'https://developer.huawei.com/repo/'}
jcenter()
}
}
Add a dependency in the app-level build.gradle file. You can replace the version number as needed.
Java:
dependencies {
implementation 'com.huawei.hms:location-ohos:6.0.0.300'
// Add a dependency on AppGallery Connect.
implementation 'com.huawei.agconnect:agconnect-core-harmony:1.1.0.300'
}
If you need to configure obfuscation, open the obfuscation configuration file proguard-rules.pro in the app's root directory of your project and add configurations to exclude the HMS Core SDK from obfuscation.
The figure below shows the demo effect.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Key Steps1. Declare required permissions in reqPermissions in the config.json file.
HarmonyOS provides two types of location permissions: ohos.permission.LOCATION (location permission) and ohos.permission.LOCATION_IN_BACKGROUND (background location permission). Note that network permission is also required.
Java:
"reqPermissions": [
{
"reason": "get Local Location",
"name": "ohos.permission.LOCATION",
"usedScene": {
"ability": [
"com.huawei.codelab.MainAbility",
],
"when": "always"
}
},
{
"name": "ohos.permission.GET_NETWORK_INFO"
},
{
"name": "ohos.permission. LOCATION_IN_BACKGROUND"
}
2. Dynamically apply for the ohos.permission.LOCATION and ohos.permission.LOCATION_IN_BACKGROUND permissions in the code.
Java:
/The following uses the location permission as an example.
if (verifySelfPermission("ohos.permission.LOCATION") != IBundleManager.PERMISSION_GRANTED) {
printLog(HiLog.INFO, TAG, "Self: LOCATION permission not granted!");
if (canRequestPermission("ohos.permission.LOCATION")) {
printLog(HiLog.INFO, TAG, "Self: can request permission here");
requestPermissionsFromUser(
new String[]{"ohos.permission.LOCATION"}, REQUEST_CODE);
} else {
printLog(HiLog.WARN, TAG, "Self: enter settings to set permission");
}
} else {
printLog(HiLog.INFO, TAG, "Self: LOCATION permission granted!");
}
Key Code1. Create a location service client.
Create a FusedLocationProviderClient instance in the onStart() method of BaseAbilitySlice, and use this instance to call location-related APIs.
Java:
public FusedLocationProviderClient fusedLocProviderClient;
@Override
protected void onStart(Intent intent) {
super.onStart(intent);
fusedLocProviderClient = new FusedLocationClient(this);
}
2. Check the device location settings.
Call LocationRequest to set location request parameters, including the location update interval (in milliseconds), weight, and location information language. Before requesting callback, call the location service to check location settings.
Java:
private void checkLocationSettings() {
LocationRequest locationRequest = new LocationRequest();
locationRequest.setPriority(100);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
LocationSettingsRequest request =
builder.addLocationRequest(locationRequest).setAlwaysShow(false).setNeedBle(false).build();
settingsClient.checkLocationSettings(request)
.addOnSuccessListener(response -> {
// Device location settings meet the requirements.
})
.addOnFailureListener(exp -> {
// Device location settings do not meet the requirements.
});
}
3. Implement the location function.
Call requestLocationUpdates() for continuous location.
Java:
fusedLocProviderClient.requestLocationUpdates(locationRequest, locationCallback)
.addOnSuccessListener(var -> {
// Processing when the API call is successful.
})
.addOnFailureListener(e -> {
// Processing when the API call fails.
});
Call removeLocationUpdates() to stop requesting location updates.
Java:
// Note: When location updates are stopped, the mLocationCallback object must be the same object as LocationCallback in the requestLocationUpdates() method.
fusedLocProviderClient.removeLocationUpdates(locationCallback)
.addOnSuccessListener(var -> {
// Processing when the API call is successful.
})
.addOnFailureListener(e -> {
// Processing when the API call fails.
});
Define the location update callback.
Java:
LocationCallback locationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult != null) {
// Process the location callback result.
}
}
@Override
public void onLocationAvailability(LocationAvailability locationAvailability) {
super.onLocationAvailability(locationAvailability);
if (locationAvailability != null) {
// Process the location status.
}
}
};
Related Parameters1. Parameter for setting the location type. The options are as follows:
100: GNSS location
102 or 104: network location
105: indicates that locations are being received passively as opposed to being requested proactively.
2. Parameter for setting the location language. Currently, the options include only EN and CN.
3. Parameter for setting the number of location updates (setNumUpdates). If the value is 3, the app will receive three location updates. To continuously receive location updates, you are advised to use the default value.
References>> Location Kit official website
>> Location Kit Development Guide
>> Reddit to join developer discussions
>> GitHub to download the sample code
>> Stack Overflow to solve integration problems
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Personalized health records and visual tools have been a godsend for digital health management, giving users the tools to conveniently track their health on their mobile phones. From diet to weight and fitness and beyond, storing, managing, and sharing health data has never been easier. Users can track their health over a specific period of time, like a week or a month, to identify potential diseases in a timely manner, and to lead a healthy lifestyle. Moreover, with personalized health records in hand, trips to the doctor now lead to quicker and more accurate diagnoses. Health Kit takes this new paradigm into overdrive, opening up a wealth of capabilities that can endow your health app with nimble, user-friendly features.
With the basic capabilities of Health Kit integrated, your app will be able to obtain users' health data on the cloud from the Huawei Health app, after obtaining users' authorization, and then display the data to users.
Effects
This demo is modified based on the sample code of Health Kit's basic capabilities. You can download the demo and try it out to build your own health app.
PreparationsRegistering an Account and Applying for the HUAWEI ID ServiceHealth Kit uses the HUAWEI ID service and therefore, you need to apply for the HUAWEI ID service first. Skip this step if you have done so for your app.
Applying for the Health Kit ServiceApply for the data read and write scopes for your app. Find the Health Kit service in the Development section on HUAWEI Developers, and apply for the Health Kit service. Select the data scopes required by your app. In the demo, the height and weight data are applied for, which are unrestricted data and will be quickly approved after your application is submitted. If you want to apply for restricted data scopes such as heart rate, blood pressure, blood glucose, and blood oxygen saturation, your application will be manually reviewed.
Integrating the HMS Core SDKBefore getting started, integrate the Health SDK of the basic capabilities into the development environment.
Use Android Studio to open the project, and find and open the build.gradle file in the root directory of the project. Go to allprojects > repositories and buildscript > repositories to add the Maven repository address for the SDK.
Code:
maven {url 'https://developer.huawei.com/repo/'}
Open the app-level build.gradle file and add the following build dependency to the dependencies block.
Code:
implementation 'com.huawei.hms:health:{version}'
Open the modified build.gradle file again. You will find a Sync Now link in the upper right corner of the page. Click Sync Now and wait until the synchronization is complete.
Configuring the Obfuscation Configuration FileBefore building the APK, configure the obfuscation configuration file to prevent the HMS Core SDK from being obfuscated.
Open the obfuscation configuration file proguard-rules.pro in the app's root directory of the project, and add configurations to exclude the HMS Core SDK from obfuscation.
Code:
-ignorewarnings
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
-keep class com.huawei.hianalytics.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}
Importing the Certificate Fingerprint, Changing the Package Name, and Configuring the JDK Build VersionImport the keystore file generated when the app is created. After the import, open the app-level build.gradle file to view the import result.
Change the app package name to the one you set in applying for the HUAWEI ID Service.
Open the app-level build.gradle file and add the compileOptions configuration to the android block as follows:
Code:
compileOptions {
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
}
Main Implementation Code1. Start the screen for login and authorization.
Code:
/**
* Add scopes that you are going to apply for and obtain the authorization intent.
*/
private void requestAuth() {
// Add scopes that you are going to apply for. The following is only an example.
// You need to add scopes for your app according to your service needs.
String[] allScopes = Scopes.getAllScopes();
// Obtain the authorization intent.
// True indicates that the Huawei Health app authorization process is enabled; False otherwise.
Intent intent = mSettingController.requestAuthorizationIntent(allScopes, true);
// The authorization screen is displayed.
startActivityForResult(intent, REQUEST_AUTH);
}
2. Call com.huawei.hms.hihealth. Then call readLatestData() of the DataController class to read the latest health-related data, including height, weight, heart rate, blood pressure, blood glucose, and blood oxygen.
Code:
/**
* Read the latest data according to the data type.
*
* @param view (indicating a UI object)
*/
public void readLatestData(View view) {
// 1. Call the data controller using the specified data type (DT_INSTANTANEOUS_HEIGHT) to query data.
// Query the latest data of this data type.
List<DataType> dataTypes = new ArrayList<>();
dataTypes.add(DataType.DT_INSTANTANEOUS_HEIGHT);
dataTypes.add(DataType.DT_INSTANTANEOUS_BODY_WEIGHT);
dataTypes.add(DataType.DT_INSTANTANEOUS_HEART_RATE);
dataTypes.add(DataType.DT_INSTANTANEOUS_STRESS);
dataTypes.add(HealthDataTypes.DT_INSTANTANEOUS_BLOOD_PRESSURE);
dataTypes.add(HealthDataTypes.DT_INSTANTANEOUS_BLOOD_GLUCOSE);
dataTypes.add(HealthDataTypes.DT_INSTANTANEOUS_SPO2);
Task<Map<DataType, SamplePoint>> readLatestDatas = dataController.readLatestData(dataTypes);
// 2. Calling the data controller to query the latest data is an asynchronous operation.
// Therefore, a listener needs to be registered to monitor whether the data query is successful or not.
readLatestDatas.addOnSuccessListener(new OnSuccessListener<Map<DataType, SamplePoint>>() {
@Override
public void onSuccess(Map<DataType, SamplePoint> samplePointMap) {
logger("Success read latest data from HMS core");
if (samplePointMap != null) {
for (DataType dataType : dataTypes) {
if (samplePointMap.containsKey(dataType)) {
showSamplePoint(samplePointMap.get(dataType));
handleData(dataType);
} else {
logger("The DataType " + dataType.getName() + " has no latest data");
}
}
}
}
});
readLatestDatas.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
String errorCode = e.getMessage();
String errorMsg = HiHealthStatusCodes.getStatusCodeMessage(Integer.parseInt(errorCode));
logger(errorCode + ": " + errorMsg);
}
});
}
The DataType object contains the specific data type and data value. You can obtain the corresponding data by parsing the object.
ConclusionPersonal health records make it much easier for users to stay informed about their health. The health records help track health data over specific periods of time, such as week-by-week or month-by-month, providing invaluable insight, to make proactive health a day-to-day reality. When developing a health app, integrating data-related capabilities can help streamline the process, allowing you to focus your energy on app design and user features, to bring users a smart handy health assistant.
ReferenceHUAWEI Developers
HMS Core Health Kit Development Guide
Integrating the HMS Core SDK
Background
Recently, I was asked to develop a pet store app that can filter out fake users when they register and sign in, to cut down on the number of fake accounts in operation. I was fortunate enough to come across the UserDetect function of HMS Core Safety Detect at the Huawei Developer Conference, so I decided to integrate this function into this app, which turned out to be very effective. Currently, this function is free of charge and is very successful in identifying fake users, helping prevent credential stuffing attacks, malicious posting, and bonus hunting from fake users.
Now, I will show you how I integrate this function.
Demo and Sample Code
The HUAWEI Developers website provides both Java and Kotlin sample code for the UserDetect function and other four functions of Safety Detect. Click here to directly download the sample code. You can modify the name of the downloaded sample code package according to tips on the website, and then run the package.
Here is my sample code. Feel free to have a look.
Preparations
Installing Android Studio
To download and install Android Studio, visit the Android Studio official website.
Configuring App Information in AppGallery Connect
Before developing your app, follow instructions here to configure app information in AppGallery Connect.
Configuring the Huawei Maven Repository Address
The procedure for configuring the Maven repository address in Android Studio differs for Gradle plugin versions earlier than 7.0, Gradle plugin 7.0, and Gradle plugin 7.1 or later. Here I use version 7.1 or later as an example.
Note that the Maven repository address cannot be accessed from a browser and can only be configured in the IDE. If there are multiple Maven repositories, add the Maven repository address of Huawei as the last one.
1. Open the project-level build.gradle file in your Android Studio project.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
2. If the agconnect-services.json file has been added to the app, go to buildscript > dependencies and add the AppGallery Connect plugin configuration and Android Gradle plugin configuration.
Code:
buildscript {
dependencies {
...
// Add the Android Gradle plugin configuration. You need to replace {version} with the actual Gradle plugin version, for example, 7.1.1.
classpath 'com.android.tools.build:gradle:{version}'
// Add the AppGallery Connect plugin configuration.
classpath 'com.huawei.agconnect:agcp:1.6.0.300'
}
}
plugins {
...
}
3. Open the project-level settings.gradle file and configure the Maven repository address for the HMS Core SDK.
Code:
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
// Configure the Maven repository address for the SDK.
maven { url 'https://developer.huawei.com/repo/' }
}
}
dependencyResolutionManagement {
...
repositories {
google()
mavenCentral()
// Configure the Maven repository address for the SDK.
maven { url 'https://developer.huawei.com/repo/' }
}
}
Adding Build Dependencies
1. Open the app-level build.gradle file of your project.
2. Add the AppGallery Connect plugin configuration in either of the following methods:
Method 1: Add the following configuration under the declaration in the file header:
Code:
apply plugin: 'com.huawei.agconnect'
Method 2: Add the plugin configuration in the plugins block.
Code:
plugins {
id 'com.android.application'
// Add the following configuration:
id 'com.huawei.agconnect'
}
3. Add a build dependency in the dependencies block.
Code:
dependencies {
implementation 'com.huawei.hms:safetydetect:{version}'
}
Note that you need to replace {version} with the actual SDK version number, for example, 6.3.0.301.
Configuring Obfuscation Scripts
If you are using AndResGuard, add its trustlist to the app-level build.gradle file of your project. You can click here to view the detailed code.
Code Development
Creating a SafetyDetectClient Instance
Code:
// Pass your own activity or context as the parameter.
SafetyDetectClient client = SafetyDetect.getClient(MainActivity.this);
Initializing UserDetect
Before using UserDetect, you need to call the initUserDetect method to complete initialization. In my pet store app, I call the initialization method in the onResume method of the LoginAct.java class. The code is as follows:
Code:
@Override
protected void onResume() {
super.onResume();
// Initialize the UserDetect API.
SafetyDetect.getClient(this).initUserDetect();
}
Initiating a Request to Detect Fake Users
In the pet store app, I set the request to detect fake users during user sign-in. You can also set the request to detect fake users in phases such as flash sales and lucky draw.
First, I call the callUserDetect method of SafetyDetectUtil in the onLogin method of LoginAct.java to initiate the request.
My service logic is as follows: Before my app verifies the user name and password, it initiates fake user detection, obtains the detection result through the callback method, and processes the result accordingly. If the detection result indicates that the user is a real one, the user can sign in to my app. Otherwise, the user is not allowed to sign in to my app.
Code:
private void onLogin() {
final String name = ...
final String password = ...
new Thread(new Runnable() {
@Override
public void run() {
// Call the encapsulated UserDetect API, pass the current activity or context, and add a callback.
SafetyDetectUtil.callUserDetect(LoginAct.this, new ICallBack<Boolean>() {
@Override
public void onSuccess(Boolean userVerified) {
// The fake user detection is successful.
if (userVerified){
// If the detection result indicates that the user is a real one, the user can continue the sign-in.
loginWithLocalUser(name, password);
} else {
// If the detection result indicates that the user is a fake one, the sign-in fails.
ToastUtil.getInstance().showShort(LoginAct.this, R.string.toast_userdetect_error);
}
}
});
}
}).start();
}
The callUserDetect method in SafetyDetectUtil.java encapsulates key processes for fake user detection, such as obtaining the app ID and response token, and sending the response token to the app server. The sample code is as follows:
Code:
public static void callUserDetect(final Activity activity, final ICallBack<? super Boolean> callBack) {
Log.i(TAG, "User detection start.");
// Read the app_id field from the agconnect-services.json file in the app directory.
String appid = AGConnectServicesConfig.fromContext(activity).getString("client/app_id");
// Call the UserDetect API and add a callback for subsequent asynchronous processing.
SafetyDetect.getClient(activity)
.userDetection(appid)
.addOnSuccessListener(new OnSuccessListener<UserDetectResponse>() {
@Override
public void onSuccess(UserDetectResponse userDetectResponse) {
// If the fake user detection is successful, call the getResponseToken method to obtain a response token.
String responseToken =userDetectResponse.getResponseToken();
// Send the response token to the app server.
boolean verifyResult = verifyUserRisks(activity, responseToken);
callBack.onSuccess(verifyResult);
Log.i(TAG, "User detection onSuccess.");
}
})
}
Now, the app can obtain the response token through the UserDetect API.
Obtaining the Detection Result
Your app submits the obtained response token to your app server, and then your app server sends it to the Safety Detect server to obtain the detection result. You can obtain the user detection result using the verify API on the cloud.
The procedure is as follows:
1. Obtain an access token.
a. Sign in to AppGallery Connect and click My projects. Then, click your project (for example, HMSPetStoreApp) and view the client ID and client secret on the Project settings page displayed.
b. Use the client ID and client secret to request an access token from the Huawei authentication server. You can find out more details in the "Client Credentials" chapter on OAuth 2.0-based Authentication.
2. Call the Safety Detect server API to obtain the result.
The app will call the check result query API of the Safety Detect server based on the obtained response token and access token. You can visit the official website for details about how to call this API.
The app server can directly return the check result to the app, which will either be True, indicating a real user, or False, indicating a fake user. Your app can respond based on the check result.
Disabling UserDetect
Remember to disable the service to release resources after using it. For example, I call the disabling API in the onPause method of the LoginAct.java class of my app to disable the API.
Code:
@Override
protected void onPause() {
super.onPause();
// Disable the UserDetect API.
SafetyDetect.getClient(this).shutdownUserDetect();
}
Conclusion
And that's how it is integrated. Pretty convenient, right? Let's take a look at the demo I just made.
You can learn more about UserDetect by visiting Huawei official website.