android-location - 是否可以从 Worker 类中获取用户位置?
问题描述
我必须安排工作以在给定的时间间隔内获取用户当前位置并更新到服务器(即使应用程序没有运行)。
我正在尝试WorkManagerAPI
实现该功能。是否可以从方法中获取用户的当前位置doWork()
?
locationManager.requestLocationUpdates(
provider, timeInterval, travelDistance, locationListener
);
当我请求位置更新时,doWork()
它会引发以下错误。
java.lang.RuntimeException:无法在未调用 Looper.prepare() 的线程内创建处理程序
解决方案
据我了解,在 Worker 线程上实现 LocationManager.requestLocationUpdates() 时,调用是在 WorkManager 创建的非 UI 后台线程上进行的。LocationManager.requestLocationUpdates() 是可能在另一个后台线程上的异步调用。要处理由 LocationListener 定义的回调,调用线程必须保持活动状态。这就是为什么例外说,
无法在未调用 Looper.prepare() 的线程内创建处理程序
检查下面的代码片段。请将此视为伪代码,我没有测试过这段代码。
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");
}
}
}
推荐阅读
- regex - 试图在 Pandas 中提取单词但得到 TypeError: expected string or bytes-like object
- .net - 如何可靠地以编程方式检查是否安装了 net5 AspnetCore Hosting Bundle?
- ios - 自定义 UITableView 未出现在 iPhone 或 iPad 上
- revit-api - Revit 的 OpenStudio 代码有哪些条款?
- vb.net - 带有选定输出的 Visual Basic 循环声音警报
- r - 在 R 中使用 ggplot2 复制 Excel 绘图
- c++ - C++ 问题中的输出
- r - 管道函数中的消息顺序
- java - JPA 不可修改的数据库行
- asp.net-mvc - MVC 部分视图未在控制器上点击 HTTP Post