[Huawei Developers] ask011:
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.

react-native init project name

2) Generating a Signing Certificate Fingerprint.

Use following command for generating certificate.

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:

keytool -list -v -keystore <application_project_dir>\android\app\<signing_certificate_fingerprint_filename>.jks

After an authentication, user can see SHA256 in below picture

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):

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):

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.

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.

<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:

HMSLocation.FusedLocation.Native.hasPermission()
.then((result) => setHasLocationPermission(result))
.catch(HMSLocation.FusedLocation.Native.requestPermission());

Step 2: Finding Current Location and Address:

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:

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:

<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:

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:

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.

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:

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