Try to search your question here, if you can't find : Ask Any Question Now ?

Why does my app crash when I run a thread to update location?

HomeCategory: stackoverflowWhy does my app crash when I run a thread to update location?
Avatargaurav asked 2 weeks ago

I made a service that updates my location, and a thread that retrieves that location, but my app crashes right when it stars. Am i doing something wrong>

I’ve tried the app on a 19API AVD.

package com.example.wert;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import android.Manifest;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;
import com.example.wert.services.LocationTracker;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptor;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class MapsActivity extends FragmentActivity implements 
 OnMapReadyCallback {

    private GoogleMap mMap;
    private boolean mLocationPermissionGranted = false;
    private static final String TAG = "blabla";
    int ERROR_DIALOG_REQUEST = 1;
    int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 2;
    int PERMISSIONS_REQUEST_ENABLE_GPS = 3;
    private static final int LOCATION_UPDATE_INTERVAL = 3000;
    private FusedLocationProviderClient mFusedLocationProviderClient;
    private Handler mHandler = new Handler();
    private Runnable mRunnable;

    public Marker MyLocation;
    public LatLng myLocation;
    private LocationTracker locationTracker;


    /////// Creating a BitMapDescriptor for the custom coffee icon

    public Bitmap resizeBitmap(String drawableName,int width, int height) 
     {
        Bitmap imageBitmap = BitmapFactory.decodeResource(getResources(),getResources().getIdentifier(drawableName, "drawable", getPackageName()));
        return Bitmap.createScaledBitmap(imageBitmap, width, height, false);
    }

    //////// Creating some fake Coffee Shops,

    CoffeeShop fiveToGo = new CoffeeShop("5 to go", new LatLng(46.544868,24.560155));
    CoffeeShop captainBean = new CoffeeShop("Captain Bean", new LatLng(46.5420565,24.5542164));
    CoffeeShop roots = new CoffeeShop("Roots", new LatLng(46.5436924, 24.5359489));

    ///// Creating the map activity

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps);
        // Obtain the SupportMapFragment and get notified when the map is ready to be used.
        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }


    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

        if (checkMapServices()) {
            getDeviceLocation();

            Marker FiveToGo = mMap.addMarker(new MarkerOptions().position(fiveToGo.getPosition())
                   .icon(BitmapDescriptorFactory.fromBitmap(resizeBitmap("coffee",140,132)))
                    .title(fiveToGo.getName()));
            Marker CaptainBean = mMap.addMarker(new MarkerOptions().position(captainBean.getPosition())
                    .icon(BitmapDescriptorFactory.fromBitmap(resizeBitmap("coffee",140,132)))
                    .title(captainBean.getName()));
            Marker Roots = mMap.addMarker(new MarkerOptions().position(roots.getPosition())
                    .icon(BitmapDescriptorFactory.fromBitmap(resizeBitmap("coffee",140,132)))
                    .title(roots.getName()));

        }
    }

    ////// REQUESTING PERMISSIONS

    public boolean isServicesOK() {
        int available = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable( MapsActivity.this );
        if (available == ConnectionResult.SUCCESS) {
            Log.d( TAG, "isServicesOK: Google Play Services is working" );
            return true;
        } else if (GoogleApiAvailability.getInstance().isUserResolvableError( available )) {
            Log.d( TAG, "isServicesOK: an error occurred but we can fix it" );
            Dialog dialog = GoogleApiAvailability.getInstance().getErrorDialog
                    ( MapsActivity.this, available,ERROR_DIALOG_REQUEST );
            dialog.show();
        } else {
            Toast.makeText( this, "You can't make map requests", Toast.LENGTH_SHORT ).show();
        }
        return false;
    }

    public boolean isMapsEnabled () {
        final LocationManager manager = (LocationManager) getSystemService( Context.LOCATION_SERVICE );
        if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            buildAlertMessageNoGps();
            return false;
        }
        return true;
    }

    private  void buildAlertMessageNoGps() {
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage("This app requires GPS, do you want to enable it?")
                .setCancelable(false)
                .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                        Intent enableGpsIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                        startActivityForResult(enableGpsIntent, PERMISSIONS_REQUEST_ENABLE_GPS);
                    }
                });
        final AlertDialog alert = builder.create();
        alert.show();
    }


    private void getLocationPermission() {
        if (ContextCompat.checkSelfPermission(this.getApplicationContext(),
                android.Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            mLocationPermissionGranted = true;
            getDeviceLocation();
        } else {
            ActivityCompat.requestPermissions(this,
                    new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
                    PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String permissions[],
                                           @NonNull int[] grantResults) {
        mLocationPermissionGranted = false;
        switch (requestCode) {
            case 2 /*PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION*/: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    mLocationPermissionGranted = true;
                }
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Log.d(TAG, "onActivityResult: called.");
        switch (requestCode) {
            case 2 /*PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION*/: {
                if (mLocationPermissionGranted) {
                    getDeviceLocation();
                } else {
                    getLocationPermission();
                }
            }
        }
    }

    private boolean checkMapServices(){
        if(isServicesOK()){
            if(isMapsEnabled()){
                return true;
            }
        }
        return false;
    }

////////GETTING INITIAL  LOCATION

    private void getDeviceLocation(){
        Log.d(TAG, "getDeviceLocation: getting device current location" );
        mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
        try{
            if (checkMapServices()){
                Task location = mFusedLocationProviderClient.getLastLocation();
                location.addOnCompleteListener(new OnCompleteListener() {
                    @Override
                    public void onComplete(@NonNull Task task) {
                        if(task.isSuccessful()){
                            Log.d(TAG, "onComplete: found location");
                            Location currentLocation = (Location) task.getResult();
                            moveCamera(currentLocation);
                            startLocationService();
                            myLocation = (new LatLng(currentLocation.getLatitude(),currentLocation.getLongitude()));
                            MyLocation = mMap.addMarker(new MarkerOptions().position
                                    (myLocation));
                            startUserLocationsRunnable();
                        } else {
                            Log.d(TAG, "onComplete current location is null");
                            Toast.makeText(MapsActivity.this, "Didn't work mate",
                                    Toast.LENGTH_SHORT).show();
                        }
                    }
                });
            }

        }catch (SecurityException e){
            Log.d(TAG, "getDeviceLocation : Security Exception: " + e.getMessage());
        }
    }


    public void moveCamera (Location location) {
        String pozitie = location.toString();
        Log.d(TAG, pozitie);
        LatLng position = new LatLng(location.getLatitude(), location.getLongitude());
        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(position,13f));
    }

    //////////INITIATiNG LOCATION SERVICE

    private void startLocationService(){
        if(!isLocationServiceRunning()){
            Intent serviceIntent = new Intent(this, LocationTracker.class);

            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O){

                MapsActivity.this.startForegroundService(serviceIntent);
            }else{
                Log.d(TAG, " starting service");
                this.startService(serviceIntent);
            }
        }
    }

    private boolean isLocationServiceRunning() {
        ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)){
            if("com.codingwithmitch.googledirectionstest.services.LocationService".equals(service.service.getClassName())) {
                Log.d(TAG, "isLocationServiceRunning: location service is already running.");
                return true;
            }
        }
        Log.d(TAG, "isLocationServiceRunning: location service is not running.");
        return false;
    }

