Current Location in background Service in android does not work [duplicate] - java

This question already has answers here:
How to request Location Permission at runtime
(8 answers)
Closed 1 year ago.
The code below does not work when the application is minimized or closed and doesn't return the current location.
For example, locationCallback only works once and does not work after the app is minimized.
It should be noted that this service has been added to the manifest. It works in the video that I saw on YouTube YouTube Link
public class UpdateLocationService extends Service {
static final int LOCATION_SERVICE_id = 175;
static final String ACTION_START_LOCATION_SERVICE = "startLocationService";
static final String ACTION_STOP_LOCATION_SERVICE = "stopLocationService";
private LocationCallback locationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
if (locationResult != null && locationResult.getLastLocation() != null) {
double lat = locationResult.getLastLocation().getLatitude();
double lng = locationResult.getLastLocation().getLongitude();
Log.d(TAG, lat + ", " + lng);
}
super.onLocationResult(locationResult);
}
};
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#RequiresApi(api = Build.VERSION_CODES.O)
private void startLocationService() {
LocationRequest locationRequest = new LocationRequest();
locationRequest.setInterval(3000);
locationRequest.setFastestInterval(2000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.getFusedLocationProviderClient(this).requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper());
startForeground(LOCATION_SERVICE_id, builder.build());
}
private void stopLocationService() {
LocationServices.getFusedLocationProviderClient(this);
stopForeground(true);
stopSelf();
}
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
String action = intent.getAction();
if (action != null)
if (action.equals(ACTION_START_LOCATION_SERVICE)){
startLocationService();
}else if (action.equals(ACTION_STOP_LOCATION_SERVICE)){
stopLocationService();
}
}
return super.onStartCommand(intent, flags, startId);
}
}

Starting background service has been restricted after Android O https://developer.android.com/about/versions/oreo/background. If you still what to get a location in the background, please consider WorkManger and Foreground services

Related

GPS location data does not match the location of AVD

