f3d0r
f3d0r

Reputation: 561

HERE Maps API Missing Libraries Error

I'm getting the MISSING_LIBRARIES error code when I try to initialize the HERE Maps Android Premium API maps fragment. I followed all the directions here and I'm still getting the same error code. For reference: here is my AndroidManifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.somepackage.main" >

<!--
     The ACCESS_COARSE/FINE_LOCATION permissions are not required to use
     Google Maps Android API v2, but you must specify either coarse or fine
     location permissions for the 'MyLocation' functionality. 
-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />



<application
    android:allowBackup="true"
    android:icon="@mipmap/appicon_iphone_icon"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme"
    android:name="ParCareApplication"
    android:hardwareAccelerated="true">

    <meta-data android:name="com.here.android.maps.appid"
        android:value="someappid"/>
    <meta-data android:name="com.here.android.maps.apptoken"
        android:value="someapptoken"/>
    <meta-data android:name="com.here.android.maps.license.key"
        android:value="somelicensekey"/>

    <service
        android:name="com.here.android.mpa.service.MapService"
        android:label="HereMapService"
        android:process="global.Here.Map.Service.v2"
        android:exported="true" >
        <intent-filter>
            <action android:name="com.here.android.mpa.service.MapService" >
            </action>
        </intent-filter>
    </service>
    <!--
         The API key for Google Maps-based APIs is defined as a string resource.
         (See the file "res/values/google_maps_api.xml").
         Note that the API key is linked to the encryption key used to sign the APK.
         You need a different API key for each encryption key, including the release key that is used to
         sign the APK for publishing.
         You can define the keys for the debug and release targets in src/debug/ and src/release/. 
    -->
    <meta-data
        android:name="com.google.android.geo.API_KEY"
        android:value="@string/google_maps_key" />

    <activity
        android:name=".SplashScreen"
        android:configChanges="keyboardHidden|orientation|screenSize"
        android:label="@string/app_name"
        android:screenOrientation="portrait"
        android:theme="@style/SplashTheme" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity
        android:name=".MainActivity"
        android:configChanges="keyboardHidden|orientation|screenSize"
        android:label="@string/title_activity_main"
        android:screenOrientation="portrait"
        android:theme="@style/AppTheme.NoActionBar" >
        <intent-filter>
            <action android:name="com.somepackage.main.MAINACTIVITY" />

            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>
</application>

Here is the app-level gradle:

apply plugin: 'com.android.application'
apply plugin: 'realm-android'

android {
compileSdkVersion 23
buildToolsVersion '23.0.3'
useLibrary 'org.apache.http.legacy'
defaultConfig {

    applicationId "com.somepackage.main"
    minSdkVersion 21
    targetSdkVersion 23

    versionCode 1
    versionName "1.0"

}
productFlavors {
    // Define separate dev and prod product flavors.
    dev {
        // dev utilizes minSDKVersion = 21 to allow the Android gradle plugin
        // to pre-dex each module and produce an APK that can be tested on
        // Android Lollipop without time consuming dex merging processes.
        minSdkVersion 21
    }
    prod {
        // The actual minSdkVersion for the application.
        minSdkVersion 21
    }
}
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}


}

repositories {
    maven {
        url "https://oss.sonatype.org/content/repositories/snapshots/"
    }

}
apply plugin: 'com.neenbedankt.android-apt'

dependencies {
    compile 'com.google.code.gson:gson:2.5'
    compile 'com.android.support:appcompat-v7:23.4.0'
    compile 'com.google.android.gms:play-services:9.0.0'
    compile 'com.android.support:design:23.4.0'
    compile 'com.android.support:cardview-v7:23.4.0'
    compile 'com.android.support:recyclerview-v7:23.4.0'
    compile 'com.squareup.retrofit2:retrofit:2.0.2'
    compile 'com.squareup.retrofit2:converter-gson:2.0.2'
    compile 'com.nineoldandroids:library:2.4.0'
    compile 'com.daimajia.easing:library:1.0.1@aar'
    compile 'com.daimajia.androidanimations:library:1.1.3@aar'
    compile 'com.jakewharton:butterknife:8.0.1'
    apt 'com.jakewharton:butterknife-compiler:8.0.1'
    compile files('libs/HERE-sdk-javadoc.jar')
    compile files('libs/HERE-sdk.jar')
}

