SDK for Android Developer's Guide

Requesting Android Permissions

If your application supports Android 6.0 or above, add the following code in your activity file to ask the application users to grant Android permissions at runtime. For more information about this requirement, see the Android Developer documentation.

Figure 1. Request Location Permission
Figure 2. Request File Access Permission
  1. Add the following import statements to the beginning of the file:
    import android.content.pm.PackageManager;
    import android.support.annotation.NonNull;
    import android.support.v4.app.ActivityCompat;
    import android.support.v4.content.ContextCompat;
    import android.Manifest;
    import android.widget.Toast;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
  2. Add these static variables to BasicMapActivity class:
    /**
     * permissions request code
     */
    private final static int REQUEST_CODE_ASK_PERMISSIONS = 1;
    
    /**
     * Permissions that need to be explicitly requested from end user.
     */
    private static final String[] REQUIRED_SDK_PERMISSIONS = new String[] {
        Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.WRITE_EXTERNAL_STORAGE };
    
    Note:
    • Starting in API level 19 android.permission.WRITE_EXTERNAL_STORAGE is no longer required if the map disk cache(See MapSettings.setDiskCacheRootPath(path)) is set under an application-specific file directory.
    • android.permission.ACCESS_FINE_LOCATION is not required to initialize or use the SDK. However, it is required if you use the following components:
      • PositioningManager
      • NavigationManager
      • PositionSimulator
      • LiveSight
    • android.permission.CAMERA is required when LiveSight (augmented reality) features are used.
  3. Add the following methods to BasicMapActivity class:
    /**
     * Checks the dynamically-controlled permissions and requests missing permissions from end user.
     */
    protected void checkPermissions() {
      final List<String> missingPermissions = new ArrayList<String>();
      // check all required dynamic permissions
      for (final String permission : REQUIRED_SDK_PERMISSIONS) {
        final int result = ContextCompat.checkSelfPermission(this, permission);
        if (result != PackageManager.PERMISSION_GRANTED) {
          missingPermissions.add(permission);
        }
      }
      if (!missingPermissions.isEmpty()) {
        // request all missing permissions
        final String[] permissions = missingPermissions
            .toArray(new String[missingPermissions.size()]);
        ActivityCompat.requestPermissions(this, permissions, REQUEST_CODE_ASK_PERMISSIONS);
      } else {
        final int[] grantResults = new int[REQUIRED_SDK_PERMISSIONS.length];
        Arrays.fill(grantResults, PackageManager.PERMISSION_GRANTED);
        onRequestPermissionsResult(REQUEST_CODE_ASK_PERMISSIONS, REQUIRED_SDK_PERMISSIONS,
            grantResults);
      }
    }
    
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[],
        @NonNull int[] grantResults) {
      switch (requestCode) {
        case REQUEST_CODE_ASK_PERMISSIONS:
          for (int index = permissions.length - 1; index >= 0; --index) {
            if (grantResults[index] != PackageManager.PERMISSION_GRANTED) {
              // exit the app if one permission is not granted
              Toast.makeText(this, "Required permission '" + permissions[index]
                  + "' not granted, exiting", Toast.LENGTH_LONG).show();
              finish();
              return;
            }
          }
          // all permissions were granted
          initialize();
          break;
      }
    }
  4. Finally, change the method call in onCreate(Bundle) from initialize() to checkPermissions() instead:
    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      checkPermissions();
    }
    

Android 10

Since Android 10, apps targeting Android 10 (API 29) by default are given a filtered view into external storage. For further information please see Scoped storage. So generally the files stored at the path /sdcard will be innaccesible. The default path for map data /sdcard/.here-maps is changed to /sdcard/Android/data/<app package name>/files/.here-maps from the version 3.13 of the SDK. Existing map cache will be moved from the old path to the new one automatically by SDK.