I write a simple code to show and update the latitude and longitude through GPS. The problem is they remain unchanged when I change the location of AVD.
public class PocketSphinxActivity extends Activity implements
RecognitionListener {
boolean updateOn = false;
private static final int PERMISSIONS_FINE_LOCATION = 99;
TextView tv_lat, tv_lon, tv_add, tv_sen, tv_ud;
#SuppressLint("UseSwitchCompatOrMaterialCode")
Switch sw_locationupdates, sw_GPS;
LocationRequest locationRequest;
LocationCallback locationCallback;
FusedLocationProviderClient fusedLocationProviderClient;
/* Named searches allow to quickly reconfigure the decoder */
private static final String KWS_SEARCH = "wakeup";
private static final String STORE_SEARCH = "store";
private static final String LIBRARY_SEARCH = "library";
private static final String MUSEUM_SEARCH = "museum";
private static final String MENU_SEARCH = "menu";
/* Keyword we are looking for to activate menu */
private static final String KEYPHRASE = "guide me";
/* Used to handle permission request */
private static final int PERMISSIONS_REQUEST_RECORD_AUDIO = 1;
private SpeechRecognizer recognizer;
private TextToSpeech tts;
private HashMap<String, Integer> captions;
#SuppressLint("SetTextI18n")
#Override
public void onCreate(Bundle state) {
super.onCreate(state);
setContentView(R.layout.main);
// Prepare the data for UI
tv_lat = findViewById(R.id.tv_lat);
tv_lon = findViewById(R.id.tv_lon);
tv_add = findViewById(R.id.tv_add);
sw_locationupdates = findViewById(R.id.sw_locationupdates);
tv_sen = findViewById(R.id.tv_sen);
sw_GPS = findViewById(R.id.sw_GPS);
tv_ud = findViewById(R.id.tv_ud);
captions = new HashMap<>();
captions.put(KWS_SEARCH, R.string.kws_caption);
captions.put(MENU_SEARCH, R.string.menu_caption);
captions.put(LIBRARY_SEARCH, R.string.digits_caption);
captions.put(MUSEUM_SEARCH, R.string.phone_caption);
captions.put(STORE_SEARCH, R.string.forecast_caption);
((TextView) findViewById(R.id.caption_text))
.setText("Preparing the recognizer");
// set properties of LocationRequest
locationRequest = LocationRequest.create();
locationRequest.setInterval(1000 * 5);
locationRequest.setFastestInterval(1000 * 1);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// triggered whenever update interval is met
locationCallback = new LocationCallback() {
#Override
public void onLocationResult(#NonNull LocationResult locationResult) {
super.onLocationResult(locationResult);
Location location = locationResult.getLastLocation();
updateUI(location);
}
};
sw_GPS.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (sw_GPS.isChecked()) {
locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
tv_sen.setText("Using Tower + Wifi");
} else {
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
tv_sen.setText("Using GPS");
}
}
});
//StartLocUpdates();
sw_locationupdates.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (sw_locationupdates.isChecked()) {
//start tracking
StartLocUpdates();
} else {
//stop tracking
StopLocUpdates();
}
}
});
// Check if user has given permission to record audio
int permissionCheck = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.RECORD_AUDIO);
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO}, PERMISSIONS_REQUEST_RECORD_AUDIO);
return;
}
// Recognizer initialization is a time-consuming and it involves IO,
// so we execute it in async task
new SetupTask(this).execute();
updateGPS();
}
private void StopLocUpdates() {
tv_lat.setText("Not tracking location");
tv_lon.setText("Not tracking location");
tv_add.setText("Not tracking location");
tv_ud.setText("Location stop tracking");
fusedLocationProviderClient.removeLocationUpdates(locationCallback);
}
private void StartLocUpdates() {
//tv_ud.setText("stop ");
tv_ud.setText("Location is being tracked");
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
fusedLocationProviderClient.requestLocationUpdates(locationRequest,locationCallback,null);
updateGPS();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//PERMISSIONS_REQUEST_RECORD_AUDIO
if (requestCode == PERMISSIONS_FINE_LOCATION || requestCode == PERMISSIONS_REQUEST_RECORD_AUDIO) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Recognizer initialization is a time-consuming and it involves IO,
// so we execute it in async task
updateGPS();
new SetupTask(this).execute();
} else {
Toast.makeText(this, "This app permission to be granted in order to work properly", Toast.LENGTH_SHORT).show();
finish();
}
}
}
private void updateGPS() {
//get permission
//get current location
//update UI
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(PocketSphinxActivity.this);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
fusedLocationProviderClient.getLastLocation().addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
//put values into UI
updateUI(location);
}
});
} else {
//
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_FINE_LOCATION);
}
}
}
private void updateUI(Location location) {
tv_lat.setText(String.valueOf(location.getLatitude()));
tv_lon.setText(String.valueOf(location.getLongitude()));
Geocoder geocoder = new Geocoder(PocketSphinxActivity.this);
try{
List<Address>addresses=geocoder.getFromLocation(location.getLatitude(),location.getLongitude(),1);
tv_add.setText(addresses.get(0).getAddressLine(0));
}
catch(Exception e){
tv_add.setText("Unable to get address");
}
}
}
It seems that the location generated by fusedLocationProviderClient.getLastLocation() in method updateGPS() never changed. I wonder why.
private void updateGPS() {
//get permission
//get current location
//update UI
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(PocketSphinxActivity.this);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
fusedLocationProviderClient.getLastLocation().addOnSuccessListener(this, new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
//put values into UI
updateUI(location);
}
});
} else {
//
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSIONS_FINE_LOCATION);
}
}

How to access location in background Android 12?

