Search code examples
androidserviceandroid-volleyandroid-locationandroid-gps

GPS is working normally but not working when it goes for background service


I'm an android developer and i'm fresher now. I'm working on a project which is used for sending location to server after x minutes and i'm using Volly for make a request. When i click on 'A' button, calling a method named 'locationService()', it's working fine, sending current location and no problem or bug occur but when i click on 'B' button it's showing me this...

NetworkDispatcher.processRequest: Unhandled exception java.lang.NullPointerException: Attempt to read from field 'double com.example.GPSTracker.latitude' on a null object reference
java.lang.NullPointerException: Attempt to read from field 'double com.example.GPSTracker.latitude' on a null object reference

When i click on button 'B', Android service is starting in background for x minutes and In service, i'm calling same method 'locationService()', Now this method is showing error, can't understand what's going wrong with me. I searched a lot but i was not able to find anything.

I'm sharing my code, this is my first question. Hope i will get best.

in oncreate:

       LocalBroadcastManager.getInstance(this).registerReceiver(
            mMessageReceiver, new IntentFilter("GPSLocationUpdates"));

these are another methods:

  private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String Latitude = intent.getStringExtra("Latitude");
        String Longitude = intent.getStringExtra("Longitude");

        Location mLocation = new Location("");
        mLocation.setLatitude(Double.parseDouble(Latitude));
        mLocation.setLongitude(Double.parseDouble(Longitude));

        locationService(mLocation);

    }
};

  public void locationService(final Location mLocation) {

    String url
            = "http://something/";

    StringRequest jsonRequest = new StringRequest
            (Request.Method.POST, url, new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    try {
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            }, new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                }
            }) {
        @Override
        public byte[] getBody() {
            HashMap<String, String> params2 = new HashMap<String, String>();
            double latitude;
            double longitude;
            // check if GPS enabled

            if (mLocation != null) {

                System.out.println("LatLong" + mLocation.getLatitude() + mLocation.getLongitude());

                latitude = mLocation.getLatitude();
                longitude = mLocation.getLongitude();
                params2.put("longitude", String.valueOf(longitude));
                params2.put("latitude", String.valueOf(latitude));
                params2.put("vehicle_no", vehicle);
                params2.put("driver_phno", mobile);
                return new JSONObject(params2).toString().getBytes();
            }
            return null;
        }

        @Override
        public String getBodyContentType() {
            return "application/json";
        }
    };
    AppController.getInstance().addToRequestQueue(jsonRequest);

}

This is button click which is calling service:

  public void b(View view){
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        ContextCompat.startForegroundService(DashboardActivity.this, new Intent(DashboardActivity.this, ServiceLocation.class));
    } else {
        startService(new Intent(DashboardActivity.this, ServiceLocation.class));
    }
   }

This is service:

  public class ServiceLocation extends Service implements
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener,
    LocationListener {

private static final String NOTIFICATION_CHANNEL_ID = "my_notification_location";
private static final long TIME_INTERVAL_GET_LOCATION = 1000 * 5; // 1 Minute
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 7; // meters

private Handler handlerSendLocation;
private Context mContext;

private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;

private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 5000;

Location locationData;

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

    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();

    // Create the LocationRequest object
    mLocationRequest = LocationRequest.create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setInterval(TIME_INTERVAL_GET_LOCATION)    // 3 seconds, in milliseconds
            .setFastestInterval(TIME_INTERVAL_GET_LOCATION); // 1 second, in milliseconds

    mContext = this;


    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
            .setOngoing(false)
            .setSmallIcon(R.drawable.ic_launcher_background)
            .setColor(getResources().getColor(R.color.colorPrimary))
            .setPriority(Notification.PRIORITY_MIN);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
                NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW);
        notificationChannel.setDescription(NOTIFICATION_CHANNEL_ID);
        notificationChannel.setSound(null, null);
        notificationManager.createNotificationChannel(notificationChannel);
        startForeground(1, builder.build());
    }
}

@Override
public IBinder onBind(Intent arg0) {
    return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    Log.w("Service Update Location", "BGS > Started");

    if (handlerSendLocation == null) {
        handlerSendLocation = new Handler();
        handlerSendLocation.post(runnableSendLocation);
        Log.w("Service Send Location", "BGS > handlerSendLocation Initialized");
    } else {
        Log.w("Service Send Location", "BGS > handlerSendLocation Already Initialized");
    }

    return START_STICKY;
}

