More information like this, you can visit HUAWEI Developer Forum
Original link: https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0201346068348190148&fid=0101188387844930001
I have written series of article on Quick App. If you are new to Quick App, refer my previous articles.
Quick App set up
A Novice Journey Towards Quick App ( Part 2 )
A Novice Journey Towards Quick App ( Part 3 )
In this article, we can learn to integrate the Account kit in Quick App.
Introduction
Huawei Account kit helps to login to applications easily and quickly. Once application access account information, user do not need to enter the details like email, name, profile picture etc. It reduces the user time, once the user sign in with trusted Huawei Account kit, then no need to verify email or phone number.
Follow the steps.
1. Create project (refer Quick App Part 1)
2. Design Sign in screen
Configuration in AGC
1. Sign in in to AppGallery and select My projects.
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
2. Click Add project.
3. Click Add app in General information tab and set Data storage location.
Note: App Id is very important.
4.Enable Account kit in Manage APIs.
5. Sign in to Huawei Developer using developer id, then click Console.
6. Select Huawei ID in App services page.
7. Now generate certificate in the Quick App IDE(Tools-> Certificate)
8. Once Certificate is creation is done copy the release folder certificates to debug folder. If there is already certificates remove it and copy from release folder.
9. Find the app from the list of app in which the Huawei ID service will be configured, then click Update.
10. Add the certificate and click Submit.
Now let us come to coding.
Add the service.account in manifest.json file
Import the service account in script.
Code:
import account from '@service.account'
Code:
<template>
<div class="container">
<div class="item-container">
<input type="button" class="btn" onclick="useAuthor" value="Login using token mode" />
</div>
<div class="item-container">
<input type="button" class="btn" onclick="getsign" value="Get Account Info" />
</div>
<div class="item-container">
<input type="button" class="btn" onclick="loginByCodeMode" value="Login using authorization code mode" />
</div>
<div class="item-container">
<input type="button" class="btn" onclick="checkUserSession" value="Check user session" />
</div>
<div class="page-title-wrap">
<text class="result" style="color: #000000;" > {{ result }}</text>
</div>
</div>
</template>
<style>
.container{
flex: 1;
flex-direction: column;
}
.page-title-wrap {
padding-top: 50px;
padding-bottom: 80px;
justify-content: center;
}
.result{
padding-top: 30px;
padding-bottom: 30px;
padding-left: 40px;
padding-right: 40px;
border-color: #bbbbbb;
color: #bbbbbb;
}
.btn {
height: 80px;
text-align: center;
border-radius: 5px;
margin-right: 40px;
margin-left: 40px;
margin-bottom: 30px;
color: #ffffff;
font-size: 30px;
background-color: #ff0f1b;
}
.item-container {
margin-top: 30px;
margin-right: 40px;
margin-left: 40px;
flex-direction: column;
}
</style>
<script>
import account from '@service.account'
import prompt from '@system.prompt'
export default {
data: {
componentName: 'account Kit',
componentData: {},
fetchData: '',
attoken: '',
accode:'',
sign: '',
result: ''
},
onInit() {
this.$page.setTitleBar({text: 'Account Kit',
textColor: '#ffffff',
backgroundColor: '#ff0f1b',
menu: false
});
this.componentData = this.$t('Account Kit');
// this.result = 'HI';
},
getsign: function () {
var that = this;
account.getProfile({
appid: "YOUR_APP_ID",
token: that.attoken,
success: function (ret) {
that.result = JSON.stringify(ret)
},
fail: function (erromsg, errocode) {
prompt.showToast({ message: 'getprofile fail --- ' + errocode + ':' + erromsg });
}
})
},
useAuthor: function () {
var that = this;
account.authorize({
appid: "YOUR_APP_ID",
type: "token",
scope: "scope.baseProfile",
state: 5,
redirectUri: "http://www.example.com/",
success: function (ret) {
that.attoken = ret.accessToken;
that.result = JSON.stringify(ret)
},
fail: function (erromsg, errocode) {
prompt.showToast({ message: 'authorize fail --- ' + errocode + ':' + erromsg });
}
})
},
// Login using Authorization Code
checkUserSession: function () {
account.checkUserSession({
success: function (data2) {
console.log('handling success profile: ' + JSON.stringify(data2));
},
fail: function (data, code) {
console.log('handling fail, code =' + code);
}
});
},
loginByCodeMode: function() {
var that = this;
account.authorize({
appid: "YOUR_APP_ID",
type: "code",
scope: "scope.baseProfile",
state:5,
redirectUri: "http://www.example.com/",
success: function (ret) {
that.atcode = ret.code;
console.log(that.componentData.result + JSON.stringify(ret));
that.result = JSON.stringify(ret)
},
fail: function (erromsg, errocode) {
prompt.showToast({ message: 'authorize fail --- ' + errocode + ':' + erromsg });
console.log({message: 'authorize fail --- ' + errocode + ':' + erromsg});
}
})
}
}
</script>
Result
Conclusion
In this article we have learnt how to integrate the Account kit in Quick App. In upcoming article, I will come up with new concept.
Reference
Account kit official document
https://developer.huawei.com/consumer/en/doc/development/quickApp-Guides/quickapp-enable-account-kit
What is the best advantage of Quick app compare to other like ionic, ReactNative
Related
More information like this, you can visit HUAWEI Developer Forum
Original link: https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0202341042270230096&fid=0101187876626530001
{
"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"
}
Introduction
Well, there are a number of reasons to love Quick Apps. Some of the major ones are the fact that they don’t need to be installed and at most can take 10 MBs of storage on your phone.
In this article I will not be discussing the setup of a project and the basics, so if you still want to know more on the facts and basics, please check-out this series of articles in the references setion below.
In this article I will be focusing integrating location kit with your Quick Apps in order to filter your content for your users based on their geographical location; and using system APIs to check the type of the network so that you can give your users the option to download content over WIFI or Cellular data.
Well, enough chit-chat and let’s look at some code.
Steps to follow:
1. Create project (refer to the articles in the reference)
2. Add system API declarations
3. Import the interfaces to the page you’ll be using
4. Call the interfaces you need.
Adding the location kit:
Step one: Declaring the system interface:
Add the following configuration to the features object in the manifest.json file.
Code:
{
"name": "system.geolocation"
}
Step two: Importing the interface:
Add the following configuration to the <script> on the page where you will be using the interface.
Code:
import geolocation from '@system.geolocation'
Now that the setup is done, let’s look at the interfaces that we can use.
Note: At the moment there is limited functionality available outside mainland China.
But don’t sweat it. There is still quite a bit you can do with this interface.
Step three: Call the interfaces you need
1. Getting the user’s current location:
Code:
geolocation.getLocation({
success: function (data) {
self.locationData = {
longitude: data.longitude,
latitude: data.latitude,
altitude: data.altitude,
time: data.time,
speed: data.speed,
accuracy: data.accuracy,
}
},
fail: function (data, code) {
console.log('handling fail, code = ' + code);
}
});
2. Monitoring to the user’s location for an extended period of time:
Code:
geolocation.subscribe({
callback: function (data) {
self.locationData = {
longitude: data.longitude,
latitude: data.longitude,
altitude: data.altitude,
time: data.time,
speed: data.speed,
accuracy: data.accuracy,
}
},
fail: function (data, code) {
console.log('handling fail, code = ' + code);
}
});
3. Canceling the monitoring of the user’s location:
Code:
geolocation.unsubscribe();
Aside: Interesting thing to try is use the openLocation() interface – which actually works even though it is officially only supported in Chinese mainland. Awesome stuff I tell you.
Now looking at the Network Status system API.
This API allows you to get the type of network the user is using and you can subscribe to it so that you can prompt the user to download using their cellular data or wait for a WIFI connection.
The declaration and import of this interface is similar to the one above.
Step one: Declaring the system interface:
In the manifest.json file, below the geolocation interface add:
Code:
{
"name": "system.network"
}
Step two: Importing the interface:
And in the <script> on the page where you intend to use it, add:
Code:
import network from '@system.network';
Now,
Step three: Call the interfaces you need
1. Get the network type: (WIFI/2G/3G/4G/none):
Code:
network.getType({
success: function (data) {
self.netwrk = data;
}
});
2. Subscribe to the network to monitor changes in the network type:
Code:
network.subscribe({
callback: function (data) {
self.netwrk = data;
}
});
3. And of course, unsubscribe to the network monitoring:
Code:
network.unsubscribe();
Code Example
So here is some code for a page that demonstrates the use of some of the interfaces above:
HTML5 Template
Code:
<template>
<!-- Only one root node is allowed in template. -->
<div class="container">
<div class="container">
<text class="title">Status</text>
</div>
<div class="info">
<label>Longitude: </label>
<text>{{ locationData.longitude }}</text>
</div>
<div class="info">
<label>Latitude: </label>
<text> {{ locationData.latitude }}</text>
</div>
<div class="info">
<label>Altitude: </label>
<text> {{ locationData.altitude }}</text>
</div>
<div class="info">
<label>Time: </label>
<text> {{ locationData.time }}</text>
</div>
<div class="info">
<label>Speed: </label>
<text> {{ locationData.speed }}</text>
</div>
<div class="info">
<label>Accuracy: </label>
<text> {{ locationData.accuracy }}</text>
</div>
<div class="info">
<label>Network Type: </label>
<text> {{ netwrk.type }}</text>
</div>
<div class="bottom">
<input type="button" class="btn" value="Settings" onclick="settings" />
</div>
</div>
</template>
CSS Code
Code:
.container{
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #00bfda;
}
.bottom{
padding-top: 200px;
margin-top: 100px;
}
.info{
font-size: 40px;
width: 70%;
}
.title{
font-size: 60px;
}
.btn{
height: 80px;
width: 230px;
font-size: 35px;
margin: 20px;
border-radius: 5px;
background-color: #1e90ff;
color: #ffffff;
}
JS Code
Code:
import router from '@system.router';
import network from '@system.network';
import geolocation from '@system.geolocation';
module.exports = {
data: {
componentName: 'SystemInfo',
componentData: {},
locationData: {},
netwrk: {}
},
onInit() {
this.$page.setTitleBar({
textColor: '#00bfda',
backgroundColor: '#00bfda',
backgroundOpacity: 1,
menu: true
});
const self = this;
network.getType({
success: function (data) {
self.netwrk = data;
}
});
geolocation.subscribe({
callback: function (data) {
self.locationData = {
longitude: data.longitude,
latitude: data.latitude,
altitude: data.altitude,
time: data.time,
speed: data.speed,
accuracy: data.accuracy,
}
},
fail: function (data, code) {
console.log('handling fail, code = ' + code);
}
});
},
settings() {
router.push({
uri: '/Settings',
})
},
};
OUTPUT
And this is what the page will look like:
Conclusion
We have learnt how to implement the location interface and network interface to be able to obtain the user's location and network status.
Well. That’s all for now from me…
References:
Quick App Documentation:
https://developer.huawei.com/consumer/en/doc/development/quickApp-Guides/quickapp-introduction
Series of Quick App articles:
Part One
https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0201303613601240080&fid=0101188387844930001
Part Two
https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0201333894482540039&fid=0101188387844930001
Part Three
https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0201339889439220082&fid=0101187876626530001
More information like this, you can visit HUAWEI Developer Forum
I have written series of article on Quick App. If you are new to Quick App refer my previous articles.
Quick App set up
A Novice Journey Towards Quick App ( Part 2 )
A Novice Journey Towards Quick App ( Part 3 )
In this article we will learn how to use Location Kit in Quick App.
Introduction
Geolocation is the ability to track a device’s using GPS, cell phone towers, Wi-Fi access points or a combination of these. Huawei Location Kit combines the GPS, Wi-Fi, and base station locations to help you quickly obtain precise user locations.
Should have
1. To integrate the location kit in Quick App you should have developer account. Register here.
2. Android version 4.4 or later.
3. HMS core version 3.0.0.300 later has to be installed.
4. Enable HMS Core Location permission, Setting >Apps > HMS Core > Permission.
{
"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"
}
5. Enable location permission for application to be tested.
6. Location service should be enabled in the notification panel.
7. Test application in good network signal to get the more accurate location information.
Steps to be followed.
1. Create project (refer Quick App Part 1).
2. Add the feature attribute in manifest.json.
Code:
{
"name": "system.geolocation"
}
3. Import the geolocation in the script
Code:
import geolocation from '@system.geolocation'
4. Design Location kit screen.
1) geolocation.getLocation(cordType, timeout, success, fail, complete)
· cordType: wgs84: This is the default value. It indicates that the geographical location will be returned by invoking the system location ability.
· Timeout: timeout duration in milliseconds. Default value is 30000. It is mandatory
· Success: It is callback function used when interface is successfully called.
· Fail: Callback function used when the interface fails to be called.
· Complete: Callback function used when the interface call is completed.
2) geolocation.subscribe(cordType, callback, fail)
· cordType: wgs84: This is the default value. It indicates that the geographical location will be returned by invoking the system location ability.
· Callback: It is called whenever location information changed.
· Fail: Callback function used when the interface fails to be called.
3) gelocation.unsubscribe() This is cancel the monitoring the geographical location.
4) geolocation.getLocationType(success, fail, complete): To get the location types currently supported by the system.
5) geolocation.openLocation: This is to view the location on the built in map. Currently it is Supported only in Chinese mainland.
6) geolocation.chooseLocation: This it open map and select location. Currently it is supported only in Chinese mainland.
Code:
<template>
<div class="container">
<div class="page-title-wrap">
<text class="page-title">{{componentName}}</text>
</div>
<div class="item-content">
<text class="txt">{{$t('Current Location')}}</text>
<text class="txt">latitude: {{geolocationGetData.latitude}}</text>
<text class="txt">longitude: {{geolocationGetData.longitude}}</text>
<text class="txt">altitude: {{geolocationGetData.altitude}}</text>
<text class="txt">accuracy: {{geolocationGetData.accuracy}}</text>
<text class="txt">heading: {{geolocationGetData.heading}}</text>
<text class="txt">speed: {{geolocationGetData.speed}}</text>
<text class="txt">time: {{geolocationGetData.time}}</text>
</div>
<input type="button" class="btn" onclick="getGeolocation" value="{{$t('Get My Current Location')}}" />
<div class="item-content">
<text class="txt">{{$t('Location')}}</text>
<text class="txt">latitude: {{geolocationListenData.latitude}}</text>
<text class="txt">longitude: {{geolocationListenData.longitude}}</text>
<text class="txt">accuracy: {{geolocationListenData.accuracy}}</text>
<text class="txt">time: {{geolocationListenData.time}}</text>
</div>
<input type="button" class="btn" onclick="listenGeolocation" value="{{$t('Monitor Location')}}" />
<input type="button" class="btn" onclick="cancelGeolocation" value="{{$t('Cancel Monitoring Location')}}" />
<div class="item-content">
<text class="txt">{{$t('Location Type: ')}}{{typeVaule}}</text>
</div>
<input type="button" class="btn" onclick="getLocationType" value="{{$t('Location type')}}" />
<input type="button" class="btn" onclick="openLocation" value="Open Location in Map" />
<input type="button" class="btn" onclick="chooseLocation" value="Choose location from Map" />
</div>
</div>
</template>
<style>
@import "../../../common/css/common.css";
.item-container {
margin-bottom: 30px;
margin-right: 60px;
margin-left: 60px;
flex-direction: column;
color: #ffffff;
}
.item-content {
flex-direction: column;
padding: 30px;
margin-bottom: 50px;
align-items: flex-start;
color: #ffffff;
}
.txt{
color: #ffffff;
}
</style>
<script>
import geolocation from '@system.geolocation'
import prompt from '@system.prompt'
export default {
data: {
componentName: 'Location Kit',
componentData: {},
deviceInfo: '',
isHuawei: false,
time: '',
geolocationGetData: {
latitude: '',
longitude: '',
altitude: '',
accuracy: '',
heading: '',
speed: '',
time: ''
},
geolocationListenData: {
latitude: '',
longitude: '',
time: '',
accuracy: ''
},
typeVaule: ''
},
onInit: function () {
this.$page.setTitleBar({ text: 'Location Kit' })
this.componentData = this.$t('message.interface.system.geolocation');
},
getGeolocation: function () {
var that = this;
if (that.isHuawei) {
prompt.showToast({
message: this.componentData.baiduMap
})
geolocation.getLocation({
coordType: "gcj02",
timeout: 2000,
success: function (ret) {
that.geolocationGetData = ret;
console.log(that.geolocationGetData.time);
var date = new Date(that.geolocationGetData.time);
that.geolocationGetData.time = date;
},
fail: function (erromsg, errocode) {
console.log('geolocation.getLocation----------' + errocode + ': ' + erromsg)
},
complete: function () {
console.log('geolocation complete----------')
}
})
} else {
prompt.showToast({
message: this.componentData.systemMap
})
geolocation.getLocation({
timeout: 2000,
success: function (ret) {
that.geolocationGetData = ret;
var time = new Date().getTime();
console.log(that.geolocationGetData.time);
var date = new Date(that.geolocationGetData.time);
that.geolocationGetData.time = date;
},
fail: function (erromsg, errocode) {
console.log('geolocation.getLocation----------' + errocode + ': ' + erromsg)
},
complete: function () {
console.log('geolocation complete----------')
}
})
}
},
listenGeolocation: function () {
var that = this;
geolocation.subscribe({
callback: function (ret) {
that.geolocationListenData = ret;
console.log(that.geolocationListenData.time);
var date = new Date(ret.time);
that.geolocationListenData.time = date;
},
fail: function (erromsg, errocode) {
console.log('geolocation.subscribe----------' + errocode + ': ' + erromsg)
}
})
},
cancelGeolocation: function () {
geolocation.unsubscribe();
},
getLocationType: function () {
var that = this;
geolocation.getLocationType({
success: function (data) {
that.typeVaule = data.types;
console.log("ret - " + data.types)
}
})
},
openLocation: function(){
geolocation.openLocation({
latitude: 12.972442,
longitude: 77.580643,
coordType:"gcj02",
name: "Bangalore",
address: "Bangalore",
scale: 18,
success: function () {
console.log('openLocation success .');
},
fail: function (erromsg, errocode) {
console.log('geolocation.openLocation----------' + errocode + ': ' + erromsg)
},
complete: function () {
console.log('openLocation complete.');
}
})
},
chooseLocation: function(){
console.log("chooseLocation");
geolocation.chooseLocation({
latitude: 12.972442,
longitude: 77.580643,
coordType:"gcj02",
success: function (data) {
console.log('chooseLocation success �� ' + JSON.stringify(data));
},
fail: function (error) {
console.log('chooseLocation fail : ' + error.message);
},
complete: function () {
console.log('chooseLocation complete.');
}
})
}
}
</script>
Result
Conclusion
In this article, we have learnt how to integrate the Location kit in Quick App. In upcoming article I will come up with new concept.
Reference
Location kit official document
Introduction
Harmony OS is a future-proof distributed operating system open to you as part of the initiatives for the all-scenario strategy, adaptable to mobile office, fitness and health, social communication, and media entertainment, to name a few. Unlike a legacy operating system that runs on a standalone device, Harmony OS is built on a distributed architecture designed based on a set of system capabilities. It can run on a wide range of device forms, including smartphones, tablets, wearables, smart TVs and head units.
In this article, we will create simple lite wearable JS application to obtain device information.
{
"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"
}
Requirements
1) DevEco IDE
2) Lite wearable simulator
Implementation
First page, index.hml contains <swiper> container that enables the switch of child components.
Code:
<swiper class="container" index="{{index}}">
<div class="swiper-item item1">
<text class="title">BRAND</text>
<text class="subtitle">{{brand}}</text>
<div class="seperator" ></div>
<text class="title">MANUFACTURER</text>
<text class="subtitle">{{manufacturer}}</text>
<div class="seperator" ></div>
<text class="title">MODEL</text>
<text class="subtitle">{{model}}</text>
</div>
<div class="swiper-item item2">
<text class="title">PRODUCT</text>
<text class="subtitle">{{product}}</text>
<div class="seperator" ></div>
<text class="title">LANGUAGE</text>
<text class="subtitle">{{language}}</text>
<div class="seperator" ></div>
<text class="title">REGION</text>
<text class="subtitle">{{region}}</text>
</div>
<div class="swiper-item item3">
<text class="title">SCREEN SHAPE</text>
<text class="subtitle">{{shape}}</text>
<div class="seperator" ></div>
<text class="title">SCREEN DENSITY</text>
<text class="subtitle">{{screendensity}}</text>
<div class="seperator" ></div>
<text class="title">DIMENSION</text>
<text class="subtitle">{{dimension}}</text>
</div>
</swiper>
index.css has style defined for the page.
Code:
.container {
left: 0px;
top: 0px;
width: 454px;
height: 454px;
}
.swiper-item {
width: 454px;
height: 454px;
flex-direction: column;
justify-content: center;
align-items: center;
}
.item1 {
background-color: #007dff;
}
.item2 {
background-color: #cc0000;
}
.item3 {
background-color: #41ba41;
}
.title {
font-size:30px;
justify-content: center;
}
.subtitle {
font-size:30px;
color: lightgrey;
margin: 15px;
justify-content: center;
}
.seperator {
height: 1px;
width: 454px;
margin-bottom: 5px;
margin-top: 5px;
background-color: white;
}
To obtain the device information, we will call device.info()
Code:
device.getInfo({
success: function(data) {
console.log('success get device info brand:' + data.brand);
_this.brand = data.brand;
_this.manufacturer = data.manufacturer;
_this.model = data.model;
_this.language = data.language;
_this.product = data.product;
_this.region = data.region;
_this.screendensity = data.screenDensity;
_this.shape = data.screenShape;
_this.dimension = data.windowWidth + ' X ' + data.windowHeight;
},
fail: function(data, code) {
console.log('fail get device info code:'+ code + ', data: ' + data);
},
});
Code Snippet of index.js
Code:
import device from '@system.device';
export default {
data: {
brand: '--',
manufacturer: '--',
language: '--',
model: '--',
product: '--',
region: '--',
dimension: '--',
screendensity: 0,
shape : '--'
}
,
onInit(){
let _this = this;
device.getInfo({
success: function(data) {
console.log('success get device info brand:' + data.brand);
_this.brand = data.brand;
_this.manufacturer = data.manufacturer;
_this.model = data.model;
_this.language = data.language;
_this.product = data.product;
_this.region = data.region;
_this.screendensity = data.screenDensity;
_this.shape = data.screenShape;
_this.dimension = data.windowWidth + ' X ' + data.windowHeight;
},
fail: function(data, code) {
console.log('fail get device info code:'+ code + ', data: ' + data);
},
});
}
}
Tips and Tricks
Not all the information can be obtained on simulator. Hence it is recommended to use physical Harmony OS wearable watch.
Conclusion
In this article, we learnt how easily we can obtain wearable device information such as brand, product, device dimension, density, etc.
References
Harmony OS JS API :
Document
developer.harmonyos.com
Harmony Official document -
Document
developer.harmonyos.com
Very useful
In this article, we can learn to get current and nearby places of user’s device using a Huawei Nearby Place Search API and also to implement it in Huawei Map.
If you want to provide a feature in your app that should display a list of places such as Restaurant, GYM, Banks, Hospitals, Business, Parks, Transport, etc. near the current location of user device, then you need to use Huawei Nearby place search API, MAP and Location Kit to implement it.
Environment Requirement
1) Node JS and Visual Studio.
2) The JDK version must be 1.8 or later.
3) React Native Location, Map and Site Plugin is not supported by Expo CLI. Use React Native CLI instead.
Project Setup
1) Creating New Project.
Code:
react-native init project name
2) Generating a Signing Certificate Fingerprint.
Use following command for generating certificate.
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
This command creates the keystore file in application_project_dir/android/app.
The next step is to obtain the SHA256 key.
To obtain it, enter the following command in terminal:
Code:
keytool -list -v -keystore <application_project_dir>\android\app\<signing_certificate_fingerprint_filename>.jks
After an authentication, user can see SHA256 in below picture
{
"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"
}
3) Create an app in the Huawei AppGallery Connect.
4) Provide the SHA256 Key in App Information section.
5) Enable Map and Site kit service under Manage APIs section.
6) Download and add the agconnect-services.json file in your project.
7) Copy and paste the below maven url inside the repositories of build script and all projects (project build.gradle file):
Java:
maven { url 'http://developer.huawei.com/repo/' }
8) Copy and paste the below AppGallery Connect plugin for the HMS SDK inside dependencies (project build.gradle file):
Java:
classpath 'com.huawei.agconnect:agcp:1.4.2.301'
9) Make sure that the minSdkVersion for your application project is 19 or higher.
10) Download the Huawei Location, Map and Site kit plugin using the following command.
Code:
npm i @hmscore/react-native-hms-location
npm i @hmscore/react-native-hms-map
npm i @hmscore/react-native-hms-site
11) Add Permissions in Android Manifest file.
XML:
<uses-permission android:name="android.permission.INTERNET" />
<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"/>
Nearby Places Example
Now let’s see how to use places API to get list of nearby places based on user’s current location, display them in Map and show the current location along with address on Huawei maps.
Step 1: Using the Places API requires ACCESS_FINE_LOCATION permission, so you need to request that in your JS file:
JavaScript:
HMSLocation.FusedLocation.Native.hasPermission()
.then((result) => setHasLocationPermission(result))
.catch(HMSLocation.FusedLocation.Native.requestPermission());
Step 2: Finding Current Location and Address:
JavaScript:
HMSLocation.FusedLocation.Native.getLastLocation()
.then((pos) => (position ? null : setPosition(pos)))
.catch((err) => console.log('Failed to get last location', err));
HMSLocation.FusedLocation.Native.getLastLocationWithAddress(locationRequest)
.then((pos) => (address ? null : setAddress(pos)))
.catch((err) => console.log('Failed to get last location address', err));
Step 3: Initialize the Site kit and get list of places such as Restaurant near the current location of user device:
JavaScript:
Position ? RNHMSSite.initializeService(config)
.then(() => {
nearbySearchReq = {
location: {
lat: position.latitude,
lng: position.longitude,
},
radius: 5000,
hwPoiType: RNHMSSite.HwLocationType.RESTAURANT,
poiType: RNHMSSite.LocationType.GYM,
countryCode: 'IN',
language: 'en',
pageIndex: 1,
pageSize: 20,
politicalView: 'en',
};
site.length === 0
? RNHMSSite.nearbySearch(nearbySearchReq)
.then((res) => {
setSite(res.sites);
console.log(JSON.stringify(res));
mapView.setCameraPosition({
target: {
latitude: site[0].location.lat,
longitude: site[0].location.lng,
},
zoom: 17,
});
})
.catch((err) => {
console.log(JSON.stringify(err));
})
: null;
})
.catch((err) => {
console.log('Error : ' + err);
})
Step 4: Display a list of places on Map such as Restaurant near the current location of user device:
JavaScript:
<MapView
style={{ height: 590 }}
camera={{
target: {
latitude: position.latitude,
longitude: position.longitude,
},
zoom: 15,
}}
ref={(e) => (mapView = e)}
myLocationEnabled={true}
markerClustering={true}
myLocationButtonEnabled={true}
rotateGesturesEnabled={true}
scrollGesturesEnabled={true}
tiltGesturesEnabled={true}
zoomGesturesEnabled={true}>
{site != null
? Object.keys(site).map(function (key, i) {
return (
<Marker
visible={true}
coordinate={{
latitude: site[i].location.lat,
longitude: site[i].location.lng,
}}
clusterable>
<InfoWindow
style={{
alignContent: 'center',
justifyContent: 'center',
borderRadius: 8,
}}>
<View style={style.markerSelectedHms}>
<Text
style={style.titleSelected}>{`${site[i].name}`}</Text>
</View>
</InfoWindow>
</Marker>
);
})
: null}
</MapView>
Step 5: Get Current location address:
JavaScript:
address ? (
<View style={style.bottomView,{ backgroundColor: "white"}}>
<View style={{ flexDirection: "row" ,marginStart: 10}}>
<Image source={require('../assets/home.png')} style={{ width: 40, height: 40 }}/>
<Text style={{ marginTop: 10 ,marginStart: 10 }}>My Address</Text>
</View>
<Text style={style.textStyle}> {address.featureName + ", " +address.city+", Postal Code = "+address.postalCode} </Text>
</View>
)
Nearby Places Example Output:
Complete Code:
Copy and paste following code in your App.js file:
JavaScript:
import 'react-native-gesture-handler';
import * as React from 'react';
import { StyleSheet} from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import MapComponent from './components/MapComponent';
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home"
component={MapComponent}
options={{ title: 'Huawei Map' }}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
MainContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
text: {
textAlign: 'center',
margin: 12,
fontSize: 22,
fontWeight: "100",
},
});
export default App;
Copy and paste following code in your MapComponent.js file:
1. Create folder components inside components, create a file called MapComponent.js.
2. Add the generated API key.
JavaScript:
import React, { Component, useState, useEffect } from 'react';
import { ActivityIndicator, SafeAreaView, View, Text , Image} from 'react-native';
import RNHMSSite from '@hmscore/react-native-hms-site';
import HMSLocation from '@hmscore/react-native-hms-location';
import MapView, { Marker, InfoWindow } from '@hmscore/react-native-hms-map';
let mapView, nearbySearchReq;const
config = {
apiKey: 'YOUR API KEY',
};
const GetPermssions = () => {
const [hasLocationPermission, setHasLocationPermission] = useState(false);
const [position, setPosition] = useState();
const [site, setSite] = useState([]);
const [address, setAddress] = useState();
locationRequest = {
priority: HMSLocation.FusedLocation.PriorityConstants.PRIORITY_HIGH_ACCURACY,
interval: 3,
numUpdates: 10,
fastestInterval: 1000.0,
expirationTime: 1000.0,
expirationTimeDuration: 1000.0,
smallestDisplacement: 0.0,
maxWaitTime: 10000.0,
needAddress: true,
language: "en",
countryCode: "en",
};
useEffect(() => {
HMSLocation.FusedLocation.Native.hasPermission()
.then((result) => setHasLocationPermission(result))
.catch(HMSLocation.FusedLocation.Native.requestPermission());
}, []);
if (hasLocationPermission) {
HMSLocation.FusedLocation.Native.getLastLocation()
.then((pos) => (position ? null : setPosition(pos)))
.catch((err) => console.log('Failed to get last location', err));
HMSLocation.FusedLocation.Native.getLastLocationWithAddress(locationRequest)
.then((pos) => (address ? null : setAddress(pos)))
.catch((err) => console.log('Failed to get last location address', err));
position
? RNHMSSite.initializeService(config)
.then(() => {
nearbySearchReq = {
location: {
lat: position.latitude,
lng: position.longitude,
},
radius: 5000,
hwPoiType: RNHMSSite.HwLocationType.RESTAURANT,
poiType: RNHMSSite.LocationType.GYM,
countryCode: 'IN',
language: 'en',
pageIndex: 1,
pageSize: 20,
politicalView: 'en',
};
site.length === 0
? RNHMSSite.nearbySearch(nearbySearchReq)
.then((res) => {
setSite(res.sites);
console.log(JSON.stringify(res));
mapView.setCameraPosition({
target: {
latitude: site[0].location.lat,
longitude: site[0].location.lng,
},
zoom: 17,
});
})
.catch((err) => {
console.log(JSON.stringify(err));
})
: null;
})
.catch((err) => {
console.log('Error : ' + err);
})
: null;
} else {
HMSLocation.FusedLocation.Native.requestPermission();
}
return (
<SafeAreaView
style={{
flex: 1,
}}>
{position ? (
<View>
<MapView
style={{ height: 590 }}
camera={{
target: {
latitude: position.latitude,
longitude: position.longitude,
},
zoom: 15,
}}
ref={(e) => (mapView = e)}
myLocationEnabled={true}
markerClustering={true}
myLocationButtonEnabled={true}
rotateGesturesEnabled={true}
scrollGesturesEnabled={true}
tiltGesturesEnabled={true}
zoomGesturesEnabled={true}>
{site != null
? Object.keys(site).map(function (key, i) {
return (
<Marker
visible={true}
coordinate={{
latitude: site[i].location.lat,
longitude: site[i].location.lng,
}}
clusterable>
<InfoWindow
style={{
alignContent: 'center',
justifyContent: 'center',
borderRadius: 8,
}}>
<View style={style.markerSelectedHms}>
<Text
style={style.titleSelected}>{`${site[i].name}`}</Text>
</View>
</InfoWindow>
</Marker>
);
})
: null}
</MapView>
</View>
) : (
<ActivityIndicator size="large" color="#0000ff" />
)}
{address ? (
<View style={style.bottomView,{ backgroundColor: "white"}}>
<View style={{ flexDirection: "row" ,marginStart: 10}}>
<Image source={require('../assets/home.png')} style={{ width: 40, height: 40 }}/>
<Text style={{ marginTop: 10 ,marginStart: 10 }}>My Address</Text>
</View>
<Text style={style.textStyle}> {address.featureName + ", " +address.city+", Postal Code = "+address.postalCode} </Text>
</View>
) : (
<ActivityIndicator s size="large" color="#0000ff" />
)}
</SafeAreaView>
);
};
export default class MapComponent extends Component {
render() {
return <GetPermssions />;
}
}
const style = (base) => ({
markerSelectedHms: {
flexDirection: 'row',
height: 50,
borderRadius: base.radius.default,
overflow: 'hidden',
alignSelf: 'center',
alignItems: 'center',
alignContent: 'center',
justifyContent: 'space-between',
},
bottomView: {
width: '100%',
height: 50,
backgroundColor: 'white',
position: 'absolute', //Here is the trick
bottom: 0, //Here is the trick
},
textStyle: {
color: '#000',
fontSize: 18,
}
});
Run the application:
Code:
react-native run-android
Tips and Tricks:
1) Do not forget to add API key in MapComponent.JS file.
2) Do not forget to enable Map and Site kit service in AGC console APP Gallery connect > Manage APIs section.
Conclusion:
In this article, you have learned to setting up your react native project for Huawei Nearby place API, getting list of places near current location of device, displaying list of places in Map with markers and displaying current location on Map with address.
Reference:
1) React native Plugin
2) Site Kit
3) Location Kit
4) Map Kit
Read In Forum
Can we search multiple POI in one requrest?
{
"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"
}
Article Introduction
In this article we will develop Qibla finder application for Huawei Smart Watch device using Huawei DevEco Studio (HarmonyOS). We will fetch Location and Compass API’s of HarmonyOS JS language to develop Application.
1. Create New Project
Let’s create Smart Watch Project and choosing ability template, Wearable and Empty Feature Ability (JS)
Define project name, package name and relevant directory where you want to save your project.
2. Preparing Files and Permission
Let’s first add images and permissions which we will use for project.
All project images will be under common/images folder, check below screenshot.
Next we need to add permissions for Internet and Location under config.json file.
JSON:
"reqPermissions": [
{
"name": "ohos.permission.INTERNET"
},
{
"name": "ohos.permission.LOCATION",
"reason": "get Qibla direction",
"usedScene": {
"ability": [
"default"
],
"when": "always"
}
}
]
3. Compass Development
In Compass screen development we will cover Location permission, Location fetching, location error and compass degree value.
Let’s start development without wasting more time.
Styling:
index.css:
CSS:
.stack {
width: 454px;
height: 454px;
justify-content: center;
background-color: whitesmoke;
}
.container {
background-color: whitesmoke;
}
.compass-container {
display: flex;
justify-content: center;
align-items: center;
left: 0px;
top: 0px;
width: 454px;
height: 454px;
background-color: whitesmoke;
}
.container-location-loading{
background-image: url('/common/images/background.png');
flex-direction: column;
padding-top: 0px;
padding-bottom: 0px;
height: 456px;
width: 456px;
}
.error-container {
background-image: url('/common/images/background.png');
padding-top: 0px;
padding-bottom: 0px;
height: 456px;
width: 100%;
}
.location_loading{
object-fit:contain;
height: 456px;
width: 292px;
}
.column{
display: flex;
flex-direction: column;
justify-content: center;
width: 100%;
}
.needle{
left: 0px;
top: 0px;
width: 220px;
height: 220px;
background-color: transparent;
z-index:99;
}
.compass, .compass2{
left: 0px;
top: 0px;
width: 220px;
height: 220px;
background-color: transparent;
z-index:98;
}
.qibla_style{
display: flex;
left: 0px;
top: 0px;
width: 220px;
height: 220px;
background-color: transparent;
z-index:100000;
}
.error_title{
display: flex;
color: red;
width: 100%;
height: 100%;
justify-content: center;
align-content: center;
text-align: center;
font-size: 24px;
}
.button-container{
display: flex;
flex-direction: row;
justify-content: center;
align-content: space-around;
position: absolute;
bottom: 10px;
}
Layout:
Location Loading Animation:
Code:
<stack if="{{isLocationLoading === true && isLocationError === false}}" class="container-location-loading">
<image src="../../common/images/location_animation.gif" class="location_loading" />
</stack>
Location Loading Output:
Location Error and Retry:
Code:
<stack if="{{isLocationLoading === false && isLocationError === true}}" class="error-container">
<text class="error_title">Location not fetch. Try again</text>
<div class="button-container">
<button type="circle" icon="/common/images/exit.png" onclick="exit"></button>
<button type="circle" icon="/common/images/refresh.png" onclick="retry"></button>
</div>
</stack>
Location Error Output:
Compass UI:
Code:
<stack class="compass-container" if="{{isLocationLoading === false && isLocationError === false}}">
<stack class="compass" style="transform:{{compass_transform}}">
<div class="needle" style="transform:{{needle_transform}}">
<image src="/common/images/needle.png"></image>
</div>
<div class="compass" >
<image src="/common/images/compass.png"></image>
</div>
</stack>
<div class="qibla_style">
<image src="/common/images/qibla.png"></image>
</div>
</stack>
Compass UI Output:
JS code:
Structural - Code:
Code:
import sensor from '@system.sensor';
import brightness from '@system.brightness';
import geolocation from '@system.geolocation';
import app from '@system.app';
export default {}
Data:
Code:
data: {
compass_transform: "rotate(0deg)",
needle_transform: "rotate(0deg)",
isLocationLoading: true,
isLocationError: false,
}
Common - Code:
Code:
onReady() {
this.setBrightnessKeepScreenOn();
},
onInit() {
this.initLocationCompass();
},
exit(){
app.terminate();
},
retry(){
this.isLocationLoading = true;
this.isLocationError = false;
this.initLocationCompass();
},
onDestroy() {
sensor.unsubscribeCompass();
},
// Setting the screen to be steady on
setBrightnessKeepScreenOn: function () {
brightness.setKeepScreenOn({
keepScreenOn: true,
success: function () {
console.log("handling set keep screen on success")
},
fail: function (data, code) {
console.log("handling set keep screen on fail, code:" + code);
}
});
},
onBackPress() {
sensor.unsubscribeCompass();
}
Location Fetching - Code:
Code:
initLocationCompass(){
var _this = this;
this.locationLoading().then(result => {
console.info("Location: " + result);
_this.loadCompass(result);
_this.isLocationLoading = false;
_this.isLocationError = false;
}, error => {
console.info("Location: error ->" + error);
_this.isLocationLoading = false;
_this.isLocationError = true;
});
},
locationLoading() {
return new Promise(function (resolve, reject) {
return geolocation.getLocation({
success: function (data) {
console.log('success get location data. latitude:' + data.latitude + 'long:' + data.longitude);
return resolve({
latitude: data.latitude,
longitude: data.longitude
});
},
fail: function (data, code) {
console.log('fail to get location. code:' + code + ', data:' + data);
return reject({
error: 'fail to get location. code:' + code + ', data:' + data
});
},
});
});
},
Compass - Code:
Code:
loadCompass(coordinates = {
latitude: 24.7136,
longitude: 46.6753
}) {
var _this = this;
var qiblaDirection = parseFloat(this.qibla(coordinates));
console.log("compass: qiblaDirection: " + qiblaDirection);
_this.needle_transform = "rotate(" + qiblaDirection + "deg)";
sensor.subscribeCompass({
success: function (ret) {
var direction = ret.direction;
var compassDirection = (360 - direction);
_this.compass_transform = "rotate(" + compassDirection + "deg)";
console.log("compass: compassDirection: " + direction);
},
fail: function (data, code) {
console.error('compass: subscribe compass fail, code: ' + code + ', data: ' + data);
},
});
},
Qibla Direction - Code:
Code:
qibla(coordinates) {
const makkah = {
latitude: 21.42252,
longitude: 39.82621
};
const term1 = Math.sin(this.degreesToRadians(makkah.longitude) - this.degreesToRadians(coordinates.longitude));
const term2 = Math.cos(this.degreesToRadians(coordinates.latitude)) * Math.tan(this.degreesToRadians(makkah.latitude));
const term3 = Math.sin(this.degreesToRadians(coordinates.latitude)) * Math.cos(this.degreesToRadians(makkah.longitude) - this.degreesToRadians(coordinates.longitude));
const angle = Math.atan2(term1, term2 - term3);
return this.unwindAngle(this.radiansToDegrees(angle));
},
degreesToRadians(degrees) {
return degrees * Math.PI / 180.0;
},
radiansToDegrees(radians) {
return radians * 180.0 / Math.PI;
},
normalizeToScale(number, max) {
return number - max * Math.floor(number / max);
},
unwindAngle(angle) {
return this.normalizeToScale(angle, 360.0);
},
Compass Screen Notes:
To manage Layout, we need to use <stack> to overlap UI component in layers. First we need to fetch location data and identify the Qibla direction in degree. And call Compass JS API to get compass degree and manage the UI accordingly.
4. Result
Tips and Tricks:
Requesting some data from internet, you must need to add Internet permission in config.json file.
Fetching Location data, you must need to add Internet Permission in config.json file.
Use Dev Eco Studio Previewer to check the screen layout and design. Previewer is developer friendly to Hot release changes on fly.
For better management of big application it’s a good practice to centralize you common scripts and common style in common folder. Add images folder for complete application images.
In JS script when you make some variable, in callback functions you can store the reference of this to some variable and then call reference variable. Like var _this = this.
References:
HarmonyOS JS API Official Documentation: click here
Geographic Location Documentation: click here
Sensor Documentation: click here
Conclusion:
Developers can able to fetch user location data and compass data to make Qibla finder application. While developing application for HarmonyOS developer can get benefit for both JS and JAVA language.
Original Source