I'm having trouble trying to get the latitude and longitude from my Service and store them as variables so I can access them from other classes I'm building. I want to have them equal to the current latitude and longitude of the user and update them through the interval set in the requestLocation() method. I would like to store them as variables as I would like to perform some calculations using them and I have also written a Content Provider/Database Helper in order to store them in my local Sqlite database but can't right now as I cannot access them. Below can be seen my code for my Location service and MainActivity.
Location Service
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
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;
public class LocationService extends Service {
FusedLocationProviderClient fusedLocationProviderClient;
LocationCallback locationCallback;
private final IBinder binder = new LocalBinder();
//public double latitude;
//public double longitude;
#Override
public IBinder onBind(Intent intent) {
return binder;
}
#Override
public void onCreate() {
super.onCreate();
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
locationCallback = new LocationCallback(){
// Whenever there is a Location Update, this method is where it occurs
#Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
// Log Result for Longitude and Latitude, call method to receive elsewhere
Log.d("myLog", "Latitude is: " + locationResult.getLastLocation().getLatitude() + ", " +
"Longitude is: " + locationResult.getLastLocation().getLongitude());
Intent intent = new Intent("ACT_LOC");
intent.putExtra("Latitude", locationResult.getLastLocation().getLatitude());
intent.putExtra("Longitude", locationResult.getLastLocation().getLongitude());
sendBroadcast(intent);
//double latitude = locationResult.getLastLocation().getLatitude();
//double longitude = locationResult.getLastLocation().getLongitude();
}
};
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
requestLocation();
return super.onStartCommand(intent, flags, startId);
}
// Method to request the Location every 3 seconds
private void requestLocation(){
LocationRequest locationRequest = new LocationRequest();
locationRequest.setInterval(3000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.myLooper());
}
public class LocalBinder extends Binder {
LocationService getService(){
return LocationService.this;
}
}
}
MainActivity
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= 23) {
// If the permission Access Fine Location is not granted
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// Request permissions again
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
} else {
// Start Location Service
startService();
}
} else {
// Start Location Service
startService();
}
}
// Start the service with a new intent for the MainActivity and Location Services
// Register Broadcast Receiver with intent action from LocationService.java
void startService() {
LocationBroadcastReceiver receiver = new LocationBroadcastReceiver();
IntentFilter filter = new IntentFilter("ACT_LOC");
Intent intent = new Intent(this, LocationService.class);
registerReceiver(receiver, filter);
startService(intent);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 1:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startService();
} else {
Toast.makeText(this, "Permissions Required", Toast.LENGTH_LONG).show();
}
}
}
public class LocationBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// check if action is required or not
if (intent.getAction().equals("ACT_LOC")) {
double lat = intent.getDoubleExtra("Latitude", 0f);
double lng = intent.getDoubleExtra("Longitude", 0f);
Toast.makeText(MainActivity.this, "Latitude is: " + lat + ", Longitude is: " + lng, Toast.LENGTH_LONG).show();
}
}
}
}
Related
I use a started service with the fused api, and implement the location listener directly on it. The Location keeps updating even when the screen is locked, But it stops if the screen goes off.
So, is there any way to make sure that the location will keep updating when the screen is off?
I read a lot of other questions and I don't really know what i'm missing.
package com.trickyworld.locationupdates;
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.graphics.Color;
import android.location.Location;
import android.os.Build;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
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 java.io.Console;
import java.util.ArrayList;
public class LocationService extends Service {
public static ArrayList<LatLng> locationArrayList = new ArrayList<LatLng>();
FusedLocationProviderClient fusedLocationClient;
LocationRequest locationRequest;
LocationCallback locationCallback;
private void startLocationUpdates() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
fusedLocationClient.requestLocationUpdates(locationRequest,
locationCallback,
Looper.getMainLooper());
}
protected void createLocationRequest() {
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setInterval(3000);
locationRequest.setFastestInterval(5000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
#Override
public void onCreate() {
super.onCreate();
new Notification();
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) createNotificationChanel() ;
else startForeground(
1,
new Notification()
);
locationRequest = LocationRequest.create();
locationRequest.setInterval(2000);
locationRequest.setFastestInterval(2000);
locationRequest.setMaxWaitTime(2000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationCallback = new LocationCallback() {
#Override
public void onLocationResult(#NonNull LocationResult locationResult) {
Location location = locationResult.getLastLocation();
//Toast.makeText(getApplicationContext(),
// "Lat: "+Double.toString(location.getLatitude()) + '\n' +
// "Long: " + Double.toString(location.getLongitude()), Toast.LENGTH_LONG).show();
Log.d("Mesage","Lat: "+Double.toString(location.getLatitude()) + '\n' +
"Long: " + Double.toString(location.getLongitude()));
//locationArrayList.add(new LatLng(location.getLatitude(), location.getLongitude()));
/* for (Location location : locationResult.getLocations()) {
location
}*/
}
};
startLocationUpdates();
}
#RequiresApi(api = Build.VERSION_CODES.O)
private void createNotificationChanel() {
String notificationChannelId = "Location channel id";
String channelName = "Background Service";
NotificationChannel chan = new NotificationChannel(
notificationChannelId,
channelName,
NotificationManager.IMPORTANCE_NONE
);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(chan);
NotificationCompat.Builder notificationBuilder =
new NotificationCompat.Builder(this, notificationChannelId);
Notification notification = notificationBuilder.setOngoing(true)
.setContentTitle("Location updates:")
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(2, notification);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_REDELIVER_INTENT;
}
#Override
public void onDestroy() {
super.onDestroy();
fusedLocationClient.removeLocationUpdates(locationCallback);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
I want to continuously get location updates in the background using service even app is paused I tried much but when the app is paused it won't get any of the user's locations.
Here is my service.java
package com.app.testservices;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.os.IBinder;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
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.location.LocationSettingsRequest;
public class MyService extends Service {
private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 3000;
private FusedLocationProviderClient mFusedLocationClient;
private LocationRequest locationRequest;
private LocationSettingsRequest locationSettingsRequest;
Notification notification;
NotificationCompat.Builder builder;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
prepareNotification(intent);
startLocationUpdates();
return START_STICKY;
}
#Override
public void onCreate() {
super.onCreate();
initData();
}
//Location Callback
private LocationCallback locationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
Location currentLocation = locationResult.getLastLocation();
Log.d("Locations", currentLocation.getLatitude() + "," + currentLocation.getLongitude());
//Share/Publish Location
builder.setContentText(currentLocation.getLatitude() + "," + currentLocation.getLongitude());
Notification nm = builder.build();
startForeground(2, nm);
}
};
private void startLocationUpdates() {
mFusedLocationClient.requestLocationUpdates(this.locationRequest,
this.locationCallback, Looper.getMainLooper());
}
public void prepareNotification(Intent intent) {
String input = intent.getStringExtra("input");
Intent notificationIntent = new Intent(this, MyService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
builder = new NotificationCompat.Builder(this, MyChannel.CHANNEL_ID)
.setContentTitle("My notification")
.setContentText(input)
.setSmallIcon(R.drawable.ic_android_black_24dp)
.setContentIntent(pendingIntent);
notification = builder.build();
startForeground(1, notification);
}
#Override
public void onDestroy() {
super.onDestroy();
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("restartservice");
broadcastIntent.setClass(this, Restarter.class);
this.sendBroadcast(broadcastIntent);
}
private void initData() {
locationRequest = LocationRequest.create();
locationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setNumUpdates(Integer.MAX_VALUE);
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(getApplicationContext());
}
#Override
public void onTaskRemoved(Intent rootIntent){
Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 10,
restartServicePendingIntent);
super.onTaskRemoved(rootIntent);
}
}
Channel.java
package com.app.testservices;
import android.app.Application;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.os.Build;
public class MyChannel extends Application {
public static final String CHANNEL_ID = "serviceChannel";
#Override
public void onCreate() {
super.onCreate();
createNotificationChannel();
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Notification service",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
}
I also tried to write a restarter to restart the service to fetch the location Restarter.java
package com.app.testservices;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.util.Log;
import android.widget.Toast;
public class Restarter extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("Broadcast Listened", "Service tried to stop");
Toast.makeText(context, "Service restarted", Toast.LENGTH_SHORT).show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(new Intent(context, MyService.class));
} else {
context.startService(new Intent(context, MyService.class));
}
}
}
Here is my MainActivity.java
package com.app.testservices;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Looper;
import android.provider.Settings;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import com.google.android.gms.common.api.ResolvableApiException;
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.location.LocationSettingsRequest;
import com.google.android.gms.location.LocationSettingsResponse;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
public class MainActivity extends AppCompatActivity {
private EditText etInput;
protected static final int REQUEST_CHECK_SETTINGS = 0x1;
FusedLocationProviderClient mFusedLocationClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etInput = findViewById(R.id.et_input_text);
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
ActivityCompat.requestPermissions(MainActivity.this, new String[]{
Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION
}, 1);
return;
}
}
public void startService(View view) {
String input = etInput.getText().toString();
Intent serviceIntent = new Intent(this, MyService.class);
serviceIntent.putExtra("input", input);
startService(serviceIntent);
}
public void stopService(View view) {
Intent serviceIntent = new Intent(this, MyService.class);
stopService(serviceIntent);
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
// If request is cancelled, the result arrays are empty.
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(MainActivity.this);
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
mFusedLocationClient.getLastLocation().addOnCompleteListener(new OnCompleteListener<Location>() {
#Override
public void onComplete(#NonNull Task<Location> task) {
Location location = task.getResult();
LocationCallback mLocationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
Location mLastLocation = locationResult.getLastLocation();
}
};
if (location == null) {
LocationRequest mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(5);
mLocationRequest.setFastestInterval(0);
mLocationRequest.setNumUpdates(2);
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(MainActivity.this);
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
ActivityCompat.requestPermissions(MainActivity.this, new String[]{
Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION
}, 1);
return;
}
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
} else {
System.out.println("Location: " + location);
}
}
});
}
}
}
public void enableLocationSettings() {
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
LocationRequest locationRequest = LocationRequest.create()
.setInterval(5)
.setFastestInterval(0)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
LocationServices.getSettingsClient(this).checkLocationSettings(builder.build())
.addOnSuccessListener(this, (LocationSettingsResponse response) -> {
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(MainActivity.this);
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
mFusedLocationClient.getLastLocation().addOnCompleteListener(task -> {
Location location = task.getResult();
LocationCallback mLocationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
Location mLastLocation = locationResult.getLastLocation();
}
};
if (location == null) {
LocationRequest mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(5);
mLocationRequest.setFastestInterval(0);
mLocationRequest.setNumUpdates(2);
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(MainActivity.this);
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
ActivityCompat.requestPermissions(MainActivity.this, new String[]{
Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION
}, 1);
return;
}
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
} else {
System.out.println("Location: " + location);
}
});
}
}).addOnFailureListener(this, ex -> {
if (ex instanceof ResolvableApiException) {
// Location settings are NOT satisfied, but this can be fixed by showing the user a dialog.
try {
startActivityForResult(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS), 1);
ResolvableApiException resolvable = (ResolvableApiException) ex;
resolvable.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException sendEx) {
// Ignore the error.
}
}
});
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (REQUEST_CHECK_SETTINGS == requestCode) {
if (Activity.RESULT_OK == resultCode) {
}
}
}
}
Any help or guidance will be appreciated. Moreover,
I also tried Android How to get user location continuously even your app is killed
this but it didn't work for me.
You need to keep a foreground service always running. You need to start it when the app is in the foreground and then keep it running all the time even when the app is in the background.
You should use a Foreground Service with a partial wakelock, in order to prevent the phone from sleeping.
Here below an example of Foreground Service Class that implements a Wakelock:
public class ICService extends Service {
private static final int ID = 1; // The id of the notification
private NotificationCompat.Builder builder;
private NotificationManager mNotificationManager;
private PowerManager.WakeLock wakeLock; // PARTIAL_WAKELOCK
/**
* Returns the instance of the service
*/
public class LocalBinder extends Binder {
public ICService getServiceInstance(){
return ICService.this;
}
}
private final IBinder mBinder = new LocalBinder(); // IBinder
#Override
public void onCreate() {
super.onCreate();
// PARTIAL_WAKELOCK
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"INSERT_YOUR_APP_NAME:wakelock");
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
startForeground(ID, getNotification());
return START_NOT_STICKY;
}
#SuppressLint("WakelockTimeout")
#Override
public IBinder onBind(Intent intent) {
if (wakeLock != null && !wakeLock.isHeld()) {
wakeLock.acquire();
}
return mBinder;
}
#Override
public void onDestroy() {
// PARTIAL_WAKELOCK
if (wakeLock != null && wakeLock.isHeld()) {
wakeLock.release();
}
super.onDestroy();
}
private Notification getNotification() {
final String CHANNEL_ID = "YOUR_SERVICE_CHANNEL";
builder = new NotificationCompat.Builder(this, CHANNEL_ID);
//builder.setSmallIcon(R.drawable.ic_notification_24dp)
builder.setSmallIcon(R.mipmap.YOUR_RESOURCE_ICON)
.setColor(getResources().getColor(R.color.colorPrimaryLight))
.setContentTitle(getString(R.string.app_name))
.setShowWhen(false)
.setPriority(NotificationCompat.PRIORITY_LOW)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.setOngoing(true)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setContentText(composeContentText());
final Intent startIntent = new Intent(getApplicationContext(), ICActivity.class);
startIntent.setAction(Intent.ACTION_MAIN);
startIntent.addCategory(Intent.CATEGORY_LAUNCHER);
startIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 1, startIntent, 0);
builder.setContentIntent(contentIntent);
return builder.build();
}
}
Obviously you still have also to disable battery optimization for your app.
You can browse a real working example of this service on a GPS Logging app here.
Don't forget to declare your service type as "location" into your AndroidManifest.xml, in order to allow your application to receive the GPS updates also after a momentary signal loss when running in background, and to add the FOREGROUND_SERVICE and WAKE_LOCK permissions:
In your manifest you should declare:
...
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
...
<!-- Recommended for Android 9 (API level 28) and lower. -->
<!-- Required for Android 10 (API level 29) and higher. -->
<service
android:name="MyGPSService"
android:foregroundServiceType="location" ... >
</service>
...
As a note, if the location requests start when the app is in the foreground, you don't need to request the android.permission.ACCESS_BACKGROUND_LOCATION permission to continue to receive locations in background, also in case of momentary signal loss. the android.permission.ACCESS_FINE_LOCATION (and, if you target API31, also android.permission.ACCESS_COARSE_LOCATION) is enough for your use.
I am trying to get location after every 10 second using FusedLocationProviderClient, However when i minimize the app or terminate it the location updates stops. Below is my code. Right now i am using android 9.0. I have no idea why this is happening any help will be grateful
Android Menifest
<service android:enabled="true" android:name=".LocationService">
</service>
LocationService.java
package com.example.locationupdate;
import android.Manifest;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import com.example.locationupdate.db.Realm$Helper;
import com.example.locationupdate.shared_pref.SaveInSharedPreference;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
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.location.LocationSettingsRequest;
import com.google.android.gms.location.SettingsClient;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import java.util.List;
import static com.google.android.gms.location.LocationServices.getFusedLocationProviderClient;
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
//private LocationRequest mLocationRequest;
private long UPDATE_INTERVAL = 10 * 1000; /* 10 secs */
private long FASTEST_INTERVAL = 2000;
int count = 0;
List<FilterData> datafromDB;
FusedLocationProviderClient mFusedLocationClient;
LocationRequest mLocationRequest;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
LocationCallback mLocationCallback = new LocationCallback(){
#Override
public void onLocationResult(LocationResult locationResult) {
for (Location location : locationResult.getLocations()) {
//Log.e("MainActivity", "Location: " + location.getLatitude() + " " + location.getLongitude());
if (SaveInSharedPreference.getInSharedPreference(LocationService.this).getLat() == 0.0 && SaveInSharedPreference.getInSharedPreference(LocationService.this).getLng() == 0.0) {
SaveInSharedPreference.getInSharedPreference(LocationService.this).setLatLong(location.getLatitude(), location.getLongitude());
}
SaveInSharedPreference.getInSharedPreference(LocationService.this).setCurrentLatLong(location.getLatitude(), location.getLongitude());
count = count + 1;
Log.e("mLocationCallbackLat", String.valueOf(location.getLatitude()));
Log.e("mLocationCallbackLong", String.valueOf(location.getLongitude()));
//LocationMatch(location);
}
/* datafromDB = Realm$Helper.getLocation$Module(LocationService.this).getAllData();
for (FilterData str : datafromDB) {
String name = str.getName();
}*/
};
};
public void onResume() {
Log.e("OnResume", "OnResumeEvent");
if (mFusedLocationClient != null) {
requestLocationUpdates();
}
}
public void requestLocationUpdates() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL); // two minute interval
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
}
}
public void onPause() {
//super.onPause();
Log.e("ONPause", "OnPauseEvent");
if (mFusedLocationClient != null) {
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
}
}
protected void startLocationUpdates() {
// Create the location request to start receiving updates
mLocationRequest = new LocationRequest();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
// Create LocationSettingsRequest object using location request
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
LocationSettingsRequest locationSettingsRequest = builder.build();
// Check whether location settings are satisfied
// https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient
SettingsClient settingsClient = LocationServices.getSettingsClient(this);
settingsClient.checkLocationSettings(locationSettingsRequest);
// new Google API SDK v11 uses getFusedLocationProviderClient(this)
getFusedLocationProviderClient(this).requestLocationUpdates(mLocationRequest, new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
// do work here
onLocationChanged(locationResult.getLastLocation());
}
},
Looper.myLooper());
}
public void onLocationChanged(Location location) {
if (SaveInSharedPreference.getInSharedPreference(LocationService.this).getLat() == 0.0 && SaveInSharedPreference.getInSharedPreference(LocationService.this).getLng() == 0.0) {
SaveInSharedPreference.getInSharedPreference(LocationService.this).setLatLong(location.getLatitude(), location.getLongitude());
}
SaveInSharedPreference.getInSharedPreference(LocationService.this).setCurrentLatLong(location.getLatitude(), location.getLongitude());
Toast.makeText(this,"onLocationChanged",Toast.LENGTH_LONG);
// New location has now been determined
String msg = "Updated Location: " +
Double.toString(location.getLatitude()) + "," +
Double.toString(location.getLongitude());
Log.e ("onLocationChangedLat", String.valueOf(location.getLatitude()));
Log.e ("onLocationChangedLong", String.valueOf(location.getLongitude()));
// You can now create a LatLng Object for use with maps
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
/*loc1.setLatitude(location.getLatitude());
loc1.setLongitude(location.getLongitude());
loc2.setLatitude(str.getLat());
loc2.setLongitude(str.getlng());
double distanceInMeters = loc1.distanceTo(loc2);
Log.e("Name", name);
Log.e("Distance", "" + distanceInMeters);*/
}
public void getLastLocation() {
// Get last known recent location using new Google Play Services SDK (v11+)
FusedLocationProviderClient locationClient = getFusedLocationProviderClient(this);
locationClient.getLastLocation()
.addOnSuccessListener(new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
// GPS location can be null if GPS is switched off
if (location != null) {
onLocationChanged(location);
}
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d("MapDemoActivity", "Error trying to get last GPS location");
e.printStackTrace();
}
});
}
#Override
public void onConnected(#Nullable Bundle bundle) {
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
}
MainActitvity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//locationTv = findViewById(R.id.location);
Intent startIntent = new Intent(this, LocationService.class);
startService(startIntent);
You can achieve this by setting up a handler and adding the required permissions to the android app. Apperantly there is a limit to how many times you can request the location in the background according to Android Location In Background but i have not seen this. Im requesting a new location every second.
First add these to your manifest:
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Then you can create a handler like this.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
createLocationHandler();
...
}
The createLocationHandler and isServiceRunning function:
public void createLocationHandler(){
HandlerThread locationHandler = new HandlerThread("LocationHandler"); //Creates a new handler thread
locationHandler.start(); //Starts the thread
Handler handler = new Handler(locationHandler.getLooper()); //Get the looper from the handler thread
handler.postDelayed(new Runnable() {//Run the runnable only after the given time
#Override
public void run() {
//Check if the location service is running, if its not. lets start it!
if(!isMyServiceRunning(LocationService.class)){
getApplicationContext().startService(new Intent(getApplicationContext(), LocationService.class));
}
//Requests a new location from the location service(Feel like it could be done in a less static way)
LocationService.requestNewLocation();
createLocationHandler();//Call the create location handler again, this will not be added to the stack because of the looper.
}
}, 10000);//Set the delay to be 10 seconds, 1 second = 1000 milliseconds
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) this.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
Remember to ask for the background_location permission before you want to start the service.
I wrote below code using fusedapi to get lat and longi.
import android.app.Service;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
/**
* Created by DELL WORLD on 1/24/2017.
*/
public class LocationWithFusedApi extends Service implements GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks, LocationListener {
private GoogleApiClient mGoogleApiClient;
Location mLastLocation;
private LocationRequest mLocationRequest;
double lat, lon;
final static String Mydata = "MyData";
/* public LocationWithFusedApi() {
super("LocationWithFusedApi");
}*/
/*
#Override
public void onDestroy() {
super.onDestroy();
mGoogleApiClient.disconnect();
}*/
#Override
public void onStart(Intent intent, int startId) {
Log.d("LocationWithFusedAPI", "Called");
super.onStart(intent, startId);
mGoogleApiClient.connect();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
/* #Override
protected void onHandleIntent(Intent intent) {
}*/
#Override
public void onCreate() {
super.onCreate();
buildGoogleApiClient();
}
#Override
public void onLocationChanged(Location location) {
lat = location.getLatitude();
lon = location.getLongitude();
System.out.println("Latest" + lat + ":" + lon);
Intent intent = new Intent();
intent.setAction("Mydata");
intent.putExtra("lat",lat);
intent.putExtra("lon",lon);
sendBroadcast(intent);
sendlat();
sendlon();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(100); // Update location every second
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
lat = mLastLocation.getLatitude();
lon = mLastLocation.getLongitude();
System.out.println("Last" + lat + ":" + lon);
sendlat();
sendlon();
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
buildGoogleApiClient();
}
synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
public double sendlat() {
return lat;
}
public double sendlon() {
return lon;
}
public void removeupdate() {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
Now trying to get lat and lon values in another activity to show to user via calling sendlat and sendlon but getting null. what mistake m I doing.
Here is code for activity where I m trying to get values.
public class ShareLocation extends AppCompatActivity {
GPSDataPicker gps;
String clickable = "";
Latlonreceiver latlonreceiver;
double lat, lon;
#Override
protected void onStart() {
latlonreceiver = new Latlonreceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(LocationWithFusedApi.Mydata);
registerReceiver(latlonreceiver, intentFilter);
Intent intent = new Intent(ShareLocation.this, LocationWithFusedApi.class);
startService(intent);
super.onStart();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* LocationWithFusedApi locationWithFusedApi = new LocationWithFusedApi();
double latitude = locationWithFusedApi.sendlat();
double longitude = locationWithFusedApi.sendlon();*/
double latitude = lat;
double longitude = lon;
setContentView(R.layout.sharelocation);
clickable = "https://maps.google.com/?q=" + latitude + "," + longitude;
}
}
#Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(latlonreceiver);
}
public class Latlonreceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
lat = intent.getDoubleExtra("lat", 0.0);
lon = intent.getDoubleExtra("lon", 0.0);
}
}
Look into using broadcast receiver. The basic mistake here is that the retrieval of the location is running on a different thread asynchronously. So by the time you call your sendXxx() methods the location has not been resolved yet. With asynchronous code you need the service to push you the result after the location has been resolved. The standard way in this case would be the broadcast receiver.
I'm really sorry ahead of time, but this question is pretty lengthy.
I have a functioning GPSTracker class that contains the means of pinging GPS Location for a device. In my MainActivity, I have a button that uses the GPS tracker to display the location in a toast. I'm trying to convert this button into an automatic action to be repeated every X minutes, let's go with 10.(Right now the alarm receiver is setup for 10 seconds)
Even when the app is in the background. So I set up an AlarmReceiver to try to do this, but I can't quite get it working.
Here's my GPSTracker class:
import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
public class GPSTracker extends Service implements LocationListener {
private final Context context;
boolean isGPSEnabled = false;
boolean canGetLocation = false;
boolean isNetworkEnabled = false;
Location location;
double latitude;
double longitude;
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10;
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1;
protected LocationManager locationManager;
public GPSTracker(Context context) {
this.context = context.getApplicationContext();
getLocation();
}
public Location getLocation(){
try {
locationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE);
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if(!isGPSEnabled && !isNetworkEnabled) {
}else {
this.canGetLocation = true;
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if(locationManager != null){
location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
if(location !=null){
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
if(isGPSEnabled){
if(location == null){
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if(locationManager !=null){
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null){
latitude = location.getLatitude();
longitude = location.getLongitude();
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return location;
}
public void stopUsingGPS() {
if(locationManager != null){
locationManager.removeUpdates(GPSTracker.this);
}
}
public double getLatitude() {
if(location!= null){
latitude = location.getLatitude();
}
return latitude;
}
public double getLongitude() {
if(location !=null){
longitude = location.getLongitude();
}
return longitude;
}
public boolean canGetLocation(){
return this.canGetLocation;
}
public void showSettingsAlert() {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
alertDialog.setTitle("GPS is settings");
alertDialog.setMessage("GPS isn't enabled. Do you want to go to settings menu?");
alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
context.startActivity(intent);
}
});
alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int i) {
dialog.cancel();
}
});
alertDialog.show();
}
#Override
public void onLocationChanged(Location location) {
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
And here's my MainActivity:
package com.example.gwyn.locationnabtest;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
public class MainActivity extends ActionBarActivity {
Button btnShowLocation;
Button btnStartService;
Button btnStopService;
GPSTracker gps;
//GoogleMap mMap;
private PendingIntent pendingIntent;
private AlarmManager manager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnShowLocation = (Button) findViewById(R.id.show_location);
btnShowLocation.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
FragmentActivity activity = (FragmentActivity)view.getContext();
FragmentManager manager = activity.getSupportFragmentManager();
//MapFragment myMap = (MapFragment) (MainActivity.getFragmentManager()).findFragmentById((R.id.mapFragment));
// Test, remove me.
// mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.mapFragment)).getMap();
gps = new GPSTracker(MainActivity.this);
if(gps.canGetLocation()) {
// Location Achieved.
double latitude = gps.getLatitude();
double longitude = gps.getLongitude();
// Draw Marker for Current Location on Fragment
// Currently Crashing App
// mMap.addMarker(new MarkerOptions().position(new LatLng(latitude, longitude)).title("Marker"));
// Toast a popup of the location data.
Toast.makeText(getApplicationContext(), "Your Location is -\nLat:" + latitude + "\nLong:" + longitude, Toast.LENGTH_LONG).show();
} else {
gps.showSettingsAlert();
}
}
});
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);
btnStartService = (Button) findViewById(R.id.start_service);
btnStartService.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
int interval = 10000;
// 10 Second Interval. Good for testing, but turn this off.
manager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);
Toast.makeText(getApplicationContext(), "Service Started", Toast.LENGTH_SHORT).show();
//startService(new Intent(getBaseContext(), MyServices.class));
}
});
btnStopService = (Button) findViewById(R.id.stop_service);
btnStopService.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Cancel pending intents
manager.cancel(pendingIntent);
Toast.makeText(getApplicationContext(), "Pending Intents Cancelled", Toast.LENGTH_SHORT).show();
}
});
}
}
To highlight specifically, this is the part in MainActivity that works to display the GPS:
public void onClick(View view) {
FragmentActivity activity = (FragmentActivity)view.getContext();
FragmentManager manager = activity.getSupportFragmentManager();
//MapFragment myMap = (MapFragment) (MainActivity.getFragmentManager()).findFragmentById((R.id.mapFragment));
// Test, remove me.
// mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.mapFragment)).getMap();
gps = new GPSTracker(MainActivity.this);
if(gps.canGetLocation()) {
// Location Achieved.
double latitude = gps.getLatitude();
double longitude = gps.getLongitude();
// Draw Marker for Current Location on Fragment
// Currently Crashing App
// mMap.addMarker(new MarkerOptions().position(new LatLng(latitude, longitude)).title("Marker"));
// Toast a popup of the location data.
Toast.makeText(getApplicationContext(), "Your Location is -\nLat:" + latitude + "\nLong:" + longitude, Toast.LENGTH_LONG).show();
} else {
gps.showSettingsAlert();
}
}
My AlarmReceiver is as follows, and produces an error when creating the GPSTracker:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class AlarmReceiver extends BroadcastReceiver {
GPSTracker gps;
#Override
public void onReceive(Context arg0, Intent arg1) {
// Here's where we'd grab location and store it into DB.
//gps = new GPSTracker(AlarmReceiver.this);
// if(gps.canGetLocation()) {
// double latitude = gps.getLatitude();
// double longitude = gps.getLongitude();
// Draw Marker for Current Location on Fragment
// Toast a popup of the location data.
// Toast.makeText(arg0, "Your Location is -\nLat:" + latitude + "\nLong:" + longitude, Toast.LENGTH_LONG).show();
// } else {
// gps.showSettingsAlert();
// }
// Toast that the alarm ran.
Toast.makeText(arg0, "Location Pinged.", Toast.LENGTH_SHORT).show();
}
More specifically, a part of the problem is the way I'm calling for the new gps Tracker object here:
//gps = new GPSTracker(AlarmReceiver.this);
I'm not sure how to achieve the original result while using the alarmreceiver instead of a button, which is the main source of my problem. Does anyone know exactly what I can tinker with here to get the alarm receiver to properly use the GPSTracker Class?
DO not use GPSTracker. Its broken in over a dozen ways. Forget it exists. If you want a better version, you can use http://gabesechansoftware.com/location-tracking/ That link also explains why GPSTracker is broken by design and why it should never be used. It basically kinda works if used in optimal circumstances, and gives you horrible data in all the others.
Secondly, if you're using GPS and not network- you need to give it time to get a location sync. This can take seconds to minutes (or hours, if the user is in a basement or something) so the immediate forms of getting a location won't work- you have to wait for it to actually sync the location.
I suggest you not look for libraries to solve this and actually try to understand how the base APIs work. Until you do, you're going to have troubles with anything you use as there's lots of corner cases here and its not a trivial thing to do.