private Runnable runnableSendLocation = new Runnable() {

    @Override
    public void run() {


        // You can get Location
        //locationData and Send Location X Minutes

        Intent intent = new Intent("GPSLocationUpdates");
        intent.putExtra("Latitude", ""+ locationData.getLatitude());
        intent.putExtra("Longitude", "" + locationData.getLongitude());
        LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);

        Log.w("==>UpdateLocation<==", "" + String.format("%.6f", locationData.getLatitude()) + "," +
                String.format("%.6f", locationData.getLongitude()));

        Log.w("Service Send Location", "BGS >> Location Updated");

        if (handlerSendLocation != null && runnableSendLocation != null)
            handlerSendLocation.postDelayed(runnableSendLocation, TIME_INTERVAL_GET_LOCATION);
    }
};



@Override
public void onConnected(@Nullable Bundle bundle) {
    if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

        return;
    }

    FusedLocationProviderClient mFusedLocationClient  = LocationServices.getFusedLocationProviderClient(this);
    mFusedLocationClient.requestLocationUpdates(mLocationRequest,new LocationCallback(){
        @Override
        public void onLocationResult(LocationResult locationResult) {
            locationData = locationResult.getLastLocation();
        }
    },null);
}

@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
    if (connectionResult.hasResolution() && mContext instanceof Activity) {
        try {
            Activity activity = (Activity) mContext;
            connectionResult.startResolutionForResult(activity, CONNECTION_FAILURE_RESOLUTION_REQUEST);
        } catch (Exception e) {
            e.printStackTrace();
        }
    } else {
        Log.i("", "Location services connection failed with code " + connectionResult.getErrorCode());
    }
}

@Override
public void onLocationChanged(Location location) {
    Log.w("==>UpdateLocation<==", "" + String.format("%.6f", location.getLatitude()) + "," + String.format("%.6f", location.getLongitude()));
    locationData = location;

}

@Override
public void onDestroy() {

    if (handlerSendLocation != null)
        handlerSendLocation.removeCallbacks(runnableSendLocation);


    Log.w("Service Update Info", "BGS > Stopped");

    stopSelf();
    super.onDestroy();
}

}

This is manifests:

 <uses-permission
    android:name="android.permission.ACCESS_COARSE_LOCATION"
    android:maxSdkVersion="22" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>

<application
    android:name=".AppController"
    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">
<service
        android:name=".MyLocatioService"
        android:enabled="true" />
    <receiver android:name=".BootCompletedIntentReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
</application>