I am making an application that fetch last known location when user clicked power key two times. I am using foreground service to register the broadcast receiver and for location I am using fusedlocationproviderclient. The user can fetch the location while app is in background. My problem is I am only able to fetch location for one time only. Second time location is null. How can I solve it?
Note:
It is working fine in android 7 version.
Service:
public class ScreenOnOffBackgroundService extends Service {
private ScreenOnOffReceiver screenOnOffReceiver = null;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
createNotificationChannel();
Intent mainIntent = new Intent(this, DashboardActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,mainIntent, 0);
Notification notification = new NotificationCompat.Builder(this,"safetyId")
.setContentTitle("Safety Service")
.setContentText("Press power key to send alert")
.setSmallIcon(R.drawable.android)
.setContentIntent(pendingIntent)
.build();
startForeground(1,notification);
return START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
// Create an IntentFilter instance.
IntentFilter intentFilter = new IntentFilter();
// Add network connectivity change action.
intentFilter.addAction("android.intent.action.SCREEN_ON");
// Set broadcast receiver priority.
intentFilter.setPriority(100);
screenOnOffReceiver = new ScreenOnOffReceiver();
HandlerThread broadcastHandlerThread = new HandlerThread("SafetyThread");
broadcastHandlerThread.start();
Looper looper = broadcastHandlerThread.getLooper();
Handler broadcastHandler = new Handler(looper);
registerReceiver(screenOnOffReceiver,intentFilter,null,broadcastHandler);
}
private void createNotificationChannel() {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ){
NotificationChannel channel = new NotificationChannel(
"safetyId",
"Safety Service",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
}
#Override
public void onDestroy() {
stopForeground(true);
stopSelf();
// Unregister screenOnOffReceiver when destroy.
if(screenOnOffReceiver!=null)
{
unregisterReceiver(screenOnOffReceiver);
}
}
}
Broadcast Receiver:
public class ScreenOnOffReceiver extends BroadcastReceiver {
private int count = 0;
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_SCREEN_ON.equals(action) || Intent.ACTION_SCREEN_OFF.equals(action)) {
count++;
if (count == 2) {
count = 0;
DashboardActivity.getInstance().getLastLocation();
}
}
}
}
Dashboard Activity:
public class DashboardActivity extends AppCompatActivity {
public Button btnAlert;
private static DashboardActivity instance;
private final static int REQUEST_CODE = 123;
private FusedLocationProviderClient locationProviderClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
instance = this;
registerService();
btnAlert = findViewById(R.id.btnAlert);
locationProviderClient = LocationServices.getFusedLocationProviderClient(this);
btnAlert.setOnClickListener(view -> getLastLocation());
}
public static DashboardActivity getInstance(){
return instance;
}
public void registerService(){
if(!foregroundServiceRunning()){
Intent backgroundService = new Intent(this, ScreenOnOffBackgroundService.class);
ContextCompat.startForegroundService(this,backgroundService);
}
}
public boolean foregroundServiceRunning(){
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for(ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)){
if(ScreenOnOffBackgroundService.class.getName().equals(service.service.getClassName())){
return true;
}
}
return false;
}
#SuppressLint("MissingPermission")
public void getLastLocation() {
// check if permissions are given
if (checkPermissions()) {
// check if location is enabled
if (isLocationEnabled()) {
locationProviderClient.getLastLocation().addOnCompleteListener(task -> {
Location location = task.getResult();
if (location == null) {
requestNewLocationData();
} else {
Toast.makeText(this, "Latitude: "+location.getLatitude(), Toast.LENGTH_LONG).show();
}
});
} else {
Toast.makeText(this, "Please turn on your location", Toast.LENGTH_LONG).show();
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
} else {
requestPermissions();
}
}
private boolean checkPermissions() {
return ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
private void requestPermissions() {
String[] permissionArray = new String[]{
android.Manifest.permission.ACCESS_COARSE_LOCATION,
android.Manifest.permission.ACCESS_FINE_LOCATION,};
ActivityCompat.requestPermissions(this, permissionArray, REQUEST_CODE);
}
#SuppressLint("MissingPermission")
private void requestNewLocationData() {
LocationRequest mLocationRequest = LocationRequest.create()
.setInterval(100)
.setFastestInterval(3000)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setMaxWaitTime(100).setNumUpdates(1);
locationProviderClient = LocationServices.getFusedLocationProviderClient(this);
locationProviderClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
}
private final LocationCallback mLocationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
Location mLastLocation = locationResult.getLastLocation();
}
};
private boolean isLocationEnabled() {
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
#Override
public void
onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
getLastLocation();
}
}
if (requestCode == 0) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
notifyPolice();
}
}
}
}
First off- DashboardActivity.getInstance()- NEVER DO THIS. You're assuming there's exactly 1 instance of an activity at all times. That's wrong. There can be 0. There can be 2. You can't make an activity a singleton. In addition, this always creates a memory leak. NEVER store an Activity in a static variable, this is always a memory leak. It's also (due to the first fact) wrong because it can point to the wrong instance of an Activity.
Secondly- you're using getLastLocation. Don't do that. That function is meant for optimization and will usually return null (I know the docs say the opposite. The docs there have always been wrong.) If you need the location, request it instead. getLastLocation should only be used to get a quick result optimisticly before requesting location updates.
Thirdly- your call to requestNewLocation is passing in a location handler that does nothing. It isn't even updating mLastLocation because that's a method level variable and not a class one.
Fourthly- did you read the new rules for background location processing in ANdroid 12? https://proandroiddev.com/android-12-privacy-changes-for-location-55ffd8c016fd
Those are just the major mistakes, not smaller things that make me go "huh?". With the best of intentions here- this code needs major refactoring. It feels like someone who didn't really understand Android cobbled it together from a dozen examples he didn't understand. If I were you I'd start by simplifying the concept- do one thing, understand it, and then do another. You're overreaching your abilities at the moment doing this all at once, and you'll be better off learning one thing at a time.

