npm package: @hmscore/hms-js-site
Description: HMS JS Site
Latest version: 5.2.0-300

# JSB Site

## Contents

- [JSB Site](#jsb-site)
  - [Contents](#contents)
  - [1. Introduction](#1-introduction)
  - [2. Installation Guide](#2-installation-guide)
    - [Creating a Project in AppGallery Connect](#creating-a-project-in-appgallery-connect)
    - [Configuring the Signing Certificate Fingerprint](#configuring-the-signing-certificate-fingerprint)
    - [React-Native Integration](#react-native-integration)
    - [Cordova Integration](#cordova-integration)
    - [Ionic Integration](#ionic-integration)
      - [Ionic with Cordova Runtime](#ionic-with-cordova-runtime)
      - [Ionic with Capacitor Runtime](#ionic-with-capacitor-runtime)
  - [3. API Reference](#3-api-reference)
    - [HMSSite](#hmssite)
      - [Function Summary](#function-summary)
    - [3.1.2 Function](#312-function)
      - [HMSSite.textSearch(textSearchRequest)](#hmssitetextsearchtextsearchrequest)
      - [HMSSite.nearbySearch(nearbySearchRequest)](#hmssitenearbysearchnearbysearchrequest)
      - [HMSSite.querySuggestion(querySuggestionRequest)](#hmssitequerysuggestionquerysuggestionrequest)
      - [HMSSite.detailSearch(detailSearchRequest)](#hmssitedetailsearchdetailsearchrequest)
      - [HMSSite.queryAutocomplete(queryAutocompleteRequest)](#hmssitequeryautocompletequeryautocompleterequest)
    - [Data Types](#data-types)
      - [Overview](#overview)
      - [Coordinate](#coordinate)
      - [Bounds](#bounds)
      - [Result](#result)
      - [TextSearchRequest](#textsearchrequest)
      - [NearbySearchRequest](#nearbysearchrequest)
      - [QuerySuggestionRequest](#querysuggestionrequest)
      - [DetailSearchRequest](#detailsearchrequest)
      - [QueryAutocompleteRequest](#queryautocompleterequest)
    - [Result Codes](#result-codes)
  - [4. Configuration and Description](#4-configuration-and-description)
    - [Configuring Obfuscation Scripts](#configuring-obfuscation-scripts)
      - [React Native](#react-native)
      - [Cordova](#cordova)
  - [5. Questions or Issues](#5-questions-or-issues)
  - [6. Licensing and Terms](#6-licensing-and-terms)

## 1. Introduction

## 2. Installation Guide

### Creating a Project in AppGallery Connect

Creating an app in AppGallery Connect is required in order to communicate with the Huawei services. To create an app, perform the following steps:

**Step 1.** Sign in to [AppGallery Connect](https://developer.huawei.com/consumer/en/service/josp/agc/index.html) and select **My projects**.

**Step 2.** Select your project from the project list or create a new one by clicking the **Add Project** button.

**Step 3.** Go to **Project Setting** > **General information**, and click **Add app**.
If an app exists in the project and you need to add a new one, expand the app selection area on the top of the page and click **Add app**.

**Step 4.** On the **Add app** page, enter the app information, and click **OK**.

- A signing certificate fingerprint is used to verify the authenticity of an app when it attempts to access an HMS Core service through the HMS Core SDK. Before using HMS Core (APK), you must locally generate a signing certificate fingerprint and configure it in AppGallery Connect. Ensure that the JDK has been installed on your computer.

### Configuring the Signing Certificate Fingerprint

**Step 1.** Go to **Project Setting > General information**. In the **App information** field, click the icon next to SHA-256 certificate fingerprint, and enter the obtained **SHA256 certificate fingerprint**.

**Step 2.** After completing the configuration, click check mark.

### React-Native Integration

**Step 1:** Sign in to [AppGallery Connect](https://developer.huawei.com/consumer/en/service/josp/agc/index.html) and select **My projects**.

**Step 2:** Find your app project, and click the desired app name.

**Step 3:** Go to **Project Setting** > **General information**. In the **App information** section, click **agconnect-service.json** to download the configuration file.

**Step 4:** Create a React Native project if you do not have one.

**Step 5:** Copy the **agconnect-service.json** file to the **android/app** directory of your React Native project.

**Step 6:** Copy the signature file that generated in [Generating a Signing Certificate](https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#3) section, to the android/app directory of your React Native project.

**Step 7:** Check whether the **agconnect-services.json** file and signature file are successfully added to the **android/app** directory of the React Native project.

**Step 8:** Open the **build.gradle** file in the **android** directory of your React Native project.

- Go to **buildscript** then configure the Maven repository address and agconnect plugin for the HMS SDK.

```groovy
buildscript {
  repositories {
    google()
    jcenter()
    maven { url 'https://developer.huawei.com/repo/' }
  }

  dependencies {
    /*
      * <Other dependencies>
      */
    classpath 'com.huawei.agconnect:agcp:1.4.2.301'
  }
}
```

- Go to **allprojects** then configure the Maven repository address for the HMS SDK.

```groovy
allprojects {
  repositories {
    /*
      * <Other repositories>
      */
    maven { url 'https://developer.huawei.com/repo/' }
  }
}
```

**Step 9:** Open the **build.gradle** file in the **android/app** directory of your React Native project.

- Package name must match with the **package_name** entry in **agconnect-services.json** file.

```groovy
defaultConfig {
  applicationId "<package_name>"
  minSdkVersion 19
  /*
   * <Other configurations>
   */
}
```

```groovy
android {
  /*
   * <Other configurations>
   */

  signingConfigs {
    config {
      storeFile file('<keystore_file>.jks')
      storePassword '<keystore_password>'
      keyAlias '<key_alias>'
      keyPassword '<key_password>'
    }
  }

  buildTypes {
    debug {
      signingConfig signingConfigs.config
    }
    release {
      signingConfig signingConfigs.config
      minifyEnabled enableProguardInReleaseBuilds
      ...
    }
  }
}
```

**Step 10:** Open the **build.gradle** file in the **android/app** directory of your React Native project.

- Configure build dependencies.

```groovy
buildscript {
  ...
  dependencies {
    /*
    * <Other dependencies>
    */
    implementation ('com.huawei.hms:rn-adapter:5.2.0.300'){
        exclude group: 'com.facebook.react'
    }
    ...
  }
}
```

**Step 11:** Import the following class to the **MainApplication.java** file of your project.

```java
import com.huawei.hms.jsb.adapter.rn.RnJSBReactPackage;
```

Then, add the **RnJSBReactPackage()** to your **getPackages** method. In the end, your file will be similar to the following:

```java
@Override
protected List<ReactPackage> getPackages() {
    List<ReactPackage> packages = new PackageList(this).getPackages();
    packages.add(new RnJSBReactPackage()); // <-- Add this line
    return packages;
}
...
```

**Step 12:** Download js-sdk using command below.

```bash
npm i @hmscore/hms-js-site
```

**Step 13:** Import **HMSSite** in App.js as following line. 

```js
import HMSSite from "@hmscore/hms-js-site";
```

**Step 14:** First you have to call the init function.

```js
import {NativeModules, DeviceEventEmitter} from "react-native";
...
HMSSite.init(NativeModules, DeviceEventEmitter);
```

**Step 15:** Run your project.

- Run the following command to the project directory.

```bash
react-native run-android
```

### Cordova Integration

**Step 1:** Install Cordova CLI if haven't done before.

```bash
npm install -g cordova
```

**Step 2:** Create a new Cordova project or use the existing one.

- To create new Cordova project, you can use **`cordova create path [id [name [config]]] [options]`** command. For more details please follow [CLI Reference - Apache Cordova](https://cordova.apache.org/docs/en/latest/reference/cordova-cli/index.html#cordova-create-command).

**Step 3:** Update the widget **`id`** property which is specified in the **`config.xml`** file. It must be same with **package_name** value of the **`agconnect-services.json`** file.

**Step 4:** Add the **Android platform** to the project if haven't done before.

```bash
cordova platform add android
```

**Step 5:** Download plugin using command below.

```bash
cordova plugin add @hmscore/hms-js-site
```

**Step 6:** Copy **`agconnect-services.json`** file to **`<project_root>/platforms/android/app`** directory.

**Step 7:** Add **`keystore(.jks)`** and **`build.json`** files to your project's root directory.

- You can refer to 3rd and 4th steps of [Generating a Signing Certificate](https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#2) Codelab tutorial page for generating keystore file.

- Fill **`build.json`** file according to your keystore information. For example:

  ```json
  {
    "android": {
      "debug": {
        "keystore": "<keystore_file>.jks",
        "storePassword": "<keystore_password>",
        "alias": "<key_alias>",
        "password": "<key_password>"
      },
      "release": {
        "keystore": "<keystore_file>.jks",
        "storePassword": "<keystore_password>",
        "alias": "<key_alias>",
        "password": "<key_password>"
      }
    }
  }
  ```

**Step 8:** Import the following class to the **MainActivity.java** file of your project. You can find this file in **`platforms/android/app/src/main/java/<your_package_name>`** directory.

```java
import com.huawei.hms.jsb.adapter.cordova.CordovaJSBInit;
```

**Step 9:** In the same file, add **CordovaJSBInit.initJSBFramework(this)** line after the **super.onCreate(savedInstanceState)** method call.

- In the end, your file will be similar to the following:

```java
  ...

  import com.huawei.hms.jsb.adapter.cordova.CordovaJSBInit;

  public class MainActivity extends CordovaActivity
  {
      @Override
      public void onCreate(Bundle savedInstanceState)
      {
          super.onCreate(savedInstanceState);
          CordovaJSBInit.initJSBFramework(this);

          ...
      }
      ...
  }
```

**Step 10:** Run the app

```bash
cordova run android
```

### Ionic Integration

Install Ionic CLI and other required tools if haven't done before.

```bash
npm install -g @ionic/cli cordova-res native-run
```

#### Ionic with Cordova Runtime

**Step 1:** Enable the **Cordova integration** if haven't done before.

```bash
ionic integrations enable cordova
```

**Step 2:** Update the widget **`id`** property which is specified in the **`config.xml`** file. It must be same with **package_name** value of the **`agconnect-services.json`** file.

**Step 3:** Add the **Android platform** to the project if haven't done before.

```bash
ionic cordova platform add android
```

**Step 4:** Install `HMS Site Plugin` to the project.

```bash
ionic cordova plugin add @hmscore/hms-js-site
```

**Step 5:** Copy **`agconnect-services.json`** file to **`<project_root>/platforms/android/app`** directory.

**Step 6:** Add **`keystore(.jks)`** and **`build.json`** files to your project's root directory.

- You can refer to 3rd and 4th steps of [Generating a Signing Certificate](https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#2) Codelab tutorial page for generating keystore file.

- Fill **`build.json`** file according to your keystore information. For example:

```json
{
  "android": {
    "debug": {
      "keystore": "<keystore_file>.jks",
      "storePassword": "<keystore_password>",
      "alias": "<key_alias>",
      "password": "<key_password>"
    },
    "release": {
      "keystore": "<keystore_file>.jks",
      "storePassword": "<keystore_password>",
      "alias": "<key_alias>",
      "password": "<key_password>"
    }
  }
}
```

**Step 7:** Import the following class to the **MainActivity.java** file of your project. You can find this file in **`platforms/android/app/src/main/java/<your_package_name>`** directory.

```java
import com.huawei.hms.jsb.adapter.cordova.CordovaJSBInit;
```

**Step 8:** In the same file, add **CordovaJSBInit.initJSBFramework(this)** line after the **super.onCreate(savedInstanceState)** method call.

- In the end, your file will be similar to the following:

```java
...

import com.huawei.hms.jsb.adapter.cordova.CordovaJSBInit;

public class MainActivity extends CordovaActivity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {f
        super.onCreate(savedInstanceState);
        CordovaJSBInit.initJSBFramework(this);

        ...
    }
    ...
}
```

**Step 9:** Run the application.

```bash
ionic cordova run android --device
```

#### Ionic with Capacitor Runtime

**Step 1:** Enable the **Capacitor integration** if haven't done before.

```bash
ionic integrations enable capacitor
```

**Step 2:** Initialize **Capacitor** if haven't done before.

```bash
npx cap init [appName] [appId]
```

- For more details please follow [Initialize Capacitor with your app information](https://capacitorjs.com/docs/getting-started/with-ionic#initialize-capacitor-with-your-app-information).

**Step 3:** Update the **`appId`** property which is specified in the **`capacitor.config.json`** file according to your project. It must be same with **package_name** value of the **`agconnect-services.json`** file.

**Step 4:** Install `HMS Site plugin` to the project.

```bash
npm install @hmscore/hms-js-site
```

**Step 5:** Build Ionic app to generate resource files.

```bash
ionic build
```

**Step 6:** Add the **Android platform** to the project.

```bash
npx cap add android
```

**Step 7:** Copy **`keystore(.jks)`** and **`agconnect-services.json`** files to **`<project_root>/android/app`** directory.

- You can refer to 3rd and 4th steps of [Generating a Signing Certificate](https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#2) Codelab tutorial page for generating keystore file.

**Step 8:** Open the **`build.gradle`** file in the **`<project_root>/android/app`** directory.

- Add `signingConfigs` entry to the **android** section and modify it according to your keystore.

- Enable `signingConfig` configuration for **debug** and **release** flavors.
- Add `apply plugin: 'com.huawei.agconnect'` to top of your build gradle file in the **`<project_root>/android/app`** directory.

```groovy
apply plugin: 'com.android.application'
apply plugin: 'com.huawei.agconnect' // Add this line

...

android {
    ...

    // Modify signingConfigs according to your keystore
    signingConfigs {
        config {
            storeFile file('<keystore_file>.jks')
            storePassword '<keystore_password>'
            keyAlias '<key_alias>'
            keyPassword '<key_password>'
        }
    }
    buildTypes {
        debug {
            signingConfig signingConfigs.config // Enable signingConfig for debug flavor
        }
        release {
            signingConfig signingConfigs.config // Enable signingConfig for release flavor
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

...
```


**Step 9:** Open the **`build.gradle`** file in the **`<project_root>/android`** directory. Add **Huawei's maven repositories** and **agconnect classpath** to the file.

```groovy
buildscript {
    repositories {
        /*
            <Other repositories>
        */
        maven { url 'https://developer.huawei.com/repo/' }
    }
    dependencies {
        /*
            <Other dependencies>
        */
        classpath 'com.huawei.agconnect:agcp:1.4.2.301'
    }
}

/*
    <Other build.gradle entries>
*/

allprojects {
    repositories {
        /*
            <Other repositories>
        */
        maven { url 'https://developer.huawei.com/repo/' }
    }
}
```

**Step 10:** Import the following class to the **MainActivity.java** file of your project. You can find this file in **`android/app/src/main/java/<your_package_name>`** directory.

```java
import com.huawei.hms.js.site.HMSSite;
```

**Step 11:** In the same file, add **add(HMSSite.class);** line to the **ArrayList**.

- In the end, your file will be similar to the following:

  ```java
  ...
  import com.huawei.hms.js.site.HMSSite;
  public class MainActivity extends BridgeActivity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Initializes the Bridge
    this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
        add(HMSSite.class);
    }});
  }
  ...
  ```

**Step 12:** Updates dependencies, and copy any web assets to your project.

```bash
npx cap sync
```

**Step 13:** Open the project in Android Studio and run it.

```bash
npx cap open android
```

## 3. API Reference

### HMSSite

#### Function Summary

| Function | Return Type | Description |
| -- | -- | -- |
| [textSearch](#hmssitetextsearchtextsearchrequest) | Promise<[Result](#result)> | Searches for a place by keyword. |
| [nearbySearch](#hmssitenearbysearchnearbysearchrequest) | Promise<[Result](#result)> | Searches for nearby places. |
| [querySuggestion](#hmssitequerysuggestionquerysuggestionrequest) | Promise<[Result](#result)> | Obtains a list of suggested places. |
| [detailSearch](#hmssitedetailsearchdetailsearchrequest) | Promise<[Result](#result)> | Searches for details about a place. |
| [queryAutocomplete](#hmssitequeryautocompletequeryautocompleterequest) | Promise<[Result](#result)> | Obtains the autocomplete result. | 

### 3.1.2 Function

#### HMSSite.textSearch(textSearchRequest)
Searches for places such as tourist attractions, enterprises, and schools based on a request object. This method takes a object as a parameter and returns a Promise object.

| Parameter | Type | Description |
| -- | -- | -- |
| textSearchRequest | [TextSearchRequest](#textsearchrequest) | Request Object. |


| Return Type | Description |
| -- | -- |
| Promise<[Result](#result)>  | Object containing search information. |

Call Example
```js
const query = "Paris";
const location = {
  lat: 48.89,
  lng: 2.33,
};
const radius = 1000;
const poiType = HMSSite.LocationType.ADDRESS;
const hwPoiType = HMSSite.HwLocationType.ADDRESS;
const countryCode = "FR";
const language = "fr";
const pageIndex = 1;
const pageSize = 5;
const children = false;

HMSSite.textSearch({
  query,
  location,
  radius,
  poiType,
  hwPoiType,
  countryCode,
  language,
  pageSize,
  pageIndex,
  children
})
  .then((res) => alert(JSON.stringify(res)))
  .catch((err) => alert(JSON.stringify(err)));
```

Response Example
```json
{
   "status":"OK",
   "resultCode":0,
   "data":{
      "sites":[
         {
            "address":{
               "adminArea":"Île-de-France",
               "country":"France",
               "countryCode":"FR",
               "subAdminArea":"Paris"
            },
            "distance":3544.28,
            "formatAddress":"France",
            "location":{
               "lat":48.858842949999996,
               "lng":2.320036116358682
            },
            "name":"Paris",
            "poi":{
               "hwPoiTypes":[
                  "ADMINISTRATIVE_AREA_LEVEL_2"
               ],
               "internationalPhone":"",
               "poiTypes":[
                  "ADMINISTRATIVE_AREA_LEVEL_2"
               ],
               "priceLevel":-1,
               "rating":0
            },
            "siteId":"23B69B9E4D681BED987B63363BBF085E",
            "utcOffset":0,
            "viewport":{
               "northeast":{
                  "lat":48.9021645,
                  "lng":2.4699053
               },
               "southwest":{
                  "lat":48.8155214,
                  "lng":2.2241006
               }
            }
         },
         {
            "address":{
               "adminArea":"Île-de-France",
               "country":"France",
               "countryCode":"FR",
               "locality":"8e Arrondissement",
               "postalCode":"75008",
               "streetNumber":"35",
               "subAdminArea":"Paris",
               "subLocality":"8e Arrondissement",
               "tertiaryAdminArea":"Paris",
               "thoroughfare":"Rue La Boétie"
            },
            "distance":2115.92,
            "formatAddress":"35 Rue La Boétie, 75008 8e Arrondissement, France",
            "location":{
               "lat":48.8737343,
               "lng":2.3150453
            },
            "name":"PARIS",
            "poi":{
               "hwPoiTypes":[
                  "BANK"
               ],
               "internationalPhone":"+33 1 58563800",
               "phone":"+33 1 58563800",
               "poiTypes":[
                  "BANK"
               ],
               "priceLevel":-1,
               "rating":0,
               "websiteUrl":""
            },
            "siteId":"9FC7F96B9AA77F51B19153E0DDE9A0C2",
            "utcOffset":0,
            "viewport":{
               "northeast":{
                  "lat":48.875006133205595,
                  "lng":2.316978998218511
               },
               "southwest":{
                  "lat":48.87246246679441,
                  "lng":2.313111601781489
               }
            }
         },
         {
            "address":{
               "adminArea":"Île-de-France",
               "country":"France",
               "countryCode":"FR",
               "locality":"Paris",
               "postalCode":"75001",
               "streetNumber":"206",
               "subAdminArea":"Paris",
               "subLocality":"1er Arrondissement",
               "tertiaryAdminArea":"Paris",
               "thoroughfare":"Rue de Rivoli"
            },
            "distance":2853.67,
            "formatAddress":"206 Rue de Rivoli, 75001 Paris, France",
            "location":{
               "lat":48.8643671,
               "lng":2.330493
            },
            "name":"Paris",
            "poi":{
               "hwPoiTypes":[
                  "FURNITURE_STORE"
               ],
               "internationalPhone":"",
               "phone":"",
               "poiTypes":[
                  "FURNITURE_STORE"
               ],
               "priceLevel":-1,
               "rating":0,
               "websiteUrl":""
            },
            "siteId":"5A4F4F0012564CDDCBE3422BC79764A7",
            "utcOffset":0,
            "viewport":{
               "northeast":{
                  "lat":48.865638933205595,
                  "lng":2.332426336252222
               },
               "southwest":{
                  "lat":48.86309526679441,
                  "lng":2.3285596637477783
               }
            }
         }        
      ],
      "totalCount":12
   }
}
```

#### HMSSite.nearbySearch(nearbySearchRequest)
Searches for nearby places based on the user's current location. This method takes a object as a parameter and returns a Promise object.

| Parameter | Type | Description |
| -- | -- | -- |
| nearbySearchRequest | [NearbySearchRequest](#nearbysearchrequest) | Request Object. |

| Return Type | Description |
| -- | -- |
| Promise<[Result](#result)>  | Object containing search information. |

Call Example
```js
const query = "Paris";
const location = {
  lat: 48.893478,
  lng: 2.334595,
};
const radius = 1000;
const poiType = HMSSite.LocationType.ADDRESS;
const hwPoiType = HMSSite.HwLocationType.ADDRESS;
const language = "fr";
const pageIndex = 1;
const pageSize = 5;
const strictBounds = true;

HMSSite.nearbySearch({
  query,
  location,
  radius,
  poiType,
  hwPoiType,
  language,
  pageSize,
  pageIndex,
  strictBounds
})
  .then((res) => alert(JSON.stringify(res)))
  .catch((err) => alert(JSON.stringify(err)));
```

Response Example
```json
{
   "status":"OK",
   "resultCode":0,
   "data":{
      "sites":[
         {
            "address":{
               "adminArea":"Île-de-France",
               "country":"France",
               "countryCode":"FR",
               "locality":"Île-de-France",
               "postalCode":"75018",
               "streetNumber":"203BIS",
               "subAdminArea":"Paris",
               "subLocality":"18e Arrondissement",
               "tertiaryAdminArea":"Paris",
               "thoroughfare":"Ordener"
            },
            "distance":65.91,
            "formatAddress":"203BIS Ordener, 75018 Île-de-France, France",
            "location":{
               "lat":48.89387,
               "lng":2.33392
            },
            "name":"Passion Beauté Paris",
            "poi":{
               "hwPoiTypes":[
                  "SPECIALTY_STORE"
               ],
               "internationalPhone":"+33142291536",
               "phone":"+33142291536",
               "poiTypes":[
                  "POINT_OF_INTEREST"
               ],
               "priceLevel":-1,
               "rating":0,
               "websiteUrl":"http://passionbeauteparis.fr"
            },
            "siteId":"201B685E7AB4A65A7AB5F31B8717E5E9",
            "utcOffset":0,
            "viewport":{
               "northeast":{
                  "lat":48.89514183320559,
                  "lng":2.335854476934061
               },
               "southwest":{
                  "lat":48.89259816679441,
                  "lng":2.331985523065939
               }
            }
         },
         {
            "address":{
               "adminArea":"Île-de-France",
               "country":"France",
               "countryCode":"FR",
               "locality":"Paris",
               "postalCode":"75018",
               "streetNumber":"181",
               "subAdminArea":"Paris",
               "subLocality":"18e Arrondissement",
               "tertiaryAdminArea":"Paris",
               "thoroughfare":"Rue Ordener"
            },
            "distance":79.11,
            "formatAddress":"181 Rue Ordener, 75018 Paris, France",
            "location":{
               "lat":48.8936283,
               "lng":2.3356514
            },
            "name":"Paris Bohème",
            "poi":{
               "hwPoiTypes":[
                  "FRENCH_RESTAURANT"
               ],
               "internationalPhone":"",
               "phone":"",
               "poiTypes":[
                  "RESTAURANT"
               ],
               "priceLevel":-1,
               "rating":0,
               "websiteUrl":""
            },
            "siteId":"0842F87439BDAEAF872B15D0CB2B83D1",
            "utcOffset":0,
            "viewport":{
               "northeast":{
                  "lat":48.894900133205596,
                  "lng":2.3375858675815695
               },
               "southwest":{
                  "lat":48.89235646679441,
                  "lng":2.333716932418431
               }
            }
         }
      ],
      "totalCount":60
   }
}
```
#### HMSSite.querySuggestion(querySuggestionRequest)
Returns suggested places during user input. This method takes a object as a parameter and returns a Promise object.

| Parameter | Type | Description |
| -- | -- | -- |
| querySuggestionRequest | [QuerySuggestionRequest](#querysuggestionrequest) | Request Object. |

| Return Type | Description |
| -- | -- |
| Promise<[Result](#result)>  | Object containing search suggestions. |

Call Example
```js
const query = "Paris";
const location = {
  lat: 48.893478,
  lng: 2.334595,
};
const bounds = {
        northeast: {
          lat: 49,
          lng: 2.47,
        },
        southwest: {
          lat: 47.8815,
          lng: 2.0,
        },
      };
const radius = 1000;
const poiTypes = [HMSSite.LocationType.ADDRESS, HMSSite.LocationType.GEOCODE];
const countryCode = "FR";
const language = "fr";
const children = true;
const strictBounds = false;

HMSSite.querySuggestion({
  query,
  location,
  bounds,
  radius,
  poiTypes,
  countryCode,
  language,
  children,
  strictBounds
})
  .then((res) => alert(JSON.stringify(res)))
  .catch((err) => alert(JSON.stringify(err)));
```

Response Example
```json
{
   "status":"OK",
   "resultCode":0,
   "data":{
      "sites":[
         {
            "address":{
               "adminArea":"Île-de-France",
               "country":"France",
               "countryCode":"FR",
               "subAdminArea":"Paris"
            },
            "distance":4000.1840673585825,
            "formatAddress":"France",
            "location":{
               "lat":48.858842949999996,
               "lng":2.320036116358682
            },
            "name":"Paris",
            "poi":{
               "childrenNodes":[
                  
               ],
               "hwPoiTypes":[
                  "ADMINISTRATIVE_AREA_LEVEL_2"
               ],
               "internationalPhone":"",
               "poiTypes":[
                  "ADMINISTRATIVE_AREA_LEVEL_2"
               ],
               "priceLevel":-1,
               "rating":0
            },
            "prediction":{
               "description":"Paris France",
               "matchedKeywords":[
                  {
                     "offset":0,
                     "value":"Paris"
                  }
               ],
               "matchedWords":[
                  {
                     "offset":0,
                     "value":"Paris"
                  },
                  {
                     "offset":7,
                     "value":"France"
                  }
               ]
            },
            "siteId":"23B69B9E4D681BED987B63363BBF085E",
            "utcOffset":0
         },
         {
            "address":{
               "adminArea":"Île-de-France",
               "country":"France",
               "countryCode":"FR",
               "postalCode":"75018",
               "subAdminArea":"Paris",
               "subLocality":"18e Arrondissement",
               "tertiaryAdminArea":"Paris"
            },
            "distance":770.1863994056979,
            "formatAddress":"Paris, France",
            "location":{
               "lat":48.8924007,
               "lng":2.3449899
            },
            "name":"Paris artonde arrondissement",
            "poi":{
               "childrenNodes":[
                  
               ],
               "hwPoiTypes":[
                  "POSTAL_CODE"
               ],
               "internationalPhone":"",
               "phone":"",
               "poiTypes":[
                  "POSTAL_CODE"
               ],
               "priceLevel":-1,
               "rating":0,
               "websiteUrl":""
            },
            "prediction":{
               "description":"Paris artonde arrondissement Paris, France",
               "matchedKeywords":[
                  {
                     "offset":0,
                     "value":"Paris"
                  }
               ],
               "matchedWords":[
                  {
                     "offset":0,
                     "value":"Paris artonde arrondissement"
                  },
                  {
                     "offset":30,
                     "value":"Paris"
                  },
                  {
                     "offset":37,
                     "value":"France"
                  }
               ]
            },
            "siteId":"471F933D3671CE1393B7AE6BE1D5691D",
            "utcOffset":0
         }
      ]
   }
}
```

#### HMSSite.detailSearch(detailSearchRequest)
Searches for place details based the unique ID (SiteId) of a place. This method takes an object as a parameter and returns a Promise object.

| Parameter | Type | Description |
| -- | -- | -- |
| detailSearchRequest | [DetailSearchRequest](#detailsearchrequest) | Request Object. |

| Return Type | Description |
| -- | -- |
| Promise<[Result](#result)>  | Object containing details of the place. |

Call Example
```js
const siteId = "16DA89C6962A36CB1752A343ED48B78A";
const language = "fr";
const children = false;

HMSSite.detailSearch({siteId, language, children})
  .then((res) => alert(JSON.stringify(res)))
  .catch((err) => alert(JSON.stringify(err)));
```
Response Example
```json
{
   "status":"OK",
   "resultCode":0,
   "data":{
      "site":{
         "address":{
            "adminArea":"Île-de-France",
            "country":"France",
            "countryCode":"FR",
            "locality":"Paris",
            "postalCode":"75004",
            "subAdminArea":"Paris",
            "subLocality":"4e Arrondissement",
            "tertiaryAdminArea":"Paris",
            "thoroughfare":"Avenue Victoria"
         },
         "distance":null,
         "formatAddress":"France",
         "location":{
            "lat":48.856895,
            "lng":2.3508487
         },
         "name":"Paris",
         "poi":{
            "hwPoiTypes":[
               "CAPITAL"
            ],
            "internationalPhone":"",
            "openingHours":{
               
            },
            "poiTypes":[
               "CAPITAL"
            ],
            "priceLevel":0,
            "rating":0.0
         },
         "siteId":"16DA89C6962A36CB1752A343ED48B78A",
         "utcOffset":60,
         "viewport":{
            "northeast":{
               "lat":48.858166833205594,
               "lng":2.3527817476503596
            },
            "southwest":{
               "lat":48.85562316679441,
               "lng":2.34891565234964
            }
         }
      }
   }
}
```

#### HMSSite.queryAutocomplete(queryAutocompleteRequest)
Returns an autocomplete place and a list of suggested places. This method takes an object as a parameter and returns a Promise object.

| Parameter | Type | Description |
| -- | -- | -- |
| queryAutocompleteRequest | [QueryAutocompleteRequest](#queryautocompleterequest) | Request Object. |

| Return Type | Description |
| -- | -- |
| Promise<[Result](#result)>  | Object containing autocomplete results |

Call Example
```js
const query = "Paris";
const location = {
  lat: 48.89,
  lng: 2.33,
};
const radius = 1000;
const language = "fr";
const children = false;

HMSSite.queryAutocomplete({query, location, radius, language, children})
  .then((res) => alert(JSON.stringify(res)))
  .catch((err) => alert(JSON.stringify(err)));
```

Response Example
```json
{
   "status":"OK",
   "resultCode":0,
   "data":{
      "predictions":[
         {
            "description":"parishad",
            "matchedKeywords":[
               {
                  "offset":0,
                  "value":"paris"
               }
            ],
            "matchedWords":[
               {
                  "offset":0,
                  "value":"parishad"
               }
            ]
         }
      ],
      "sites":[
         {
            "address":{
               "adminArea":"Île-de-France",
               "country":"France",
               "countryCode":"FR",
               "subAdminArea":"Paris"
            },
            "distance":3544.277473207532,
            "formatAddress":"France",
            "location":{
               "lat":48.858842949999996,
               "lng":2.320036116358682
            },
            "name":"Paris",
            "poi":{
               "hwPoiTypes":[
                  "ADMINISTRATIVE_AREA_LEVEL_2"
               ],
               "internationalPhone":"",
               "poiTypes":[
                  "ADMINISTRATIVE_AREA_LEVEL_2"
               ],
               "priceLevel":-1,
               "rating":0
            },
            "prediction":{
               "description":"Paris France",
               "matchedKeywords":[
                  {
                     "offset":0,
                     "value":"Paris"
                  }
               ],
               "matchedWords":[
                  {
                     "offset":0,
                     "value":"Paris"
                  },
                  {
                     "offset":7,
                     "value":"France"
                  }
               ]
            },
            "siteId":"23B69B9E4D681BED987B63363BBF085E",
            "utcOffset":0
         },
         {
            "address":{
               "adminArea":"Île-de-France",
               "country":"France",
               "countryCode":"FR",
               "locality":"Dugny",
               "postalCode":"93440",
               "subAdminArea":"Seine-Saint-Denis",
               "tertiaryAdminArea":"Dugny",
               "thoroughfare":"Esplanade de l'Air et de l'Espace"
            },
            "distance":10103.434361204923,
            "formatAddress":"Esplanade de l'Air et de l'Espace, Dugny, France",
            "location":{
               "lat":48.9483079,
               "lng":2.4358455
            },
            "name":"Paris-Le Bourget Airport",
            "poi":{
               "hwPoiTypes":[
                  "PRIVATE_AUTHORITY"
               ],
               "internationalPhone":"+33 1 48621656",
               "phone":"+33 1 48621656",
               "poiTypes":[
                  "AIRPORT"
               ],
               "priceLevel":-1,
               "rating":0,
               "websiteUrl":"www.parisaeroport.fr"
            },
            "prediction":{
               "description":"Paris-Le Bourget Airport Esplanade de l'Air et de l'Espace, Dugny, France",
               "matchedKeywords":[
                  {
                     "offset":0,
                     "value":"Paris"
                  }
               ],
               "matchedWords":[
                  {
                     "offset":0,
                     "value":"Paris-Le Bourget Airport"
                  },
                  {
                     "offset":26,
                     "value":"Esplanade de l'Air et de l'Espace"
                  },
                  {
                     "offset":61,
                     "value":"Dugny"
                  },
                  {
                     "offset":68,
                     "value":"France"
                  }
               ]
            },
            "siteId":"2264272F8B865B95FBA2EC4156416DD4",
            "utcOffset":0
         }
      ]
   }
}
```


### Data Types

#### Overview

| Type | Description |
| -- | -- |
| [Coordinate](#Coordinate) | Coordinate of the location. |
| [Bounds](#Bounds) | Bound coordinates of the area. |
| [Result](#Result) | Result object of the requested data. |
| [TextSearchRequest](#TextSearchRequest) | Request object of the textSearch function. |
| [NearbySearchRequest](#NearbySearchRequest) | Request object of the nearbySearch function. |
| [QuerySuggestionRequest](#QuerySuggestionRequest) | Request object of the querySuggestion function. |
| [DetailSearchRequest](#DetailSearchRequest) | Request object of the detailSearch function. |
| [QueryAutocompleteRequest](#QueryAutocompleteRequest) | Request object of the queryAutocomplete function. |


#### Coordinate
This object indicates the coordinate of the location.

| Name | Type | Description |
| -- | -- | -- |
| lat | number | Latitude of the location. |
| lng | number | Longitude of the location. |

#### Bounds
This object indicates the northeast and southwest coordinates of the bound. 

| Name | Type | Description |
| -- | -- | -- |
| northeast | [Coordinate](#coordinate) | Northeast coordinate of the bound. |
| southwest | [Coordinate](#coordinate) | Southwest coordinate of the bound. |
#### Result

It is an object that contains common information on the returns of all functions.

| Name | Type | Description |
| -- | -- | -- |
| resultCode | number \| string | One of the [ResultCodes](#result-codes) returns. |
| status | string | Result status string in terms of result code. |
| data | object \| string | It contains the result object returned from the respective api. If there is a JSON parse error occurs the data may be return as string. |

#### TextSearchRequest

| Name | Type | Description |
| -- | -- | -- |
| query | string | Search keyword. **Mandatory.** |
| location |  [Coordinate](#coordinate) | Longitude and latitude to which search results need to be biased. **Optional.** |
| radius | number | Search radius, in meters. The value ranges from 1 to 50000. The default value is 50000. This parameter is used to specify an area where places are searched in priority, but not restrict the search result to this area. **Optional.** |
| poiType | string | POI type of returned places. The value range is the same as that of LocationType. hwPoiType is recommended. **Optional.**  |
| hwPoiType | string | Huawei POI type of returned places. This parameter is recommended. **Optional.**  |
| countryCode | string | Code of the country where places are searched, which complies with the ISO 3166-1 alpha-2 standard. This parameter is used to return search results in the specified country in priority, but not filter out all search results that are not in this country. **Optional.** |
| language | string | Language in which search results are displayed. For details about the value range, please refer to language codes in Supported Languages. If this parameter is not passed, English will be used. If English is unavailable, the local language will be used. **Optional.**  |
| pageSize | number | Number of records on each page. The value ranges from 1 to 20. The default value is 20. **Optional.** |
| pageIndex | number | Current page number. The value ranges from 1 to 60. The default value is 1. **Optional.**  |
| children | boolean | Indicates whether to return information about child nodes. The default value is false. If this parameter is set to true, full information about child nodes, if any, will be returned. **Optional.**  |

#### NearbySearchRequest

| Name | Type | Description |
| -- | -- | -- |
| location |  [Coordinate](#coordinate) | Longitude and latitude to which search results need to be biased. **Mandatory.**|
| query | string | Search keyword. **Optional.**|
| radius | number | Search radius, in meters. The value ranges from 1 to 50000. The default value is 50000. This parameter is used to specify an area where places are searched in priority, but not restrict the search result to this area. **Optional.** |
| poiType | string | POI type of returned places. The value range is the same as that of LocationType. hwPoiType is recommended. **Optional.** |
| hwPoiType | string | Huawei POI type of returned places. This parameter is recommended. **Optional.** |
| countryCode | string | Code of the country where places are searched, which complies with the ISO 3166-1 alpha-2 standard. This parameter is used to return search results in the specified country in priority, but not filter out all search results that are not in this country. **Optional.** |
| language | string | Language in which search results are displayed. For details about the value range, please refer to language codes in Supported Languages. If this parameter is not passed, English will be used. If English is unavailable, the local language will be used. **Optional.**  |
| pageSize | number | Number of records on each page. The value ranges from 1 to 20. The default value is 20. **Optional.** |
| pageIndex | number | Current page number. The value ranges from 1 to 60. The default value is 1. **Optional.** |
| strictBounds | boolean | Indicates whether to strictly restrict place search in the bounds specified by location and radius. The default value is true. **Optional.** |

#### QuerySuggestionRequest

| Name | Type | Description |
| -- | -- | -- |
| query | string | Search keyword. **Mandatory.**|
| location |  [Coordinate](#coordinate) | Longitude and latitude to which search results need to be biased. **Optional.** |
| radius | number | Search radius, in meters. The value ranges from 1 to 50000. The default value is 50000. This parameter is used to specify an area where places are searched in priority, but not restrict the search result to this area. **Optional.** |
| bounds | [Bounds](#bounds) | Coordinate bounds to which search results need to be biased. **Optional.** |
| poiTypes | string[] | List of POI types. The value range is a subset of LocationType. **Optional.** |
| countryCode | string | Code of the country where places are searched, which complies with the ISO 3166-1 alpha-2 standard. This parameter is used to return search results in the specified country in priority, but not filter out all search results that are not in this country. **Optional.** |
| language | string | Language in which search results are displayed. For details about the value range, please refer to language codes in Supported Languages. If this parameter is not passed, English will be used. If English is unavailable, the local language will be used. **Optional.** |
| children | boolean | Indicates whether to return information about child nodes. The default value is false. If this parameter is set to true, full information about child nodes, if any, will be returned. **Optional.** |
| strictBounds | boolean | Indicates whether to strictly restrict place search in the bounds specified by location and radius. The default value is true. **Optional.**  |

#### DetailSearchRequest

| Parameter | Type | Description |
| -- | -- | -- |
| siteId | string | ID of a place. **Mandatory** |
| language | string | Language in which search results are displayed. For details about the value range, please refer to language codes in Supported Languages. If this parameter is not passed, English will be used. If English is unavailable, the local language will be used. **Optional.**  |
| children | boolean | Indicates whether to return information about child nodes. The default value is false. If this parameter is set to true, full information about child nodes, if any, will be returned. **Optional.** |

#### QueryAutocompleteRequest

| Parameter | Type | Description |
| -- | -- | -- |
| query | string | Search keyword. **Mandatory** |
| location |  [Coordinate](#coordinate) | Longitude and latitude to which search results need to be biased. **Optional.** |
| radius | number | Search radius, in meters. The value ranges from 1 to 50000. The default value is 50000. This parameter is used to specify an area where places are searched in priority, but not restrict the search result to this area. **Optional.** |
| language | string | Language in which search results are displayed. For details about the value range, please refer to language codes in Supported Languages. If this parameter is not passed, English will be used. If English is unavailable, the local language will be used. **Optional.** |
| children | boolean | Indicates whether to return information about child nodes. The default value is false. If this parameter is set to true, full information about child nodes, if any, will be returned. **Optional.** |

### Result Codes

| Result Code | Result Status | Description |
| -- | -- | -- |
| 0 | OK | Success  |
| 5 | NOT_FOUND | The request URI is incorrect.  |
| 6 | REQUEST_DENIED | Invalid API key or token. |
| 7 | INVALID_REQUEST | Invalid content type.  |
| 8 | INVALID_REQUEST | Invalid Accept type. |
| 105 | INVALID_REQUEST |  Incorrect parameter. |
| 110 | UNKNOWN_ERROR | Internal service error.  |
| 111 | UNKNOWN_ERROR | The request is discarded because the service is busy.  |
| 403 | REQUEST_DENIED | The app ID does not have the service call permission.  |
| 10001 | UNKNOWN_ERROR | The authentication service is abnormal.  |
| 10002 | REQUEST_DENIED | Incorrect certificate fingerprint.  |
| 10003 | REQUEST_DENIED | Unauthorized API call.  |
| 10004 | ZERO_RESULTS | The search is successful but no record is found. |
| 10005 | REQUEST_DENIED | Authentication failed.  |
| 10006 | OVER_QUERY_LIMIT | API call quota is used up.  |
| 10007 | INVALID_REQUEST | API call quota is used up.  |
| 10009 | INVALID_REQUEST | Cross-region route planning is not supported.  |
| 10010 | INVALID_REQUEST | Incorrect parameter.  |
| 10011 | NOT_FOUND | No resource is found.  |
| 10012 | UNKNOWN_ERROR | Internal server error.  |
| 10017 | REQUEST_DENIED | Invalid request signature. |
| 10018 | REQUEST_DENIED | The service is degraded because the server is busy. |
| 10024 | OVER_QUERY_LIMIT | The API is in arrears.  |
| 10027 | OVER_QUERY_LIMIT | You have not subscribed to any pay-as-you-go plan.  |
| 70003 | NETWORK_ERROR | Network error.  |
| 70004 | NETWORK_ERROR | Internal service error.  |
| 70005 | ACCESS_TIMEOUT | Network connection timeout. |
| 70006 | BUSINESS_VERIFICATION_FAILED | Service verification failed. |
| 70100 | QUERY_CANCELED | User tapped the back icon to cancel the search when using the search widget. |
| 6003 | CERT_FINGERPRINT_ERROR | Signature certificate fingerprint error |
| 010002 |SCOPE_FINGERPRINT_ERROR | Incorrect certificate fingerprint. |
| 010012 | UNKNOWN_ERROR | Internal server error. |
| 070004 | INTERNAL_ERROR_CODE | Internal service error. |
| 907135000 | ARGUMENTS_INVALID | The input parameter is incorrect. |
| 907135001 | INTERNAL_ERROR | Internal error, indicating that an internal error occurs and cannot be rectified. |
| 907135701 | SCOPE_LIST_EMPTY | No scope is configured for the OpenGW. |
| 907135702 | CERT_FINGERPRINT_EMPTY | No fingerprint certificate is configured for the OpenGW. |
| 907135703 | PERMISSION_LIST_EMPTY | No permission is configured for the OpenGW. |
| 907135704 | GET_SCOPE_NETWORK_ERROR | Failed to invoke the gateway to query the application scope. The error is caused by an exception returned by the server. |
| UNKNOWN_ERROR | UNKNOWN_ERROR_REASON | Internal server error. |
| INTERNAL_ERROR | INTERNAL_ERROR_REASON | Internal error on the device side. |
| REQUEST_DENIED | ERROR_REQUEST_DENIED | An exception occurred when accessing the ScopeServer. |

## 4. Configuration and Description

### Configuring Obfuscation Scripts

#### React Native

In order to prevent error while release build, you may need to add following lines in **`proguard-rules.pro`** file.

```text
-ignorewarnings
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keep class com.hianalytics.android.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}
-repackageclasses
```

#### Cordova

Before building the APK, configure the obfuscation configuration file to prevent the HMS Core SDK from being obfuscated.

**NOTE**: This step is required only if you want to minify and obfuscate your app. By default obfuscation is disabled in Cordova and Ionic apps.

The obfuscation is done by **`ProGuard`.** By default, in Cordova and Ionic apps ProGuard is disabled. Even though ProGuard is not available, ProGuard support can be added through 3rd party ProGuard plugins. If ProGuard is enabled in your project, the Huawei Cordova Site plugin's ProGuard rules need to be added to your project. These rules are as follows:

```text
-ignorewarnings
-keepattributes *Annotation*
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keep class com.huawei.hianalytics.**{*;}
-keep class com.huawei.updatesdk.**{*;}
-keep class com.huawei.hms.**{*;}
-repackageclasses
```

---

## 5. Questions or Issues

If you have questions about how to use HMS samples, try the following options:

- [Stack Overflow](https://stackoverflow.com/questions/tagged/huawei-mobile-services) is the best place for any programming questions. Be sure to tag your question with **huawei-mobile-services**.
- [Huawei Developer Forum](https://forums.developer.huawei.com/forumPortal/en/home?fid=0101187876626530001) HMS Core Module is great for general questions, or seeking recommendations and opinions.
- [Huawei Developer Docs](https://developer.huawei.com/consumer/en/doc/overview/HMS-Core-Plugin) is place to official documentation for all HMS Core Kits, you can find detailed documentations in there.

---

## 6. Licensing and Terms

Huawei JS SDK is licensed under [Apache 2.0 license](LICENCE).