Solution

  • Please use this service:

    Gradle

    implementation 'com.google.android.gms:play-services:12.0.1'
    implementation 'gun0912.ted:tedpermission:2.1.0'
    

    onCreate In Activity Class

    TedPermission.with(getActivity())
                    .setPermissionListener(permissionlistener)
                    .setDeniedMessage("If you reject permission,you can not use this service\n\nPlease turn on permissions at [Setting] > [Permission]")
                    .setPermissions(Manifest.permission.ACCESS_FINE_LOCATION)
                    .check();
    
    LocalBroadcastManager.getInstance(this).registerReceiver(
                    mMessageReceiver, new IntentFilter("GPSLocationUpdates"));
    
    
    PermissionListener permissionlistener = new PermissionListener() {
            @Override
            public void onPermissionGranted() {
    
            }
    
            @Override
            public void onPermissionDenied(ArrayList<String> deniedPermissions) {
            }
        };
    
    private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String Latitude = intent.getStringExtra("Latitude");
                String Longitude = intent.getStringExtra("Longitude");
    
                Location mLocation = new Location("");
                mLocation.setLatitude(Double.parseDouble(Latitude));
                mLocation.setLongitude(Double.parseDouble(Longitude));
    
                locationService(mLocation);
    
            }
        };
    
    
    public void locationService(final Location mLocation)) {
    
            String url
                    = "http://something/";
    
            StringRequest jsonRequest = new StringRequest
                    (Request.Method.POST, url, new Response.Listener<String>() {
                        @Override
                        public void onResponse(String response) {
                            try {
                            } catch (Exception ex) {
                                ex.printStackTrace();
                            }
                        }
                    }, new Response.ErrorListener() {
                        @Override
                        public void onErrorResponse(VolleyError error) {
                        }
                    }) {
                @Override
                public byte[] getBody() {
                    HashMap<String, String> params2 = new HashMap<String, String>();
                    double latitude;
                    double longitude;
                    // check if GPS enabled
    
                    if (mLocation != null) {
    
                        System.out.println("LatLong" + mLocation.getLatitude() + mLocation.getLongitude());
    
                        latitude = mLocation.getLatitude();
                        longitude = mLocation.getLongitude();
                        params2.put("longitude", String.valueOf(longitude));
                        params2.put("latitude", String.valueOf(latitude));
                        params2.put("vehicle_no", vehicle);
                        params2.put("driver_phno", mobile);
                        return new JSONObject(params2).toString().getBytes();
                    }
                    return null;
                }
    
                @Override
                public String getBodyContentType() {
                    return "application/json";
                }
            };
            AppController.getInstance().addToRequestQueue(jsonRequest);
    
        }
    

    Start Service

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
         ContextCompat.startForegroundService(MainActivity.this, new Intent(MainActivity.this, ServiceLocation.class));
     } else {
         startService(new Intent(MainActivity.this, ServiceLocation.class));
     }
    

    Service Class

    public class ServiceLocation extends Service implements
            GoogleApiClient.ConnectionCallbacks,
            GoogleApiClient.OnConnectionFailedListener,
            LocationListener {
    
        private static final String NOTIFICATION_CHANNEL_ID = "my_notification_location";
        private static final long TIME_INTERVAL_GET_LOCATION = 1000 * 5; // 1 Minute
        private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 7; // meters
    
        private Handler handlerSendLocation;
        private Context mContext;
    
        private GoogleApiClient mGoogleApiClient;
        private LocationRequest mLocationRequest;
    
        private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 5000;
    
        Location locationData;
    
        @Override
        public void onCreate() {
            super.onCreate();
    
            mGoogleApiClient = new GoogleApiClient.Builder(this)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
    
            // Create the LocationRequest object
            mLocationRequest = LocationRequest.create()
                    .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                    .setInterval(TIME_INTERVAL_GET_LOCATION)    // 3 seconds, in milliseconds
                    .setFastestInterval(TIME_INTERVAL_GET_LOCATION); // 1 second, in milliseconds
    
            mContext = this;
    
    
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID)
                    .setOngoing(false)
                    .setSmallIcon(R.drawable.ic_notification)
                    .setColor(getResources().getColor(R.color.fontColorDarkGray))
                    .setPriority(Notification.PRIORITY_MIN);
    
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
                        NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW);
                notificationChannel.setDescription(NOTIFICATION_CHANNEL_ID);
                notificationChannel.setSound(null, null);
                notificationManager.createNotificationChannel(notificationChannel);
                startForeground(1, builder.build());
            }
        }
    
        @Override
        public IBinder onBind(Intent arg0) {
            return null;
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
    
            Log.w("Service Update Location", "BGS > Started");
    
            if (handlerSendLocation == null) {
                handlerSendLocation = new Handler();
                handlerSendLocation.post(runnableSendLocation);
                Log.w("Service Send Location", "BGS > handlerSendLocation Initialized");
            } else {
                Log.w("Service Send Location", "BGS > handlerSendLocation Already Initialized");
            }
    
            return START_STICKY;
        }
    
        private Runnable runnableSendLocation = new Runnable() {
    
            @Override
            public void run() {
    
    
                // You can get Location
                //locationData and Send Location X Minutes
                if (locationData != null) {
                    Intent intent = new Intent("GPSLocationUpdates");
                    intent.putExtra("Latitude", "" + locationData.getLatitude());
                    intent.putExtra("Longitude", "" + locationData.getLongitude());
    
    
                    LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
    
                    Log.w("==>UpdateLocation<==", "" + String.format("%.6f", locationData.getLatitude()) + "," +
                            String.format("%.6f", locationData.getLongitude()));
    
                    Log.w("Service Send Location", "BGS >> Location Updated");
                }
                if (handlerSendLocation != null && runnableSendLocation != null)
                    handlerSendLocation.postDelayed(runnableSendLocation, TIME_INTERVAL_GET_LOCATION);
            }
        };
    
    
        @Override
        public void onConnected(@Nullable Bundle bundle) {
            if (ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                    ActivityCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    
                return;
            }
    
    
            FusedLocationProviderClient mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
            mFusedLocationClient.requestLocationUpdates(mLocationRequest, new LocationCallback() {
                @Override
                public void onLocationResult(LocationResult locationResult) {
                    locationData = locationResult.getLastLocation();
                }
            }, null);
        }
    
        @Override
        public void onConnectionSuspended(int i) {
    
        }
    
        @Override
        public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
            if (connectionResult.hasResolution() && mContext instanceof Activity) {
                try {
                    Activity activity = (Activity) mContext;
                    connectionResult.startResolutionForResult(activity, CONNECTION_FAILURE_RESOLUTION_REQUEST);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                Log.i("", "Location services connection failed with code " + connectionResult.getErrorCode());
            }
        }
    
        @Override
        public void onLocationChanged(Location location) {
            Log.w("==>UpdateLocation<==", "" + String.format("%.6f", location.getLatitude()) + "," + String.format("%.6f", location.getLongitude()));
            locationData = location;
    
        }
    
        @Override
        public void onDestroy() {
    
            if (handlerSendLocation != null)
                handlerSendLocation.removeCallbacks(runnableSendLocation);
    
    
            Log.w("Service Update Info", "BGS > Stopped");
    
            stopSelf();
            super.onDestroy();
        }
    
    
    }
    

    AndroidManifest.XML

    <service
                android:name=".ServiceLocation"
                android:enabled="true"
                android:exported="true" />