HERE CompositeFragment MAP无法初始化引擎两次

时间:2017-03-09 11:21:49

标签: android here-api

我从HERE的官方入门指南pdf中完全复制了此代码,但是当我尝试运行它时,它componentFragment.init()失败并出现UNKNOWN错误。

错误详细信息:

java.lang.RuntimeException: Cannot initialize the engine twice
    at com.nokia.maps.MapsEngine.<init>(MapsEngine.java:604)
    at com.nokia.maps.MapsEngine.b(MapsEngine.java:897)
    at com.nokia.maps.MapsEngine.b(MapsEngine.java:394)
    at com.nokia.maps.MapsEngine.a(MapsEngine.java:346)
    at com.here.android.mpa.common.MapEngine.init(MapEngine.java:129)
    at com.nokia.maps.al.a(CompositeFragmentImpl.java:92)
    at com.here.android.mpa.ar.CompositeFragment.init(CompositeFragment.java:108)
    at hu.appz4.heretest.BasicMapActivity.init(BasicMapActivity.java:106)
    at hu.appz4.heretest.BasicMapActivity.onRequestPermissionsResult(BasicMapActivity.java:97)
    at hu.appz4.heretest.BasicMapActivity.checkPermissions(BasicMapActivity.java:80)
    at hu.appz4.heretest.BasicMapActivity.onCreate(BasicMapActivity.java:58)
    at android.app.Activity.performCreate(Activity.java:6272)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2387)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2494)
    at android.app.ActivityThread.access$900(ActivityThread.java:157)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1356)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5551)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)

BasicMapActivity.java

package hu.appz4.heretest;

import android.Manifest;
import android.Manifest.permission;
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.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

