I'm trying to use Here Maps Sdk with the Premium trial. I've followed this tutorial : https://developer.here.com/documentation/android-premium/topics/app-simple-android-studio.html
But when running the app I have an error: Fragment UNKNOWN
and a blank map fragment.
Of course I've checked the package name, app id, app code and License key inside the AndroidManifest.
I've built the BasicMapSolution SDK sample project, replacing app id etc., and BasicMapSolution works just fine. I can't find what's wrong in my project.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="fr.alan.myapp">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:hardwareAccelerated="true">
<activity android:name=".MapActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data android:name="com.here.android.maps.appid"
android:value="App id from Here website"/>
<meta-data android:name="com.here.android.maps.apptoken"
android:value="App code from Here website "/>
<meta-data android:name="com.here.android.maps.license.key"
android:value="License key"/>
<service
android:name="com.here.android.mpa.service.MapService"
android:label="MyAppMapService"
android:exported="false">
<intent-filter>
<action android:name="fr.alan.myapp.MapService">
</action>
</intent-filter>
</service>
</application>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
build.gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 27
defaultConfig {
applicationId "fr.alan.myapp"
minSdkVersion 16
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
implementation(name:'HERE-sdk', ext:'aar')
implementation 'com.google.code.gson:gson:2.2.4'
implementation 'com.android.support:support-v4:27.0.2'
implementation 'com.android.support:support-annotations:27.0.2'
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
MapActivity.java
package fr.alan.myapp
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import android.Manifest;
import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.widget.Toast;
import com.here.android.mpa.common.GeoCoordinate;
import com.here.android.mpa.common.OnEngineInitListener;
import com.here.android.mpa.mapping.Map;
import com.here.android.mpa.mapping.MapFragment;
public class MapActivity extends Activity {
// 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 };
// map embedded in the map fragment
private Map map = null;
// map fragment embedded in this activity
private MapFragment mapFragment = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
checkPermissions();
}
private void initialize() {
setContentView(R.layout.activity_map);
// Search for the map fragment to finish setup by calling init().
mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.mapfragment);
// Set up disk cache path for the map service for this application
boolean success = com.here.android.mpa.common.MapSettings.setIsolatedDiskCacheRootPath(
getApplicationContext().getExternalFilesDir(null) + File.separator + ".here-maps",
"com.here.android.tutorial.MapService");
if (!success) {
Toast.makeText(getApplicationContext(), "Unable to set isolated disk cache path.", Toast.LENGTH_LONG);
} else {
mapFragment.init(new OnEngineInitListener() {
@Override
public void onEngineInitializationCompleted(OnEngineInitListener.Error error) {
if (error == OnEngineInitListener.Error.NONE) {
// retrieve a reference of the map from the map fragment
map = mapFragment.getMap();
// Set the map center to the Vancouver region (no animation)
map.setCenter(new GeoCoordinate(49.196261, -123.004773, 0.0),
Map.Animation.NONE);
// Set the zoom level to the average between min and max
map.setZoomLevel((map.getMaxZoomLevel() + map.getMinZoomLevel()) / 2);
} else {
Log.e("Error", "ERROR: Cannot initialize Map Fragment " + error);
}
}
});
}
}
/**
* 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;
}
}
}
activity_map.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World"
tools:context=".BasicMapActivity" />
<!-- Map Fragment embedded with the map object -->
<fragment
class="com.here.android.mpa.mapping.MapFragment"
android:id="@+id/mapfragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
I found the bug by myself.
when i call
boolean success = com.here.android.mpa.common.MapSettings.setIsolatedDiskCacheRootPath(
getApplicationContext().getExternalFilesDir(null) + File.separator + ".here-maps",
"fr.alan.myapp.MapService");
"fr.alan.myapp.MapService"
: that's the intent name of the map service.
Must match in AndroidManifest :
<service
android:name="com.here.android.mpa.service.MapService"
android:label="MyAppMapService"
android:exported="false">
<intent-filter>
<action android:name="fr.alan.myapp.MapService">
</action>
</intent-filter>
</service>`