///////// UPDATING LOCATION


    private void startUserLocationsRunnable(){
        Log.d(TAG, "startUserLocationsRunnable: starting runnable for retrieving updated locations.");
        mHandler.postDelayed(mRunnable = new Runnable() {
            @Override
            public void run() {
                Log.d(TAG, "Runnable running");
                updateMyLocation(); // Marker
                mHandler.postDelayed(mRunnable, LOCATION_UPDATE_INTERVAL);
            }
        }, LOCATION_UPDATE_INTERVAL);
    }

    public void updateMyLocation() {
        Log.d(TAG, "Managed to obtain updated location :" + locationTracker.getUpdatedLocation());
        myLocation = (LatLng) locationTracker.getUpdatedLocation();
        Log.d(TAG, "Setting location to" + myLocation);
        MyLocation.setPosition(myLocation);
    }
}

I also get a NullPointerException when the service method that get’s the updated location is being called.

This is the Service:

package com.example.wert.services;

import android.Manifest;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Build;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import com.example.wert.MapsActivity;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;

public class LocationTracker extends Service {

    private static final String TAG = "LocationTracker";
    private FusedLocationProviderClient mFusedLocationClient;
    private final static long UPDATE_INTERVAL = 4 * 1000;  /* 4 secs */
    private final static long FASTEST_INTERVAL = 2000; /* 2 sec */
    private Location currentLocation;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    @Override
    public void onCreate() {
        super.onCreate();

        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);

        if (Build.VERSION.SDK_INT >= 26) {
            String CHANNEL_ID = "my_channel_01";
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID,"My Channel",
                    NotificationManager.IMPORTANCE_DEFAULT);
            ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
            Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                    .setContentTitle("")
                    .setContentText("").build();
            startForeground(1, notification);
        }
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand: called.");
        getLocation();
        return START_NOT_STICKY;
    }
     private void getLocation() {
            LocationRequest mLocationRequestHighAccuracy = new 
            LocationRequest();                                                                                 
            mLocationRequestHighAccuracy.setPriority(LocationRequest.
            PRIORITY_HIGH_ACCURCY);  
            mLocationRequestHighAccuracy.setInterval(UPDATE_INTERVAL);
  mLocationRequestHighAccuracy.setFastestInterval(FASTEST_INTERVAL);
            if (ActivityCompat.checkSelfPermission(this,
                    Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                Log.d(TAG, "getLocation: stopping the location service.");
                stopSelf();
                return;
            }
            Log.d(TAG, "getLocation: getting location information.");
          mFusedLocationClient.requestLocationUpdates(mLocationRequestHighAccuracy, new LocationCallback() {
                        @Override
                        public void onLocationResult(LocationResult locationResult) {
                            Log.d(TAG, "onLocationResult: got location result." + locationResult.getLastLocation());
                            currentLocation = locationResult.getLastLocation();

                        }
                    },
                    Looper.myLooper());
        }
        public LatLng getUpdatedLocation() {
            Log.d(TAG,"Doing something");
            LatLng location = new LatLng(currentLocation.getLatitude(),currentLocation.getLongitude());
            Log.d(TAG, "This is the updated location : " + location);
            return location;
        }
    }
1 Answers
Best Answer
AvatarMatthias answered 2 weeks ago
Your Answer

11 + 3 =

Popular Tags

WP Facebook Auto Publish Powered By : XYZScripts.com