import com.here.android.mpa.ar.ARController;
import com.here.android.mpa.ar.ARController.Error;
import com.here.android.mpa.ar.ARIconObject;
import com.here.android.mpa.ar.CompositeFragment;
import com.here.android.mpa.common.GeoCoordinate;
import com.here.android.mpa.common.Image;
import com.here.android.mpa.common.MapEngine;
import com.here.android.mpa.common.OnEngineInitListener;
import com.here.android.mpa.mapping.Map;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class BasicMapActivity extends Activity {
    /**
     * permissions request code
     */
    private final static int REQUEST_CODE_ASK_PERMISSIONS = 1000;

    /**
     * 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,
                                                                          Manifest.permission.CAMERA, permission.ACCESS_NETWORK_STATE, permission.ACCESS_WIFI_STATE,
                                                                          permission.INTERNET};
    private Map               map;
    private ARController      arController;
    // buttons which will allow the user to start LiveSight and add objects
    private Button            startButton;
    private Button            stopButton;
    private Button            toggleObjectButton;
    // ARIconObject represents the image model which LiveSight accepts for display
    private ARIconObject      arIconObject;
    private boolean           objectAdded;
    private CompositeFragment compositeFragment;

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

    /**
     * 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
                init();
                break;
        }
    }

    private void init() {
        setContentView(R.layout.activity_main);
        // Search for the composite fragment to finish setup by calling init().
        compositeFragment = (CompositeFragment) getFragmentManager().findFragmentById(R.id.compositefragment);
        compositeFragment.init(this, new OnEngineInitListener() {
            @Override
            public void onEngineInitializationCompleted(OnEngineInitListener.Error error) {
                if (error == OnEngineInitListener.Error.NONE) {
                    // retrieve a reference of the map from the composite fragment
                    map = compositeFragment.getMap();
                    // Set the map center to the Vancouver Downtown region
                    map.setCenter(new GeoCoordinate(47.529877, 19.032750, 0.0), Map.Animation.NONE);
                    // Set the map zoom level to the average between min and max
                    map.setZoomLevel((map.getMaxZoomLevel() + map.getMinZoomLevel()) / 2);
                    // LiveSight setup should be done after fragment init is complete
                    setupLiveSight();
                } else {
                    Toast.makeText(BasicMapActivity.this, "ERROR: Cannot initialize Composite Fragment" + " - " + error.getDetails(), Toast.LENGTH_SHORT).show();
                    System.out.println("ERROR: Cannot initialize Composite Fragment" + " - " + error.getDetails());
                }
            }
        });
        // hold references to the buttons for future use
        startButton = (Button) findViewById(R.id.startLiveSight);
        stopButton = (Button) findViewById(R.id.stopLiveSight);
        toggleObjectButton = (Button) findViewById(R.id.toggleObject);
        startButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(final View v) {
                startLiveSight(v);
            }
        });
        stopButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(final View v) {
                stopLiveSight(v);
            }
        });
        toggleObjectButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(final View v) {
                toggleObject(v);
            }
        });
    }

    private void setupLiveSight() {
        // ARController should not be used until fragment init has completed
        arController = compositeFragment.getARController();
        // tells LiveSight to display icons while viewing the map (pitch down)
        arController.setUseDownIconsOnMap(true);
        // tells LiveSight to use a static mock location instead of the devices GPS fix
        arController.setAlternativeCenter(new GeoCoordinate(47.529877, 19.032750, 0.0));
    }

    public void startLiveSight(View view) {
        if (arController != null) {
            // triggers the transition from Map mode to LiveSight mode
            Error error = arController.start();
            if (error == Error.NONE) {
                startButton.setVisibility(View.GONE);
                stopButton.setVisibility(View.VISIBLE);
            } else {
                Toast.makeText(getApplicationContext(), "Error starting LiveSight: " + error.toString(), Toast.LENGTH_LONG).show();
            }
        } else {
            Toast.makeText(getApplicationContext(), "ArController NULL", Toast.LENGTH_LONG).show();
        }
    }

    public void stopLiveSight(View view) {
        if (arController != null) {
            // exits LiveSight mode and returns to Map mode
            Error error = arController.stop(true);
            if (error == Error.NONE) {
                startButton.setVisibility(View.VISIBLE);
                stopButton.setVisibility(View.GONE);
            } else {
                Toast.makeText(getApplicationContext(), "Error stopping LiveSight: " + error.toString(), Toast.LENGTH_LONG).show();
            }
        }
    }

    public void toggleObject(View view) {
        if (arController != null) {
            if (!objectAdded) {
                if (arIconObject == null) {
                    final Image image = new Image();
                    try {
                        image.setImageResource(R.mipmap.ic_launcher);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    // creates a new icon object which uses the same image in up and down views
                    arIconObject = new ARIconObject(new GeoCoordinate(47.529877, 19.032750, 2.0), (View) null, image);
                }
                // adds the icon object to LiveSight to be rendered
                arController.addARObject(arIconObject);
                objectAdded = true;
                toggleObjectButton.setText("Remove Object");
            } else {
                // removes the icon object from LiveSight, it will no longer be renderedarController.removeARObject(arIconObject);
                objectAdded = false;
                toggleObjectButton.setText("Add Object");
            }
        }
    }
}

build.Gradle依赖项(按照guide.pdf中的步骤导入官方HERE-sdk.aar)

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:25.2.0'
    testCompile 'junit:junit:4.12'
    compile project(':HERE-sdk')
}

的AndroidManifest.xml

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

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <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"/>
    <!-- Additional permission for LiveSight
    <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />-->
    <uses-permission android:name="android.permission.CAMERA"/>
    <application
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.AppCompat">
        <activity
            android:name="hu.appz4.heretest.BasicMapActivity"
            android:label="@string/app_name">
            <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="the app id from HERE site"/>
        <meta-data
            android:name="com.here.android.maps.apptoken"
            android:value="the app code from HERE site"/>
        <meta-data
            android:name="com.here.android.maps.license.key"
            android:value="the license key from HERE site"/>
    </application>
</manifest>

activity_main.xml中

<?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"
    tools:context="hu.appz4.heretest.BasicMapActivity">

    <fragment
        class="com.here.android.mpa.ar.CompositeFragment"
        android:id="@+id/compositefragment"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>
    <Button
        android:id="@+id/startLiveSight"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:onClick="startLiveSight"
        android:text="@string/label_button_startlivesight" />
    <Button
        android:id="@+id/stopLiveSight"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:onClick="stopLiveSight"
        android:text="@string/label_button_stoplivesight"
        android:visibility="gone" />
    <Button
        android:id="@+id/toggleObject"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:onClick="toggleObject"
        android:text="@string/label_button_addobject" />
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>

2 个答案:

答案 0 :(得分:1)

我偶然设法通过将此代码添加到 AndroidManifest.xml

来解决此问题
<service
    android:name="com.here.android.mpa.service.MapService"
    android:exported="true"
    android:label="HereMapService"
    android:process="global.Here.Map.Service.v2">
      <intent-filter>
        <action android:name="com.here.android.mpa.service.MapService"/>
      </intent-filter>
</service>

答案 1 :(得分:0)

在棉花糖中,你需要添加4个权限,你的地图才能正常工作

 @Override
public void onPause() {
    super.onPause();
    if (compositeFragment != null){
        try {
            this.getFragmentManager().beginTransaction().remove(compositeFragment).commit();
        }catch (Exception exONDestroyView){
            System.out.println(exONDestroyView);
        }
    }
}


@Override
public void onDestroy() {
    super.onDestroy();

    if (compositeFragment != null){
        try {
           this.getFragmentManager().beginTransaction().remove(compositeFragment).commit();
        }catch (Exception exONDestroy){
            System.out.println(exONDestroy);
        }
    }

}

使用此链接获取权限

Request Check Multiple Run time Permissions at once in android Marshmallow

{{1}}

在您的活动中添加两个方法希望此帮助