Here is the XML layout with the maps fragment:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="com.somepackage.main.MainActivity"
tools:showIn="@layout/app_bar_main">

<!-- 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"/>

and here is the relevant MainActivity code that tries to initialize the MapsFragment:

package com.somepackage.main;

import android.app.FragmentManager;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.util.Log;
import android.view.View;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;

import com.somepackage.main.retrofit_interfaces.ParCareRetrofitService;
import com.somepackage.main.retrofit_interfaces.ParkingSpotList;
import com.somepackage.main.retrofit_interfaces.Sensor;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.common.GooglePlayServicesRepairableException;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.places.Place;
import com.google.android.gms.location.places.ui.PlaceAutocomplete;
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;

import java.util.ArrayList;
import java.util.Timer;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, LocationListener {
private FragmentManager sFm; //implementer for supportfragments

public static final int PLACE_AUTOCOMPLETE_REQUEST_CODE = 1; //request code for auto-complete Google address input

NavigationView navigationView; //navigationdrawer
public static FloatingActionButton fab; //floating button to start navigation
public static DrawerLayout drawer; //drawer for navigationdrawer
public static Location currentLocation;

LocationRequest mLocationRequest;

Retrofit retrofit;

ParCareRetrofitService parCareRetrofitService;

ArrayList<Sensor> sensors = new ArrayList<Sensor>();
RawSensorList list;

private Map map = null;

private MapFragment mapFragment = null;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); //initializes toolbar
    setSupportActionBar(toolbar); //sets toolbar

    retrofit = new Retrofit.Builder()
            .baseUrl("http://parcare.ddns.net:8080/")
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    parCareRetrofitService = retrofit.create(ParCareRetrofitService.class);

    fab = (FloatingActionButton) findViewById(R.id.fab); //gets floating action button from layout
    fab.setOnClickListener(new View.OnClickListener() { //sets on click listener for button
        @Override
        public void onClick(View view) {

        }
    });
    fab.hide(); //hides fab until needed
    drawer = (DrawerLayout) findViewById(R.id.drawer_layout); //gets drawer button
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( //intializes toggle for navigationdrawer
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle); //sets toggle for navigationdrawer
    toggle.setDrawerIndicatorEnabled(false); //disables default burger icon (set to true to set default icon)
    toggle.setHomeAsUpIndicator(R.drawable.drawer_burger_icon); //sets new icon for drawer
    toggle.syncState(); //syncs drawer button
    toggle.setToolbarNavigationClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) { //toggles navigationdrawer
            drawer.openDrawer(GravityCompat.START);
        }
    });
    navigationView = (NavigationView) findViewById(R.id.nav_view); //initializes list of items in navigationdrawer
    navigationView.setNavigationItemSelectedListener(this); //sets listener for items in navigationdrawer
    navigationView.getMenu().getItem(0).setChecked(true); //sets "Map" as checked
    mLocationRequest = LocationRequest.create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setInterval(10 * 1000)        // 10 seconds, in milliseconds
            .setFastestInterval(1 * 1000); // 1 second, in milliseconds

    mapFragment = (MapFragment)getFragmentManager().findFragmentById(
            R.id.mapfragment);
    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 {
                System.out.println("ERROR: Cannot initialize Map Fragment");
                System.out.println(error);
            }
        }
    });

}

Please tell me what needs to be done to get rid of this error, I've followed the instructions multiple times now, and I still can't get rid of the error. Thanks!

Upvotes: 0

Views: 3020

Answers (1)

AndrewJC
AndrewJC

Reputation: 1478

The MISSING_LIBRARIES error indicates that either the jars or native libraries (in armeabi-v7 folder) required by the SDK are not able to be found.

I know you mentioned you followed the instructions here several times, but just to be sure, please try to follow the "Add HERE SDK Libraries to Your Project" section again.

Specifically:

  1. From the directory where you installed the HERE SDK, copy the contents of the HERE-sdk/libs/ folder , except the armeabi-v7a folder, to your project's app/libs/ folder.
  2. From the directory where you installed the HERE SDK, copy the contents of the HERE-sdk/libs/armeabi-v7a folder to your project's app/src/main/jniLibs/armeabi folder. You need to create the jniLibs and armeabi subfolders.
  3. In your Android Studio project's app/libs/ folder, right-click the *.JAR files and select Add as Library..., then under the Add To module, select app and click OK.

Upvotes: 3

Related Questions