Issue
I have a PWA inside a webview made in Android Studio, it takes the user's location perfectly as long as the user has internet, gps and the app in foreground.
My problem is when they minimize or close the app. i need to keep collecting the user's location.
Is there any way that my webview allows my PWA to continue collecting the location in the background or when the app is closed?
Solution
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 here.
Don't forget to declare your service type as "location" into your AndroidManifest.xml
, in order to allow the service to receive the GPS updates also after a momentary signal loss when running in background:
<!-- 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" ... >
<!-- Any inner elements would go here. -->
</service>
As a note, once the GPS is accessed in the foreground, there is no need to request the android.permission.ACCESS_BACKGROUND_LOCATION
permission to continue to receive locations in background: the android.permission.ACCESS_FINE_LOCATION
is enough for your use.
Answered By - Graziano
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.