Hello everyone, in this article series, I will tell you about what is HMS Site Kit and how to use it’s features. With HMS Site Kit, you can basically provide users with easy and reliable access to services to related to locations and places.
With the HMS Site Kit, we can provide them make use of this features while helping users to to discover world quickly;
We can take place suggestions according to the keywords that we have determined,
According to the location of the user’s device, we can search for nearby places,
We can get detailed information about a location,
We can learn the human readable address information of a coordinate point,
We can learn the time period where a coordinate point is found.
In the first article of Site Kit series, I will give you an information about how to setup Site Kit to Android project and how to use Keyword Search.
How to integrate HMS Site Kit to project?
First of all, we need to create a signed Bundle/APK of our project. For this, you can follow the steps which have shown in the picture below.
We can start to creating signature by clicking on the Build->Generate Signed Bundle/APK menu on Android Studio. Then, we can start the process of generating a signed APK by selecting the APK option on screen that comes up.
{
"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"
}
By pressing the Create New button on the screen that comes up, we can determine the path, password, key alias and key password values of the .jks file to be created for our application. Informations in the Certificate field is not mandatory.
After clicking OK button, we can continue the APK signing process by entering our password informations.
Then, we can complete the signing process by choosing which version of our application we want to sign such as release and debug, together with the signature versions.
After completing this process, we need to make configurations of this signature file in the build.gradle file at the app level of our application.
Code:
signingConfigs {
release {
storeFile file('SiteKitDemo.jks')
keyAlias 'SiteKitDemo'
keyPassword '****'
storePassword '****'
v1SigningEnabled true
v2SigningEnabled true
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug {
signingConfig signingConfigs.release
debuggable true
}
}
After performing this process, we can perform the operations related to Gradle synchronization by clicking on the sync now button.
After performing this process, we need to add ‘SHA-256 certificate fingerprint’ value of our application to AppGallery Connect.
We can learn value of ‘SHA-256 certificate fingerprint’ via termianl/CMD. For this, we need to go by terminal to the bin folder under the jre(Java Runtime Environment) installed on our system and run the command below.
Code:
C:\Program Files (x86)\Java\jre1.8.0_251\bin>keytool -list -v -keystore <keystore-path>
We will see a screen output as follows. Here, we need to get the value of SHA256.
We need to add this SHA256 value which we have received to the General Information field in the Project Settings menu on AppGalleryConnect. After performing this process, we can download the agconnect-services.json file.
After performing this process, we need to enable Site Kit service in Manage APIs tab on Project Settings tab.
We need to add agconnect-services.json file which we have downloaded, to under app folder on Android Studio of our project as follows.
After performing this process, we need to add Maven libraries and dependency values on build.gradle files.
First of all, we need to open build.gradle file at the project level and add the lines shown below:
Code:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.3.61'
repositories {
google()
jcenter()
maven { url 'https://developer.huawei.com/repo/' } // HUAWEI Maven repository
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
def agcpVersion = "1.3.1.300"
classpath "com.huawei.agconnect:agcp:${agcpVersion}" // HUAWEI agcp plugin
}
}
allprojects {
repositories {
google()
jcenter()
maven { url 'https://developer.huawei.com/repo/' } // HUAWEI Maven repository
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
After performing this process, we need to add plugin and dependency values in the build.gradle file at the app level as follows.
Code:
apply plugin: 'com.huawei.agconnect'
...
...
dependencies {
...
def siteKitVersion = "4.0.3.300"
implementation "com.huawei.hms:site:${siteKitVersion}"
}
To prevent HMS SDK from hiding, we need to add following lines of code to proguard-rules.pro file which is located under the app folder.
Code:
-ignorewarnings
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
-keep class com.hianalytics.android.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}
HMS Site Kit — Keyword Search
Thanks to this feature provided by Site Kit, we can search for many places such as tourist attractions, restaurants, schools and hotels by entering information such as keywords, coordinates.
Thanks to the data from this search result, we can easily access many different information about places such as name, address, coordinates, phone numbers, pictures, address details. Within the AddressDetail model, we can easily access information about the address piece by piece through different variables and change the way the address’ notation as we wish.
First of all, after sharing sharing the method what we can search by keyword, we will examine these pieces of code and parameters one by one.
Code:
fun keywordSearch(coordinate: Coordinate, keyword: String, radius: Int,
pageIndex: Int, pageSize: Int, countryCode: String){
val searchService = SearchServiceFactory.create(context,
URLEncoder.encode(
"Your-API-KEY",
"utf-8"))
var request = TextSearchRequest()
request.query = keyword
request.location = coordinate
request.radius = radius
request.pageIndex = pageIndex
request.pageSize = pageSize
request.language = Locale.getDefault().language // Getting system language
request.countryCode = countryCode
searchService.textSearch(request, object: SearchResultListener<TextSearchResponse>{
override fun onSearchError(searchStatus: SearchStatus?) {
Log.e("SITE_KIT","${searchStatus?.errorCode} - ${searchStatus?.errorMessage}")
}
override fun onSearchResult(textSearchResponse: TextSearchResponse?) {
var siteList = textSearchResponse?.sites
siteList?.let {
for(site in siteList){
Log.i("SITE_KIT", "Name => ${site.name}," +
"Format address => ${site.formatAddress}, " +
"Coordinate => ${site.location.lat} - ${site.location.lng}, " +
"Phone => ${site.poi.phone}, " +
"Photo URLS => ${site.poi.photoUrls}, " +
"Rating => ${site.poi.rating}, " +
"Address Detail => ${site.address.thoroughfare}, ${site.address.subLocality}, " +
"${site.address.locality}, ${site.address.adminArea}, ${site.address.country}")
}
} ?: kotlin.run {
Log.e("SITE_KIT","There is not any site")
}
}
})
}
First, we need to create a SearchService object from the SearchServiceFactory class. For this, we can use the create() method of the SearchServiceFactory class. We need to declare two parameters in create() method.
The first of these parameters is context value. It is recommended that Context value should be in Activity type. Otherwise, when HMS Core(APK) needs to be updated, we can not receive any notification about it.
The second parameter is API Key value that we can access via AppGallery Connect. This value is generated automatically by AppGallery Connect when a new app is created. We need to encode API parameter as encodeURI.
We need to create a TextSearchRequest object to perform searching by keyword. We will perform the related search criteria on this TextSearchRequest object.
While performing the searching operation, we can set many different criteria as we see in the code snippet. Let us examine the duties of these criteria one by one if you want to:
Query: Used to specify the keyword that we will use during the search process.
Location: It is used to specify latitude and longitude values with a Coordinate object to ensure that search results are searched as closely to the location that we want.
Radius: It is used to make the search results within in a radius determined in meters. It can take values between 1 and 50000, and its default value is 50000.
CountryCode: It is using to limit search results according to certain country borders.
Language: It is used to specify the language that search results have to be returned. If this parameter is not specified, the language of the query field we have specified in the query field is accepted by default. In example code snippet in above, the language of device has been added automatically in order to get a healthy result.
PageSize: Results return with the Pagination structure. This parameter is used to determine the number of Sites to be found in each page.
PageIndex: It is used to specify the number of the page to be returned with the Pagination structure.
Once we have determined our criteria, we can start the search using textSearch() method of SearchService object. textSearch() method takes two parameters.
First parameter is TextSearchRequest object which we have defined above. Here, our search criterias are defined.
For the second parameter, we need to implement SearchResultListener interface. Since the SearchResultListener interface is generic, we need the data type that results will return here. Here we can specify TextSearchResponse class that is model provided by Huawei Site Kit. This interface contains two methods, onSearchError() and onSearchResult() methods. We can configure these methods according to logic of our program and take necessary actions.
Related
Today we're going to go through getting started with Huawei's Safety Detect SDK. We'll talk about how to get set up, as well as some basic examples of how to use it.
What is Huawei Safety Detect?
Safety Detect builds robust security capabilities, including system integrity check (SysIntegrity), app security check (AppsCheck), malicious URL check (URLCheck), fake user detection (UserDetect), and malicious Wi-Fi detection (WifiDetect), into your app, effectively protecting it against security threats.
Preparation
First up, make sure you have a Huawei Developer Account. This process can take a couple days, and you'll need one to use this SDK, so be sure to start that as soon as possible. You can sign up at https://developer.huawei.com.
Next, you'll want to obtain the SHA-256 representation of your app's signing key. If you don't have a signing key yet, be sure to create one before continuing. To obtain your signing key's SHA-256, you'll need to use Keytool which is part of the JDK installation. Keytool is a command-line program. If you're on Windows, open CMD. If you're on Linux, open Terminal.
On Windows, you'll need to "cd" into the directory containing the Keytool executable. For example, if you have JDK 1.8 v231 installed, Keytool will be located at the following path:
Code:
C:\Program Files\Java\jdk1.8.0_231\bin\
Once you find the directory, "cd" into it:
Code:
C: #Make sure you're in the right drive
cd C:\Program Files\Java\jdk1.8.0_231\bin\
Next, you need to find the location of your keystore. Using Android's debug keystore as an example, where the Android SDK is hosted on the "E:" drive in Windows, the path will be as follows:
Code:
E:\AndroidSDK\.android\debug.keystore
(Keytool also supports JKS-format keystores.)
Now you're ready to run the command. On Windows, it'll look something like this:
Code:
keytool -list -v -keystore E:\AndroidSDK\.android\debug.keystore
On Linux, the command should be similar, just using UNIX-style paths instead.
Enter the keystore password, and the key name (if applicable), and you'll be presented with something similar to the following:
{
"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"
}
Make note of the SHA256 field.
SDK Setup
Now we're ready to add the Safety Detect SDK to your Android Studio project. Go to your Huawei Developer Console and click the HUAWEI AppGallery tile. Agree to the terms of use if prompted.
Click the "My projects" tile here. If you haven't already added your project to the AppGallery, add it now. You'll be asked for a project name. Make it something descriptive so you know what it's for.
Now, you should be on a screen that looks something like the following:
Click the "Add app" button. Here, you'll need to provide some details about your app, like its name and package name.
Once you click OK, some SDK setup instructions will be displayed. Follow them to get everything added to your project. You'll also need to add the following to the "dependencies" section of your app-level build.gradle file:
Code:
implementation 'com.huawei.hms:safetydetect:4.0.3.300'
If you ever need to come back to these instructions, you can always click the "Add SDK" button after "App information" on the "Project setting" page.
Now you should be back on the "Project setting" page. Find the "SHA-256 certificate fingerprint" field under "App information," click the "+" button, and paste your SHA-256.
Now, go to the Manage APIs tab on the "Project setting" page. Scroll down until you find "Safety Detect" and make sure it's enabled.
Now, if you're using obfuscation in your app, you'll need to whitelist a few things for HMS to work properly.
For ProGuard:
Code:
-ignorewarnings
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
-keep class com.hianalytics.android.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}
For AndResGuard:
Code:
"R.string.hms*",
"R.string.agc*",
"R.string.connect_server_fail_prompt_toast",
"R.string.getting_message_fail_prompt_toast",
"R.string.no_available_network_prompt_toast",
"R.string.third_app_*",
"R.string.upsdk_*",
"R.layout.hms*",
"R.layout.upsdk_*",
"R.drawable.upsdk*",
"R.color.upsdk*",
"R.dimen.upsdk*",
"R.style.upsdk*
That's it! The Safety Detect SDK should now be available in your project.
Basic Usage
Now that the SDK is set up, it's time to actually use it. Safety Detect currently has 5 APIs you can use: SysIntegrity, AppsCheck, URLCheck, UserDetect, and WifiDetect.
The first thing you'll want to do when using any of these APIs is to check whether HMS is actually available:
Code:
if (HuaweiApiAvailability.getInstance().isHuaweiMobileServicesAvailable(context) == ConnectionResult.SUCCESS) {
//HMS is available
} else {
//HMS isn't available. Act accordingly
}
Without HMS, these APIs won't work. Prompt the user to update/install HMS, or simply silently fail, depending on your needs.
SysIntegrity
The SysIntegrity API is similar to Google's SafetyNet. You can use it to check if the current device is insecure (e.g. is rooted). If your app relies heavily on running in a secure environment, you can use this check and refuse to run if it fails.
To use SysIntegrity, you need a few things: a nonce value, your app ID, and an active internet connection. The nonce value should be a secret, needs to be at least 16 bytes long, and can only be used once. It'll be contained in the SysIntegrity check result, so you can verify that the result is genuine.
You can find your app ID under the "App information" section on the "Project Setting" page.
Here's a quick example in Kotlin of how to set up the integrity check request:
Code:
fun checkSysIntegrity() {
val client = SafetyDetect.getClient(context)
//Ideally, you'd use a better nonce generation method, either from your own server
//or some other secure environment.
val nonce = "NONCE_${System.currentTimeMillis()}".toByteArray()
//You can find your APP_ID under "App information" in your project's settings on the AppGallery Developer Console.
val task = client.sysIntegrity(nonce, "APP_ID")
task.addOnSuccessListener {
val result = it.result
//Process the result. It will be in the JWS (JSON Web Signature) format, containing a header, payload, and signature.
//The header contains a certificate chain that should be verified against the HUAWEI CGB Root CA.
//Make sure the domain name of the leaf certificate in the certificate chain is `sysintegrity.platform.hicloud.com`.
//Verify the signature.
//Next, check the payload for the nonce and result. The payload format is something like the following:
/*
{
"advice":"RESTORE_TO_FACTORY_ROM",
"apkCertificateDigestSha256":[
"yT5JtXRgeIgXssx1gQTsMA9GzM9ER4xAgCsCC69Fz3I="
],
"apkDigestSha256":"6Ihk8Wcv1MLm0O5KUCEVYCI/0KWzAHn9DyN38R3WYu8=",
"apkPackageName":"com.huawei.hms.safetydetectsample",
"basicIntegrity":false,
"nonce":"R2Rra24fVm5xa2Mg",
"timestampMs":1571708929141
}
*/
//If basicIntegrity is false, then the check failed and you should handle it appropriately.
//You can use the following library to parse the JWS string: https://mvnrepository.com/artifact/com.nimbusds/nimbus-jose-jwt
}
task.addOnFailureListener {
//The request failed. If `it is ApiException`, you might be able to get more details about why the failure occurred.
//Note that this doesn't imply that the device has failed an integrity check. It merely means the check itself has failed.
//You can choose to retry, or simply ignore the error.
}
}
Put that code in a helper Class, and call it as needed. It is an asynchronous API, so make sure you account for that.
AppsCheck
The functionality of AppsCheck is pretty simple. It'll return a list of apps installed on the current device that are potentially malicious. You can use the result to decide on whether or not you want to restrict features, or prevent your app from running.
To get you up and running, a basic example is provided below. You can use it as the base for your implementation.
Code:
fun checkApps() {
val client = SafetyDetect.getClient(context)
val task = client.maliciousAppsList
task.addOnSuccessListener {
if (it.rtnCode == CommonCode.OK) {
//The request truly succeeded
//An ArrayList<MaliciousAppsData>
val apps = it.maliciousAppsList
if (apps.isEmpty()) {
//No malicious apps were found
} else {
//HMS found at least one potentially malicious app
apps.forEach {
//The package name of the potentially malicious app
val packageName = it.apkPackageName
//The SHA-256 of the potentially malicious app
val sha256 = it.apkSha256
//The category of the potentially malicious app
//Constants are defined in the AppsCheckConstants class
//Currently, this can return either VIRUS_LEVEL_RISK (1)
//or VIRUS_LEVEL_VIRUS (2)
val category = it.apkCategory
}
}
} else {
//Something went wrong with the request
//Use `it.getErrorReason()` to see why
}
}
task.addOnFailureListener {
//A communication error occurred.
//If `it is ApiException`, you may be able to get more details about why
//the failure occurred.
}
}
URLCheck
If your app allows users to visit URLs you aren't able to verify (forum app, social media app, etc), URLCheck can help you screen links that users click. If the URL is detected as malicious, you can prompt the user.
If you want to implement this for yourself, start with the example code below:
Code:
fun checkUrl(url: String) {
val client = SafetyDetect.getClient(context)
//Ensure the URLCheck API is initialized
val initTask = client.initUrlCheck()
initTask.addOnSuccessListener {
//Initialization was successful.
//Make sure to remove any query parameters from the URL before checking it.
//For example, if the full URL is https://google.com/home?someKey=true, you need to pass
//https://google.com/home.
//...
//UrlCheckThreat can either be MALWARE or PHISHING.
//Each category is fairly self-explanatory.
//The threat argument is a vararg, so you can pass one or both.
//...
//You can find your APP_ID under "App information" in your project's settings on the AppGallery Developer Console.
val task = client.urlCheck(url, "APP_ID", UrlCheckThreat.MALWARE, UrlCheckThreat.PHISHING)
task.addOnSuccessListener {
//API call succeeded.
if (it.urlCheckResponse.isEmpty()) {
//URL is safe, continue
} else {
//URL matches either MALWARE or PHISHING category or both. Notify user or refuse to visit
//as is appropriate.
//Get the first threat type. Will match one of the UrlCheckThreat values you pass to
//the urlCheck() method.
val type = it.urlCheckResponse[0].urlCheckResult
}
}
task.addOnFailureListener {
//A communication error occurred.
//If `it is ApiException`, you may be able to get more details about why
//the failure occurred.
}
}
initTask.addOnFailureListener {
//Initialization failed.
}
}
UserDetect
UserDetect is essentially a realtime Captcha service. If there are parts of your app that you don't want to be used by bots (i.e. a clicker game), you can trigger a detection request to determine if the user is a bot or a person.
This one is a bit more complicated to implement, as it requires that you use HMS' cloud API to make the final request (i.e. a web server).
An example implementation in Kotlin is shown below:
Code:
fun checkUser() {
val client = SafetyDetect.getClient(context)
val initTask = client.initUserDetect()
initTask.addOnSuccessListener {
//Initialization was successful
//You can find your APP_ID under "App information" in your project's settings on the AppGallery Developer Console.
val task = client.userDetection("APP_ID")
task.addOnSuccessListener {
val responseToken = it.responseToken
if (responseToken.isNotEmpty()) {
//Pass this token to your server, and have it call HMS' cloud API to do the actual verification.
}
}
task.addOnFailureListener {
//A communication error occurred.
//If `it is ApiException`, you may be able to get more details about why
//the failure occurred.
}
}
initTask.addOnFailureListener {
//Initialization failed.
}
}
WifiDetect
If your app relies on a secure WiFi connection, this API may be helpful to you. You can use it to check whether the user's WiFI connection is actually secure.
Here's a quick example stub in Kotlin:
Code:
fun checkWifi() {
val client = SafetyDetect.getClient(context)
val task = client.wifiDetectStatus
task.addOnSuccessListener {
//The status will either be 0, 1, or 2, depending on the WiFi network state.
//0 means WiFi is disconnected.
//1 means WiFi is secure.
//2 means WiFi is insecure.
val status = it.wifiDetectStatus
}
task.addOnFailureListener {
//A communication error occurred.
//If `it is ApiException`, you may be able to get more details about why
//the failure occurred.
}
}
Conclusion
That's all for the SafetyDetect SDK! If you're using HMS, or you're planning to use HMS, and you want to make sure your app is properly secured, the various included APIs are sure to be helpful.
You can find more details, including the full API reference for the Safety Detect SDK, on Huawei's developer website.
Have you ever wanted to be able to scan and create 13+ different types of barcodes from your app? Hopefully you have, otherwise I'm not sure why you're reading this. If you do, then Huawei has an SDK for you: Scan Kit.
Scan Kit allows you to scan and generate various different one-dimensional and two-dimensional barcodes with ease, and you don't even need a Huawei device to use it.
Interested? No? Well, get interested. Now? Good. Let's get started.
Preparation
First up, make sure you have a Huawei Developer Account. This process can take a couple days, and you'll need one to use this SDK, so be sure to start that as soon as possible. You can sign up at https://developer.huawei.com.
Next, you'll want to obtain the SHA-256 representation of your app's signing key. If you don't have a signing key yet, be sure to create one before continuing. To obtain your signing key's SHA-256, you'll need to use Keytool which is part of the JDK installation. Keytool is a command-line program. If you're on Windows, open CMD. If you're on Linux, open Terminal.
On Windows, you'll need to "cd" into the directory containing the Keytool executable. For example, if you have JDK 1.8 v231 installed, Keytool will be located at the following path:
Code:
C:\Program Files\Java\jdk1.8.0_231\bin\
Once you find the directory, "cd" into it:
Code:
C: #Make sure you're in the right drive
cd C:\Program Files\Java\jdk1.8.0_231\bin\
Next, you need to find the location of your keystore. Using Android's debug keystore as an example, where the Android SDK is hosted on the "E:" drive in Windows, the path will be as follows:
Code:
E:\AndroidSDK\.android\debug.keystore
(Keytool also supports JKS-format keystores.)
Now you're ready to run the command. On Windows, it'll look something like this:
Code:
keytool -list -v -keystore E:\AndroidSDK\.android\debug.keystore
On Linux, the command should be similar, just using UNIX-style paths instead.
Enter the keystore password, and the key name (if applicable), and you'll be presented with something similar to the following:
{
"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"
}
Make note of the SHA256 field.
SDK Setup
Now we're ready to add the Scan Kit SDK to your Android Studio project. Go to your Huawei Developer Console and click the HUAWEI AppGallery tile. Agree to the terms of use if prompted.
Click the "My projects" tile here. If you haven't already added your project to the AppGallery, add it now. You'll be asked for a project name. Make it something descriptive so you know what it's for.
Now, you should be on a screen that looks something like the following:
Click the "Add app" button. Here, you'll need to provide some details about your app, like its name and package name.
Once you click OK, some SDK setup instructions will be displayed. Follow them to get everything added to your project.
You'll also need to add one of the following to the "dependencies" section of your app-level build.gradle file:
Code:
implementation 'com.huawei.hms:scan:1.2.0.301'
implementation 'com.huawei.hms:scanplus:1.2.0.301'
The difference between these dependencies is fairly simple. The basic Scan Kit SDK is only about 0.8MB in size, while the Scan Kit Plus SDK is about 3.3MB. The basic SDK will function identically to the Plus SDK on Huawei devices. On non-Huawei devices, you'll lose the enhanced recognition capabilities with the basic SDK.
If your app has size restrictions, and you only need basic QR code recognition, then the basic SDK is the best choice. Otherwise, pick the Plus SDK.
If you ever need to come back to these instructions, you can always click the "Add SDK" button after "App information" on the "Project setting" page.
Now you should be back on the "Project setting" page. Find the "SHA-256 certificate fingerprint" field under "App information," click the "+" button, and paste your SHA-256.
Now, if you're using obfuscation in your app, you'll need to whitelist a few things for HMS to work properly.
For ProGuard:
Code:
-ignorewarnings
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
-keep class com.hianalytics.android.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}
For AndResGuard:
Code:
"R.string.hms*",
"R.string.agc*",
"R.string.connect_server_fail_prompt_toast",
"R.string.getting_message_fail_prompt_toast",
"R.string.no_available_network_prompt_toast",
"R.string.third_app_*",
"R.string.upsdk_*",
"R.layout.hms*",
"R.layout.upsdk_*",
"R.drawable.upsdk*",
"R.color.upsdk*",
"R.dimen.upsdk*",
"R.style.upsdk*
That's it! The Scan Kit SDK should now be available in your project.
Basic Usage
In order to properly use Scan Kit, you'll need to declare some permissions in your app:
XML:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
These are both dangerous-level permissions, so make sure you request access to them at runtime on Marshmallow and later.
You should also declare a couple required device features, to make sure distribution platforms can hide your app on incompatible devices:
XML:
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
Now that you've got the permissions and features declared, it's time to start scanning. There are four modes you can use: Default View, Customized View, Bitmap, and MultiProcessor.
Default View
The Default View is the quickest way to get set up and running. Scan Kit provides the UI and does all the scanning work for you. This mode is able to scan barcodes live through the camera viewfinder, or by scanning existing images.
The first thing you'll need to do to use this is to declare the Scan Kit's scanner Activity in your Manifest:
XML:
<activity android:name="com.huawei.hms.hmsscankit.ScanKitActivity" />
Next, simply call the appropriate method to start the Activity. This must be done from an Activity context, since it makes use of Android's onActivityResult() API.
Code:
//The options here are optional. You can simply pass null
//to the startScan() method below.
//This is useful if you're only looking to scan certain
//types of codes. Scan Kit currently supports 13. You can
//see the list here: https://developer.huawei.com/consumer/en/doc/HMSCore-Guides-V5/barcode-formats-supported-0000001050043981-V5
val options = HmsScanAnalyzerOptions.Creator()
.setHmsScanTypes(
HmsScan.QRCODE_SCAN_TYPE,
HmsScan.DATAMATRIX_SCAN_TYPE
)
.create()
ScanUtil.startScan(activity, REQUEST_CODE, options)
Now you just need to handle the result:
Code:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode != Activity.RESULT_OK || data == null) {
//Scanning wasn't successful. Nothing to handle.
return
}
if (requestCode == REQUEST_CODE) {
//Scan succeeded. Let's get the data.
val hmsScan = data.getParcelableExtra<HmsScan>(ScanUtil.RESULT)
if (hmsScan != null) {
//Handle appropriately.
}
}
}
We'll talk more about handling the result later.
Customized View
Customized View is similar to Default View in that Scan Kit will handle the scanning logic for you. The difference is that this mode lets you create your own UI. You're also limited to using the live viewfinder.
The following code should be placed inside your Activity's onCreate() method:
Code:
override fun onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_scan)
//A ViewGroup to hold the scanning View that HMS will create
val container = findViewById<FrameLayout>(R.id.scanning_container)
//The position/size of the scanning area inside the scanning
//View itself. This is optional.
val scanBounds = Rect()
//The scanning View itself.
val scanView = RemoteView.Builder()
.setContext(this)
.setBoundingBox(scanBounds) //optional
.setFormat(HmsScan.QR_SCAN_TYPE) //optional, accepts a vararg of formats
.build()
//Initialize the scanning View.
scanView.onCreate(savedInstanceState)
container.addView(scanView)
scanView.setOnResultCallback { result ->
//`result` is an Array<HmsScan>
//Handle accordingly.
}
}
We'll talk about how to handle the HmsScan object later.
In a real application, the "scanView" variable should be a global variable. It's lifecycle-aware, so it has all the lifecycle methods, which you should probably call:
Code:
override fun onStart() {
super.onStart()
scanView.onStart()
}
//etc
Bitmap
This mode is useful if you have a Bitmap and you want to decode it. You can get that Bitmap however you want. All that matters is that you have one.
The example below shows how to obtain a Bitmap either from a camera capture frame or from an existing image in internal storage, and how to pass that Bitmap to Scan Kit for processing.
Code:
val img = YuvImage(
//A byte array representation of an image.
data,
//Depends on your image type: https://developer.android.com/reference/android/graphics/ImageFormat
ImageFormat.NV21,
//The width of the image data.
width,
//The height of the image data.
height
)
val stream = ByteArrayOutputStream()
//Copy the data to an output stream.
img.compressToJpeg(
//Size of the JPEG, in a Rect representation.
Rect(0, 0, width, height),
//Quality.
100,
//Output stream.
stream
)
//Create a Bitmap
val bmp = BitmapFactory.decodeByteArray(
stream.asByteArray(),
0,
stream.asByteArray().size
)
//If you want to use a pre-existing image, just obtain
//a Bitmap for that. This example would be placed in
//onActivityResult() after using ACTION_GET_CONTENT for an image.
val bmp = MediaStore.Images.Media.getBitmap(contentResolver, data.data)
//Set up the options.
val options = HmsScanAnalyzerOptions.Creator()
//Scan types are optional.
.setHmsScanTypes(
HmsScan.QRCODE_SCAN_TYPE,
HmsScan.DATAMATRIX_SCAN_TYPE
)
//If you're retrieving a Bitmap from an existing photo,
//set this to `true`.
.setPhotoMode(false)
.create()
//Send the scanning request and get the result.
val scans: Array<HmsScan> = ScanUtil.decodeWithBitmap(context, bmp, options)
if (!scans.isNullOrEmpty()) {
//Scanning was successful.
//Check individual scanning results.
scans.forEach {
//Handle.
//If zoomValue != 1.0, make sure you update
//the focal length of your camera interface,
//if you're using a camera. See Huawei's
//documentation for details on this.
//https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/android-bitmap-camera-0000001050042014
val zoomValue = it.zoomValue
}
}
We'll go over how to handle the HmsScan later on.
MultiProccessor
The MultiProcessor mode supports both existing images and using a viewfinder. It can take image frames and analyze them using machine learning to simultaneously detect multiple barcodes, along with other objects, like faces.
There are two ways to implement this mode: synchronously, and asychronously.
Here's an example showing how to implement it synchronously.
Code:
//Create the options (optional).
val options = HmsScanAnalyzerOptions.Creator()
.setHmsScanTypes(
HmsScan.QRCODE_SCAN_TYPE,
HmsScan.DATAMATRIX_SCAN_TYPE
)
.create()
//Set up the barcode detector.
val barcodeDetector = HmsScanAnalyzer(options /* or null */)
//You'll need some sort of Bitmap reference.
val bmp = /* However you want to obtain it */
//Convert that Bitmap to an MLFrame.
val frame = MLFrame.fromBitmap(bmp)
//Analyze and handle result(s).
val results: SparseArray<HmsScan> = barcodeDetector.analyseFrame(frame)
results.forEach {
//Handle accordingly.
}
To analyze asynchronously, just change the method called on "barcodeDetector":
Code:
barcodeDetector.analyzInAsyn(frame)
.addOnSuccessListener { scans ->
//`scans` is a List<HmsScan>
scans?.forEach {
//Handle accordingly.
}
}
.addOnFailureListener { error ->
//Scanning failed. Check Exception.
}
Parsing Barcodes
It's finally time to talk about parsing the barcodes! Yay!
The HmsScan object has a bunch of methods you can use to retrieve information about barcodes scanned by each method.
Code:
val scan: HmsScan = /* some HmsScan instance */
//The value contained in the code. For instance,
//if it's a QR code for an SMS, this value will be
//something like: "smsto:1234567890:Hi!".
val originalValue = scan.originalValue
//The type of code. For example, SMS_FORM, URL_FORM,
//or WIFI_CONNTENT_INFO_FORM. You can find all the forms
//here: https://developer.huawei.com/consumer/en/doc/development/HMSCore-References-V5/scan-hms-scan4-0000001050167739-V5.
val scanTypeForm = scan.scanTypeForm
//If it's a call or SMS, you can retrieve the
//destination phone number. This will be something
//like "1234567890".
val destPhoneNumber = scan.destPhoneNumber
//If it's an SMS, you can retrieve the message
//content. This will be something like "Hi!".
val smsContent = scan.smsContent
There are plenty more methods in the HmsScan class to help you parse various barcodes. You can see them all in Huawei's API reference.
Barcode Generation
Finally, let's talk about how to make your own barcodes using Scan Kit. This example will show you how to make a QR code, although you should be able to create any of the formats supported by Scan Kit.
Code:
//The code's content.
val content = "Some Content"
//Can be any supported type.
val type = HmsScan.QRCODE_SCAN_TYPE
//Output dimensions.
val width = 400
val height = 400
//Create the options.
val options = HmsBuildBitmapOption.Creator()
//The background of the barcode image. White is the default.
.setBitmapBackgroundColor(Color.RED)
//The color of the barcode itself. Black is the default
.setBitmapColor(Color.BLUE)
//Margins around the barcode. 1 is the default.
.setBitmapMargin(3)
.create()
try {
//Build the output Bitmap.
val output = ScanUtil.buildBitmap(content, type, width, height, options)
//Save it to internal storage, upload it somewhere, etc.
} catch (e: WriterException) {
//Creation failed. This can happen if one of the arguments for `buildBitmap()` is invalid.
}
Conclusion
And that's it!
Scan Kit is a powerful SDK that doesn't even require a Huawei device to work. Hopefully, this guide helped you get up and running. For more details on implementation, along with the API reference, be sure to check out Huawei's full documentation.
The HMS Site Kit SDK is a handy set of APIs to help you implement location and address-based searching in your app with ease. If you want to target Huawei devices with your app, and you're looking for a simple way to find and show results to your user, you've come to the right place.
This guide will get you started with the Site Kit SDK, and give you some basic implementation examples. Let's get started.
Preparation
First up, make sure you have a Huawei Developer Account. This process can take a couple days, and you'll need one to use this SDK, so be sure to start that as soon as possible. You can sign up at https://developer.huawei.com.
Next, you'll want to obtain the SHA-256 representation of your app's signing key. If you don't have a signing key yet, be sure to create one before continuing. To obtain your signing key's SHA-256, you'll need to use Keytool which is part of the JDK installation. Keytool is a command-line program. If you're on Windows, open CMD. If you're on Linux, open Terminal.
On Windows, you'll need to "cd" into the directory containing the Keytool executable. For example, if you have JDK 1.8 v231 installed, Keytool will be located at the following path:
Code:
C:\Program Files\Java\jdk1.8.0_231\bin\
Once you find the directory, "cd" into it:
Code:
C: #Make sure you're in the right drive
cd C:\Program Files\Java\jdk1.8.0_231\bin\
Next, you need to find the location of your keystore. Using Android's debug keystore as an example, where the Android SDK is hosted on the "E:" drive in Windows, the path will be as follows:
Code:
E:\AndroidSDK\.android\debug.keystore
(Keytool also supports JKS-format keystores.)
Now you're ready to run the command. On Windows, it'll look something like this:
Code:
keytool -list -v -keystore E:\AndroidSDK\.android\debug.keystore
On Linux, the command should be similar, just using UNIX-style paths instead.
Enter the keystore password, and the key name (if applicable), and you'll be presented with something similar to the following:
{
"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"
}
Make note of the SHA256 field.
SDK Setup
Now we're ready to add the Site Kit SDK to your Android Studio project. Go to your Huawei Developer Console and click the HUAWEI AppGallery tile. Agree to the terms of use if prompted.
Click the "My projects" tile here. If you haven't already added your project to the AppGallery, add it now. You'll be asked for a project name. Make it something descriptive so you know what it's for.
Now, you should be on a screen that looks something like the following:
Click the "Add app" button. Here, you'll need to provide some details about your app, like its name and package name.
Once you click OK, some SDK setup instructions will be displayed. Follow them to get everything added to your project. You'll also need to add the following to the "dependencies" section of your app-level build.gradle file:
Code:
implementation 'com.huawei.hms:site:5.0.0.300'
If you ever need to come back to these instructions, you can always click the "Add SDK" button after "App information" on the "Project setting" page.
Now you should be back on the "Project setting" page. Find the "SHA-256 certificate fingerprint" field under "App information," click the "+" button, and paste your SHA-256.
Now, go to the Manage APIs tab on the "Project setting" page. Scroll down until you find "Site Kit" and make sure it's enabled.
Now, if you're using obfuscation in your app, you'll need to whitelist a few things for HMS to work properly.
For ProGuard:
Code:
-ignorewarnings
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
-keep class com.hianalytics.android.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}
For AndResGuard:
Code:
"R.string.hms*",
"R.string.agc*",
"R.string.connect_server_fail_prompt_toast",
"R.string.getting_message_fail_prompt_toast",
"R.string.no_available_network_prompt_toast",
"R.string.third_app_*",
"R.string.upsdk_*",
"R.layout.hms*",
"R.layout.upsdk_*",
"R.drawable.upsdk*",
"R.color.upsdk*",
"R.dimen.upsdk*",
"R.style.upsdk*"
That's it! The Site Kit SDK should now be available in your project.
Basic Usage
Huawei's Site Kit SDK gives you quite a few useful features.
There's Keyword Search, which lets the user type in a search query, along with other options, and see relevant results.
There's Nearby Place Search, which returns points of interest close to the user. There's a Place Details API, to let the user find out more about a specific place.
There's the Place Search Suggestion feature, which adds autofill-like search suggestions in real-time.
And finally, there's the Widget component, which implements Place Search Suggestion in a search bar for you.
We'll go over each feature one by one.
Keyword Search
Below is an example of how you might implement a keyword search.
Code:
//Create the search service. It's recommended you use an Activity
//Context, although it's not required.
//You can find your API key on the Project Setting page for your
//project in AppGallery Connect, under App Information.
val searchService = SearchServiceFactory.create(context, "API_KEY")
//Create a request. For this example, we're going to be
//using dummy inputs, but in a real app, these would
//be provided by the user.
val request = TextSearchRequest()
//This can be any keyword, like "McDonald's" or
//"Washington".
request.setQuery("London")
//Define a location (optional). This could be the user's
//current location, or some other area.
val location = Coordinate(48.893478, 2.334595)
request.setLocation(location)
//Set a radius in meters (optional). The default is 50,000.
location.setRadius(1000)
//Set the type of location (optional, but recommended).
//Values can be found in the HwLocationType class.
request.setHwPoiType(HwLocationType.ENTERTAINMENT_PLACE)
//Set the country code to where these results should be
//confined (optional). Uses the ISO-3166-1 alpha-2 standard.
request.setCountryCode("FR")
//Set the language for results to appear in (optional).
request.setLanguage("fr")
//Set the current page (from 1-60). Default is 1.
request.setPageIndex(1)
//Set how many results should appear per-page (from 1-20).
//Default is 20.
request.setPageSize(5)
//Create a result listener for handling search results.
val resultListener = object : SearchResultListener<TextSearchResponse>() {
override fun onSearchResult(result: TextSearchResponse?) {
//We've got results.
if (result == null || result.totalCount <= 0) {
//We actually don't have results. Return.
return
}
val sites: List<Site>? = result.sites
if (sites.isNullOrEmpty()) {
//Couldn't find any sites. Return.
return
}
//Handle results.
sites.forEach { site ->
val id = site.siteId
val name = site.name
}
}
override fun onSearchError(state: SearchStatus) {
//There was an error retrieving results.
val code = status.errorCode
val message = status.errorMessage
}
}
//Finally, initiate the search.
searchService.textSearch(request, resultListener)
Nearby Place Search
A Nearby Place Search is practically identical to a Keyword Search in terms of implementation. Simply replace the textSearch() call with a nearbySearch() call. Almost everything else is identical.
Code:
//Use this instead of `textSearch()`.
//One notable difference is that the default radius
//for a nearby search is 1,000 meters instead of 50,000.
searchService.nearbySearch(request, resultListener)
Place Details
Creating a Place Details request is similar to the previous two, although there are some differences in implementation. For one, you should know the site ID of the place whose details you're querying, which you can get using one of the above methods.
Code:
/Create the search service. It's recommended you use an Activity
//Context, although it's not required.
//You can find your API key on the Project Setting page for your
//project in AppGallery Connect, under App Information.
val searchService = SearchServiceFactory.create(context, "API_KEY")
//Create the details request.
val request = DetailSearchRequest()
//Set the site ID. You can retrieve this from a keyword or
//nearby place search result.
request.setSiteId("THE_SIDE_ID")
//Set the language (optional).
request.setLanguage("fr")
//Create a results listener.
val resultListener = object : SearchResultListener<DetailSearchResponse>() {
override fun onSearchResult(result: DetailSearchResponse?) {
//Detail search succeeded.
if (result == null) {
//Something weird happened. Return.
return
}
//Retrieve the site. Return if null.
val site = result.site ?: return
//Retrieve various details about the site and display
//for the user.
}
override fun onSearchError(status: SearchStatus) {
//There was an error retrieving results.
val code = status.errorCode
val message = status.errorMessage
}
}
//Initiate the request.
searchService.detailSearch(request, resultListener)
Place Search Suggestion
This feature is similar to the Keyword and Nearby Search features, except that it returns a limited set of results. It's more suitable for rapid-fire requests, such as real-time search suggestions.
Here's an example for how to implement it.
Code:
/Create the search service. It's recommended you use an Activity
//Context, although it's not required.
//You can find your API key on the Project Setting page for your
//project in AppGallery Connect, under App Information.
val searchService = SearchServiceFactory.create(context, "API_KEY")
//Create the request.
val request = QuerySuggestionRequest()
//Set the user's current query.
request.setQuery("Pari")
//Set a location (optional).
val location = Coordinate(48.893478, 2.334595)
request.setLocation(location)
//Set a radius in meters (optional) (from 1-50,000).
//Default is 50,000.
request.setRadius(50)
//Set the search country (optional).
request.setCountryCode("FR")
//Set the language results should appear in
//(optional).
request.setLanguage("fr")
//Set a specific POI type (optional). Should
//be a subset of the values found in LocationType.
request.setPoiTypes(LocationType.ADDRESS)
//Create a results listener.
val resultListener = object : SearchResultListener<QuerySuggestionResponse>() {
override fun onSearchResult(result: QuerySuggestionResponse?) {
if (result == null) {
//No results. Return.
return
}
val sites: List<Site>? = result.sites
if (sites.isNullOrEmpty()) {
//No sites. Return.
return
}
//Handle results.
sites.forEach { site ->
val id = site.sideId
val name = site.name
}
}
override fun onSearchError(status: SearchStatus) {
//There was an error retrieving results.
val code = status.errorCode
val message = status.errorMessage
}
}
//Initiate the search request.
searchServie.querySuggestion(request, resultListener)
Widget
The Site Kit can take care of search logic for you, including suggestions. Here's how.
The first thing you need to do is implement the Fragment in your layout.
XML:
<fragment
android:id="@+id/search_fragment"
android_name="com.huawei.hms.site.widget.SearchFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
You can also create a reference in code and use a FragmentManager to add and remove it as needed.
Next, you need to implement the search functionality.
Code:
//Get a reference to the Fragment. This example assumes it's
//in your layout XML.
val searchFragment = supportFragmentManager.findFragmentById(R.id.search_fragment) as SearchFragment
//Set the API key.
//You can find your API key on the Project Setting page for your
//project in AppGallery Connect, under App Information.
searchFragment.setApiKey("API_KEY")
//Set a selection listener.
searchFragment.setOnSiteSelectedListener(object : SiteSelectionListener() {
override fun onSiteSelected(site: Site) {
//The user has selected a site returned by HMS.
//Handle as applicable.
}
override fun onError(status: SearchStatus) {
//There was an error retrieving results.
val code = status.errorCode
val message = status.errorMessage
}
})
Conclusion
That's it! As you can probably see, HMS Site Kit makes it pretty easy to implement location searching in your app.
This is only for devices that come with HMS pre-installed, but it's certainly a useful set of tools. Be sure to check out Huawei's full documentation for more details.
Introduction
In this article, we will be learning how to integrate the Huawei Site kit and Cloud DB integrations in Android using Kotlin. Using AGC Cloud DB service, Service Providers from multiple cities can manage their data through CRUD (Create, Read, Update and Delete) operations. Using Site Kit user can search nearby stores and check stores details.
Development Overview
You need to install Android Studio and I assume that you have prior knowledge about the Android and Kotlin
Hardware Requirements
A computer (desktop or laptop) running Windows 10.
A Huawei phone (with the USB cable), which is used for debugging.
Software Requirements
Java JDK 1.7 or later
Android studio installed.
HMS Core (APK) 4.x or later
Integration of Site Kit
Site Kit provides place search services including keyword search, nearby place search, place detail search, and place search suggestion, helping your app provide convenient place-related services to attract more users and improve user loyalty.
Step 1: To integrate Site kit, need to add the below library:
Java:
implementation 'com.huawei.hms:site:5.0.2.300’
Step 2: How to get API Key?
Create an app in AppGallery Connect enter all necessary information.
Generate and configure the signing certificate fingerprint.
Add the AppGallery Connect plug-in and the Maven repository in the project-level build.gradle file. Configure the signature file in Android Studio.
For details, refer to Preparations for Integrating HUAWEI HMS Core.
After configure project, you can find API key in below 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"
}
Step 3: To initialize HMS Site kit:
Java:
searchService = SearchServiceFactory.create(this, Utils.getApiKey())
To fetch nearby stores based on user’s current location:
SearchServiceActivity.kt
Java:
intent.let {
val request = NearbySearchRequest().apply {
queryString=it.getStringExtra(AppConstants.REQUEST_QUERY).toString()
setQuery(queryString)
setLocation(
Coordinate(
it.getDoubleExtra(AppConstants.SERVICE_LAT_KEY, 0.0),
it.getDoubleExtra(AppConstants.SERVICE_LNG_KEY, 0.0)
)
)
}
imageString = it.getStringExtra(AppConstants.PROVIDER_IMAGE_KEY).toString()
searchService?.nearbySearch(request, searchResultListener)
}
Results
Note: For more details, refer Site kit integration procedure. Site kit- SDK integration
Integration of Cloud DB
In this scenario, we can learn about a database service that runs on a cloud and is accessible from anywhere. Find the following points for better understand:
How to use Cloud DB to develop applications?
How to read, write and query application data to Cloud DB?
This service provides the synergy database product that provides data synergy management capabilities between the device and the cloud, unified data models, and various data management APIs.
Cloud DB supplies us simply cloud database and our project work together successfully and we can take advantages of CRUD (Create, Read, Update and Delete) operations.
Prerequisites
To use the Cloud DB for build application service, you need to complete the following preparations:
You have registered an account on the AppGallery Connect console and passed real-name authentication.
You have created a project and application on the AppGallery Connect console.
You have enabled the Anonymous account authentication service for the application to use permissions of the authentication user.
You have installed Android Studio on the local host.
Enable Cloud DB Service
Before using the Cloud DB service, you need to enable it.
Log in to AppGallery Connect and click My Projects.
Select a project from the project list and click an app for which you need to enable the Cloud DB service.
In the navigation bar, choose Build > Cloud DB.
Click Enable now to enable the Cloud DB service.
Select the Data storage location.
After the service is initialized, the Cloud DB service is enabled successfully.
Adding and Exporting Object Types
The following example shows how to create object types on the AppGallery Connect console and export the object type file in the Java format for Android application development.
1. Log in to AppGallery Connect and click My projects.
2. Select a project from the project list and click an app for which you need to add an object type.
3. In the navigation bar, choose Build > Cloud DB.
4. Click Add to navigate to the object type creation page.
5. Set Object Type Name to LoginInfo, and click Next.
6. Click “+Add Field”, add the fields as per your requirements and click Next.
7. (Optional) Click “+Add Index”.
8. Add permissions as follows and click Next. (For Everyone, upsert and delete access is not allowed).
9. Click OK. Object types are created and displayed in the object type list.
The created object types are displayed in the object type list.
Repeat the above steps to create to create multiple table.
10. Click “Export” button
11. Set the format of the file to be exported to JAVA.
12. Set the Java file type to Android.
13. Enter the package name in the JAVA file.
The package name can contain only the following three types:\
Letters: A–Z or a–z, which are mandatory
Digits: 0–9
Special characters: underscore (_) and period (.)
15. Click Export. The file that contains all object types will be downloaded. Add the exported JAVA file in your project. The file that contains all object types in the version is exported to the local PC. The exported Java file will be added to the local development environment in subsequent steps.
Cloud DB Zone
You can create a Cloud DB zone on the AppGallery Connect console. Perform the following steps to set Cloud DB Zone Name.
1. Log in to AppGallery Connect and click My projects.
2. Select a project from the project list and click an app for which you need to add a Cloud DB zone.
3. In the navigation tree, choose Build > Cloud DB.
4. Click the Cloud DB Zones tab.
5. Click Add to go to the Cloud DB zone creation page.
6. Enter Your App Name in the Cloud DB Zone Name text box.
7. Click OK the created Cloud DB zones are displayed in the Cloud DB zone list.
Configuring the Development Environment
Add a Cloud DB SDK to the dependencies node in the build.gradle file in the Project/app directory.
Java:
implementation <strong>'com.huawei.agconnect:agconnect=database:1.2.3.301’</strong>
In the build.gradle file, set the compatibility mode of Java source code to JDK1.8.
Java:
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
Adding Object Type Files
During application development, you can directly add the JAVA files exported from the AppGallery Connect console to the local development environment, and use the createObjectType() method in the AGConnectCloudDB class to define and create object types. Then you do not need to create object types for local application development.
Add all exported files to the local development environment.
Initialize Cloud DB. Use the createObjectType() method in the AGConnectCloudDB class to define and create object types.
Initializing
After adding an object type file, you can use the Cloud DB to develop an application. When developing an application, you need to initialize AGConnectCloudDB, and create Cloud DB zone and object types.
Initialize AGConnectCloudDB in an application’s CloudDBZoneWrapper
Java:
public static void initAGConnectCloudDB(Context context) {
AGConnectCloudDB.initialize(context);
}
Obtain the AGConnectCloudDB instance and create object types.
Java:
mCloudDB = AGConnectCloudDB.getInstance();
mCloudDB.createObjectType(ObjectTypeInfoHelper.getObjectTypeInfo());
Create the Cloud DB zone configuration object and open the Cloud DB zone. Add the below code in CloudDBZoneWrapper class.
Java:
public void openCloudDBZoneV2() {
mConfig = new CloudDBZoneConfig(AppConstants.URBAN_HOME_SERVICES,
CloudDBZoneConfig.CloudDBZoneSyncProperty.CLOUDDBZONE_CLOUD_CACHE, CloudDBZoneConfig.CloudDBZoneAccessProperty.CLOUDDBZONE_PUBLIC);
mConfig.setPersistenceEnabled(true);
Task<CloudDBZone> openDBZoneTask = mCloudDB.openCloudDBZone2(mConfig, true);
openDBZoneTask.addOnSuccessListener(cloudDBZone -> {
Log.w(TAG, "open clouddbzone success");
mCloudDBZone = cloudDBZone;
// Add subscription after opening cloudDBZone success
mUiCallBack.onInitCloud();
addSubscription();
}).addOnFailureListener(e ->
Log.w(TAG, "open clouddbzone failed for”));
}
Writing Data
You can use the executeUpsert() API to write one object or a group of objects to the current Cloud DB zone.
Add the below code in CloudDBZoneWrapper class.
Java:
public void insertDbZoneInfo(T objectInfo) {
if (mCloudDBZone == null) {
Log.w(TAG, "CloudDBZone is null, try re-open it");
return;
}
Task<Integer> upsertTask = mCloudDBZone.executeUpsert(objectInfo);
upsertTask.addOnSuccessListener(cloudDBZoneResult -> {
mUiCallBack.onInsertSuccess(cloudDBZoneResult);
}).addOnFailureListener(e -> {
mUiCallBack.updateUiOnError("Insert table info failed");
});
}
Viewing Data
Data added on the application page will be stored on the cloud. After a listener for data changes is registered on the device, the device will be notified when there is any changes on the cloud, and the local data will be updated in time.
You can use the query condition together with the subscribeSnapshot() method to specify an object to be listened on. When the data of the object is changed, the device will be notified and the original data stored on the cloud will be synchronized to the device based on the data changes information obtained by snapshots.
Add the below code in CloudDBZoneWrapper class.
Java:
private OnSnapshotListener<T> mSnapshotListener = (cloudDBZoneSnapshot, e) -> {
if (e != null) {
Log.w(TAG, "onSnapshot" );
return;
}
CloudDBZoneObjectList<T> snapshotObjects = cloudDBZoneSnapshot.getSnapshotObjects();
List<T> dbZoneList = new ArrayList<>();
try {
if (snapshotObjects != null) {
while (snapshotObjects.hasNext()) {
T objectInfo = snapshotObjects.next();
dbZoneList.add(objectInfo);
}
}
mUiCallBack.onSubscribe(dbZoneList);
} catch (AGConnectCloudDBException snapshotException) {
Log.w(TAG, "onSnapshot:(getObject)");
} finally {
cloudDBZoneSnapshot.release();
}
};
Querying Data
The executeQuery(), addOnSuccessListener(), and addOnFailureListener() methods are used together to query data in asynchronous mode.
Add the below code in CloudDBZoneWrapper class.
Java:
public void queryAllData(CloudDBZoneQuery<T> query) {
if (mCloudDBZone == null) {
Log.w(TAG, "CloudDBZone is null, try re-open it");
return;
}
Task<CloudDBZoneSnapshot<T>> queryTask = mCloudDBZone.executeQuery(query,
CloudDBZoneQuery.CloudDBZoneQueryPolicy.POLICY_QUERY_FROM_CLOUD_ONLY);
queryTask.addOnSuccessListener(new OnSuccessListener<CloudDBZoneSnapshot<T>>() {
@Override
public void onSuccess(CloudDBZoneSnapshot<T> snapshot) {
processQueryResult(snapshot);
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
mUiCallBack.updateUiOnError("Query failed");
}
});
}
Deleting Data
You can use the executeDelete() method to delete a single object or a group of objects. When deleting data, Cloud DB will delete the corresponding data based on the input object primary key and does not check whether other attributes of the object are consistent with the stored data. When a group of objects are deleted, the deletion operation is atomic. That is, objects in the list are either all deleted successfully or all fail to be deleted.
Add the below code in CloudDBZoneWrapper class.
Java:
public void deleteTableData(List<T> tableObject) {
if (mCloudDBZone == null) {
Log.w(TAG, "CloudDBZone is null, try re-open it");
return;
}
Task<Integer> deleteTask = mCloudDBZone.executeDelete(tableObject);
if (deleteTask.getException() != null) {
mUiCallBack.updateUiOnError("Delete service type table failed");
return;
}
mUiCallBack.onDelete(tableObject);
}
}
Editing Data
You can use the editService() method to edit professional’s details.
Add the below code in ManageServiceActivity.kt class.
Java:
override fun editService(listObject: ServiceType) {
val intent = Intent(this, AddServiceActivity::class.java)
intent.apply {
putExtra(AppConstants.CATEGORY_NAME, listObject.cat_name)
putExtra(AppConstants.PROVIDER_PH_NUM, listObject.phone_number.toString())
putExtra(AppConstants.PROVIDER_MAIL_ID, listObject.email_id)
putExtra(AppConstants.PROVIDER_COUNTRY, listObject.country)
putExtra(AppConstants.PROVIDER_ID, listObject.id)
putExtra(AppConstants.PROVIDER_NAME, listObject.service_provider_name)
putExtra(AppConstants.PROVIDER_CITY, listObject.city)
putExtra(AppConstants.PROVIDER_STATE, listObject.state)
}
startActivity(intent)
}
Results
Tips and Tricks
Always use the latest version of the library.
Always provide proper Roles to user in Object Types.
Note: For more details, please refer Cloud Db service integration documentation, Cloud DB- Introduction
Conclusion
By using Cloud DB you can connect with Database without the need of APIs. You can perform the CRUD operations and also can restrict user access for the tables. Easy to connect with the application. Also you can search nearby service (plumber, electrician, painter etc) using site kit like as etc.
Site Kit to fetch nearby stores.
Cloud DB service to add, delete and edit professional’s details.
References
Site Kit
Cloud DB- Applying for Cloud BD
Cloud DB- Introduction
Read In Forum
Does CloudDB supports offline operations ?
What is the max size of data to be stored on Cloud DB?
Cloud DB is a device-cloud synergy database product that provides data synergy management capabilities between the device and cloud, unified data models, and various data management APIs. In addition to ensuring data availability, reliability, consistency, and security, Cloud DB enables seamless data synchronization between the device and cloud, and supports offline app operations, helping you quickly develop device-cloud and multi-device synergy apps. For more information about Cloud DB, please click here.
Cloud DB can be easily integrated into apps through its SDK and APIs, ensuring security and reliability. During integration, the SDK and APIs ease your workload by performing server setup, deployment, and O&M for you.
Now, let’s first take a look at how to quickly integrate Cloud DB in Android apps. You only need to perform the following three steps:
1. Create an object type and a Cloud DB zone.
2. Export the object type and perform account authentication.
3. Integrate the Cloud DB SDK into your Android project and call APIs to add, delete, modify, or query data.
1. Creating an Object Type and a Cloud DB ZoneCloud DB is still in beta, so you’ll need to send an email to apply for the service. For more details on how to do so, please read the following documentation.
1.1. What Is an Object Type?Simply put, each object type corresponds to a table used to store data in your database. Think of it as creating an Excel file to store data, whereby each sheet in the Excel file is equivalent to an object type in Cloud DB.
1.2. What Is a Cloud DB Zone?A Cloud DB zone is an independent data storage zone. Multiple Cloud DB zones are independent of each other. Going back to the Excel file analogy, imagine that you’re a teacher responsible for multiple classes, and you record the scores of students in each class in an Excel file. Each Excel file contains a student information sheet and a score sheet that are independent of each other. A Cloud DB zone is akin to an Excel file in this analogy.
1.3. Creating an Object TypeBefore you start, apply for and enable Cloud DB by performing the following:
1. Sign in to AppGallery Connect and click My projects. Select your project and app. Go to Build > Cloud DB, click the ObjectTypes tab, and create an object type.
{
"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. Create an object type named StudentInfo. Please remember to set the primary key and select the upsert and delete permissions for the Authenticated user.
1.4. Creating a Cloud DB ZoneOn the Cloud DB Zones tab page, click Add, enter the name of the Cloud DB zone, and click OK.
Before You StartWhen using Cloud DB, you need to export the object type first.
You need to export the object type created in the previous step to your local Android project. This synchronizes data between your Android project and Cloud DB.
Remember to place the exported object type in your Android project. In the example below, I placed the object type in the model directory.
Integrating Cloud DB in Your Android Project1. Integrating the Cloud DB SDK1. In AppGallery Connect, click My projects, and click a project card. Go to Project settings > General information, and download the agconnect-services.json file in the App information area. Then, place the JSON file under the app directory in your Android project.
2.Configure the project-level build.gradle file.
XML:
buildscript {
repositories {
google()
jcenter()
maven {url 'https://developer.huawei.com/repo/'}
}
dependencies {
classpath 'com.android.tools.build:gradle:4.0.1'
classpath 'com.huawei.agconnect:agcp:1.4.2.301'
}
}
allprojects {
repositories {
google()
jcenter()
maven {url 'https://developer.huawei.com/repo/'}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
3. Configure the app-level build.gradle file.
XML:
apply plugin: 'com.android.application'
apply plugin: 'com.huawei.agconnect'
...
android {
......
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
}
dependencies {
...
implementation 'com.huawei.agconnect:agconnect-auth:1.4.2.300' // Auth Service of AppGallery Connect, for account authentication.
implementation 'com.huawei.agconnect:agconnect-database:1.2.3.301' // Cloud DB SDK.
}
1.1 Preparations
Cloud DB places operation restrictions on users. Only authenticated users can add, delete, and modify data. Therefore, you’ll need to integrate Auth Service first.
Enable Auth Service in AppGallery Connect. Using anonymous account authentication as an example, click My projects, click a project card, and go to Build > Auth Service to enable it.
Sample code for enabling anonymous account authentication:
Java:
AGConnectAuth.getInstance().signInAnonymously().addOnSuccessListener(new OnSuccessListener<SignInResult>() {
@Override
public void onSuccess(SignInResult signInResult) {
// onSuccess
AGConnectUser user = signInResult.getUser();
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(Exception e) {
// onFail
}
});
2. Completing InitializationThe initialization consists of three parts: initializing Cloud DB, creating an object type, and creating and opening a Cloud DB zone.
1. Define required parameters in onCreate:
Java:
private AGConnectCloudDB mCloudDB;
private CloudDBZoneConfig mConfig;
private CloudDBZone mCloudDBZone;
2.Initialize AGConnectCloudDB.
Java:
AGConnectCloudDB.initialize(this);
3.Obtain an AGConnectCloudDB instance and create an object type.
Java:
mCloudDB = AGConnectCloudDB.getInstance();
try {
mCloudDB.createObjectType(ObjectTypeInfoHelper.getObjectTypeInfo());
} catch (AGConnectCloudDBException e) {
Log.e("CloudDB", "createObjectType Failed " + e.getMessage());
}
4. Create and open a Cloud DB zone.
Java:
Config = new CloudDBZoneConfig("classs1",
CloudDBZoneConfig.CloudDBZoneSyncProperty.CLOUDDBZONE_CLOUD_CACHE,
CloudDBZoneConfig.CloudDBZoneAccessProperty.CLOUDDBZONE_PUBLIC);
mConfig.setPersistenceEnabled(true);
try {
CloudDBZone = mCloudDB.openCloudDBZone(mConfig, true);
} catch (AGConnectCloudDBException e) {
Log.e("CloudDB", "openCloudDBZone failed: " + e.getMessage());
}
Note that you can also use the asynchronous openCloudDBZone2 method. The detailed operations are not described here. For details, please refer to:
https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-Guides/agc-clouddb-get-started#h1-1594008398022
3. Using Cloud DB FunctionsOnce you have completed authentication, you can perform related operations on Cloud DB. The following uses the query operation as an example:
1. In AppGallery Connect, insert two records — test1 and test2 — for testing.
2. Go back to your Android project and call executeQuery to query all data.
Java:
Task<CloudDBZoneSnapshot<StudentInfo>> queryTask = mCloudDBZone.executeQuery(
CloudDBZoneQuery.where(StudentInfo.class),
CloudDBZoneQuery.CloudDBZoneQueryPolicy.POLICY_QUERY_FROM_CLOUD_ONLY);
queryTask.addOnSuccessListener(new OnSuccessListener<CloudDBZoneSnapshot<StudentInfo>>() {
@Override
public void onSuccess(CloudDBZoneSnapshot<StudentInfo> snapshot) {
//
CloudDBZoneObjectList<StudentInfo> InfoCursor = snapshot.getSnapshotObjects();
ArrayList<StudentInfo> infoList = new ArrayList<>();
StudentInfo studentInfo = new StudentInfo();
try {
while (InfoCursor.hasNext()) {
studentInfo = InfoCursor.next();
infoList.add(studentInfo);
}
Log.i("CloudDB", "query success: " + JSONArray.toJSONString(studentInfo));
} catch (AGConnectCloudDBException e) {
Log.e("CloudDB", "query failed: " + e.getMessage());
}
snapshot.release();
}
});
3. Then, you can view the corresponding query data in Logcat.
4. You can refer to the configuration guide and API reference to learn more about the add, delete, and modify operations:
Configuration guide:
https://developer.huawei.com/consum...allery-connect-Guides/agc-clouddb-insert-data
API reference:
https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-References/clouddb
SummaryYou can use Cloud DB after performing just three easy steps:
1. Create an object type and a Cloud DB zone.
2. Export the object type to an Android project.
3. Integrate the SDK into the Android project and call related APIs.
Once you have completed these steps, you will have integrated a database system into your app, without having to perform any setup or deployment operations. Currently, Cloud DB is still free to use.
Cloud DB links:
Development guide:
https://developer.huawei.com/consum...llery-connect-Guides/agc-clouddb-introduction
API reference:
https://developer.huawei.com/consumer/en/doc/development/AppGallery-connect-References/clouddb
Demo:
https://github.com/AppGalleryConnect/agc-demos/tree/main/Android/clouddb-java