0

I am using Here maps SDK and have initialized the map and PositioningManager for get the current location of user in initialize() method now I have 2 getDirections(View v) which is being called from the view layout xml file hence it is able to access the posManager which is instance of PositioningManager class but my second method track_my_ride which gets called by Button.onclick method and here when I try to use posManager app throws an error

com.sjain.routeplanner E/AndroidRuntime: FATAL EXCEPTION: main Process: com.sjain.routeplanner, PID: 26948 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sjain.routeplanner/com.sjain.routeplanner.ViewMapActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'com.here.android.mpa.common.GeoPosition com.here.android.mpa.common.PositioningManager.getPosition()' on a null object reference

......

     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'com.here.android.mpa.common.GeoPosition
    com.here.android.mpa.common.PositioningManager.getPosition()' on a
     null object reference

at com.sjain.routeplanner.ViewMapActivity.track_my_ride(ViewMapActivity.java:334) at com.sjain.routeplanner.ViewMapActivity.intentInfo(ViewMapActivity.java:137) at com.sjain.routeplanner.ViewMapActivity.onCreate(ViewMapActivity.java:101) at android.app.Activity.performCreate(Activity.java:6298)

.....

I have read answers how to pass the current activity view also but none of them seems to work. This exception does not occur if I try to access posManager from my getDirection(View v) method which has the view reference so I suppose it's not the issue of my posManager not being initialized.

This is my ViewMapActivity.java file

public class ViewMapActivity extends AppCompatActivity {
    private static final String LOG_TAG = ViewMapActivity.class.getSimpleName();

