Integration of Huawei Map Kit and Location Kit in Android KnowMyBoard App using Navigation Component in Java
Tags: huaweilocationkit, navigationcomponent, hmscore, huaweimapkit
Published: 2022-06-17 12:05:12

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8huh2vrrkgz58lap86qo.png)
Introduction
In this article, we will learn how to integrate Huawei ML kit, Map kit and Location kit in Android application KnowMyBoard. Account Kit provides seamless login functionality to the app with large user base.

Location kit SDK for Android offers location-related APIs for Android apps. These APIs mainly relate to 6 functions like fused location, activity identification, geofence, high-precision location, indoor location, and geocoding. This mode is applicable to mobile phones and Huawei tablets. We are using Location kit to get location of user.

Huawei Map SDK for Android is a set of APIs that can be called to develop maps. You can use this SDK to easily add map-related functions to your Android app, including map display, map interaction, map drawing, and map style customization.

Supported Devices
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y4bddb701rww1dr9t9s0.png)
**Supported Countries/Regions**

 Supported Countries/Regions

**Development Overview**

You need to install Android Studio IDE and I assume that you have prior knowledge of Android application development.

**Hardware Requirements**
- A computer (desktop or laptop) running Windows 10.
- Android phone (with the USB cable), which is used for debugging.

**Software Requirements**

- Java JDK 1.8 or later.
- Android Studio software or Visual Studio or Code installed.
- HMS Core (APK) 4.X or later

