从服务访问android位置?
Posted
技术标签:
【中文标题】从服务访问android位置?【英文标题】:Access android location from service? 【发布时间】:2013-02-08 01:31:08 【问题描述】:我在从服务启动的线程请求位置更新时遇到问题。
我的应用程序需要从后台服务获取位置更新(没有任何 UI 线程)。我将解释我的应用程序的结构。
-
它有一个由 Boot Receiver 启动的服务。
在
onStartCommand()
的service中,它启动了一个调度线程。
调度程序线程请求位置更新。
问题是当调度程序调用locationMgr.requestLocationUpdates()
它说Can't create handler inside thread that has not called Looper.prepare()
我已经为其他人看到了类似的问题,但找不到任何解决方案。我听说我们可以直接从服务调用以获取位置更新而没有任何问题,但由于我找不到睡眠服务的方法(如调度程序线程),我想我需要一个单独的线程。
请解释为什么会这样? android 是否需要 UI 线程来请求位置?有什么办法可以通过改变我的应用结构来解决吗?
【问题讨论】:
【参考方案1】:Looper
是不断轮询Message
's/Runnable
s 的线程队列(通过该线程上的Handler
发布的那些)。 UI 线程默认有一个。对于自定义线程,您需要在启动线程之前进行设置。
As mentioned in the example:
用于为线程运行消息循环的类。线程默认做 没有与之关联的消息循环;创建一个,调用 prepare() 在要运行循环的线程中,然后 loop() 到 让它处理消息直到循环停止。
现在,RequestLocationUpdates()
需要一种机制来为您的线程提供更新,但您的线程没有 Looper
轮询。
考虑将RequestLocationUpdates()
及其对应的removeUpdates()
移动到服务线程。最有可能在服务开始和停止的地方。
【讨论】:
【参考方案2】:发生的原因是:getLooper 连接到 context 的 UI,但是 service 是 ackground 进程没有直接连接到 UI。所以你得到错误。
您的问题的解决方案:
1) 将位置类放在其他包中。 2)导入该包名称。 3) 在你的包中使用一个回调接口。 4)在你的服务组件中使用接口实例。 5)它会工作!
【讨论】:
【参考方案3】:我已经使用了这个并且工作正常:获取服务位置
这里的服务类:
public class MyService extends Service
@Override
public IBinder onBind(Intent arg0)
// TODO Auto-generated method stub
return null;
@Override
public void onCreate()
// TODO Auto-generated method stub
super.onCreate();
@Override
public void onDestroy()
// TODO Auto-generated method stub
super.onDestroy();
@Override
public void onStart(Intent intent, int startId)
// TODO Auto-generated method stub
super.onStart(intent, startId);
// start location manager
LocationDetermined objLocationDetemined = new LocationDetermined(this);
objLocationDetemined.getlocation(this);
objLocationDetemined.getRecentKnownLocation(this);
这里的位置类:
public class LocationDetermined implements OnInitListener
String TAG = "LocationDeterminedClass";
private static LocationManager locationManager;
double Lat = 0.0;
double Long = 0.0;
GeoPoint geoPoint;
private Toast mToast;
Context appContext;
static MyLocationListener locationListener;
public LocationDetermined(Context context)
this.appContext = context;
public MyLocationListener getlocation(Context appContext)
locationManager = (LocationManager) appContext
.getSystemService(Context.LOCATION_SERVICE);
locationListener = new MyLocationListener();
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_COARSE);
String provider = locationManager.getBestProvider(criteria, true);
Log.d(TAG, "------provider------" + provider);
if (provider != null && locationManager.isProviderEnabled(provider))
locationManager.requestLocationUpdates(provider, 0, 0,
locationListener);
else
Toast.makeText(appContext, "No provider available to get loctaion",
2000).show();
return locationListener;
private class MyLocationListener implements LocationListener
public void onProviderDisabled(String provider)
// TODO Auto-generated method stub
public void onProviderEnabled(String provider)
// TODO Auto-generated method stub
public void onStatusChanged(String provider, int status, Bundle extras)
// TODO Auto-generated method stub
public void onLocationChanged(final Location argLocation)
// TODO Auto-generated method stub
if (argLocation != null)
Lat = argLocation.getLatitude();
Long = argLocation.getLongitude();
Log.e("OnLocationChanged:", "lat:" + Lat + " long:" + Long);
Log.d("service gps", "lat" + argLocation.getLatitude() + "-"
+ argLocation.getLongitude());
Constant.mLatitude = argLocation.getLatitude();
Constant.mLongitude = argLocation.getLongitude();
public GeoPoint getRecentKnownLocation(Context appContext)
Location locGps = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
Location locNet = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
Location locPassive = locationManager
.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);
if (locGps != null)
Lat = locGps.getLatitude();
Long = locGps.getLongitude();
Constant.mLatitude = locGps.getLatitude();
Constant.mLongitude = locGps.getLongitude();
geoPoint = new GeoPoint((int) (Lat * 1000000),
(int) (Long * 1000000));
return geoPoint;
else if (locNet != null)
Lat = locNet.getLatitude();
Long = locNet.getLongitude();
Constant.mLatitude = locNet.getLatitude();
Constant.mLongitude = locNet.getLongitude();
geoPoint = new GeoPoint((int) (Lat * 1000000),
(int) (Long * 1000000));
return geoPoint;
return geoPoint;
private void fetchedSavedLocationDetail(Context mContext)
@Override
public void onInit(int status)
// TODO Auto-generated method stub
public static void removeLocationListener()
locationManager.removeUpdates(locationListener);
我在常量类中使用这些变量来存储位置 public static double mLatitude = 0.0, mLongitude = 0.0;
启动服务 startService(new Intent(this, MyService.class));
【讨论】:
【参考方案4】:我已经使用处理程序修复了它。
-
我创建了一个处理程序。
我把服务代码放在它的
handleMessage()
创建一个线程,在所需的时间间隔(while 循环)向处理程序发送空消息。
因此,当处理程序接收到空消息时,它会运行包含实际调度程序循环的handleMessage()
【讨论】:
以上是关于从服务访问android位置?的主要内容,如果未能解决你的问题,请参考以下文章
使用哪个 API 访问 Android 设备上的 GPS 位置? Android API 或 Google 位置服务 API