Introduction
In this article, we will learn how to implement Huawei Safety detect kit in to mobile applications. Mobile devices have become more popular than laptops. Now a days users engage in nearly all activities on mobile devices, right from watching the news, checking emails, online shopping, doing bank transactions. Through these apps, business can gather usable information, which can help business to take precise decisions for better services.
{
"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"
}
What is Huawei Safety Detect Service?
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.
1. SysIntegrity API: Checks whether the device running your app is secure, for example, whether it is rooted.
2. AppsCheck API: Checks for malicious apps and provides you with a list of malicious apps.
3. URLCheck API: Determines the threat type of a specific URL.
4. UserDetect API: Checks whether your app is interacting with a fake user.
5. WifiDetect API: Checks whether the Wi-Fi to be connected is secure.
Why Security is required for Apps
Mobile app security is a measure to secure application from threats like malware and other digital frauds that risk critical personal and financial information from hackers to avoid all of these we need to integrate the safety detect.
What are all the restrictions exists?
Currently two restrictions are there WifiDetect and UserDetect.
1. WifiDetect function available only in Chinese mainland.
2. UserDetect function not available in Chinese mainland.
Advantages
1. Provides a Trusted Execution Environment (TEE) to check system integrity.
2. Makes building security into your app easy with a rapid integration wizard.
3. Checks security for a diversity of apps: e-commerce, finance, multimedia, and news.
Requirements
1. Any operating system(i.e. MacOS, Linux and Windows)
2. Any IDE with Flutter SDK installed (i.e. IntelliJ, Android Studio and VsCode etc.)
3. A little knowledge of Dart and Flutter.
4. A Brain to think
Setting up the project
1. Before start creating application we have to make sure we connect our project to AppGallery. For more information check this link
2. After that follow the URL for cross-platform plugins. Download required plugins.
3. Enable the Safety Detect in the Manage API section and add the plugin.
4. After completing all the above steps, you need to add the required kits’ Flutter plugins as dependencies to pubspec.yaml file. You can find all the plugins in pub.dev with the latest versions.
Code:
huawei_safetydetect:
path: ../huawei_safetydetect/
After adding them, run flutter pub get command. Now all the plugins are ready to use.
Note: Set multiDexEnabled to true in the android/app directory, so the app will not crash.
Why we need SysIntegrity API and How to Use?
The SysIntegrity API is called to check the system integrity of a device. If the device is not safe, appropriate measures are taken.
Before implementing this API we need to check device have latest version of HMS core must be installed on users device.
Obtain a nonce value will be used to determine whether the returned result corresponds to the request and did not encounter and replay attacks. The nonce value must contain a minimum of 16 bytes and is intended to be used only once. Request for the AppId as input parameters.
Code:
getAppId() async {
String appID = await SafetyDetect.getAppID;
setState(() {
appId = appID;
});
}
checkSysIntegrity() async {
Random secureRandom = Random.secure();
List randomIntegers = List<int>();
for (var i = 0; i < 24; i++) {
randomIntegers.add(secureRandom.nextInt(255));
}
Uint8List nonce = Uint8List.fromList(randomIntegers);
try {
String result = await SafetyDetect.sysIntegrity(nonce, appId);
List<String> jwsSplit = result.split(".");
String decodedText = utf8.decode(base64Url.decode(jwsSplit[1]));
showToast("SysIntegrityCheck result is: $decodedText");
} on PlatformException catch (e) {
showToast("Error occured while getting SysIntegrityResult. Error is : $e");
}
}
}
Why we need AppsCheck API and How to Use?
You can obtain all malicious applications and evaluate whether you can restrict the behaviour of your application based on the risk.
You can directly call the getMaliciousAppsList() method to get all the malicious apps.
Code:
void getMaliciousAppsList() async {
List<MaliciousAppData> maliciousApps = List();
maliciousApps = await SafetyDetect.getMaliciousAppsList();
setState(() {
showToast("malicious apps: ${maliciousApps.toString()}");
});
}
In the return from task, you will get a list of malicious applications. You can find out the package name, SHA256 value and category of an application in this list.
Why we need User Detect API and How to Use?
This API can help your app prevent batch registration, credential stuffing attacks, activity bonus hunting, and content crawling. If a user is a suspicious one or risky one, a verification code is sent to the user for secondary verification. 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 MainPage.
Code:
void _signInHuawei() async {
final helper = new HmsAuthParamHelper();
helper
..setAccessToken()
..setIdToken()
..setProfile()
..setEmail()
..setAuthorizationCode();
try {
HmsAuthHuaweiId authHuaweiId =
await HmsAuthService.signIn(authParamHelper: helper);
StorageUtil.putString("Token", authHuaweiId.accessToken);
} on Exception catch (e) {}
}
userDetection() async {
try {
String token = await SafetyDetect.userDetection(appId);
print("User verification succeded, user token: $token");
if(token!=null){
userDetection();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomePageScreen()),
);
}
} on PlatformException catch (e) {
print(
"Error occurred: " + e.code + ":" + SafetyDetectStatusCodes[e.code]);
}
}
Why we need URLCheck API and How to Use?
You can determine the dangerous urls using URL Check API. Currently UrlSafety API provide determinate MALWARE and PHISHING threats. When you visit a URL, this API checks whether the URL is a malicious one. If so, you can evaluate the risk and alert the user about the risk or block the URL.
Code:
InkWell(
onTap: () {
loadUrl();
},
child: Text(
'Visit: $url',
style:
TextStyle(color: textColor),
))
void loadUrl() async {
Future.delayed(const Duration(seconds: 5), () async {
urlCheck();
});
}
void urlCheck() async {
List<UrlThreatType> threatTypes = [
UrlThreatType.malware,
UrlThreatType.phishing
];
List<UrlCheckThreat> urlCheckResults =
await SafetyDetect.urlCheck(url, appId, threatTypes);
if (urlCheckResults.length == 0) {
showToast("No threat is detected for the URL");
} else {
urlCheckResults.forEach((element) {
print("${element.getUrlThreatType} is detected on the URL");
});
}
}
Why we need WifiDetect API and How to Use?
This API checks characteristics of the Wi-Fi and router to be connected, analyzes the Wi-Fi information, and returns the Wi-Fi detection results after classification, helping you prevent possible attacks to your app from malicious Wi-Fi. If attacks are detected app can interrupt the user operation or it will asks user permission.
Code:
@override
void initState() {
getWifiDetectStatus();
super.initState();
}
getWifiDetectStatus() async {
try {
WifiDetectResponse wifiDetectStatus =
await SafetyDetect.getWifiDetectStatus();
ApplicationUtils.displayToast(
'Wifi detect status is: ${wifiDetectStatus.getWifiDetectType.toString()}');
} on PlatformException catch (e) {
if (e.code.toString() == "19003") {
ApplicationUtils.displayToast(' The WifiDetect API is unavailable in this region');
}
}
}
Note: Currently this API supports Chinese mainland.
Demo
Tips & Tricks
1. Download latest HMS Flutter plugin.
2. Set minSDK version to 19 or later.
3. Do not forget to click pug get after adding dependencies.
4. Latest HMS Core APK is required.
Conclusion
These were some of the best practices that a mobile app developer must follow in order to have a fully secure and difficult-to-crack application.
In the near future, security will act as one of the differentiating and competing innovations in the app world, with customers preferring secure apps to maintain the privacy of their data over other mobile applications.
Thanks for reading! If you enjoyed this story, please click the Like button and Follow. Feel free to leave a Comment below.
Reference
Safety detect Kit URL
Checkout in forum
Related
More information like this, you can visit HUAWEI Developer Forum
Original link: https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0201326975480310022&fid=0101246461018590361
Hello everyone , in this article we’re going to take a look at the Huawei Health Kit features so we can easily put these features to our apps.
Health app industry have shown an important increase in recent years.The software and healthcare industry are working together to find the latest technology products for the needs of patients and families.Huawei offers high technology service for the health and fitness app ecosystem with HealthKit and HiHealthKit service.Huawei and third-party partner capabilities track and customize all aspects of better living.
Data storage : Provides a platform for users to store their fitness and health data.
Data openness : Provides a wide range of APIs for writing and reading speed, positioning, blood sugar level, and other data.
Data interaction : Enables you and your users to agree on data access, guaranteeing proper use and security of personal data.
HealthKit:
https://developer.huawei.com/consumer/en/hms/huawei-healthkit
HiHealth:
https://developer.huawei.com/consumer/en/hms/huawei-healthkit
We will examine the differences between HealthKit and HiHealth in our next articles.I created a sample app which I’ve open-sourced on GitHub for enthusiasts who want to use this service.
https://github.com/tualdev/hms-health-kit-demo
Setting up the Health Kit
You’ll need to do setup before you can use the Health Kit.You can follow the official documentation on how to prepare app and enable Health Kit on App Gallery Connect.
Also you can follow this blog post to integrate your apps with Huawei HMS Core:
https://medium.com/huawei-developers/android-integrating-your-apps-with-huawei-hms-core-1f1e2a090e98
I’ll show you how to implement Data Controller features in this article for your android projects.Let’s get started!
Add the required dependencies to the build.gradle file under app folder.We need some dependencies.
Code:
implementation 'com.huawei.hms:hwid:4.0.1.300'
implementation 'com.huawei.agconnect:agconnect-core:1.3.1.300'
implementation 'com.huawei.agconnect:agconnect-auth:1.3.1.300'
implementation 'com.huawei.hms:hihealth-base:5.0.0.300'
Add the required permissions to the AndroidManifest.xml file under app/src/main folder.
Code:
<uses-permission android:name="android.permission.INTERNET" />
You need to give some permissions after applying for HealthKit in service cards area.The applied permissions will be displayed on the user authorization page.
{
"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"
}
Let’s continue by coding Data Controller functionalities in our project.
Sign-in before using Data Controller
Firstly, we need to configure Huawei ID sign in.After that, we will start sign intent while using startActivityForResult method.We added also some scopes to apply for. The following only shows an example. You need to add scopes according to your specific needs.
Code:
huaweiIdAuthParamsHelper = HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM)
val scopeList = listOf(
Scope(HwIDConstant.SCOPE.SCOPE_ACCOUNT_EMAIL),
Scope(HwIDConstant.SCOPE.ACCOUNT_BASEPROFILE),
Scope(Scopes.HEALTHKIT_STEP_BOTH),
Scope(Scopes.HEALTHKIT_HEIGHTWEIGHT_BOTH),
Scope(Scopes.HEALTHKIT_HEARTRATE_BOTH)
)
huaweiIdAuthParamsHelper.setScopeList(scopeList)
authParams = huaweiIdAuthParamsHelper.setAccessToken().createParams()
authService = HuaweiIdAuthManager.getService(this, authParams)
HEALTHKIT_STEP_BOTH → View and save step counts in HUAWEI Health Kit.
HEALTHKIT_HEIGHTWEIGHT_BOTH → View and save height and weight in HUAWEI Health Kit.
HEALTHKIT_HEARTRATE_BOTH → View and save the heart rate data in HUAWEI Health Kit.
For details about the mapping between scopes and permissions, see Scope in the API reference.After successfully sign process , we can move to crud and other operations. We are able to call ten methods in DataController to perform operations on the fitness and health data.The methods include:
insert: inserts data.
delete: deletes data.
update: updates data.
read: reads data.
readTodaySummation: queries the summarized data of the current day.
readTodaySummationFromDevice: queries the summarized data of the local device of the current day.
registerModifyDataMonitor: registers a listener for data updates.
unregisterModifyDataMonitor: unregisters a listener for data updates.
syncAll: syncs data between the device and cloud.
clearAll: clears data of the app from the device and cloud.
We need to create the data controller object before starting operations.
Code:
val hiHealthOptions = HiHealthOptions.builder()
.addDataType(DataType.DT_CONTINUOUS_STEPS_DELTA, HiHealthOptions.ACCESS_READ)
.addDataType(DataType.DT_CONTINUOUS_STEPS_DELTA, HiHealthOptions.ACCESS_WRITE)
.addDataType(DataType.DT_INSTANTANEOUS_HEIGHT, HiHealthOptions.ACCESS_READ)
.addDataType(DataType.DT_INSTANTANEOUS_HEIGHT, HiHealthOptions.ACCESS_WRITE)
.addDataType(DataType.DT_INSTANTANEOUS_BODY_WEIGHT, HiHealthOptions.ACCESS_READ)
.addDataType(DataType.DT_INSTANTANEOUS_BODY_WEIGHT, HiHealthOptions.ACCESS_WRITE)
.build()
val signInHuaweiId = HuaweiIdAuthManager.getExtendedAuthResult(hiHealthOptions)
dataController = HuaweiHiHealth.getDataController(this, signInHuaweiId)
Inserting Data
We build a DataCollector object to insert body weight.
Code:
val dataCollector: DataCollector = DataCollector.Builder().setPackageName(this)
.setDataType(DataType.DT_INSTANTANEOUS_BODY_WEIGHT)
.setDataStreamName("BODY_WEIGHT_DELTA")
.setDataGenerateType(DataCollector.DATA_TYPE_RAW)
.build()
We will create a sampling dataset based on the data collector.
Code:
val sampleSet = SampleSet.create(dataCollector)
We will create the start time, end time, and weight value for a DT_INSTANTANEOUS_BODY_WEIGHT sampling point.The weight value must be in float format.
Code:
val dateFormat = SimpleDateFormat("yyyy-MM-dd hh:mm:ss", Locale.getDefault())val currentDate = dateFormat.format(Date())val startDate: Date = dateFormat.parse(currentDate)val endDate: Date = dateFormat.parse(currentDate)val samplePoint = sampleSet.createSamplePoint().setTimeInterval(startDate.time, endDate.time, TimeUnit.MILLISECONDS)samplePoint.getFieldValue(Field.FIELD_BODY_WEIGHT).setFloatValue(weight)
sampleSet.addSample(samplePoint)
And in this time, we need to call the data controller to insert the sampling dataset into the Health platform.
Code:
val insertTask: Task = dataController.insert(sampleSet)
insertTask.addOnSuccessListener {
Log.i("HomeFragment","Success insert a SampleSet into HMS core")
showSampleData(sampleSet, "Insert Weight")
}.addOnFailureListener { e ->
Toast.makeText(this, e.message.toString(), Toast.LENGTH_LONG).show()
}
If you examine the showSampleData function, you can see how the added data was reached.
Code:
private fun showSampleData(sampleSet: SampleSet, desc: String) {
val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
for (samplePoint in sampleSet.samplePoints) {
Log.i("HomeFragment","Sample point type: " + samplePoint.dataType.name)
Log.i("HomeFragment", "Start: " + dateFormat.format(Date(samplePoint.getStartTime(TimeUnit.MILLISECONDS))))
Log.i("HomeFragment", "End: " + dateFormat.format(Date(samplePoint.getEndTime(TimeUnit.MILLISECONDS))))
for (field in samplePoint.dataType.fields) {
Log.i("HomeFragment", "Field: " + field.name + " Value: " + samplePoint.getFieldValue(field))
Toast.makeText(this, desc + samplePoint.getFieldValue(field), Toast.LENGTH_LONG).show()
}
}
}
Deleting Data
We will build a DataCollector object for data deletion.
Code:
val dataCollector: DataCollector = DataCollector.Builder().setPackageName(this)
.setDataType(DataType.DT_INSTANTANEOUS_BODY_WEIGHT)
.setDataStreamName("BODY_WEIGHT_DELTA")
.setDataGenerateType(DataCollector.DATA_TYPE_RAW)
.build()
After creating data collector object, we need to build the time range for the deletion: start time and end time.
Code:
val dateFormat = SimpleDateFormat("yyyy-MM-dd hh:mm:ss", Locale.getDefault())
val startDate: Date = dateFormat.parse(startTimeEditText.text.toString())
val endDate: Date = dateFormat.parse(endTimeEditText.text.toString())
We build a parameter object as the conditions for the deletion while using DeleteOptions.So, the data in this time interval will be deleted.Also note that: Only historical data that has been inserted by the current app can be deleted from the Health platform.
Code:
val deleteOptions = DeleteOptions.Builder()
.addDataCollector(dataCollector)
.setTimeInterval(startDate.time, endDate.time, TimeUnit.MILLISECONDS)
.build()
And as last step, we use the specified condition deletion object to call the data controller to delete the sampling dataset.
Calling the data controller to delete the sampling dataset is an asynchronous operation. Therefore, a listener needs to be registered to monitor whether the data deletion is successful or not.
Code:
val deleteTask = dataController.delete(deleteOptions)
deleteTask.addOnSuccessListener {
Log.i("HomeFragment","Success delete steps data")
Toast.makeText([email protected], "Delete success", Toast.LENGTH_LONG).show()
}.addOnFailureListener {
Log.v(TAG, it.message.toString())
}
Updating Data
We will build a DataCollector object for data update.
This is not the end. For full content, you can visit https://forums.developer.huawei.com/forumPortal/en/home
What is the difference between Huawei Health kit and Hihealth kit ?
Hello. Is there a way to correct data in the Huawei Health database?. For instance remove steps from a certain date?. Thank you!
Introduction
In this article, I will talk about that how Flutter project integrates Huawei kits, and learn how to use them in your Flutter projects. Apps are tested many times before they released, but still crashes are there. There is a Huawei Crash Service to minimize these risks. Learning app which highlights recommended courses and Topic based courses, here I will cover below kits.
1. IAP kit
2. Crash Service
Requirements
1. Any operating system (i.e. MacOS, Linux and Windows).
2. Any IDE with Flutter SDK installed (i.e. IntelliJ, Android Studio and VsCode etc.).
3. A little knowledge of Dart and Flutter.
4. Minimum API Level 24 is required.
5. Required EMUI 5.0 and later version devices.
Setting up the Project
1. First create a developer account in AppGallery Connect. After create your developer account, you can create a new project and new app. For more information, click here
2. Generating a Signing certificate fingerprint, follow the command
Code:
keytool -genkey -keystore <application_project_dir>\android\app\<signing_certificate_fingerprint_filename>.jks -storepass <store_password> -alias <alias> -keypass <key_password> -keysize 2048 -keyalg RSA -validity 36500
3. The above command creates the keystore file in appdir/android/app.
4. Now we need to obtain the SHA256 key. Follow the command
Code:
keytool -list -v -keystore <application_project_dir>\android\app\<signing_certificate_fingerprint_filename>.jks
5. Now you need to apply for merchant service and enable IAP. To enable Merchant Service, Choose My Projects > Manage APIs > In-App Purchases. You will be asked to apply for Merchant Service. Here, you’ll need to enter your bank information and go through a review process. This review process can take up to 2 days.
{
"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"
}
6. Once Merchant service activated, Navigate to Earning > In-App Purchases if this is the first time, then you need to sign the agreement.
7. After the configuration is successful, the page displays the public key used for subsequent payment signature verification and a parameter for configuring the subscription notification URL.
8. We need Sandbox account in order to test the IAP. Navigate to App Gallery > Users and Permissions > Sandbox >Test account.
9. We have to enable Analytics to use Crash Service. Navigate to App Gallery > Huawei Analytics. The Analytics page is displayed.
10. We have to enable the Crash service, Navigate to Quality > Crash and enable Crash service.
11. After configuring project, we need to download agconnect-services.json file in your project and add into your project.
12. After that follow the URL for cross-platform plugins. Download required plugins.
13. The following dependencies for HMS usage need to be added to build.gradle file under the android directory.
Code:
buildscript {
ext.kotlin_version = '1.3.50'
repositories {
google()
jcenter()
maven {url 'http://developer.huawei.com/repo/'}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
classpath 'com.huawei.agconnect:agcp:1.4.1.300'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
jcenter()
maven {url 'http://developer.huawei.com/repo/'}
}
}
14. Add the below plugin in build.gradle file under the android/app directory.
Code:
apply plugin: 'com.huawei.agconnect'
15. Add the required permissions in AndroidManifest.xml file under app/src/main folder.
XML:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
16. After completing all the above steps, you need to add the required kits’ Flutter plugins as dependencies to pubspec.yaml file. You can find all the plugins in pub.dev with the latest versions.
Code:
huawei_iap:
path: ../huawei_iap/
agconnect_crash: ^1.1.0
After adding them, run flutter pub get command. Now all the plugins are ready to use.
Note: Set multiDexEnabled to true in the android/app directory, so that app will not crash.
IAP Kit Introduction
In-app purchases can be used to sell a variety of content through your app, including subscriptions, new features, and services. Users can make in-app purchases on all sorts of devices and operating systems — not just their mobile phones.
There are 4 types of in-app purchases available in Huawei IAP Kit.
Consumables: Users can purchase different types of consumables, such as extra lives or gems in a game, to further their progress through an app. Consumable in-app purchases are used once, are depleted, and can be purchased again.
Non-Consumables: Users can purchase non-consumable, premium features within an app, such as additional filters in a photo app. Non-consumables are purchased once and do not expire.
Auto-Renewable Subscriptions: Users can purchase access to services or periodically updated content, such as monthly access to cloud storage or a weekly subscription to a magazine. Users are charged on a recurring basis until they decide to cancel.
Non-Renewing Subscriptions: Users can purchase access to services or content for a limited time, such as a season pass to streaming content. This type of subscription does not renew automatically, so users need to renew at the end of each subscription period.
How to Configure Product info
To add product, Navigate to My Apps > Learning app > Operate > Product operation > Product management. Click Products tab and click Add product. Configure Product information and click Save.
Now we successfully added consumable products, we need to activate the product.
Let’s implement code
First we need to check whether environment and sandbox account is ready.
YAML:
checkEnv() async {
isEnvReadyStatus = null;
try {
IsEnvReadyResult response = await IapClient.isEnvReady();
isEnvReadyStatus = response.status.statusMessage;
if (isEnvReadyStatus != null) {
checkSandboxAccount();
}
} on PlatformException catch (e) {
if (e.code == HmsIapResults.LOG_IN_ERROR.resultCode) {
print(HmsIapResults.LOG_IN_ERROR.resultMessage);
} else {
print(e.toString());
}
}
}
checkSandboxAccount() async {
isSandBoxStatus = null;
try {
IsSandboxActivatedResult result = await IapClient.isSandboxActivated();
isSandBoxStatus = result.status.statusMessage;
} on PlatformException catch (e) {
if (e.code == HmsIapResults.LOG_IN_ERROR.resultCode) {
print(HmsIapResults.LOG_IN_ERROR.resultMessage);
} else {
print(e.toString());
}
}
}
Fetch products
Use the obtainProductInfo API to get details of in-app products configured in AppGallery Connect.
Perform the following development steps
Construct a ProductInfoReq object to get ProductInfo.
Pass the Product ID that was defined and effective in AppGallery Connect to the ProductInfoReq object and specify the priceType for a product
YAML:
fetchConsumable() async {
try {
ProductInfoReq req = new ProductInfoReq();
req.priceType = IapClient.IN_APP_CONSUMABLE;
req.skuIds = ["ED_1011"];
ProductInfoResult res = await IapClient.obtainProductInfo(req);
consumable = [];
for (int i = 0; i < res.productInfoList.length; i++) {
consumable.add(res.productInfoList[i]);
}
} on PlatformException catch (e) {
if (e.code == HmsIapResults.ORDER_HWID_NOT_LOGIN.resultCode) {
print(HmsIapResults.ORDER_HWID_NOT_LOGIN.resultMessage);
} else {
print(e.toString());
}
}
}
Purchase products
You can initiate a purchase request through the createPurchaseIntent API. Call createPurchaseIntent with the appropriate parameters to automatically display the HUAWEI IAP payment page.
YAML:
subscribeProduct(String productID) async {
PurchaseIntentReq request = PurchaseIntentReq();
request.priceType = IapClient.IN_APP_CONSUMABLE;
request.productId = productID;
request.developerPayload = "Course";
try {
PurchaseResultInfo result = await IapClient.createPurchaseIntent(request);
if (result.returnCode == HmsIapResults.ORDER_STATE_SUCCESS.resultCode) {
log("Successfully plan subscribed");
} else if (result.returnCode ==
HmsIapResults.ORDER_STATE_FAILED.resultCode) {
log("Product subscription failed");
} else if (result.returnCode ==
HmsIapResults.ORDER_STATE_CANCEL.resultCode) {
log("User cancel the payment");
} else if (result.returnCode ==
HmsIapResults.ORDER_PRODUCT_OWNED.resultCode) {
log("Already Product subscribed");
} else {
log(result.errMsg);
}
} on PlatformException catch (e) {
if (e.code == HmsIapResults.ORDER_HWID_NOT_LOGIN.resultCode) {
log(HmsIapResults.ORDER_HWID_NOT_LOGIN.resultMessage);
} else {
log(e.toString());
}
}
}
Crash Service Introduction
This service help us to minimize these crash risks. Also this service integration is relatively simple and doesn’t require coding. The Crash Service provides crash reports which are easy to reference and analyze.
Huawei Crash Service provides a powerful yet lightweight solution to app crash problems. With the service, you can quickly detect, locate, and resolve app crashes (unexpected exits of apps), and have access to highly readable crash reports in real time, without the required to write any code.
Crash Service provides some various features
1. The last-hour crash report allows you to monitor the quality of your app in real time.
2. The Crash service automatically categorizes crashes, and provides indicator data of the crashes allowing you to prioritize the most important crashes.
3. You can view information about a specific crash, and analyze the app and Android versions with the crash.
4. You can also view information about the app, operating system, and device corresponding to a specific crash, as well as the crashed stack.
5. The Crash service can also detect major crashes in real time. After you enable crash notifications, App Gallery Connect can send you an email when a major crash occurs.
To create a crash we have a AGCCrash.instance().testIt() method. By calling it we can crash our app. On button click add this method and crash your app
Code:
Positioned(
top:30,
child: Container(
child: IconButton(
onPressed: (){
AGCCrash.instance.testIt();// To test crash
},
icon: Icon(Icons.arrow_back,color: Colors.white,),
),
),
)
We also have custom report methods such as setUserId, log, setCustomValue and so on. In this example I created a test button Custom Report in ViewController class. You can click the button to call the setUserId method to set the user ID, the log:level method to record logs, and the setCustomValue:value method to add custom key-value pairs.
Code:
void handleCrash() async{
await AGCCrash.instance.enableCrashCollection(true);
AGCCrash.instance.setUserId("11223344");
AGCCrash.instance.setCustomKey("Huawei", "Reporting crashed"); AGCCrash.instance.log(level: LogLevel.debug,message: "Crash has successfully reported.");
}
How we can check crash Report
Crash Service automatically reports the occurred crashes to AppGallery Connect. Details and the cause of crash can also be viewed in the statistics page on AppGallery Connect.
How to access to the Crash Service Page:
Navigate to Quality > Crash. The Crash page is displayed.
Tips & Tricks
1. Download latest HMS Flutter plugin.
2. Do not forget to create sandbox account.
3. Do not forget to click pug get after adding dependencies.
4. Latest HMS Core APK is required.
Conclusion
In this article, we have learnt integration of Huawei Iap kit, Crash service into Flutter project.
Thanks for reading! If you enjoyed this story, please click the Like button and Follow. Feel free to leave a Comment below.
Reference
In-App Purchase Kit URL
Crash service URL
Original Source
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