**Integration steps**
Step 1. Huawei developer account and complete identity verification in Huawei developer website, refer to register [Huawei ID.](https://developer.huawei.com/consumer/en/doc/start/registration-and-verification-0000001053628148)
Step 2. [Create project in AppGallery Connect](https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#0)

Step 3. [Adding HMS Core SDK](https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/android-sdk-integrating-sdk-0000001061671869)

**Let's start coding**

**MainActivity.java**

```
 public class MainActivity extends AppCompatActivity {

    LoginViewModel loginViewModel;
    private MLTextAnalyzer mTextAnalyzer;
    public Uri imagePath;
    Bitmap bitmap;
    static String TAG = "TAG";
    ArrayList<String> result = new ArrayList<>();
    MLLocalLangDetector myLocalLangDetector;
    MLLocalTranslator myLocalTranslator;
    String textRecognized;
    ProgressDialog progressDialog;
    NavController navController;
    ActivityMainBinding activityMainBinding;
    BottomNavigationView bottomNavigationView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        activityMainBinding = DataBindingUtil.setContentView(MainActivity.this,R.layout.activity_main);
        loginViewModel = new ViewModelProvider(MainActivity.this).get(LoginViewModel.class);

        navController = Navigation.findNavController(MainActivity.this, R.id.nav_host_fragment);
        MyApplication.setActivity(this);
        progressDialog = new ProgressDialog(this);
        progressDialog.setCancelable(false);
        bottomNavigationView = activityMainBinding.bottomNavigation;
        NavigationUI.setupWithNavController(bottomNavigationView, navController);
    }
   
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        // Process the authorization result to obtain the authorization code from AuthAccount.
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == 8888) {

            Task<AuthAccount> authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data);
            if (authAccountTask.isSuccessful()) {
                // The sign-in is successful, and the user's ID information and authorization code are obtained.
                AuthAccount authAccount = authAccountTask.getResult();
                UserData userData = new UserData();
                userData.setAccessToken(authAccount.getAccessToken());
                userData.setCountryCode(authAccount.getCountryCode());
                userData.setDisplayName(authAccount.getDisplayName());
                userData.setEmail(authAccount.getEmail());
                userData.setFamilyName(authAccount.getFamilyName());
                userData.setGivenName(authAccount.getGivenName());
                userData.setIdToken(authAccount.getIdToken());
                userData.setOpenId(authAccount.getOpenId());
                userData.setUid(authAccount.getUid());
                userData.setPhotoUriString(authAccount.getAvatarUri().toString());
                userData.setUnionId(authAccount.getUnionId());
                Gson gson = new Gson();
                Log.e("TAG", "sign in success : " + gson.toJson(authAccount));
                loginViewModel = new ViewModelProvider(MainActivity.this).get(LoginViewModel.class);
                loginViewModel.sendData(authAccount.getDisplayName());

            } else {
                // The sign-in failed.
                Log.e("TAG", "sign in failed:" + ((ApiException) authAccountTask.getException()).getStatusCode());

            }
        }
        if (requestCode == 2323 && resultCode == RESULT_OK && data != null) {
            progressDialog.setMessage("Initializing text detection..");
            progressDialog.show();
            imagePath = data.getData();
            try {
                bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imagePath);
            } catch (IOException e) {
                e.printStackTrace();
                Log.e("TAG", " BITMAP ERROR");
            }
            Log.d("TAG", "Path " + imagePath.getPath());
            try {
                Bitmap selectedBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), imagePath);
                asyncAnalyzeText(selectedBitmap);
            } catch (IOException e) {
                e.printStackTrace();
                progressDialog.dismiss();
            }
        }
    }

    private void asyncAnalyzeText(Bitmap bitmap) {

        if (mTextAnalyzer == null) {
            createMLTextAnalyzer();
        }

        MLFrame frame = MLFrame.fromBitmap(bitmap);

        Task<MLText> task = mTextAnalyzer.asyncAnalyseFrame(frame);
        task.addOnSuccessListener(new OnSuccessListener<MLText>() {
            @Override
            public void onSuccess(MLText text) {
                progressDialog.setMessage("Initializing language detection..");
                Log.d("TAG", "#==>" + text.getStringValue());
                textRecognized = text.getStringValue().trim();
                if(!textRecognized.isEmpty()){
                    // Create a local language detector.
                    MLLangDetectorFactory factory = MLLangDetectorFactory.getInstance();
                    MLLocalLangDetectorSetting setting = new MLLocalLangDetectorSetting.Factory()
                            // Set the minimum confidence threshold for language detection.
                            .setTrustedThreshold(0.01f)
                            .create();
                    myLocalLangDetector = factory.getLocalLangDetector(setting);
                    Task<String> firstBestDetectTask = myLocalLangDetector.firstBestDetect(textRecognized);
                    firstBestDetectTask.addOnSuccessListener(new OnSuccessListener<String>() {
                        @Override
                        public void onSuccess(String languageDetected) {
                            progressDialog.setMessage("Initializing text translation..");
                            // Processing logic for detection success.
                            Log.d("TAG", "Lang detect :" + languageDetected);
                            textTranslate(languageDetected, textRecognized, bitmap);
                        }
                    }).addOnFailureListener(new OnFailureListener() {
                        @Override
                        public void onFailure(Exception e) {
                            // Processing logic for detection failure.
                            Log.e("TAG", "Lang detect error:" + e.getMessage());
                        }
                    });
                }else{
                    progressDialog.dismiss();
                    showErrorDialog("Failed to recognize text.");

                }

            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(Exception e) {
                Log.e("TAG", "#==>" + e.getMessage());
            }
        });
    }

    private void showErrorDialog(String msg) {
        AlertDialog alertDialog = new AlertDialog.Builder(this).create();
        alertDialog.setTitle("Error");
        alertDialog.setMessage(msg);

        alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });

        alertDialog.show();
    }

    private void textTranslate(String languageDetected, String textRecognized, Bitmap uri) {
        MLApplication.initialize(getApplication());
        MLApplication.getInstance().setApiKey("$54fDAEDAF4 C9qhwQ==");

        // Create an offline translator.
        MLLocalTranslateSetting setting = new MLLocalTranslateSetting.Factory()
                // Set the source language code. The ISO 639-1 standard is used. This parameter is mandatory. If this parameter is not set, an error may occur.
                .setSourceLangCode(languageDetected)
                // Set the target language code. The ISO 639-1 standard is used. This parameter is mandatory. If this parameter is not set, an error may occur.
                .setTargetLangCode("en")
                .create();

         myLocalTranslator = MLTranslatorFactory.getInstance().getLocalTranslator(setting);
        // Set the model download policy.
        MLModelDownloadStrategy downloadStrategy = new MLModelDownloadStrategy.Factory()
                .needWifi()// It is recommended that you download the package in a Wi-Fi environment.
                .create();
        // Create a download progress listener.
        MLModelDownloadListener modelDownloadListener = new MLModelDownloadListener() {
            @Override
            public void onProcess(long alreadyDownLength, long totalLength) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // Display the download progress or perform other operations.
                    }
                });
            }
        };

        myLocalTranslator.preparedModel(downloadStrategy, modelDownloadListener).
                addOnSuccessListener(new OnSuccessListener<Void>() {
                    @Override
                    public void onSuccess(Void aVoid) {
                        // Called when the model package is successfully downloaded.
                        // input is a string of less than 5000 characters.
                        final Task<String> task = myLocalTranslator.asyncTranslate(textRecognized);
                        // Before translation, ensure that the models have been successfully downloaded.
                        task.addOnSuccessListener(new OnSuccessListener<String>() {
                            @Override
                            public void onSuccess(String translated) {
                                // Processing logic for detection success.
                                result.clear();
                                result.add(languageDetected.trim());
                                result.add(textRecognized.trim());
                                result.add(translated.trim());
                                loginViewModel.setImage(uri);
                                loginViewModel.setTextRecongnized(result);
                                progressDialog.dismiss();
                            }
                        }).addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(Exception e) {
                                // Processing logic for detection failure.
                                progressDialog.dismiss();
                            }
                        });
                    }
                }).addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(Exception e) {
                        // Called when the model package fails to be downloaded.
                        progressDialog.dismiss();
                    }
                });

    }

    private void createMLTextAnalyzer() {
        MLLocalTextSetting setting = new MLLocalTextSetting.Factory()
                .setOCRMode(MLLocalTextSetting.OCR_DETECT_MODE)
                .create();
        mTextAnalyzer = MLAnalyzerFactory.getInstance().getLocalTextAnalyzer(setting);

    }

    @Override
    protected void onStop() {
        if (myLocalLangDetector != null) {
            myLocalLangDetector.stop();
        }
        if (myLocalTranslator!= null) {
            myLocalTranslator.stop();
        }
        if(progressDialog!= null){
            progressDialog.dismiss();
        }
        super.onStop();
    }
}

```
**LoginViewModel.java**

```
public class LoginFragment extends Fragment implements OnMapReadyCallback{

    FragmentLoginBinding loginBinding;
    LoginViewModel loginViewModel;
    Menu menu;
    SharedPreferences prefs;
    SharedPreferences.Editor editor;
    NavController navController;
    private String MY_PREF_NAME = "my_pref_name";
    private String TAG = "TAG";
    private static final String MAPVIEW_BUNDLE_KEY = "MapViewBundleKey";

    RequestLocationData locationData;
    HuaweiMap hMap;
    public LoginFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        loginBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_login, container, false);
        loginViewModel = new ViewModelProvider(getActivity()).get(LoginViewModel.class);
        loginBinding.setLoginViewModel(loginViewModel);

        locationData = new RequestLocationData(getContext(),getActivity(),loginViewModel);
        locationData.setLoginViewModel(loginViewModel);
        locationData.initFusionLocationProviderClint();
        locationData.checkPermission();
        locationData.checkDeviceLocationSettings();

       initMap(savedInstanceState);
        loginViewModel.getLocationResult().observeForever(new Observer<LocationResult>() {
            @Override
            public void onChanged(LocationResult locationResult) {
               refreshLocation(locationResult);
            }
        });

        return loginBinding.getRoot();
    }

    private void initMap(Bundle savedInstanceState) {

        Bundle mapViewBundle = null;
        if (savedInstanceState != null) {
            mapViewBundle = savedInstanceState.getBundle("MapViewBundleKey");
        }
        loginBinding.mapview.onCreate(mapViewBundle);
        loginBinding.mapview.getMapAsync(this) ;

    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
        // Initialize the SDK.
        MapsInitializer.initialize(getContext());

    }

    @Override
    public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
        menu.clear();
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.main, menu);
        this.menu = menu;
        disableMenu(menu);

    }

    private void disableMenu(Menu menu) {
        try {
            if (menu != null) {
                if (getPreferenceValue().equals("user_name")) {
                    menu.findItem(R.id.menu_login_logout).setVisible(false);
                    menu.findItem(R.id.menu_cancel_auth).setVisible(false);
                    menu.findItem(R.id.menu_login).setVisible(true);
                    getActivity().setTitle(getResources().getString(R.string.app_name));
                } else {
                    menu.findItem(R.id.menu_login_logout).setVisible(true);
                    menu.findItem(R.id.menu_cancel_auth).setVisible(true);
                    menu.findItem(R.id.menu_login).setVisible(false);
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private void enableMenu(Menu menu) {
        try {
            menu.findItem(R.id.menu_login_logout).setVisible(true);
            menu.findItem(R.id.menu_cancel_auth).setVisible(true);
            menu.findItem(R.id.menu_login).setVisible(false);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @SuppressLint("NonConstantResourceId")
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_cancel_auth:
                setPreferenceValue("user_name");
                loginViewModel.cancelAuthorization();
                disableMenu(menu);
                return true;
            case R.id.menu_login_logout:

                setPreferenceValue("user_name");
                loginViewModel.logoutHuaweiID();
                disableMenu(menu);
                return true;
            case R.id.menu_login:
                loginViewModel.loginClicked();
                return true;
                case R.id.option_refresh_location:
                locationData.refreshLocation();

                return true;

            default:
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    public void updateMessage(String msg) {
        getActivity().setTitle(msg);

    }

    void setPreferenceValue(String userName) {
        editor = getActivity().getSharedPreferences(MY_PREF_NAME, MODE_PRIVATE).edit();
        editor.putString("user_name", userName);
        editor.apply();
    }

    String getPreferenceValue() {
        prefs = getActivity().getSharedPreferences(MY_PREF_NAME, MODE_PRIVATE);
        return prefs.getString("user_name", "user_name");

    }

    @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE})
    @Override
    public void onMapReady(HuaweiMap huaweiMap) {
        try{
            Log.d(TAG, "Map ready");
            hMap = huaweiMap;
            onHuaweiMapReady();
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    private void onHuaweiMapReady() {
        if(hMap!=null){
            hMap.setMapType(MAP_TYPE_NORMAL);
            hMap.setBuildingsEnabled(true);
            // Enable the my-location layer.
            hMap.setMyLocationEnabled(true);
            // Enable the my-location icon.
            hMap.getUiSettings().setMyLocationButtonEnabled(true);
            hMap.getUiSettings().setGestureScaleByMapCenter(true);
        }
        if(locationData!=null){
           locationData.refreshLocation();
        }

    }

    private void refreshLocation(LocationResult locationResult) {
        try{
            Log.d(TAG, "Map updated with ");
            Log.d(TAG, "Latitude :"+locationResult.getLastLocation().getLongitude()+" Longitude :"+locationResult.getLastLocation().getLongitude());
            LatLng latLng1 = new LatLng(locationResult.getLastHWLocation().getLatitude(), locationResult.getLastHWLocation().getLongitude());
            float zoom = 10.0f;
            CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng1,zoom);
            hMap.animateCamera(cameraUpdate);

        }catch (Exception e){
            e.printStackTrace();
            // onHuaweiMapReady();
        }
    }
    @Override
    public void onLowMemory() {
        super.onLowMemory();
        loginBinding.mapview.onLowMemory();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        loginBinding.mapview.onDestroy();
    }

    @Override
    public void onStop() {
        super.onStop();
        loginBinding.mapview.onStop();
        locationData.disableLocationData();

    }

    @Override
    public void onPause() {
        super.onPause();
        loginBinding.mapview.onPause();
    }

    @Override
    public void onStart() {
        super.onStart();
        loginBinding.mapview.onStart();

    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        Bundle mapViewBundle = outState.getBundle(MAPVIEW_BUNDLE_KEY);
        if (mapViewBundle == null) {
            mapViewBundle = new Bundle();
            outState.putBundle(MAPVIEW_BUNDLE_KEY, mapViewBundle);
        }
        loginBinding.mapview.onSaveInstanceState(mapViewBundle);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        navController = Navigation.findNavController(view);
    }
}

```
**RequestLocationData.java**

```
public class RequestLocationData {
    static String TAG = "TAG";
    SettingsClient settingsClient;
    private int isLocationSettingSuccess = 0;
    private LocationRequest myLocationRequest;
    // Define a fusedLocationProviderClient object.
    private FusedLocationProviderClient fusedLocationProviderClient;
    LocationCallback myLocationCallback;
    Context context;
    Activity activity;
    LocationResult locationResult;
    LoginViewModel loginViewModel;
    public RequestLocationData(Context context, FragmentActivity activity, LoginViewModel loginViewModel) {
        setContext(context);
        setActivity(activity);
        setLoginViewModel(loginViewModel);
    }

    public LoginViewModel getLoginViewModel() {
        return loginViewModel;
    }

    public void setLoginViewModel(LoginViewModel loginViewModel) {
        this.loginViewModel = loginViewModel;
    }

    public Context getContext() {
        return context;
    }

    public void setContext(Context context) {
        this.context = context;
    }

    public Activity getActivity() {
        return activity;
    }

    public void setActivity(Activity activity) {
        this.activity = activity;
    }

    public void initFusionLocationProviderClint(){
       // Instantiate the fusedLocationProviderClient object.
       fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(getActivity());
       settingsClient = LocationServices.getSettingsClient(getActivity());
    }
    public void checkDeviceLocationSettings() {
        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
        myLocationRequest = new LocationRequest();
        builder.addLocationRequest(myLocationRequest);
        LocationSettingsRequest locationSettingsRequest = builder.build();
        // Check the device location settings.
        settingsClient.checkLocationSettings(locationSettingsRequest)
                // Define the listener for success in calling the API for checking device location settings.
                .addOnSuccessListener(locationSettingsResponse -> {
                    LocationSettingsStates locationSettingsStates =
                            locationSettingsResponse.getLocationSettingsStates();
                    StringBuilder stringBuilder = new StringBuilder();
                    // Check whether the location function is enabled.
                    stringBuilder.append(",\nisLocationUsable=")
                            .append(locationSettingsStates.isLocationUsable());
                    // Check whether HMS Core (APK) is available.
                    stringBuilder.append(",\nisHMSLocationUsable=")
                            .append(locationSettingsStates.isHMSLocationUsable());
                    Log.i(TAG, "checkLocationSetting onComplete:" + stringBuilder.toString());
                    // Set the location type.
                    myLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
                    // Set the number of location updates to 1.
                    myLocationRequest.setNumUpdates(1);
                    isLocationSettingSuccess = 1;


                })
                // Define callback for failure in checking the device location settings.
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(Exception e) {
                        Log.i(TAG, "checkLocationSetting onFailure:" + e.getMessage());
                    }
                });

    }

    public void checkPermission() {
        // Dynamically apply for required permissions if the API level is 28 or lower.
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
            Log.i(TAG, "android sdk <= 28 Q");
            if (ActivityCompat.checkSelfPermission(getContext(),
                    Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    && ActivityCompat.checkSelfPermission(getContext(),
                    Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                String[] strings =
                        {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.MANAGE_MEDIA,Manifest.permission.MEDIA_CONTENT_CONTROL,Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};
                ActivityCompat.requestPermissions(getActivity(), strings, 1);
            }
        } else {
            // Dynamically apply for the android.permission.ACCESS_BACKGROUND_LOCATION permission in addition to the preceding permissions if the API level is higher than 28.
            if (ActivityCompat.checkSelfPermission(getActivity(),
                    Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    && ActivityCompat.checkSelfPermission(getContext(),
                    Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    && ActivityCompat.checkSelfPermission(getContext(),
                    "android.permission.ACCESS_BACKGROUND_LOCATION") != PackageManager.PERMISSION_GRANTED) {
                String[] strings = {android.Manifest.permission.ACCESS_FINE_LOCATION,
                        android.Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.MEDIA_CONTENT_CONTROL,Manifest.permission.MANAGE_MEDIA,
                        "android.permission.ACCESS_BACKGROUND_LOCATION"};
                ActivityCompat.requestPermissions(getActivity(), strings, 2);
            }
        }
    }
    public LocationResult refreshLocation() {
   
        if (isLocationSettingSuccess == 1) {
            myLocationCallback = new LocationCallback() {
                @Override
                public void onLocationResult(LocationResult locationResult) {
                    if (locationResult != null) {                 
                        getLoginViewModel().setLocationResult(locationResult);
                    }
                }
            };
            fusedLocationProviderClient.requestLocationUpdates(myLocationRequest, myLocationCallback, Looper.getMainLooper());

        } else {
            Log.d(TAG, "Failed to get location settings");
        }
        return locationResult;
    }

    public void disableLocationData(){
        fusedLocationProviderClient.disableBackgroundLocation();
        fusedLocationProviderClient.removeLocationUpdates(myLocationCallback);
    }
    
}

```
**navigation_graph.xml**

```
 <?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/navigation_graph"
    app:startDestination="@id/loginFragment">
    <fragment
        android:id="@+id/loginFragment"
        android:name="com.huawei.hms.knowmyboard.dtse.activity.fragments.LoginFragment"
        android:label="LoginFragment"/>
    <fragment
        android:id="@+id/mainFragment"
        android:name="com.huawei.hms.knowmyboard.dtse.activity.fragments.MainFragment"
        android:label="MainFragment"/>
    <fragment
        android:id="@+id/cameraFragment"
        android:name="com.huawei.hms.knowmyboard.dtse.activity.fragments.CameraFragment"
        android:label="fragment_camera"
        tools:layout="@layout/fragment_camera" />
</navigation>

```
**bottom_navigation_menu.xml **

```
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/loginFragment"
        android:icon="@android:drawable/ic_menu_agenda"
        android:title="Home" />
    <item
        android:id="@+id/mainFragment"
        app:showAsAction="always"
        android:icon="@android:drawable/ic_menu_gallery"
        android:title="Gallery" />
    <item
        android:id="@+id/cameraFragment"
        android:icon="@android:drawable/ic_menu_camera"
        app:showAsAction="always"
        android:title="Camera" />
</menu>

```
**LoginFragment.java**

```
public class LoginFragment extends Fragment implements OnMapReadyCallback{

FragmentLoginBinding loginBinding;

LoginViewModel loginViewModel;

Menu menu;

SharedPreferences prefs;

SharedPreferences.Editor editor;

NavController navController;

private String MY_PREF_NAME = "my_pref_name";

private String TAG = "TAG";

private static final String MAPVIEW_BUNDLE_KEY = "MapViewBundleKey";

RequestLocationData locationData;

HuaweiMap hMap;

public LoginFragment() {

// Required empty public constructor

}

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container,

Bundle savedInstanceState) {

loginBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_login, container, false);

loginViewModel = new ViewModelProvider(getActivity()).get(LoginViewModel.class);

loginBinding.setLoginViewModel(loginViewModel);

locationData = new RequestLocationData(getContext(),getActivity(),loginViewModel);

locationData.setLoginViewModel(loginViewModel);

locationData.initFusionLocationProviderClint();

locationData.checkPermission();

locationData.checkDeviceLocationSettings();

initMap(savedInstanceState);

loginViewModel.getMessage().observeForever(new Observer<String>() {

@Override

public void onChanged(String message) {

updateMessage(message);

if (!message.equals(getResources().getString(R.string.app_name))) {

setPreferenceValue(message);

enableMenu(menu);

} else {

disableMenu(menu);

setPreferenceValue("user_name");

}

}

});

loginViewModel.getLocationResult().observeForever(new Observer<LocationResult>() {

@Override

public void onChanged(LocationResult locationResult) {

refreshLocation(locationResult);

}

});

return loginBinding.getRoot();

}

private void initMap(Bundle savedInstanceState) {

Bundle mapViewBundle = null;

if (savedInstanceState != null) {

mapViewBundle = savedInstanceState.getBundle("MapViewBundleKey");

}

loginBinding.mapview.onCreate(mapViewBundle);

loginBinding.mapview.getMapAsync(this) ;

}

@Override

public void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setHasOptionsMenu(true);

// Initialize the SDK.

MapsInitializer.initialize(getContext());

}

@Override

public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {

menu.clear();

super.onCreateOptionsMenu(menu, inflater);

inflater.inflate(R.menu.main, menu);

this.menu = menu;

disableMenu(menu);

}

private void disableMenu(Menu menu) {

try {

if (menu != null) {

if (getPreferenceValue().equals("user_name")) {

menu.findItem(R.id.menu_login_logout).setVisible(false);

menu.findItem(R.id.menu_cancel_auth).setVisible(false);

menu.findItem(R.id.menu_login).setVisible(true);

getActivity().setTitle(getResources().getString(R.string.app_name));

} else {

menu.findItem(R.id.menu_login_logout).setVisible(true);

menu.findItem(R.id.menu_cancel_auth).setVisible(true);

menu.findItem(R.id.menu_login).setVisible(false);

}

}

} catch (Exception e) {

e.printStackTrace();

}

}

private void enableMenu(Menu menu) {

try {

menu.findItem(R.id.menu_login_logout).setVisible(true);

menu.findItem(R.id.menu_cancel_auth).setVisible(true);

menu.findItem(R.id.menu_login).setVisible(false);

} catch (Exception e) {

e.printStackTrace();

}

}

@SuppressLint("NonConstantResourceId")

@Override

public boolean onOptionsItemSelected(MenuItem item) {

switch (item.getItemId()) {

case R.id.menu_cancel_auth:

setPreferenceValue("user_name");

loginViewModel.cancelAuthorization();

disableMenu(menu);

return true;

case R.id.menu_login_logout:

setPreferenceValue("user_name");

loginViewModel.logoutHuaweiID();

disableMenu(menu);

return true;

case R.id.menu_login:

loginViewModel.loginClicked();

return true;

case R.id.option_refresh_location:

locationData.refreshLocation();

return true;

default:

break;

}

return super.onOptionsItemSelected(item);

}

public void updateMessage(String msg) {

getActivity().setTitle(msg);

}

void setPreferenceValue(String userName) {

editor = getActivity().getSharedPreferences(MY_PREF_NAME, MODE_PRIVATE).edit();

editor.putString("user_name", userName);

editor.apply();

}

String getPreferenceValue() {

prefs = getActivity().getSharedPreferences(MY_PREF_NAME, MODE_PRIVATE);

return prefs.getString("user_name", "user_name");

}

@RequiresPermission(allOf = {ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE})

@Override

public void onMapReady(HuaweiMap huaweiMap) {

try{

Log.d(TAG, "Map ready");

hMap = huaweiMap;

onHuaweiMapReady();

}catch (Exception e){

e.printStackTrace();

}

}

private void onHuaweiMapReady() {

if(hMap!=null){

hMap.setMapType(MAP_TYPE_NORMAL);

hMap.setBuildingsEnabled(true);

// Enable the my-location layer.

hMap.setMyLocationEnabled(true);

// Enable the my-location icon.

hMap.getUiSettings().setMyLocationButtonEnabled(true);

hMap.getUiSettings().setGestureScaleByMapCenter(true);

}

if(locationData!=null){

locationData.refreshLocation();

}

}

private void refreshLocation(LocationResult locationResult) {

try{

Log.d(TAG, "Map updated with ");

Log.d(TAG, "Latitude :"+locationResult.getLastLocation().getLongitude()+" Longitude :"+locationResult.getLastLocation().getLongitude());

LatLng latLng1 = new LatLng(locationResult.getLastHWLocation().getLatitude(), locationResult.getLastHWLocation().getLongitude());

float zoom = 10.0f;

CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng1,zoom);

hMap.animateCamera(cameraUpdate);



}catch (Exception e){

e.printStackTrace();



}

}

@Override

public void onLowMemory() {

super.onLowMemory();

loginBinding.mapview.onLowMemory();

}

@Override

public void onDestroy() {

super.onDestroy();

loginBinding.mapview.onDestroy();

}

@Override

public void onStop() {

super.onStop();

loginBinding.mapview.onStop();

locationData.disableLocationData();

}

@Override

public void onPause() {

super.onPause();

loginBinding.mapview.onPause();

}

@Override

public void onStart() {

super.onStart();

loginBinding.mapview.onStart();

}

@Override

public void onSaveInstanceState(@NonNull Bundle outState) {

super.onSaveInstanceState(outState);

Bundle mapViewBundle = outState.getBundle(MAPVIEW_BUNDLE_KEY);

if (mapViewBundle == null) {

mapViewBundle = new Bundle();

outState.putBundle(MAPVIEW_BUNDLE_KEY, mapViewBundle);

}

loginBinding.mapview.onSaveInstanceState(mapViewBundle);

}

@Override

public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {

super.onViewCreated(view, savedInstanceState);

navController = Navigation.findNavController(view);

}

}
```
Result

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dgvsmjo70zgqynpjyw57.gif)

**Tricks and Tips**

Makes sure that agconnect-services.json file added.
Make sure required dependencies are added
Make sure that service is enabled in AGC
Enable data binding in gradle.build file
Make sure bottom navigation id's should be same as fragment id's in navigation graph

**Conclusion**

In this article, we have learnt how to integrate Huawei Map kit, Location kit in Android application KnowMyBoard. You can also go through previous article part-2 here. Hoping that the Map kit capabilities are helpful to you as well, like this sample, you can make use of Map kit as per your requirement.

Thank you so much for reading. I hope this article helps you to understand the integration of Huawei Map kit and Location kit in Android application KnowMyBoard.

**Reference**

[Map Kit](https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/android-sdk-introduction-0000001061991291) – [Training video](https://developer.huawei.com/consumer/en/training/course/video/101590716045317017)

[Location Kit](https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/introduction-0000001050706106) – [Training video](https://developer.huawei.com/consumer/en/training/course/video/101595238364454068)