位置侦听器从服务而不是 IntentService 工作
Posted
技术标签:
【中文标题】位置侦听器从服务而不是 IntentService 工作【英文标题】:Location listener works from a Service but not an IntentService 【发布时间】:2013-11-27 12:56:37 【问题描述】:我有一个应用程序,我试图定期获取用户位置并发送到服务器。我有一个附加到AlarmManager
的服务,它每分钟执行一次(用于测试)。该服务正确找到用户位置并注销 GPS 坐标。一旦有 GPS 锁定,我就会取消定位请求并停止服务。当我要求位置更新时,我会启动一个 Handler
,它会在 20 秒后执行,这个 Handler
会删除位置更新并停止 Service
,以防没有锁定。这一切都有效。
下面是使用Service
类的代码。
public class TrackingService extends Service
private static final String TAG = TrackingService.class.getSimpleName();
LocationManager mlocManager;
LocationListener mlocListener;
NfcScannerApplication nfcscannerapplication;
String carerID;
Handler endServiceHandler;
Runnable endServiceRunnable;
@Override
public void onCreate()
super.onCreate();
nfcscannerapplication = (NfcScannerApplication) getApplication();
mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mlocListener = new MyLocationListener();
Log.e(TAG, "Service created and location manager and listener created");
@Override
public void onDestroy()
super.onDestroy();
Log.e(TAG, "in onDestroy in LocationService class");
mlocManager.removeUpdates(mlocListener);
@Override
public void onStart(Intent intent, int startId)
super.onStart(intent, startId);
mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
Log.e(TAG, "requesting location updates");
enableMenuButtonsHandler();
endServiceHandler.postDelayed(endServiceRunnable,20 * 1000);
@Override
public IBinder onBind(Intent intent)
return null;
private class MyLocationListener implements LocationListener
@Override
public void onLocationChanged(Location loc)
Log.e(TAG, "in TrackingService onlocationChanged and about to send lon/lat " + loc.getLongitude() + " " + loc.getLatitude());
DateTime dt = new DateTime();
DateTimeFormatter df3 = DateTimeFormat.forPattern("yyyy-MM-dd H:mm:ss.SSS");
String formattedNowTime3 = df3.print(dt);
Log.e(TAG, "Time of location fix in TrackingServive = " + formattedNowTime3);
Cursor c = nfcscannerapplication.loginValidate.queryAllFromCarer();
if (c.getCount() > 0)
if(c.moveToLast())
carerID = c.getString(c.getColumnIndex(LoginValidate.C_CARER_ID));
Log.e(TAG, "carer ID = " + carerID);
mlocManager.removeUpdates(mlocListener);
Log.e(TAG, "removed updates(TrackingService)");
TrackingService.this.stopSelf();
Log.e(TAG, "called stopSelf on TrackingService");
@Override
public void onProviderDisabled(String provider)
// TODO Auto-generated method stub
@Override
public void onProviderEnabled(String provider)
// TODO Auto-generated method stub
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
// TODO Auto-generated method stub
// end of MyLocationListener
public void enableMenuButtonsHandler()
endServiceHandler = new Handler();
endServiceRunnable = new Runnable()
public void run()
endService();
private void endService()
mlocManager.removeUpdates(mlocListener);
Log.e(TAG, "removed updates(TrackingService) from the endService handler");
TrackingService.this.stopSelf();
Log.e(TAG, "called stopSelf on TrackingService from the endService handler");
;
// end of service
我遇到的问题是,一旦我有 GPS 锁定,我想将经纬度坐标发送到服务器。我知道我可以从Service
使用AsyncTask
,但我不想这样做。我更喜欢使用IntentService
,因为它在自己的后台线程中运行。这样我就可以直接从IntentService
进行网络调用。
以下代码实现了IntentService
类,但它似乎没有获得锁。 GPS 会无限期地在手机上闪烁。日志语句一直到“请求位置更新”,然后就没有了。
有没有人知道为什么没有锁定?提前致谢。
public class TrackingService extends IntentService
private static final String TAG = TrackingService.class.getSimpleName();
LocationManager mlocManager;
LocationListener mlocListener;
NfcScannerApplication nfcscannerapplication;
String carerID;
Handler endServiceHandler;
Runnable endServiceRunnable;
public TrackingService()
super("TrackingService");
@Override
protected void onHandleIntent(Intent intent)
nfcscannerapplication = (NfcScannerApplication) getApplication();
mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mlocListener = new MyLocationListener();
Log.e(TAG, "Service created and location manager and listener created");
mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
Log.e(TAG, "requesting location updates");
enableMenuButtonsHandler();
endServiceHandler.postDelayed(endServiceRunnable,20 * 1000);
private class MyLocationListener implements LocationListener
@Override
public void onLocationChanged(Location loc)
Log.e(TAG, "in TrackingService onlocationChanged and about to send lon/lat " + loc.getLongitude() + " " + loc.getLatitude());
DateTime dt = new DateTime();
DateTimeFormatter df3 = DateTimeFormat.forPattern("yyyy-MM-dd H:mm:ss.SSS");
String formattedNowTime3 = df3.print(dt);
Log.e(TAG, "Time of location fix in TrackingServive = " + formattedNowTime3);
Cursor c = nfcscannerapplication.loginValidate.queryAllFromCarer();
if (c.getCount() > 0)
if(c.moveToLast())
carerID = c.getString(c.getColumnIndex(LoginValidate.C_CARER_ID));
Log.e(TAG, "carer ID = " + carerID);
mlocManager.removeUpdates(mlocListener);
Log.e(TAG, "removed updates(TrackingService)");
TrackingService.this.stopSelf();
Log.e(TAG, "called stopSelf on TrackingService");
@Override
public void onProviderDisabled(String provider)
// TODO Auto-generated method stub
@Override
public void onProviderEnabled(String provider)
// TODO Auto-generated method stub
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
// TODO Auto-generated method stub
// end of MyLocationListener
public void enableMenuButtonsHandler()
endServiceHandler = new Handler();
endServiceRunnable = new Runnable()
public void run()
endService();
private void endService()
mlocManager.removeUpdates(mlocListener);
Log.e(TAG, "removed updates(TrackingService) from the endService handler");
TrackingService.this.stopSelf();
Log.e(TAG, "called stopSelf on TrackingService from the endService handler");
;
//end of trackingService
[编辑1]
public class TrackingService extends Service
private static final String TAG = TrackingService.class.getSimpleName();
LocationManager mlocManager;
LocationListener mlocListener;
NfcScannerApplication nfcscannerapplication;
String carerID;
Handler endServiceHandler;
Runnable endServiceRunnable;
@Override
public int onStartCommand(Intent intent, int flags, int startId)
nfcscannerapplication = (NfcScannerApplication) getApplication();
mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mlocListener = new MyLocationListener();
Log.e(TAG, "Service created and location manager and listener created");
mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
Log.e(TAG, "requesting location updates");
enableMenuButtonsHandler();
endServiceHandler.postDelayed(endServiceRunnable, 20 * 1000);
return super.onStartCommand(intent, flags, startId);
@Override
public void onDestroy()
super.onDestroy();
Log.e(TAG, "in onDestroy in LocationService class");
mlocManager.removeUpdates(mlocListener);
@Override
public IBinder onBind(Intent intent)
return null;
private class MyLocationListener implements LocationListener
@Override
public void onLocationChanged(Location loc)
Log.e(TAG, "in TrackingService onlocationChanged and about to send lon/lat " + loc.getLongitude() + " " + loc.getLatitude());
DateTime dt = new DateTime();
DateTimeFormatter df3 = DateTimeFormat.forPattern("yyyy-MM-dd H:mm:ss.SSS");
String formattedNowTime3 = df3.print(dt);
Log.e(TAG, "Time of location fix in TrackingServive = " + formattedNowTime3);
Cursor c = nfcscannerapplication.loginValidate.queryAllFromCarer();
if (c.getCount() > 0)
if(c.moveToLast())
carerID = c.getString(c.getColumnIndex(LoginValidate.C_CARER_ID));
Log.e(TAG, "carer ID = " + carerID);
mlocManager.removeUpdates(mlocListener);
Log.e(TAG, "removed updates(TrackingService)");
TrackingService.this.stopSelf();
Log.e(TAG, "called stopSelf on TrackingService");
@Override
public void onProviderDisabled(String provider)
// TODO Auto-generated method stub
@Override
public void onProviderEnabled(String provider)
// TODO Auto-generated method stub
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
// TODO Auto-generated method stub
// end of MyLocationListener
public void enableMenuButtonsHandler()
endServiceHandler = new Handler();
endServiceRunnable = new Runnable()
public void run()
endService();
private void endService()
mlocManager.removeUpdates(mlocListener);
Log.e(TAG, "removed updates(TrackingService) from the endService handler");
TrackingService.this.stopSelf();
Log.e(TAG, "called stopSelf on TrackingService from the endService handler");
;
// end of service
[编辑2]
@Override
public int onStartCommand(Intent intent, int flags, int startId)
nfcscannerapplication = (NfcScannerApplication) getApplication();
mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mlocListener = new MyLocationListener();
Log.e(TAG, "Service created and location manager and listener created");
HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();
Looper looper = handlerThread.getLooper();
Handler handler = new Handler(looper);
mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener, looper);
Log.e(TAG, "requesting location updates");
enableMenuButtonsHandler();
endServiceHandler.postDelayed(endServiceRunnable, 20 * 1000);
return super.onStartCommand(intent, flags, startId);
[编辑3]
public class TrackingService extends Service
private static final String TAG = TrackingService.class.getSimpleName();
LocationManager mlocManager;
LocationListener mlocListener;
NfcScannerApplication nfcscannerapplication;
String carerID;
Handler endServiceHandler;
Runnable endServiceRunnable;
HandlerThread handlerThread;
Looper looper;
@Override
public int onStartCommand(Intent intent, int flags, int startId)
nfcscannerapplication = (NfcScannerApplication) getApplication();
mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
mlocListener = new MyLocationListener();
Log.e(TAG, "Service created and location manager and listener created");
Log.e(TAG, "creating handlerthread and looper");
handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();
looper = handlerThread.getLooper();
mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener, looper);
Log.e(TAG, "requesting location updates");
enableMenuButtonsHandler();
endServiceHandler.postDelayed(endServiceRunnable, 20 * 1000);
return super.onStartCommand(intent, flags, startId);
@Override
public void onDestroy()
super.onDestroy();
Log.e(TAG, "in onDestroy in LocationService class");
mlocManager.removeUpdates(mlocListener);
@Override
public IBinder onBind(Intent intent)
return null;
private class MyLocationListener implements LocationListener
@Override
public void onLocationChanged(Location loc)
Log.e(TAG, "in TrackingService onlocationChanged and about to send lon/lat " + loc.getLongitude() + " " + loc.getLatitude());
DateTime dt = new DateTime();
DateTimeFormatter df3 = DateTimeFormat.forPattern("yyyy-MM-dd H:mm:ss.SSS");
String formattedNowTime3 = df3.print(dt);
Log.e(TAG, "Time of location fix in TrackingServive = " + formattedNowTime3);
Cursor c = nfcscannerapplication.loginValidate.queryAllFromCarer();
if (c.getCount() > 0)
if(c.moveToLast())
carerID = c.getString(c.getColumnIndex(LoginValidate.C_CARER_ID));
Log.e(TAG, "carer ID = " + carerID);
nfcscannerapplication.loginWebservice.sendCarerLocation(carerID, formattedNowTime3, String.valueOf(loc.getLatitude()), String.valueOf(loc.getLongitude()));
Log.e(TAG, "quiting handlerthread");
handlerThread.quit();
mlocManager.removeUpdates(mlocListener);
Log.e(TAG, "removed updates(TrackingService)");
TrackingService.this.stopSelf();
Log.e(TAG, "called stopSelf on TrackingService");
@Override
public void onProviderDisabled(String provider)
// TODO Auto-generated method stub
@Override
public void onProviderEnabled(String provider)
// TODO Auto-generated method stub
@Override
public void onStatusChanged(String provider, int status, Bundle extras)
// TODO Auto-generated method stub
// end of MyLocationListener
public void enableMenuButtonsHandler()
endServiceHandler = new Handler();
endServiceRunnable = new Runnable()
public void run()
endService();
private void endService()
mlocManager.removeUpdates(mlocListener);
Log.e(TAG, "removed updates(TrackingService) from the endService handler");
TrackingService.this.stopSelf();
Log.e(TAG, "called stopSelf on TrackingService from the endService handler");
Log.e(TAG, "quiting handlerthread from the endService handler");
handlerThread.quit();
;
// end of service
【问题讨论】:
仅使用服务... IntentService 在onHandleIntent
完成后销毁。
你有什么错误吗?如果是,则提供 lagcat
@AM 没有错误。它在 onHandleIntent 代码中请求位置更新......然后什么都没有。
@PankajKumar 所以在 gps 找到锁时无法保持 onHandleIntent 存活?
android LocationLister implemented in IntentService never execute the OnLocationChanged() method 的可能重复项
【参考方案1】:
正如 Pankaj Kumar 所指出的,IntentService
不适用于要完成的工作本质上是异步的情况。一旦onHandleIntent()
返回,你的服务就会被销毁。
使用常规的Service
,在onStartCommand()
中注册位置,使用HandlerThread
处理结果(这样您就可以将其Looper
传递给requestLocationUpdates()
)。收到您的位置信息或达到合适的超时时间后,请执行您的工作并在服务上调用 stopSelf()
将其关闭。
【讨论】:
您的回复。我已经编辑了问题 [Edit1]。我已按照您的建议将代码改回使用 Service 并覆盖 onStartCommand 。您能否解释和扩展一些有关 handlerThread、looper 和传递到 requestlocationUpdates 的内容。我不太清楚你的意思。谢谢 @turtleboy: developer.android.com/reference/android/location/… 使用带有Looper
的requestLocationUpdates()
变体允许您在HandlerThread
(developer.android.com/reference/android/os/HandlerThread.html) 上接收LocationListener
回调。这为您提供了工作所需的后台线程。
我再次编辑了帖子 [edit2]。你介意看一下吗,我已经修改了 onStartCommand 方法。我创建了一个 HandlerThread 并启动了它。然后我从 handlerThread 创建了一个 looper 并将它传递给 requestLocationUpdates() ,它接受一个 looper 参数。我还是有点迷失在这里。您之前发送给我的文档说我可以从 looper 获取处理程序,但我不确定从这里做什么以及如何创建您提到的后台线程,我可以将 long 和 lat 传递给网络调用。你介意再详细说明一下吗?谢谢
@turtleboy:“如何创建你提到的后台线程”——你已经创建并启动了HandlerThread
。 “我可以将 long 和 lat 传递给网络调用”——在 onLocationChanged()
中。完成网络 I/O 后,您可以通过 quit()
HandlerThread
和 stopSelf()
清理服务,就像 IntentService
在幕后所做的那样。
谢谢,现在可以正常使用了。我已经发布了现在的代码。(edit3)我想我已经按照你的描述做了?我想更多地了解这一切是如何运作的。我之前使用过 requestLocationUpdates() 并从主线程调用它而没有循环。我查了一下Service,它不在自己的线程中运行,所以我认为它在主线程中运行。那么为什么我需要一个活套?您能否简要解释一下这里涉及的机制与主线程、服务、handlerthread、looper 以及它们如何相互交互。感谢您到目前为止的时间。马特以上是关于位置侦听器从服务而不是 IntentService 工作的主要内容,如果未能解决你的问题,请参考以下文章
Android:如何确定 IntentService 是不是正在运行?
未从 IntentService 调用 onLocationChanged