    // 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,
    Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.ACCESS_COARSE_LOCATION};

    // map embedded in the map fragment
    private Map map = null;

    // map fragment embedded in this activity
    private MapFragment mapFragment = null;

    // TextView for displaying the current map scheme
    private TextView textViewResult;

    // MapRoute for this activity
    private static MapRoute mapRoute = null;

    private PositioningManager posManager;
    boolean paused = false;
    private MapMarker marker;
    private RouteItem route = null;

    // Define positioning listener
    PositioningManager.OnPositionChangedListener positionListener = new
            PositioningManager.OnPositionChangedListener() {

                public void onPositionUpdated(PositioningManager.LocationMethod method,
                                              GeoPosition position, boolean isMapMatched) {
                    // set the center only when the app is in the foreground
                    // to reduce CPU consumption
                    if (!paused) {
                        map.setCenter(position.getCoordinate(),
                                Map.Animation.NONE);
                        Log.d("MainActivity.class", "onPositionUpdated: " + position.getCoordinate().toString());
                        marker.setCoordinate(position.getCoordinate());
                    }
                }

                @Override
                public void onPositionFixChanged(PositioningManager.LocationMethod locationMethod, PositioningManager.LocationStatus locationStatus) {
                    Log.d("MainActivity.class", "onPositionFixChanged: " + locationStatus);
                    String status = locationStatus.toString();
                    if (Objects.equals(status, "AVAILABLE")) {
                        marker.setCoordinate(posManager.getPosition().getCoordinate());
                    } else if (Objects.equals(status, "TEMPORARILY_UNAVAILABLE")) {
                        marker.setCoordinate(posManager.getLastKnownPosition().getCoordinate());
                    }
                }
            };

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

    private void intentInfo() {
        try{
            ......
            String type = this.getIntent().getStringExtra("type");
            // if type is display just display the route
            // if track then display the eta and current status
            if(Objects.equals(type, "track")) {
                String location = this.getIntent().getStringExtra("location");
                 track_my_ride(location);
            }
        }
        catch (Error e) {
            Log.e("ViewMapActivity.class", "intentInfo: ", e);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        paused = false;
        if (posManager != null) {
            posManager.start(PositioningManager.LocationMethod.GPS);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (posManager != null) {
            posManager.stop();
        }
        paused = true;
        super.onPause();
    }

    @Override
    protected void onDestroy() {
        if (posManager != null) {
            // Cleanup
            posManager.removeListener(positionListener);
        }
        map = null;
        super.onDestroy();
    }

    private void initialize() {
        setContentView(R.layout.activity_map_view);

        // Search for the map fragment to finish setup by calling init().
        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 coordinate to the Vancouver region (no animation)
                    map.setCenter(new GeoCoordinate(19.152568, 72.855825), Map.Animation.NONE);
                    // Set the map zoom level to the average between min and max (no animation)
                    map.setZoomLevel((map.getMaxZoomLevel() + map.getMinZoomLevel()) / 2);

                    // get users current location
                    posManager = PositioningManager.getInstance();
                    posManager.start(PositioningManager.LocationMethod.GPS);
                    posManager.addListener(new WeakReference<>(positionListener));
                    // create marker to display users current location
                    marker = new MapMarker();
                    marker.setCoordinate(posManager.getLastKnownPosition().getCoordinate());
                    map.addMapObject(marker);
                } else {
                    Log.e(LOG_TAG, "Cannot initialize MapFragment (" + error + ")");
                }
            }
        });
    }

    /**
     * Checks the dynamically controlled permissions and requests missing permissions from end user.
     */
    protected void checkPermissions() {
        final List<String> missingPermissions = new ArrayList<>();
        // 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;
        }
    }
    public void getDirections(View v) {
    // posManager Works here without any error.
        GeoCoordinate coordinate;
        if(posManager.getPosition().getCoordinate() != null) {
            coordinate = posManager.getPosition().getCoordinate();
        }
        else if(posManager.getLastKnownPosition().getCoordinate() != null ){
            coordinate = posManager.getLastKnownPosition().getCoordinate();
        }
        else {
            // default nesco it park coordinates
            //coordinates taken from here maps
            coordinate = new GeoCoordinate(19.15254,72.85571);
        }
    }

    public void track_my_ride(String location) {
        // 1. clear previous results
        textViewResult = (TextView) findViewById(R.id.result);
        textViewResult.setText("");
        if (map != null && mapRoute != null) {
            map.removeMapObject(mapRoute);
            mapRoute = null;
        }

        // 2. Initialize RouteManager
        RouteManager routeManager = new RouteManager();

        // 3. Select routing options
        RoutePlan routePlan = new RoutePlan();

        RouteOptions routeOptions = new RouteOptions();
        routeOptions.setTransportMode(RouteOptions.TransportMode.CAR);
        routeOptions.setRouteType(RouteOptions.Type.FASTEST);
        routePlan.setRouteOptions(routeOptions);

        GeoCoordinate coordinate;
        if(posManager.getPosition().getCoordinate() != null) {
            coordinate = posManager.getPosition().getCoordinate();
        }
        else if(posManager.getLastKnownPosition().getCoordinate() != null ){
            coordinate = posManager.getLastKnownPosition().getCoordinate();
        }
        else {
            // default nesco it park coordinates
            //coordinates taken from here maps
            coordinate = new GeoCoordinate(19.15254,72.85571);
        }
        // 4. Select Waypoints for your routes
        routePlan.addWaypoint(coordinate);

        // supposed to be current or last known location of bus
        String[] bus_coordinate = location.split(",");
        routePlan.addWaypoint(new GeoCoordinate(
                Double.parseDouble(bus_coordinate[0]),
                Double.parseDouble(bus_coordinate[1])));

        // 5. Retrieve Routing information via RouteManagerEventListener
        RouteManager.Error error = routeManager.calculateRoute(routePlan, routeManagerListener);
        if (error != RouteManager.Error.NONE) {
            Toast.makeText(getApplicationContext(),
                    "Route calculation failed with: " + error.toString(), Toast.LENGTH_SHORT)
                    .show();
        }
    }

    private RouteManager.Listener routeManagerListener = new RouteManager.Listener() {
        public void onCalculateRouteFinished(RouteManager.Error errorCode,
                                             List<RouteResult> result) {

            if (errorCode == RouteManager.Error.NONE && result.get(0).getRoute() != null) {
                // create a map route object and place it on the map
                mapRoute = new MapRoute(result.get(0).getRoute());
                map.addMapObject(mapRoute);

                // Get the bounding box containing the route and zoom in (no animation)
                GeoBoundingBox gbb = result.get(0).getRoute().getBoundingBox();
                map.zoomTo(gbb, Map.Animation.NONE, Map.MOVE_PRESERVE_ORIENTATION);

                textViewResult.setText(String.format(getString(R.string.route_maneuvers), result.get(0).getRoute().getManeuvers().size()));
            } else {
                textViewResult.setText(
                        String.format("Route calculation failed: %s", errorCode.toString()));
            }
        }

        public void onProgress(int percentage) {
            textViewResult.setText(String.format(getString(R.string.precent_done), percentage));
        }
    };
}

