Reputation: 83
I have to schedule a work to fetch user current location and update to server in a given interval (Even the app is not running).
I am trying to WorkManagerAPI
to implement the functionality.
Is it possible to fetch the current location of the user from the doWork()
method ?
locationManager.requestLocationUpdates(
provider, timeInterval, travelDistance, locationListener
);
When I request Location updates from the doWork()
it throws below error.
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
Upvotes: 4
Views: 1086
Reputation: 2451
As per my understanding, when implementing LocationManager.requestLocationUpdates() on a Worker thread, the call is being made on a non-UI, background thread created by WorkManager. LocationManager.requestLocationUpdates() is an asynchronous call possibly on another background thread. To handle the callbacks defined by the LocationListener, the calling thread must stay alive. Thats why the exception says,
Can't create handler inside thread that has not called Looper.prepare()
Check the code snippet below. Please consider this as pseudocode, I haven't tested this piece of code.
public class LocationWorker extends Worker {
String LOG_TAG = "LocationWorker";
private Context mContext;
private MyHandlerThread mHandlerThread;
public LocationWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
mContext = context;
}
@NonNull
@Override
public Result doWork() {
Log.d(LOG_TAG, "doWork");
mHandlerThread = new MyHandlerThread("MY_THREAD");
mHandlerThread.start();
Runnable runnable = new Runnable() {
@Override
public void run() {
LocationManager locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
String bestProvider = locationManager.getBestProvider(new Criteria(), true);
boolean permission = false;
if (PermissionChecker.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
PermissionChecker.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
Log.e(LOG_TAG, "This app requires ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions.");
permission = true;
}
Log.d(LOG_TAG, "permission: "+permission);
Log.d(LOG_TAG, "bestProvider: "+bestProvider);
if (permission && bestProvider != null) {
MyLocationListener locListener = new MyLocationListener();
locationManager.requestLocationUpdates(bestProvider, 500, 1, locListener, mHandlerThread.getLooper());
}
}
};
mHandlerThread.post(runnable);
return Result.success();
}
class MyHandlerThread extends HandlerThread {
Handler mHandler;
MyHandlerThread(String name) {
super(name);
}
@Override
protected void onLooperPrepared() {
Looper looper = getLooper();
if (looper != null)
mHandler = new Handler(looper);
}
void post(Runnable runnable) {
if (mHandler != null)
mHandler.post(runnable);
}
}
class MyLocationListener implements LocationListener
{
@Override
public void onLocationChanged(final Location loc)
{
Log.d(LOG_TAG, "Location changed: " + loc.getLatitude() +","+ loc.getLongitude());
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{
Log.d(LOG_TAG, "onStatusChanged");
}
@Override
public void onProviderDisabled(String provider)
{
Log.d(LOG_TAG, "onProviderDisabled");
}
@Override
public void onProviderEnabled(String provider)
{
Log.d(LOG_TAG, "onProviderEnabled");
}
}
}
Upvotes: 1