More information like this, you can visit HUAWEI Developer Forum
Introduction
Hi everyone, this article provides example of HUAWEI Location Kit using the Cordova and Capacitor for Ionic mobile application. First of all, I would like to talk about the possibilities that HUAWEI Location Kit provides.
About HUAWEI Location Kit
Huawei Location Kit combines the GPS(Global Positioning System), Wi-Fi, and base station locations to help you quickly obtain precise user locations, build up global positioning capabilities, and reach a wide range of users around the globe. Currently, it provides the three main capabilities: Fused Location, Activity Identification, and Geofence.
Fused Location: Quickly obtain the device location based on the Wi-Fi, GPS and base station location data.
Activity Identification: Identifies user motion status through the acceleration sensor, cellular network information, and magnetometer, helping you adjust your app based on user behavior.
Geofence: Allows you to set an interested area through an API so that your app can receive a notification when a specified action such as leaving, entering, or lingering in the area occurs.
{
"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"
}
HUAWEI Mobile Services(HMS): Location Kit Advantages
HUAWEI Mobile Services - Location Kit
Ionic Project Demo Using HMS Location Kit
Download the project from the link.
Ionic Project Sample Code
Download the Huawei Location Plugin from the link.
Cordova Huawei Location Plugin
Prerequisites
Install @iONiC/ionic-native/core
Code:
npm install [user=1329689]@iONiC[/user]-native/core --save
# or
# npm install
Ionic Native is a curated set of wrappers for Cordova plugins that make adding any native functionality you need to your Ionic mobile app easy.
Ionic Native wraps plugin callbacks in a Promise or Observable, providing a common interface for all plugins and making it easy to use plugins with Angular change detection.
Using Cordova
Add android platform to the project with using Cordova.
Code:
ionic cordova platform add android
Integrate Huawei Location Plugin to your project with using Cordova.
Code:
# ionic cordova plugin add PATH_TO_CORDOVA_LOCATION_PLUGIN
ionic cordova plugin add ../cordova-plugin-hms-location
Copy the “node_modules @hmscore/cordova-plugin-hms-location/ionic/dist/hms-location” folder from library to “node_modules @iONiC-native” folder under your Ionic project.
Run the project
Code:
ionic cordova run android
Using Capacitor
Integrate Huawei Location Plugin to your project with using npm.
Code:
# npm install <CORDOVA_LOCATION_PLUGIN_PATH>
npm install ../cordova-plugin-hms-location
NPM Package: @hmscore/cordova-plugin-hms-location
Add android platform to the project with using Capacitor.
Code:
ionic capacitor add android
Copy the “node_modules @hmscore/cordova-plugin-hms-location/ionic/dist/hms-location” folder from library to “node_modules @iONiC-native” folder under your Ionic project.
Run the project
Code:
ionic capacitor run android --device
Cordova HMS Location Kit APIs Overview
HMS Location Kit: Cordova APIs Tutorial
Import and Providers: location.module.ts
Code:
/**
* Copyright 2020 Huawei Technologies Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from [user=1329689]@iONiC[/user]/angular';
import { LocationPageRoutingModule } from './location-routing.module';
import { LocationPage } from './location.page';
import {
HMSFusedLocation,
HMSActivityIdentification,
HMSGeofence,
LocationRequest,
PriorityConstants,
Events,
Activities,
ActivityConversions
} from [user=1329689]@iONiC[/user]-native/hms-location/ngx';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
LocationPageRoutingModule,
],
declarations: [LocationPage],
providers: [
HMSFusedLocation,
HMSActivityIdentification,
HMSGeofence
]
})
export class LocationPageModule {}
Using HMS Location Functions: location.page.ts
Code:
/**
* Copyright 2020 Huawei Technologies Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, OnInit, NgZone } from '@angular/core';
import { Platform } from [user=1329689]@iONiC[/user]/angular';
import {
HMSFusedLocation,
HMSActivityIdentification,
HMSGeofence,
LocationRequest,
PriorityConstants,
Events,
Activities,
ActivityConversions,
GeofenceRequestConstants
} from [user=1329689]@iONiC[/user]-native/hms-location/ngx';
import { HMSLocationKit } from [user=1329689]@iONiC[/user]-native/hms-location';
const asStr = (x) => JSON.stringify(x, null, 2);
@Component({
selector: 'app-location',
templateUrl: './location.page.html',
styleUrls: ['./location.page.scss'],
})
export class LocationPage implements OnInit {
locationHasPermissionResult = '';
locationRequestPermissionResult = '';
getLastLocationResult = '';
getLocationAvailabilityResult = '';
getLastLocationWithAddressResult = '';
flushLocationsResult = '';
checkLocationSettingsResult = '';
hasActivityPermissionResult = '';
createActivityConversionUpdatesResult = '';
registerActivityConversionUpdatesResult = '';
createActivityIdentificationUpdatesResult = '';
registerActivityIdentificationUpdatesResult = '';
createGeofenceListResult = '';
registerGeofenceUpdatesResult = '';
constructor(
private platform: Platform,
private fusedLocation: HMSFusedLocation,
private activityIdentification: HMSActivityIdentification,
private geofence: HMSGeofence,
private ngZone: NgZone
) {
this.platform.ready().then(() => {
console.log("Platform is ready.");
})
}
ngOnInit() {
HMSLocationKit.init();
}
//
// Fused Location
//
async runFunction(fn: () => any, field: string) {
console.log(`Updating ${field}`);
let result = "";
try {
result = asStr(await fn());
} catch (ex) {
result = asStr(ex);
}
console.log(result);
this[field] = result;
return field;
}
newLocationRequest(): LocationRequest {
return {
id: "locationRequest" + Math.random() * 10000,
priority: PriorityConstants.PRIORITY_HIGH_ACCURACY,
interval: 3,
numUpdates: 1,
fastestInterval: 1000.0,
expirationTime: 1000.0,
expirationTimeDuration: 1000.0,
smallestDisplacement: 0.0,
maxWaitTime: 1000.0,
needAddress: false,
language: "en",
countryCode: "en",
}
}
hasPermission() {
this.runFunction(() => this.fusedLocation.hasPermission(), 'locationHasPermissionResult');
}
requestLocationPermission() {
this.runFunction(() => this.fusedLocation.requestPermission(), 'locationRequestPermissionResult');
}
getLastLocation() {
this.runFunction(() => this.fusedLocation.getLastLocation(), 'getLastLocationResult');
}
getLocationAvailability() {
this.runFunction(() => this.fusedLocation.getLocationAvailability(), 'getLocationAvailabilityResult');
}
getLastLocationWithAddress() {
this.runFunction(() => this.fusedLocation.getLastLocationWithAddress(this.newLocationRequest()), 'getLastLocationWithAddressResult');
}
flushLocations() {
this.runFunction(() => this.fusedLocation.flushLocations(), 'flushLocationsResult');
}
checkLocationSettings() {
this.runFunction(() => this.fusedLocation.checkLocationSettings({
alwaysShow: true,
needBle: true,
locationRequests: []
}), 'checkLocationSettingsResult');
}
//
// Activity Identification
//
hasActivityPermission() {
this.runFunction(() => this.activityIdentification.hasPermission(), 'hasActivityPermissionResult');
}
requestAcitvityPermission() {
this.runFunction(() => this.activityIdentification.requestPermission(), 'locationRequestPermissionResult');
}
createActivityConversionUpdates() {
const activityConversions = [
// STILL
{
conversionType: ActivityConversions.ENTER_ACTIVITY_CONVERSION,
activityType: Activities.STILL
},
{
conversionType: ActivityConversions.EXIT_ACTIVITY_CONVERSION,
activityType: Activities.STILL
},
// ON FOOT
{
conversionType: ActivityConversions.ENTER_ACTIVITY_CONVERSION,
activityType: Activities.FOOT
},
{
conversionType: ActivityConversions.EXIT_ACTIVITY_CONVERSION,
activityType: Activities.FOOT
},
// RUNNING
{
conversionType: ActivityConversions.ENTER_ACTIVITY_CONVERSION,
activityType: Activities.RUNNING
},
{
conversionType: ActivityConversions.EXIT_ACTIVITY_CONVERSION,
activityType: Activities.RUNNING
}
];
this.runFunction(
() => this.activityIdentification.createActivityConversionUpdates(activityConversions),
'createActivityConversionUpdatesResult'
);
}
registerActivityConversionUpdates() {
window.registerHMSEvent(Events.ACTIVITY_CONVERSION_RESULT, (result) =>
this.ngZone.run(() => this.registerActivityConversionUpdatesResult = asStr(result)));
}
createActivityIdentificationUpdates() {
this.runFunction(
() => this.activityIdentification.createActivityIdentificationUpdates(2000),
'createActivityIdentificationUpdatesResult'
);
}
registerActivityIdentificationUpdates() {
window.registerHMSEvent(Events.ACTIVITY_IDENTIFICATION_RESULT, (result) =>
this.ngZone.run(() => this.registerActivityIdentificationUpdatesResult = asStr(result)));
}
//
// Geofences
//
createGeofenceList() {
const geofence1 = {
longitude: 42.0,
latitude: 29.0,
radius: 20.0,
uniqueId: 'geofence' + Math.random() * 10000,
conversions: 1,
validContinueTime: 10000.0,
dwellDelayTime: 10,
notificationInterval: 1,
};
const geofence2 = {
longitude: 41.0,
latitude: 27.0,
radius: 340.0,
uniqueId: 'geofence' + Math.random() * 10000,
conversions: 2,
validContinueTime: 1000.0,
dwellDelayTime: 10,
notificationInterval: 1,
};
this.runFunction(
() => this.geofence.createGeofenceList(
[geofence1, geofence2],
GeofenceRequestConstants.ENTER_INIT_CONVERSION,
GeofenceRequestConstants.COORDINATE_TYPE_WGS_84
),
'createGeofenceListResult'
);
}
registerGeofenceUpdates() {
window.registerHMSEvent(Events.GEOFENCE_RESULT, (result) =>
this.ngZone.run(() => this.registerGeofenceUpdatesResult = asStr(result)));
}
}
HMS Location Kit: location.page.html
Code:
<!--
Copyright 2020 Huawei Technologies Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<ion-header>
<ion-toolbar>
<ion-title>HMSLocationKit Demo</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<h1>Fused Location</h1>
<ion-button (click)="hasPermission()">Check Permission</ion-button>
<ion-text>{{ locationHasPermissionResult }}</ion-text>
<ion-button (click)="requestLocationPermission()">Get Permission</ion-button>
<ion-text>{{ locationRequestPermissionResult }}</ion-text>
<ion-button (click)="getLocationAvailability()">Get Location Availability</ion-button>
<ion-text>{{ getLocationAvailabilityResult }}</ion-text>
<ion-button (click)="getLastLocation()">Get Last Location</ion-button>
<ion-text>{{ getLastLocationResult }}</ion-text>
<ion-button (click)="getLastLocationWithAddress()">Get Last Location With Address</ion-button>
<ion-text>{{ getLastLocationWithAddressResult }}</ion-text>
<ion-button (click)="flushLocations()">Flush Locations</ion-button>
<ion-text>{{ flushLocationsResult }}</ion-text>
<ion-button (click)="checkLocationSettings()">Check Location Settings</ion-button>
<ion-text>{{ checkLocationSettingsResult }}</ion-text>
<h1>Activity Identification</h1>
<ion-button (click)="hasActivityPermission()">Check Permission</ion-button>
<ion-text>{{ hasActivityPermissionResult }}</ion-text>
<ion-button (click)="requestAcitvityPermission()">Get Permission</ion-button>
<ion-text>{{ hasPermissionResult }}</ion-text>
<ion-button (click)="createActivityConversionUpdates()">Create Activity Conversion Updates</ion-button>
<ion-text>{{ createActivityConversionUpdatesResult }}</ion-text>
<ion-button (click)="registerActivityConversionUpdates()">Register Activity Conversion Updates</ion-button>
<ion-text>{{ registerActivityConversionUpdatesResult }}</ion-text>
<ion-button (click)="createActivityIdentificationUpdates()">Create Activity Identification Updates</ion-button>
<ion-text>{{ createActivityIdentificationUpdatesResult }}</ion-text>
<ion-button (click)="registerActivityIdentificationUpdates()">Register Activity Identification Updates</ion-button>
<ion-text>{{ registerActivityIdentificationUpdatesResult }}</ion-text>
<h1>Geofences</h1>
<ion-button (click)="createGeofenceList()">Create Geofence List</ion-button>
<ion-text>{{ createGeofenceListResult }}</ion-text>
<ion-button (click)="registerGeofenceUpdates()">Register Geofence Updates</ion-button>
<ion-text>{{ registerGeofenceUpdatesResult }}</ion-text>
</ion-content>
Conclusion
In this article, I explained what is the HUAWEI Location Kit, what capabilities it provides, and how to use it in the Ionic mobile application. If you have any questions, you can write the question in the comment section.
Github link: https://github.com/HMS-Core/hms-cordova-plugin/tree/master/cordova-plugin-hms-location
Related
{
"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"
}
While working with Ionic, it is recommended to use the Capacitor for new Ionic apps but sometimes you need to use some Cordova or Ionic Native plugins. In this guide you will learn how to use HMS IAP Cordova Plugin with an Ionic Capacitor application.
In order to use IAP Plugin with any application, you have to create an application on Huawei Developer Console and add some products.
You can read this guide for further details to create an application and add purchasable products to work with.
Huawei In-App Purchases
Huawei In-App Purchases (IAP) provides multiple payment methods for global payments and can be easily integrated into your application to help increase your revenue. Users can purchase a variety of products and services, including popular virtual products and subscriptions, from within your direct application.
Create an Application with Ionic
Install the Ionic CLI with npm if you haven’t already.
Code:
ionic start HMS-IAP-Demo blank --capacitor
cd HMS-IAP-Demo
npm run build
Add your agconnect-services.json and keystore files to project folder as explained in the guide I mentioned above.
Add the AppID you got from the Huawei Developer console to the AndroidManifest.xml file. (inside application tag)
Code:
<meta-data
android:name="com.huawei.hms.client.appid"
android:value="appid=102461279">
</meta-data>
Add HMS IAP Cordova Plugin & Ionic Native
Code:
npm i @hmscore/cordova-plugin-hms-iap --save
npm i @ionic-native/core --save-dev
Copy the “ionic/dist/hms-in-app-purchases” folder from library in node_modules to the “node_modules/@ionic-native” folder in your ionic project.
Code:
ionic capacitor add add android
ionic capacitor sync
ionic capacitor build android
Run the project on a connected device
Run the Ionic application with the command below to try the application with a Huawei device. We’re using the --livereload and --external options to see changes on tthe device when changes in the app are detected.
Code:
ionic capacitor run android --livereload --external
Exploring IAP Library
You have to login with your Huawei ID on the device you’re going to install application. Otherwise, you will get an error. (Error Code: 60050). You can check the error details and other error codes here.
Adding Library to Providers
You have to add library to the providers section in app.module.ts before using it.
Code:
import { HMSInAppPurchases } from '@ionic-native/hms-in-app-purchases/ngx';
@NgModule({
...
providers: [
HMSInAppPurchases,
],
bootstrap: [AppComponent]
})
export class AppModule {}
Checking Environment
Before fetching the products, you should check the environment is ready.
Code:
import { Component } from '@angular/core';
import { HMSInAppPurchases } from '@ionic-native/hms-in-app-purchases/ngx';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss']
})
export class HomePage {
constructor(public iap: HMSInAppPurchases) { }
async ngOnInit() {
try {
let message = await this.iap.isEnvReady();
console.log(message);
} catch (error) {
console.error(error);
}
}
}
Fetching Products
If you have configured products in AppGallery Connect, you need to use the obtainProductInfo API to obtain details of these products.
Perform the following steps:
Construct a ProductInfoReq object and pass the product ID that has been defined and taken effect in AppGallery Connect to the ProductInfoReq object, and specify priceType for a product. “priceType” is type of the product. Check the code below for price types and their integer equivalents.
If the operation is successful, obtainProductInfo will return a ProductInfoResult object that contains productInfoList. You can use it to display the product information within your application.
Code:
import { Component } from '@angular/core';
import { HMSInAppPurchases } from '@ionic-native/hms-in-app-purchases/ngx';
import { HMSAppLinking } from '@ionic-native/hms-applinking/ngx';
const DEVELOPERPAYLOAD = "HMSCoreDeveloper"
const DEVELOPERCHALLENGE = "HMSCoreDeveloperChallenge"
const PRICETYPE = {
CONSUMABLE : 0,
NONCONSUMABLE : 1,
SUBSCRIPTION : 2,
}
const PRODUCTS = {
consumable: {
type: PRICETYPE.CONSUMABLE,
products: [{
id: 'test',
name: 'Consumable Item'
}]
},
nonconsumable: {
type: PRICETYPE.NONCONSUMABLE,
products: [{
id: 'non_consumable_item_1',
name: 'Non Consumable Item'
}, ]
},
subscription: {
type: PRICETYPE.SUBSCRIPTION,
products: [{
id: 'subscription_item_1',
name: 'Subscription Item'
}, ]
},
}
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
constructor(private iap: HMSInAppPurchases) {}
ngOnInit() {
...
this.getProductsInformation();
}
getProductsInformation = () => {
Object.keys(PRODUCTS).map(async product_type=> {
await this.obtainProductInfoFromType(product_type);
});
}
obtainProductInfoFromType = async (product_type) => {
try {
let products = await this.iap.obtainProductInfo({
priceType: PRODUCTS[product_type].type,
productList: PRODUCTS[product_type].products.map(p=>p.id)
});
console.log(products);
} catch (err) {
console.log(err);
}
}
}
Initiating a Purchase
Your app can display the purchase screen through the createPurchaseIntent API.
Call createPurchaseIntent with required parameter. Parameter is an object includes productId, priceType and developerPayload. If parameters are correct it automatically brings the checkout page. If a problem occurs the createPurchaseIntent API will return a Status object describing the error.
Code:
import { Component } from '@angular/core';
import { HMSInAppPurchases } from '@ionic-native/hms-in-app-purchases/ngx';
import { HMSAppLinking } from '@ionic-native/hms-applinking/ngx';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
constructor(private iap: HMSInAppPurchases) {}
ngOnInit() {
...
}
createPurchaseIntent = async (product) => {
try {
let message = await this.iap.createPurchaseIntent({
priceType: product.priceType,
productId: product.productId,
developerPayload: DEVELOPERPAYLOAD
});
if (message.returnCode === 0) {// if successful
console.log(message);
} else {
alert('Purchase was not successful.');
console.log(message);
}
} catch (err) {
console.log(err);
}
}
}
Auto-renewable Subscriptions
Users can purchase access to value-added functions or content in a specified period of time. The subscriptions are automatically renewed on a recurring basis until users decide to cancel.
You can use the createPurchaseIntent API like the example above to display the subscription purchase page. HMS IAP Plugin provides startIapActivity API to display subscription management and subscription editing pages.
Simply call the startIapActivity API to display the subscription management page. If you want to display display the subscription editing page you just need to pass the ID of the product as a parameter.
Code:
import { Component } from '@angular/core';
import { HMSInAppPurchases } from '@ionic-native/hms-in-app-purchases/ngx';
import { HMSAppLinking } from '@ionic-native/hms-applinking/ngx';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
constructor(private iap: HMSInAppPurchases) {}
async ngOnInit() {
...
}
editSubscription = (product_id) => {
this.iap.startIapActivity(product_id).then(() => {
console.log('Subscription editing page is displayed');
}).catch(error => {
console.log(error);
})
}
manageSubscriptions = () => {
this.iap.startIapActivity().then(() => {
console.log('Subscription management page is displayed');
}).catch(error => {
console.log(error);
});
}
}
In this article, I tried to explain to you the use of the In-App Purchases Cordova Plugin through code examples.
More information like this, you can visit HUAWEI Developer Forum
Introduction
Hi everyone, this article provides example of HUAWEI Location Kit using the Cordova and Capacitor for Ionic mobile application. First of all, I would like to talk about the possibilities that HUAWEI Location Kit provides.
About HUAWEI Location Kit
Huawei Location Kit combines the GPS(Global Positioning System), Wi-Fi, and base station locations to help you quickly obtain precise user locations, build up global positioning capabilities, and reach a wide range of users around the globe. Currently, it provides the three main capabilities: Fused Location, Activity Identification, and Geofence.
Fused Location: Quickly obtain the device location based on the Wi-Fi, GPS and base station location data.
Activity Identification: Identifies user motion status through the acceleration sensor, cellular network information, and magnetometer, helping you adjust your app based on user behavior.
Geofence: Allows you to set an interested area through an API so that your app can receive a notification when a specified action such as leaving, entering, or lingering in the area occurs.
{
"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"
}
HUAWEI Mobile Services(HMS): Location Kit Advantages
HUAWEI Mobile Services - Location Kit
Ionic Project Demo Using HMS Location Kit
Download the project from the link.
Ionic Project Sample Code
Download the Huawei Location Plugin from the link.
Cordova Huawei Location Plugin
Prerequisites
Install @iONiC/ionic-native/core
Code:
npm install [user=1329689]@iONiC[/user]-native/core --save
# or
# npm install
Ionic Native is a curated set of wrappers for Cordova plugins that make adding any native functionality you need to your Ionic mobile app easy.
Ionic Native wraps plugin callbacks in a Promise or Observable, providing a common interface for all plugins and making it easy to use plugins with Angular change detection.
Using Cordova
Add android platform to the project with using Cordova.
Code:
ionic cordova platform add android
Integrate Huawei Location Plugin to your project with using Cordova.
Code:
# ionic cordova plugin add PATH_TO_CORDOVA_LOCATION_PLUGIN
ionic cordova plugin add ../cordova-plugin-hms-location
Copy the “node_modules @hmscore/cordova-plugin-hms-location/ionic/dist/hms-location” folder from library to “node_modules @iONiC-native” folder under your Ionic project.
Run the project
Code:
ionic cordova run android
Using Capacitor
Integrate Huawei Location Plugin to your project with using npm.
Code:
# npm install <CORDOVA_LOCATION_PLUGIN_PATH>
npm install ../cordova-plugin-hms-location
NPM Package: @hmscore/cordova-plugin-hms-location
Add android platform to the project with using Capacitor.
Code:
ionic capacitor add android
Copy the “node_modules @hmscore/cordova-plugin-hms-location/ionic/dist/hms-location” folder from library to “node_modules @iONiC-native” folder under your Ionic project.
Run the project
Code:
ionic capacitor run android --device
Cordova HMS Location Kit APIs Overview
HMS Location Kit: Cordova APIs Tutorial
Import and Providers: location.module.ts
Code:
/**
* Copyright 2020 Huawei Technologies Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from [user=1329689]@iONiC[/user]/angular';
import { LocationPageRoutingModule } from './location-routing.module';
import { LocationPage } from './location.page';
import {
HMSFusedLocation,
HMSActivityIdentification,
HMSGeofence,
LocationRequest,
PriorityConstants,
Events,
Activities,
ActivityConversions
} from [user=1329689]@iONiC[/user]-native/hms-location/ngx';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
LocationPageRoutingModule,
],
declarations: [LocationPage],
providers: [
HMSFusedLocation,
HMSActivityIdentification,
HMSGeofence
]
})
export class LocationPageModule {}
Using HMS Location Functions: location.page.ts
Code:
/**
* Copyright 2020 Huawei Technologies Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, OnInit, NgZone } from '@angular/core';
import { Platform } from [user=1329689]@iONiC[/user]/angular';
import {
HMSFusedLocation,
HMSActivityIdentification,
HMSGeofence,
LocationRequest,
PriorityConstants,
Events,
Activities,
ActivityConversions,
GeofenceRequestConstants
} from [user=1329689]@iONiC[/user]-native/hms-location/ngx';
import { HMSLocationKit } from [user=1329689]@iONiC[/user]-native/hms-location';
const asStr = (x) => JSON.stringify(x, null, 2);
@Component({
selector: 'app-location',
templateUrl: './location.page.html',
styleUrls: ['./location.page.scss'],
})
export class LocationPage implements OnInit {
locationHasPermissionResult = '';
locationRequestPermissionResult = '';
getLastLocationResult = '';
getLocationAvailabilityResult = '';
getLastLocationWithAddressResult = '';
flushLocationsResult = '';
checkLocationSettingsResult = '';
hasActivityPermissionResult = '';
createActivityConversionUpdatesResult = '';
registerActivityConversionUpdatesResult = '';
createActivityIdentificationUpdatesResult = '';
registerActivityIdentificationUpdatesResult = '';
createGeofenceListResult = '';
registerGeofenceUpdatesResult = '';
constructor(
private platform: Platform,
private fusedLocation: HMSFusedLocation,
private activityIdentification: HMSActivityIdentification,
private geofence: HMSGeofence,
private ngZone: NgZone
) {
this.platform.ready().then(() => {
console.log("Platform is ready.");
})
}
ngOnInit() {
HMSLocationKit.init();
}
//
// Fused Location
//
async runFunction(fn: () => any, field: string) {
console.log(`Updating ${field}`);
let result = "";
try {
result = asStr(await fn());
} catch (ex) {
result = asStr(ex);
}
console.log(result);
this[field] = result;
return field;
}
newLocationRequest(): LocationRequest {
return {
id: "locationRequest" + Math.random() * 10000,
priority: PriorityConstants.PRIORITY_HIGH_ACCURACY,
interval: 3,
numUpdates: 1,
fastestInterval: 1000.0,
expirationTime: 1000.0,
expirationTimeDuration: 1000.0,
smallestDisplacement: 0.0,
maxWaitTime: 1000.0,
needAddress: false,
language: "en",
countryCode: "en",
}
}
hasPermission() {
this.runFunction(() => this.fusedLocation.hasPermission(), 'locationHasPermissionResult');
}
requestLocationPermission() {
this.runFunction(() => this.fusedLocation.requestPermission(), 'locationRequestPermissionResult');
}
getLastLocation() {
this.runFunction(() => this.fusedLocation.getLastLocation(), 'getLastLocationResult');
}
getLocationAvailability() {
this.runFunction(() => this.fusedLocation.getLocationAvailability(), 'getLocationAvailabilityResult');
}
getLastLocationWithAddress() {
this.runFunction(() => this.fusedLocation.getLastLocationWithAddress(this.newLocationRequest()), 'getLastLocationWithAddressResult');
}
flushLocations() {
this.runFunction(() => this.fusedLocation.flushLocations(), 'flushLocationsResult');
}
checkLocationSettings() {
this.runFunction(() => this.fusedLocation.checkLocationSettings({
alwaysShow: true,
needBle: true,
locationRequests: []
}), 'checkLocationSettingsResult');
}
//
// Activity Identification
//
hasActivityPermission() {
this.runFunction(() => this.activityIdentification.hasPermission(), 'hasActivityPermissionResult');
}
requestAcitvityPermission() {
this.runFunction(() => this.activityIdentification.requestPermission(), 'locationRequestPermissionResult');
}
createActivityConversionUpdates() {
const activityConversions = [
// STILL
{
conversionType: ActivityConversions.ENTER_ACTIVITY_CONVERSION,
activityType: Activities.STILL
},
{
conversionType: ActivityConversions.EXIT_ACTIVITY_CONVERSION,
activityType: Activities.STILL
},
// ON FOOT
{
conversionType: ActivityConversions.ENTER_ACTIVITY_CONVERSION,
activityType: Activities.FOOT
},
{
conversionType: ActivityConversions.EXIT_ACTIVITY_CONVERSION,
activityType: Activities.FOOT
},
// RUNNING
{
conversionType: ActivityConversions.ENTER_ACTIVITY_CONVERSION,
activityType: Activities.RUNNING
},
{
conversionType: ActivityConversions.EXIT_ACTIVITY_CONVERSION,
activityType: Activities.RUNNING
}
];
this.runFunction(
() => this.activityIdentification.createActivityConversionUpdates(activityConversions),
'createActivityConversionUpdatesResult'
);
}
registerActivityConversionUpdates() {
window.registerHMSEvent(Events.ACTIVITY_CONVERSION_RESULT, (result) =>
this.ngZone.run(() => this.registerActivityConversionUpdatesResult = asStr(result)));
}
createActivityIdentificationUpdates() {
this.runFunction(
() => this.activityIdentification.createActivityIdentificationUpdates(2000),
'createActivityIdentificationUpdatesResult'
);
}
registerActivityIdentificationUpdates() {
window.registerHMSEvent(Events.ACTIVITY_IDENTIFICATION_RESULT, (result) =>
this.ngZone.run(() => this.registerActivityIdentificationUpdatesResult = asStr(result)));
}
//
// Geofences
//
createGeofenceList() {
const geofence1 = {
longitude: 42.0,
latitude: 29.0,
radius: 20.0,
uniqueId: 'geofence' + Math.random() * 10000,
conversions: 1,
validContinueTime: 10000.0,
dwellDelayTime: 10,
notificationInterval: 1,
};
const geofence2 = {
longitude: 41.0,
latitude: 27.0,
radius: 340.0,
uniqueId: 'geofence' + Math.random() * 10000,
conversions: 2,
validContinueTime: 1000.0,
dwellDelayTime: 10,
notificationInterval: 1,
};
this.runFunction(
() => this.geofence.createGeofenceList(
[geofence1, geofence2],
GeofenceRequestConstants.ENTER_INIT_CONVERSION,
GeofenceRequestConstants.COORDINATE_TYPE_WGS_84
),
'createGeofenceListResult'
);
}
registerGeofenceUpdates() {
window.registerHMSEvent(Events.GEOFENCE_RESULT, (result) =>
this.ngZone.run(() => this.registerGeofenceUpdatesResult = asStr(result)));
}
}
HMS Location Kit: location.page.html
Code:
<!--
Copyright 2020 Huawei Technologies Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<ion-header>
<ion-toolbar>
<ion-title>HMSLocationKit Demo</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<h1>Fused Location</h1>
<ion-button (click)="hasPermission()">Check Permission</ion-button>
<ion-text>{{ locationHasPermissionResult }}</ion-text>
<ion-button (click)="requestLocationPermission()">Get Permission</ion-button>
<ion-text>{{ locationRequestPermissionResult }}</ion-text>
<ion-button (click)="getLocationAvailability()">Get Location Availability</ion-button>
<ion-text>{{ getLocationAvailabilityResult }}</ion-text>
<ion-button (click)="getLastLocation()">Get Last Location</ion-button>
<ion-text>{{ getLastLocationResult }}</ion-text>
<ion-button (click)="getLastLocationWithAddress()">Get Last Location With Address</ion-button>
<ion-text>{{ getLastLocationWithAddressResult }}</ion-text>
<ion-button (click)="flushLocations()">Flush Locations</ion-button>
<ion-text>{{ flushLocationsResult }}</ion-text>
<ion-button (click)="checkLocationSettings()">Check Location Settings</ion-button>
<ion-text>{{ checkLocationSettingsResult }}</ion-text>
<h1>Activity Identification</h1>
<ion-button (click)="hasActivityPermission()">Check Permission</ion-button>
<ion-text>{{ hasActivityPermissionResult }}</ion-text>
<ion-button (click)="requestAcitvityPermission()">Get Permission</ion-button>
<ion-text>{{ hasPermissionResult }}</ion-text>
<ion-button (click)="createActivityConversionUpdates()">Create Activity Conversion Updates</ion-button>
<ion-text>{{ createActivityConversionUpdatesResult }}</ion-text>
<ion-button (click)="registerActivityConversionUpdates()">Register Activity Conversion Updates</ion-button>
<ion-text>{{ registerActivityConversionUpdatesResult }}</ion-text>
<ion-button (click)="createActivityIdentificationUpdates()">Create Activity Identification Updates</ion-button>
<ion-text>{{ createActivityIdentificationUpdatesResult }}</ion-text>
<ion-button (click)="registerActivityIdentificationUpdates()">Register Activity Identification Updates</ion-button>
<ion-text>{{ registerActivityIdentificationUpdatesResult }}</ion-text>
<h1>Geofences</h1>
<ion-button (click)="createGeofenceList()">Create Geofence List</ion-button>
<ion-text>{{ createGeofenceListResult }}</ion-text>
<ion-button (click)="registerGeofenceUpdates()">Register Geofence Updates</ion-button>
<ion-text>{{ registerGeofenceUpdatesResult }}</ion-text>
</ion-content>
Conclusion
In this article, I explained what is the HUAWEI Location Kit, what capabilities it provides, and how to use it in the Ionic mobile application. If you have any questions, you can write the question in the comment section.
Github link: https://github.com/HMS-Core/hms-cordova-plugin/tree/master/cordova-plugin-hms-location
Introduction
This article provides information to book any trip using Trip Booking Android app. It provides a solution for HMS based multiple kits such as Account Kit, Huawei Ads, Huawei Map Direction Polyline API, Huawei Location, Huawei Map, Huawei Awareness Weather API, and Huawei Analytics to use in Trip Booking.
The following HMS Kits used in this application:
1) Huawei Account Kit: Integrated this kit for login and logout.
2) Huawei Ads: Integrated this kit for better ads experiences so that users can find the better advertisements.
3) Huawei Analytics: Integrated this kit in this application for better analysis.
4) Huawei Map: Integrated this kit for better real time experience of trip booking so that user can identify the location of trip on map.
5) Huawei Direction API: Integrated this API for better trip booking experience such as users can identify the trip direction from his/her location on map.
6) Huawei Awareness Weather API: Integrated this API for weather forecast of trip.
7) Huawei Location: Integrated this Kit to get current location of user so that users can identify from current location to desire trip location.
Note: Refer to the previous articles.
1) Explore the world Trip Booking App, Part-1 login with Huawei ID
2) Explore the world Trip Booking App, Part-2 Ads and Analytics
3) Explore the world Trip Booking App, Part-3 Map and direction API
Prerequisite
1. A computer (desktop or laptop)
2. A Huawei phone, which is used to debug the developed app
3. HUAWEI Analytics Kit 5.0.3.
4. Android SDK applicable to devices using Android API-Level 19 (Android 4.4 KitKat) or higher.
5. Android Studio
6. Java JDK 1.7 or later (JDK 1.8 recommended).
Things Need To Be Done
To integrate HUAWEI HMS Core services, you must complete the following preparations:
1. Create an app in AppGallery Connect.
2. Create an Android Studio project.
3. Add the app package name and save the configuration file.
4. Configure the Maven repository address and AppGallery Connect gradle plug-in.
Weather Awareness API
HUAWEI Awareness Kit provides your app with the ability to obtain contextual information including users' current time, location, behavior, audio device status, ambient light, weather, and nearby beacons. Your app can gain insight into a user's current situation more efficiently, making it possible to deliver a smarter, more considerate user experience.
Integration process
1) Assigning Permissions in the Manifest File
2) Importing API Classes
3) Developing Capabilities
1) Assigning Permissions in the Manifest File
Before calling the weather awareness capability, assign required permissions in the manifest file.
Code:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
2) Importing API Classes
To use the weather awareness capability, you need to import the public capability classes of Awareness Kit, and also the weather-related classes.
Code:
import com.huawei.hmf.tasks.OnFailureListener;import com.huawei.hmf.tasks.OnSuccessListener;import com.huawei.hms.kit.awareness.Awareness;
import com.huawei.hms.kit.awareness.status.WeatherStatus;
import com.huawei.hms.kit.awareness.status.weather.Situation;
import com.huawei.hms.kit.awareness.status.weather.WeatherSituation;
3) Developing Capabilities
Obtain the Capture Client object of Awareness Kit.
Code:
public class AwarenessWeather {
private static final String TAG = AwarenessWeather.class.getName();
public CurrentWeather.Current getWeatherSituation(Context context) {
CurrentWeather.Current current = new CurrentWeather().new Current();
Awareness.getCaptureClient(context).getWeatherByDevice()
.addOnSuccessListener(weatherStatusResponse -> {
WeatherStatus weatherStatus = weatherStatusResponse.getWeatherStatus();
WeatherSituation weatherSituation = weatherStatus.getWeatherSituation();
Situation situation = weatherSituation.getSituation();
String weatherInfoStr =
"Time Zone : " + (weatherSituation.getCity().getTimeZone()) + "\n\n" +
"Weather id : " + situation.getWeatherId() + "\n\n" +
"Temperature : " + situation.getTemperatureC() + "℃" +
"/" + situation.getTemperatureF() + "℉" + "\n\n" +
"Wind speed : " + situation.getWindSpeed() + "km/h" + "\n\n" +
"Wind direction : " + situation.getWindDir() + "\n\n" +
"Humidity : " + situation.getHumidity() + "%";
Log.i(TAG, weatherInfoStr);
current.setObservationTime("Day");
current.setTemperature(Math.toIntExact(situation.getTemperatureC()));
current.setIsDay(url);
})
.addOnFailureListener(e -> {
Log.e(TAG, "get weather failed");
});
return current;
}
}
Location Kit
HUAWEI Location Kit combines the GNSS, Wi-Fi, and base station location functionalities into your app to build up global positioning capabilities, allows you to provide flexible location-based services targeted at users around the globe. Currently, it provides three main capabilities: Fused location, Activity identification, and Geofence. You can call one or more of these capabilities as required.
1) Fused location: Provides a set of simple and easy-to-use APIs for your app to quickly obtain the device location based on the GNSS, Wi-Fi, and base station location data.
2) Activity identification: Identifies user motion status through the acceleration sensor, cellular network information, and magnetometer, help to adapt the app to user behavior.
3) Geofence: Allows you to set an interesting area through an API so that your app can receive a notification when a specified action (such as leaving, entering, or staying in the area) occurs.
Integration process
1) Add following dependency in Gradle File.
Code:
implementation 'com.huawei.hms:location:5.0.2.301
2) Assigning App Permissions.
Apply for location permissions in the AndroidManifest.xml file.
Code:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
3) Creating a Location Service Client.
Create a FusedLocationProviderClient instance using the onCreate() method of Activity and use the instance to call location-related APIs.
Code:
private FusedLocationProviderClient fusedLocationProviderClient;
private LocationRequest mLocationRequest;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
}
4) Check permission.
Code:
// check location permisiion
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
Log.i(TAG, "sdk < 28 Q");
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
String[] strings =
{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};
ActivityCompat.requestPermissions(this, strings, 1);
}
} else {
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this,
"android.permission.ACCESS_BACKGROUND_LOCATION") != PackageManager.PERMISSION_GRANTED) {
String[] strings = {android.Manifest.permission.ACCESS_FINE_LOCATION,
android.Manifest.permission.ACCESS_COARSE_LOCATION,
"android.permission.ACCESS_BACKGROUND_LOCATION"};
ActivityCompat.requestPermissions(this, strings, 2);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1) {
if (grantResults.length > 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, "onRequestPermissionsResult: apply LOCATION PERMISSION successful");
} else {
Log.i(TAG, "onRequestPermissionsResult: apply LOCATION PERMISSSION failed");
}
}
if (requestCode == 2) {
if (grantResults.length > 2 && grantResults[2] == PackageManager.PERMISSION_GRANTED
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
&& grantResults[1] == PackageManager.PERMISSION_GRANTED) {
Log.i(TAG, "onRequestPermissionsResult: apply ACCESS_BACKGROUND_LOCATION successful");
} else {
Log.i(TAG, "onRequestPermissionsResult: apply ACCESS_BACKGROUND_LOCATION failed");
}
}
}
Huawei Map Direction API
Huawei Map provides Direction API so that user can access all the information related to Map in RESTful API.
Huawei has provided the following API endpoint to access Direction API.
https://mapapi.cloud.huawei.com/mapApi/v1
Huawei provides the following direction API:
1. Walking Route Planning
2. Bicycling Route Planning
3. Driving Route Planning
Implemented the Driving Route API with the help of Retrofit and MVVM.
Retrofit Client
Created MapApiClient class for accessing the Direction API.
Code:
public class MapApiClient {
private final static HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
private static OkHttpClient okHttpClient;
public static Service getClient() {
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
interceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
interceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
if (okHttpClient == null) {
okHttpClient = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Consants.BASE_URL)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build();
return retrofit.create(Service.class);
}
public interface Service {
@POST("mapApi/v1/routeService/driving")
Single<PolylineResponse> getPolylines(
@Query("key") String apiKey,
@Body PolylineBody polylineBody);
}
}
API Repository
I have created MapApiRepo class for accessing the API client.
Code:
public class MapApiRepo {
private MapApiClient.Service mService;
public MapApiRepo() {
this.mService = MapApiClient.getClient();
}
public Single<PolylineResponse> executeMapApi(PolylineBody polylineBody) {
return mService.getPolylines(Consants.API_KEY, polylineBody);
}
}
ViewModel
I have created MapApiViewModel class for handling the API calls.
Code:
public class MapApiViewModel extends ViewModel {
private final CompositeDisposable disposables = new CompositeDisposable();
private MapApiRepo mapApiRepo = new MapApiRepo();
private MutableLiveData<PolylineResponse> mPolylineLiveData = new MutableLiveData<>();
public LiveData<PolylineResponse> getPolylineLiveData(PolylineBody body) {
disposables.add(mapApiRepo.executeMapApi(body)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> mPolylineLiveData.setValue(result),
throwable -> mPolylineLiveData.setValue(null)
));
return mPolylineLiveData;
}
@Override
protected void onCleared() {
disposables.clear();
}
}
Drawing Polyline
I have implemented this functionality in the following activity.
Code:
mapApiViewModel.getPolylineLiveData(getPolylineBody()).observe(this, result -> {
Log.d(TAG, result.toString());
getPolylineData(result);
}); private PolylineBody getPolylineBody() {
PolylineBody polylineBody = new PolylineBody();
Origin origin = new Origin();
origin.setLat("30.0444");
origin.setLng("31.2357");
Destination destination = new Destination();
destination.setLat("30.0131");
destination.setLng("31.2089");
polylineBody.setDestination(destination);
polylineBody.setOrigin(origin);
return polylineBody;
}
public void getPolylineData(PolylineResponse polylineResponse) {
List<Routes> routesList = polylineResponse.getRoutes();
List<Paths> paths = new ArrayList<>();
List<Steps> steps = new ArrayList<>();
List<Polyline> polylines = new ArrayList<>();
latLngList = new ArrayList<>();
for (int x = 0; x < routesList.size(); x++) {
//here we can access each array list with main.get(x).
for (Paths paths1 : routesList.get(x).getPaths()) {
paths.add(paths1);
}
for (int y = 0; y < paths.size(); y++) {
for (Steps step :
paths.get(y).getSteps()) {
steps.add(step);
}
}
for (int i = 0; i < steps.size(); i++) {
for (Polyline polyline :
steps.get(i).getPolyline()) {
polylines.add(polyline);
}
}
}
for (int i = 0; i < polylines.size(); i++) {
latLngList.add(new LatLng(Double.valueOf(polylines.get(i).getLat())
, Double.valueOf(polylines.get(i).getLng())));
}
hmap.addPolyline(new PolylineOptions()
.addAll(latLngList)
.color(Color.BLUE)
.width(3));
}
App Development
Created the following package inside the project. In which integrated as Account Kit, Huawei Ads, Huawei Map Direction Polyline API, Huawei Location, Huawei Map, Huawei Awareness Weather API, and Huawei Analytics.
{
"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"
}
PolyLineActivity
In this activity, I have integrated Location kit, Map, and Direction API.
Launch the application
Let us launch our application, see the result
If you have any doubts or queries. Leave your valuable comment in the comment section and do not forget to like and follow me
Conclusion
In this article, I have explained how to integrate Location Kit and Weather Awareness in Trip Booking application and draw a route between origins to destination.
References
Driving Direction API:
https://developer.huawei.com/consumer/en/doc/development/HMSCore-References-V5/directions-driving-0000001050161496-V5
Introduction
The API can perfectly retrieve the information of tables as well as text from cells, besides, merged cells can also be recognized. It supports recognition of tables with clear and unbroken lines, but not supportive of tables with crooked lines or cells divided by color background. Currently the API supports recognition from printed materials and snapshots of slide meetings, but it is not functioning for the screenshots or photos of excel sheets and any other table editing software.
Here, the image resolution should be higher than 720p (1280×720 px), and the aspect ratio (length-to-width ratio) should be lower than 2:1.
In this article, we will learn how to implement Huawei HiAI kit using Table Recognition service into android application, this service helps us to extract the table content from images.
Software requirements
1. Any operating system (MacOS, Linux and Windows).
2. Any IDE with Android SDK installed (IntelliJ, Android Studio).
3. HiAI SDK.
4. Minimum API Level 23 is required.
5. Required EMUI 9.0.0 and later version devices.
6. Required processors kirin 990/985/980/970/ 825Full/820Full/810Full/ 720Full/710Full
How to integrate Table recognition.
1. Configure the application on the AGC.
2. Apply for HiAI Engine Library.
3. Client application development process.
Configure application on the AGC
Follow the steps.
Step 1: We need to register as a developer account in AppGallery Connect. If you are already a developer ignore this step.
Step 2: Create an app by referring to Creating a Project and Creating an App in the Project
Step 3: Set the data storage location based on the current location.
Step 4: Generating a Signing Certificate Fingerprint.
Step 5: Configuring the Signing Certificate Fingerprint.
Step 6: Download your agconnect-services.json file, paste it into the app root directory.
Apply for HiAI Engine Library
What is Huawei HiAI?
HiAI is Huawei's AI computing platform. HUAWEI HiAI is a mobile terminal–oriented artificial intelligence (AI) computing platform that constructs three layers of ecology: service capability openness, application capability openness, and chip capability openness. The three-layer open platform that integrates terminals, chips, and the cloud brings more extraordinary experience for users and developers.
How to apply for HiAI Engine?
Follow the steps
Step 1: Navigate to this URL, choose App Service > Development and click HUAWEI HiAI.
{
"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 2: Click Apply for HUAWEI HiAI kit.
Step 3: Enter required information like Product name and Package name, click Next button.
Step 4: Verify the application details and click Submit button.
Step 5: Click the Download SDK button to open the SDK list.
Step 6: Unzip downloaded SDK and add into your android project under libs folder.
Step 7: Add jar files dependences into app build.gradle file.
implementation fileTree(include: ['*.aar', '*.jar'], dir: 'libs')
implementation 'com.google.code.gson:gson:2.8.6'
repositories {
flatDir {
dirs 'libs'
}
}Copy code
Client application development process
Follow the steps.
Step 1: Create an Android application in the Android studio (Any IDE which is your favorite).
Step 2: Add the App level Gradle dependencies. Choose inside project Android > app > build.gradle.
Code:
apply plugin: 'com.android.application'
apply plugin: 'com.huawei.agconnect'
Root level gradle dependencies.
Code:
maven { url 'https://developer.huawei.com/repo/' }
classpath 'com.huawei.agconnect:agcp:1.4.1.300'
Step 3: Add permission in AndroidManifest.xml
XML:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
Step 4: Build application.
Java:
import android.Manifest;
import android.content.Intent;
import android.graphics.Bitmap;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TableLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.huawei.hiai.vision.common.ConnectionCallback;
import com.huawei.hiai.vision.common.VisionBase;
import com.huawei.hiai.vision.common.VisionImage;
import com.huawei.hiai.vision.image.sr.ImageSuperResolution;
import com.huawei.hiai.vision.text.TableDetector;
import com.huawei.hiai.vision.visionkit.text.config.VisionTableConfiguration;
import com.huawei.hiai.vision.visionkit.text.table.Table;
import com.huawei.hiai.vision.visionkit.text.table.TableCell;
import com.huawei.hiai.vision.visionkit.text.table.TableContent;
import java.util.List;
public class TableRecognition extends AppCompatActivity {
private boolean isConnection = false;
private int REQUEST_CODE = 101;
private int REQUEST_PHOTO = 100;
private Bitmap bitmap;
private Button btnImage;
private ImageView originalImage;
private ImageView conversionImage;
private TextView textView;
private TextView tableContentText;
private final String[] permission = {
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE};
private ImageSuperResolution resolution;
private TableLayout tableLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_table_recognition);
requestPermissions(permission, REQUEST_CODE);
initializeVisionBase();
originalImage = findViewById(R.id.super_origin);
conversionImage = findViewById(R.id.super_image);
textView = findViewById(R.id.text);
tableContentText = findViewById(R.id.content_text);
btnImage = findViewById(R.id.btn_album);
tableLayout = findViewById(R.id.tableLayout);
btnImage.setOnClickListener(v -> {
selectImage();
tableLayout.removeAllViews();
});
}
private void initializeVisionBase() {
VisionBase.init(this, new ConnectionCallback() {
@Override
public void onServiceConnect() {
isConnection = true;
DoesDeviceSupportTableRecognition();
}
@Override
public void onServiceDisconnect() {
}
});
}
private void DoesDeviceSupportTableRecognition() {
resolution = new ImageSuperResolution(this);
int support = resolution.getAvailability();
if (support == 0) {
Toast.makeText(this, "Device supports HiAI Image super resolution service", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Device doesn't supports HiAI Image super resolution service", Toast.LENGTH_SHORT).show();
}
}
public void selectImage() {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, REQUEST_PHOTO);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (data != null && requestCode == REQUEST_PHOTO) {
try {
bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), data.getData());
originalImage.setImageBitmap(bitmap);
if (isConnection) {
extractTableFromTheImage();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
private void extractTableFromTheImage() {
tableContentText.setVisibility(View.VISIBLE);
TableDetector mTableDetector = new TableDetector(this);
VisionImage image = VisionImage.fromBitmap(bitmap);
VisionTableConfiguration mTableConfig = new VisionTableConfiguration.Builder()
.setAppType(VisionTableConfiguration.APP_NORMAL)
.setProcessMode(VisionTableConfiguration.MODE_OUT)
.build();
mTableDetector.setVisionConfiguration(mTableConfig);
mTableDetector.prepare();
Table table = new Table();
int mResult_code = mTableDetector.detect(image, table, null);
if (mResult_code == 0) {
int count = table.getTableCount();
List<TableContent> tc = table.getTableContent();
StringBuilder sbTableCell = new StringBuilder();
List<TableCell> tableCell = tc.get(0).getBody();
for (TableCell c : tableCell) {
List<String> words = c.getWord();
StringBuilder sb = new StringBuilder();
for (String s : words) {
sb.append(s).append(",");
}
String cell = c.getStartRow() + ":" + c.getEndRow() + ": " + c.getStartColumn() + ":" +
c.getEndColumn() + "; " + sb.toString();
sbTableCell.append(cell).append("\n");
tableContentText.setText("Count = " + count + "\n\n" + sbTableCell.toString());
}
}
}
}Copy code
Result
Tips and Tricks
Recommended image should be larger than 720px.
Multiple table recognition currently not supported.
If you are taking Video from a camera or gallery make sure your app has camera and storage permission.
Add the downloaded huawei-hiai-vision-ove-10.0.4.307.aar, huawei-hiai-pdk-1.0.0.aar file to libs folder.
Check dependencies added properly.
Latest HMS Core APK is required.
Min SDK is 21. Otherwise you will get Manifest merge issue.
Conclusion
In this article, we have done table content extraction from image, for further analysis with statistics or just for editing it. This works for tables with clear and simple structure information. We have learnt the following concepts.
1. Introduction of Table recognition?
2. How to integrate Table using Huawei HiAI
3. How to Apply Huawei HiAI
4. How to build the application
Reference
Table Recognition
Apply for Huawei HiAI
Happy coding
useful sharing,thanks!
Introduction
In this article, we will learn how to detect human skeletal detection.
The key skeletal features are important for describing human posture and predicting human behavior. Therefore, the recognition of key skeletal features is the basis for a diversity of computer vision tasks, such as motion categorizations, abnormal behavior detection, and auto-navigation. In recent years, improved skeletal feature recognition has been widely applied to the development of deep learning technology, especially domains relating to computer vision.
Pose estimation mainly detects key human body features such as joints and facial features, and provides skeletal information based on such features.
If input a portrait image, users will obtain the coordinate information of 14 key skeletal features of each portrait in it. The algorithm supports real-time processing and returns the result within 70 ms. The result presents posture information regarding head, neck, right and left shoulders, right and left elbows, right and left wrists, and right and left hips, right and left knees, and right and left ankles.
How to integrate Pose Estimation
1. Configure the application on the AGC.
2. Apply for HiAI Engine Library.
3. Client application development process.
Configure application on the AGC
Follow the steps
Step 1: We need to register as a developer account in AppGallery Connect. If you are already a developer ignore this step.
Step 2: Create an app by referring to Creating a Project and Creating an App in the Project
Step 3: Set the data storage location based on the current location.
Step 4: Generating a Signing Certificate Fingerprint.
Step 5: Configuring the Signing Certificate Fingerprint.
Step 6: Download your agconnect-services.json file, paste it into the app root directory.
Apply for HiAI Engine Library
What is Huawei HiAI?
HiAI is Huawei’s AI computing platform. HUAWEI HiAI is a mobile terminal–oriented artificial intelligence (AI) computing platform that constructs three layers of ecology: service capability openness, application capability openness, and chip capability openness. The three-layer open platform that integrates terminals, chips, and the cloud brings more extraordinary experience for users and developers.
How to apply for HiAI Engine?
Follow the steps
Step 1: Navigate to this URL, choose App Service > Development and click HUAWEI HiAI.
{
"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 2: Click Apply for HUAWEI HiAI kit.
Step 3: Enter required information like Product name and Package name, click Next button.
Step 4: Verify the application details and click Submit button.
Step 5: Click the Download SDK button to open the SDK list.
Step 6: Unzip downloaded SDK and add into your android project under libs folder.
Step 7: Add jar files dependences into app build.gradle file.
Code:
implementation fileTree(include: ['*.aar', '*.jar'], dir: 'libs')
implementation 'com.google.code.gson:gson:2.8.6'
repositories {
flatDir {
dirs 'libs'
}
}
Client application development process
Follow the steps.
Step 1: Create an Android application in the Android studio (Any IDE which is your favorite).
Step 2: Add the App level Gradle dependencies. Choose inside project Android > app > build.gradle.
Code:
apply plugin: 'com.android.application'
apply plugin: 'com.huawei.agconnect'
Root level gradle dependencies.
Code:
maven { url 'https://developer.huawei.com/repo/' }
classpath 'com.huawei.agconnect:agcp:1.4.1.300'
Step 3: Add permission in AndroidManifest.xml.
XML:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
Step 4: Build application.
Java:
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import android.widget.Toast;
import com.huawei.hiai.pdk.pluginservice.ILoadPluginCallback;
import com.huawei.hiai.pdk.resultcode.HwHiAIResultCode;
import com.huawei.hiai.vision.common.ConnectionCallback;
import com.huawei.hiai.vision.common.VisionBase;
import com.huawei.hiai.vision.common.VisionImage;
import com.huawei.hiai.vision.image.detector.PoseEstimationDetector;
import com.huawei.hiai.vision.visionkit.image.detector.BodySkeletons;
import com.huawei.hiai.vision.visionkit.image.detector.PeConfiguration;
import com.huawei.hiai.vision.visionkit.text.config.VisionTextConfiguration;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MainActivity extends AppCompatActivity {
private Object mWaitResult = new Object(); // The user establishes a semaphore and waits for the callback information of the bound service
private ImageView mImageView;
private ImageView yogaPose;
[USER=439709]@override[/USER]
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageView = (ImageView) findViewById(R.id.skeleton_img);
yogaPose = (ImageView) findViewById(R.id.yogaPose);
//The application needs to bind the CV service first, and monitor whether the service is successfully connected
VisionBase.init(getApplicationContext(), new ConnectionCallback() {
public void onServiceConnect() { // Listen to the message that the service is successfully bound
Log.d("SkeletonPoint", "HwVisionManager onServiceConnect OK.");
Toast.makeText(getApplicationContext(),"Service binding successfully!",Toast.LENGTH_LONG).show();
synchronized (mWaitResult) {
mWaitResult.notifyAll();
doSkeletonPoint();
}
}
public void onServiceDisconnect() { // Listen to the message that the binding service failed
Log.d("SkeletonPoint", "HwVisionManager onServiceDisconnect OK.");
Toast.makeText(getApplicationContext(),"Service binding failed!",Toast.LENGTH_LONG).show();
synchronized (mWaitResult) {
mWaitResult.notifyAll();
}
}
});
}
[USER=439709]@override[/USER]
protected void onResume() {
super.onResume();
}
[USER=439709]@override[/USER]
protected void onDestroy() {
super.onDestroy();
}
private void doSkeletonPoint() {
// Declare the skeleton detection interface object, and set the plug-in to cross-process mode MODE_OUT (also can be set to the same process mode MODE_IN)
PoseEstimationDetector mPoseEstimationDetector = new PoseEstimationDetector(MainActivity.this);
PeConfiguration config = new PeConfiguration.Builder()
.setProcessMode(VisionTextConfiguration.MODE_OUT)
.build();
mPoseEstimationDetector.setConfiguration(config);
// Currently, the skeleton detection interface accepts input as Bitmap, which is encapsulated into VisionImage. Video streaming will be supported in the future
Bitmap bitmap = null;
VisionImage image = null;
// TODO: Developers need to create a Bitmap here
BufferedInputStream bis = null;
try {
bis = new BufferedInputStream(getAssets().open("0.jpg"));
} catch (IOException e) {
Log.d("SkeletonPoint", e.toString());
Toast.makeText(getApplicationContext(), e.toString(),Toast.LENGTH_LONG).show();
}
bitmap = BitmapFactory.decodeStream(bis);
yogaPose.setImageBitmap(bitmap);
Bitmap bitmap2 = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
image = VisionImage.fromBitmap(bitmap);
// Query whether the capability supports the installation of plug-ins at the same time. getAvailability() returns -6 to indicate that the current engine supports this ability, but the plug-in needs to be downloaded and installed on the cloud side
int availability = mPoseEstimationDetector.getAvailability();
int installation = HwHiAIResultCode.AIRESULT_UNSUPPORTED; // Indicates that it does not support
if (availability == -6) {
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
LoadPluginCallback cb = new LoadPluginCallback(lock, condition);
// Download and install the plugin
mPoseEstimationDetector.loadPlugin(cb);
lock.lock();
try {
condition.await(90, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Log.e("SkeletonPoint", e.getMessage());
} finally {
lock.unlock();
}
installation = cb.mResultCode;
}
// You can call the interface after downloading and installing successfully
if ((availability == HwHiAIResultCode.AIRESULT_SUCCESS)
|| (installation == HwHiAIResultCode.AIRESULT_SUCCESS)) {
// Load model and resources
mPoseEstimationDetector.prepare();
// Skeleton point result returned
List<BodySkeletons> mBodySkeletons = new ArrayList<>();
// The run method is called synchronously. At present, the maximum interface run time is 70 ms, and it is recommended to use another thread to call every frame
// After detect, bitmap will be released
int resultCode = mPoseEstimationDetector.detect(image, mBodySkeletons, null);
Toast.makeText(getApplicationContext(),"resultCode: " + resultCode,Toast.LENGTH_LONG).show();
// Draw a point
if (mBodySkeletons.size() != 0) {
drawPointNew(mBodySkeletons, bitmap2);
mImageView.setImageBitmap(bitmap2);
}
// Release engine
mPoseEstimationDetector.release();
}
}
public static class LoadPluginCallback extends ILoadPluginCallback.Stub {
private int mResultCode = HwHiAIResultCode.AIRESULT_UNKOWN;
private Lock mLock;
private Condition mCondition;
LoadPluginCallback(Lock lock, Condition condition) {
mLock = lock;
mCondition = condition;
}
[USER=439709]@override[/USER]
public void onResult(int resultCode) throws RemoteException {
Log.d("SkeletonPoint", "LoadPluginCallback, onResult: " + resultCode);
mResultCode = resultCode;
mLock.lock();
try {
mCondition.signalAll();
} finally {
mLock.unlock();
}
}
[USER=439709]@override[/USER]
public void onProgress(int i) throws RemoteException {
}
}
private void drawPointNew(List<BodySkeletons> poseEstimationMulPeopleSkeletons, Bitmap bmp) {
if ((poseEstimationMulPeopleSkeletons == null)
|| (poseEstimationMulPeopleSkeletons.size() < 1)) {
return;
}
int humanNum = poseEstimationMulPeopleSkeletons.size();
int points = 14;
int size = humanNum * points;
int[] xArr = new int[size];
int[] yArr = new int[size];
for (int j = 0; (j < humanNum) && (j < 6); j++) {
for (int i = 0; i < points; i++) {
xArr[j * points + i] = (int)((float)poseEstimationMulPeopleSkeletons.get(j).getPosition().get(i).x);
yArr[j * points + i] = (int)((float)poseEstimationMulPeopleSkeletons.get(j).getPosition().get(i).y);
}
}
Paint p = new Paint();
p.setStyle(Paint.Style.FILL_AND_STROKE);
p.setStrokeWidth(5);
p.setColor(Color.GREEN);
Canvas canvas = new Canvas(bmp);
int len = xArr.length;
int[] color = {0xFF000000, 0xFF444444, 0xFF888888, 0xFFCCCCCC, 0xFFFF0000, 0xFF00FF00, 0xFF0000FF,
0xFFFFFF00, 0xFF00FFFF, 0xFFFF00FF, 0xFF8800FF, 0xFF4400FF, 0xFFFFDDDD};
p.setColor(color[4]);
for (int i = 0; i < len; i++) {
canvas.drawCircle(xArr, yArr, 10, p);
}
for (int i = 0; i < humanNum; i++) {
int j = 0;
p.setColor(color[j++]);
if ((xArr[0+points*i]>0) &&(yArr[0+points*i]>0)&&(xArr[1+points*i]>0)&&(yArr[1+points*i]>0)) {
canvas.drawLine(xArr[0+points*i], yArr[0+points*i], xArr[1+points*i], yArr[1+points*i], p);
}
p.setColor(color[j++]);
if ((xArr[1+points*i]>0)&&(yArr[1+points*i]>0)&&(xArr[2+points*i]>0)&&(yArr[2+points*i]>0)) {
canvas.drawLine(xArr[1+points*i], yArr[1+points*i], xArr[2+points*i], yArr[2+points*i], p);
}
p.setColor(color[j++]);
if ((xArr[2+points*i]>0)&&(yArr[2+points*i]>0)&&(xArr[3+points*i]>0)&&(yArr[3+points*i]>0)) {
canvas.drawLine(xArr[2+points*i], yArr[2+points*i], xArr[3+points*i], yArr[3+points*i], p);
}
p.setColor(color[j++]);
if ((xArr[3+points*i]>0)&&(yArr[3+points*i]>0)&&(xArr[4+points*i]>0)&&(yArr[4+points*i]>0)) {
canvas.drawLine(xArr[3+points*i], yArr[3+points*i], xArr[4+points*i], yArr[4+points*i], p);
}
p.setColor(color[j++]);
if ((xArr[1+points*i]>0)&&(yArr[1+points*i]>0)&&(xArr[5+points*i]>0)&&(yArr[5+points*i]>0)) {
canvas.drawLine(xArr[1+points*i], yArr[1+points*i], xArr[5+points*i], yArr[5+points*i], p);
}
p.setColor(color[j++]);
if ((xArr[5+points*i]>0)&&(yArr[5+points*i]>0)&&(xArr[6+points*i]>0)&&(yArr[6+points*i]>0)) {
canvas.drawLine(xArr[5+points*i], yArr[5+points*i], xArr[6+points*i], yArr[6+points*i], p);
}
p.setColor(color[j++]);
if ((xArr[6+points*i]>0)&&(yArr[6+points*i]>0)&&(xArr[7+points*i]>0)&&(yArr[7+points*i]>0)) {
canvas.drawLine(xArr[6+points*i], yArr[6+points*i], xArr[7+points*i], yArr[7+points*i], p);
}
p.setColor(color[j++]);
if ((xArr[1+points*i]>0)&&(yArr[1+points*i]>0)&&(xArr[8+points*i]>0)&&(yArr[8+points*i]>0)) {
canvas.drawLine(xArr[1+points*i], yArr[1+points*i], xArr[8+points*i], yArr[8+points*i], p);
}
p.setColor(color[j++]);
if ((xArr[8+points*i]>0)&&(yArr[8+points*i]>0)&&(xArr[9+points*i]>0)&&(yArr[9+points*i]>0)) {
canvas.drawLine(xArr[8+points*i], yArr[8+points*i], xArr[9+points*i], yArr[9+points*i], p);
}
p.setColor(color[j++]);
if ((xArr[9+points*i]>0)&&(yArr[9+points*i]>0)&&(xArr[10+points*i]>0)&&(yArr[10+points*i]>0)) {
canvas.drawLine(xArr[9+points*i], yArr[9+points*i], xArr[10+points*i], yArr[10+points*i], p);
}
p.setColor(color[j++]);
if ((xArr[1+points*i]>0)&&(yArr[1+points*i]>0)&&(xArr[11+points*i]>0)&&(yArr[11+points*i]>0)) {
canvas.drawLine(xArr[1+points*i], yArr[1+points*i], xArr[11+points*i], yArr[11+points*i], p);
}
p.setColor(color[j++]);
if ((xArr[11+points*i]>0)&&(yArr[11+points*i]>0)&&(xArr[12+points*i]>0)&&(yArr[12+points*i]>0)) {
canvas.drawLine(xArr[11+points*i], yArr[11+points*i], xArr[12+points*i], yArr[12+points*i], p);
}
p.setColor(color[j]);
if ((xArr[12+points*i]>0)&&(yArr[12+points*i]>0)&&(xArr[13+points*i]>0)&&(yArr[13+points*i]>0)) {
canvas.drawLine(xArr[12+points*i], yArr[12+points*i], xArr[13+points*i], yArr[13+points*i], p);
}
}
}
}
Result
Tips and Tricks
This API provides optimal detection results when no more than three portraits are not appear in the image.
This API works better when the proportion of a portrait in an image is high.
At least four skeletal features of the upper part of the body are required for reliable recognition results.
If you are taking Video from a camera or gallery make sure your app has camera and storage permissions.
Add the downloaded huawei-hiai-vision-ove-10.0.4.307.aar, huawei-hiai-pdk-1.0.0.aar file to libs folder.
Check dependencies added properly.
Latest HMS Core APK is required.
Min SDK is 21. Otherwise you will get Manifest merge issue.
Conclusion
In this article, we have learnt what the pose estimation is and how to integrate pose estimation using Huawei HiAI in android with java. We able to detect the image skeleton in the example. It is able to detect head, neck, elbow, knee and ankle.
Reference
Pose Estimation
Apply for Huawei HiAI