Location Service data not working on certain phones but working on Pixel 3

I have a location service:
public class LocationService extends Service implements Serializable {
public static final String TAG = "LocationService";
private LocationListener locationListener;
private LocationManager locationManager;
public static boolean locationUpdateSent = false;
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public void onCreate() {
super.onCreate();
startMyOwnForeground();
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationListener = new LocationListener() {
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public void onLocationChanged(Location location) {
buildLocationEvent(location);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
};
locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
}
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
#RequiresApi(api = Build.VERSION_CODES.O)
private void startMyOwnForeground(){
String NOTIFICATION_CHANNEL_ID = "LocationChannel";
String channelName = "Location Service";
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_HIGH);
chan.setLightColor(Color.GRAY);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(chan);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
Notification locNotification = notificationBuilder.setOngoing(true)
.setContentTitle("Location is running in background")
.setPriority(NotificationManager.IMPORTANCE_HIGH)
.setCategory(Notification.CATEGORY_SERVICE)
.setSmallIcon(android.R.drawable.ic_menu_mylocation)
.build();
startForeground(1, locNotification);
}
#Override
public void onDestroy() {
super.onDestroy();
if(locationManager != null){
locationManager.removeUpdates(locationListener);
}
stopSelf();
stopForeground(true);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#RequiresApi(api = Build.VERSION_CODES.O)
public void buildLocationEvent(Location location){
//Do Something
}
}
This works fine on Pixel 3A and on a second Pixel, however it does not work on a galaxy S10, A5 and a Pixel XL. Has anyone any experience of any restrictions which would stop this happening? I know it's not much to go on but hopefully if you have seen this behaviour before you might be able to point me in the right direction.
use google fusedlocation client
public class fusedLocation {
Context act;
FusedLocationProviderClient mFusedLocationClient;
Location myLocation=null;
static final int REQUEST_PERMS = 1;
public interface LocationChangListener{
void OnlocationChanged(Location current_location);
}
LocationChangListener main_handler=new LocationChangListener() {
#Override
public void OnlocationChanged(Location current_location) {
}
};
public fusedLocation(final Activity act,LocationChangListener handler_) {
this.act = act;
this.main_handler=handler_;
mFusedLocationClient=LocationServices.getFusedLocationProviderClient(act);
final String permissions[] = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION};
if (ActivityCompat.checkSelfPermission(act, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
update_tm.schedule(new TimerTask() {
#Override
public void run() {
act.runOnUiThread(new Runnable() {
#Override
public void run() {
getLastLocation();
}
});
}
},100,10000);
} else {
ActivityCompat.requestPermissions(act, permissions, REQUEST_PERMS);
}
}
Timer update_tm=new Timer();
private void getLastLocation() {
mFusedLocationClient.getLastLocation().addOnCompleteListener(new OnCompleteListener<Location>() {
#Override
public void onComplete(#NonNull Task<Location> task) {
Location location = task.getResult();
if (location == null) {
requestNewLocationData();
Log.e("Main", " location is null men");
} else {
Log.e("my coords==> ", "lats " + location.getLatitude() + " longs " + location.getLongitude());
main_handler.OnlocationChanged(location);
}
}
});
}
private void requestNewLocationData() {
LocationRequest mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(0);
mLocationRequest.setFastestInterval(0);
mLocationRequest.setNumUpdates(1);
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(act);
mFusedLocationClient.requestLocationUpdates(
mLocationRequest, mLocationCallback,
Looper.myLooper()
);
}
private LocationCallback mLocationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
Location mLastLocation = locationResult.getLastLocation();
Log.e("my refreshed coords==> ", "lats " + mLastLocation.getLatitude() + " longs " + mLastLocation.getLongitude());
main_handler.OnlocationChanged(mLastLocation);
}
};
}
Use the class as below
fusedLocation fusedLocation = new fusedLocation(your_context, new fusedLocation.LocationChangListener() {
#Override
public void OnlocationChanged(Location current_location) {
//Do as you please with the location
Log.e("Position ","mypos_lat "+current_location.getLatitude()+" <==> mypos_long "+current_location.getLongitude());
}
});