Can someone please help me out here

EDIT

After seeing the error it might seem like I have not initialized posManager but I have already initialized it while initializing my MAP without any error. How am I supposed to get the instance of posManager in track_my_ride() method even though it should be accessible to complete class and I can access it in other method having reference to View i.e. getDirection(View v) but not in track_my_ride() method

warl0ck
  • 3,356
  • 4
  • 27
  • 57
  • posManager is not initialized – Alexandre BOURETZ May 22 '17 at 12:24
  • Possible duplicate of [What is a NullPointerException, and how do I fix it?](https://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) – Alexandre BOURETZ May 22 '17 at 12:24
  • isnt it initialized in `initialize()` method as in PositioningManager only get access to the PositioningManager Singleton and I am able to access it in my getDirection method but not in `track_my_ride` method – warl0ck May 22 '17 at 12:29
  • Make sure that initialize() gets called and error == OnEngineInitListener.Error.NONE – Alexandre BOURETZ May 22 '17 at 12:36
  • it is getting called after checking all the permissions, and as I said I am able to access It form the getDirection method but not from track_my_ride method since i am unable to pass View v param to it. – warl0ck May 22 '17 at 12:37
  • Okay, sorry if I don't understand your problem. It seems that track_my_ride() can get called before onRequestPermissionsResult in your onCreate(). Have you tried to debug this code ? – Alexandre BOURETZ May 22 '17 at 12:45
  • yes I have and no it won't get called before initialization as in onCreate method `checkPermission()` initializes the map by calling the `initialize()` method then only intentInfo() is called – warl0ck May 22 '17 at 12:48
  • As you can see in the [documentation](https://developer.android.com/training/permissions/requesting.html) the resquestPermissions() method functions asynchronously. If your app doesn't have all the permissions you need, initialize() will not get called until the user allows all the permissions, but track_my_ride() will be called before. – Alexandre BOURETZ May 22 '17 at 12:59
  • then it should have failed first time not the second time after I have given permission isn't then why is it failing again and again and assuming that is not the case then now am I supposed to go on ? – warl0ck May 22 '17 at 15:38

1 Answers1

1

This is happening because your initial track_my_ride() call is coming from onCreate(). Most likely the initialization has not finished and because the init is asynchronous you cannot assume the HERE SDK objects are usable at the onCreate point. If you are using a debugger, the behavior maybe different because the timing is different.

The solution is to call intentInfo() when OnEngineInitListener#onEngineInitializationCompleted is called back.

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    checkPermissions();
    intentInfo();   // NOT GOOD HERE.
}

private void intentInfo() {
    try{
        ......
        String type = this.getIntent().getStringExtra("type");
        // if type is display just display the route
        // if track then display the eta and current status
        if(Objects.equals(type, "track")) {
            String location = this.getIntent().getStringExtra("location");
             track_my_ride(location); // You're gonna NPE HERE.
        }
    }
    catch (Error e) {
        Log.e("ViewMapActivity.class", "intentInfo: ", e);  // You're gonna NPE catch  HERE.
    }
}
David Leong
  • 1,662
  • 1
  • 11
  • 7