Some Times Location Service is not working in background

I used Location Service in my android application, which extends Service and implements the GoogleApiClient, LocationListener. I am updating location onLocationChanged() method and my loaction update interval is 20 second. Sometimes Location Service is not working even though the app is in the background. I want to run my location service always anyhow. Each and every version of Android & every mobile, even though the app is killing from background also.
I call location service using AlarmManager also.
I gave call for location update in onStartCommand() method .
If location service is stopped then it will go to the onDestroy() method or onTaskRemoved() method in that method again I am calling startLocation method like,
startService(new Intent(this, LocationService.class));
My manifest code for service:
<service
android:name=".LocationService"
android:enabled="true"
android:stopWithTask="false"
/>
you can create location service like below.which run on background and foreground mode
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();
}
}
Declare this service in android manifest file like below
<service
android:name=".ServiceLocation"
android:enabled="true"
android:exported="true" />
you can start service from activity using this code
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));
}

Receive location updates even when phone is locked?

I have been trying to receive location updates when my phone is locked I am using a service that is launched by my main activity. I receive location updates when the application is open just fine but when locking the phone the service continues to run but the location stored is the same every time.
import static com.example.kromby.mapsapplication.featureOptions.date;
public class BackgroundLocationUpdate extends Service implements GoogleApiClient.ConnectionCallbacks, LocationListener {
// I've removed code that does not relate to the question so please ignore most imports.
private GoogleApiClient mClient;
private boolean connected = false;
private LocationRequest mLocationRequest;
public static List<LatLng> globalLatLng = Collections.synchronizedList(new ArrayList<LatLng>());
public static GoogleMap mMap;
Location mLastLocation;
private static double latitude;
private static double longitude;
public LatLng mLatLng = new LatLng(latitude, longitude);
private static final String TAG = "MapActivity";
#Override
public IBinder onBind(Intent intent) {
return null;
}
#TargetApi(Build.VERSION_CODES.O)
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Runnable r = new Runnable() {
#Override
public void run() {
buildGoogleApiClient();
}
};
Runnable q = new Runnable() {
#Override
public void run() {
long p = System.currentTimeMillis() + 4000;
boolean continueLooping = true;
while (continueLooping) {
if (System.currentTimeMillis() >= p) {
locationUpdates();
continueLooping = false;
}
}
}
};
Thread mThread = new Thread(r);
Thread mThreadTwo = new Thread(q);
mThread.start();
mThreadTwo.start();
return Service.START_STICKY;
}
public void locationUpdates() {
long i = System.currentTimeMillis();
while (true) {
if (System.currentTimeMillis() == i) {
i = System.currentTimeMillis() + 3000;
// Checks that the application has user permissions to location.
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mClient);
// Once the phone is locked this will return the same location each time and not change.
Log.d(TAG, "Client is working " + mClient.isConnected() + "\n Current mLastLocation LatLng " + mLastLocation.getLatitude() + "," + mLastLocation.getLatitude());
latitude = mLastLocation.getLatitude();
longitude = mLastLocation.getLongitude();
Log.d(TAG, "latitude = " + String.valueOf(latitude) );
mLatLng = new LatLng(latitude, longitude);
globalLatLng.add(mLatLng);
Log.d(TAG, "Global List = " + globalLatLng);
}
}
}
protected synchronized void buildGoogleApiClient() {
mClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addApi(LocationServices.API).build();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mClient.connect();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
connected = true;
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(3000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mClient, mLocationRequest, this);
}
#Override
public void onConnectionSuspended(int i) {
mClient.connect();
}
#Override
public void onDestroy() {
Log.i(TAG, "OnDestroy method called");
}
}
My aim is to receive a location save that into a Latlng list and store it into a text file, that can be read and shown on the map in a polyline. I am running them on two seperate threads because googles api clients does not finish so it wont reach any other code.

Categories

Resources