- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
检索fused location在后台,我创建了一个与 cwac-locpoll 非常相似的库由 Commonsguy 创建的库。
在 PollerThread 中,我尝试使用 LocationClient
连接、请求和检索位置。
我可以通过在 onConnected
方法上接收回调来建立连接,但我无法在 onLocationChanged
方法上获得回调。所以我的 onTimeout
线程按照决定的间隔执行。
注意: 只有当屏幕灯熄灭时才会出现此问题。否则一切正常。
我怀疑新的 Location Api 中可能存在错误。
这是我的PollerThread
的实现,
private class PollerThread extends WakefulThread implements GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener,LocationListener{
private static final String TAG = "PollerThread";
//context
private Context mContext=null;
private LocationClient mLocationClient=null;
private LocationRequest mLocationRequest=null;
private LocationManager locMgr=null;
private Intent intentTemplate=null;
private Handler handler=new Handler();
private Runnable onTimeout = new Runnable() {
@Override
public void run() {
Log.e(TAG, "onTimeout");
//prepare broadcast intent
Intent toBroadcast=new Intent(intentTemplate);
toBroadcast.putExtra(FusedPoller.EXTRA_ERROR, "Timeout!");
toBroadcast.putExtra(
FusedPoller.EXTRA_ERROR_PROVIDER_DISABLED, false);
toBroadcast.putExtra(FusedPoller.EXTRA_LASTKNOWN,
mLocationClient.getLastLocation());
sendBroadcast(toBroadcast);
//stop the thread
quit();
}
};
PollerThread(Context mContext,LocationRequest mLocationRequest,PowerManager.WakeLock lock, LocationManager locMgr,
Intent intentTemplate) {
super(lock, "LocationPoller-PollerThread");
Log.e(TAG, "PollerThread");
this.mContext=mContext;
this.mLocationRequest=mLocationRequest;
this.locMgr=locMgr;
this.intentTemplate=intentTemplate;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
Log.e(TAG, "onPreExecute");
//setup timeout
setTimeoutAlarm();
//initiate connection
initiateConnection();
}
@Override
protected void onPostExecute() {
super.onPostExecute();
Log.e(TAG, "onPostExecute");
//remove timeout
removeTimeoutAlarm();
//disconnect
initiateDisconnection();
}
/**
* Called when the WakeLock is completely unlocked.
* Stops the service, so everything shuts down.
*/
@Override
protected void onUnlocked() {
Log.e(TAG, "onUnlocked");
stopSelf();
}
private void setTimeoutAlarm() {
Log.e(TAG, "setTimeoutAlarm");
handler.postDelayed(onTimeout, FusedLocationUtils.DEFAULT_TIMEOUT);
}
private void removeTimeoutAlarm()
{
Log.e(TAG, "removeTimeoutAlarm");
handler.removeCallbacks(onTimeout);
}
private void initiateConnection()
{
Log.e(TAG, "initiateConnection");
mLocationClient = new LocationClient(this.mContext, this, this);
mLocationClient.connect();
}
private void initiateDisconnection()
{
Log.e(TAG, "initiateDisconnection");
if(mLocationClient.isConnected())
{
mLocationClient.disconnect();
}
}
@Override
public void onConnected(Bundle arg0) {
Log.e(TAG, "onConnected");
Log.e(TAG, "provider: GPS-"+locMgr.isProviderEnabled(LocationManager.GPS_PROVIDER)+" NETWORK-"+locMgr.isProviderEnabled(LocationManager.NETWORK_PROVIDER));
if (!(locMgr.isProviderEnabled(LocationManager.GPS_PROVIDER)) && !(locMgr.isProviderEnabled(LocationManager.NETWORK_PROVIDER))) {
Log.e(TAG, "both disabled");
//get last location and broadcast it
getLastLocationAndBroadcast();
//stop the thread
quit();
}
else
{
Log.e(TAG, "provider enabled");
//get latest location and broadcast it
getLatestLocationAndBroadcast();
//don't quit from here,quit from onLocationChanged
}
}
@Override
public void onDisconnected() {
Log.e(TAG, "onDisconnected");
// TODO Auto-generated method stub
}
@Override
public void onConnectionFailed(ConnectionResult arg0) {
Log.e(TAG, "onConnectionFailed");
// TODO Auto-generated method stub
}
@Override
public void onLocationChanged(Location location) {
Log.e(TAG, "onLocationChanged");
//prepare broadcast intent
Intent toBroadcast=new Intent(intentTemplate);
toBroadcast.putExtra(FusedPoller.EXTRA_LOCATION, location);
sendBroadcast(toBroadcast);
//stop further updates
stopUpdates();
//stop the thread
quit();
}
private void getLatestLocationAndBroadcast() {
Log.e(TAG, "getLatestLocationAndBroadcast");
if(mLocationClient.isConnected() && servicesConnected())
{
Log.e(TAG, "going to request updates");
Log.e(TAG, "lockStatic.isHeld(): "+lockStatic.isHeld());
mLocationClient.requestLocationUpdates(mLocationRequest, this);
}
else
{
Log.e(TAG, "not going to request updates");
}
}
private void stopUpdates() {
Log.e(TAG, "stopUpdates");
if(servicesConnected())
{
Log.e(TAG,getString(R.string.location_updates_stopped));
mLocationClient.removeLocationUpdates(this);
}
else
{
Log.e(TAG,"can't do:"+getString(R.string.location_updates_stopped));
}
}
private void getLastLocationAndBroadcast() {
Log.e(TAG, "getLastLocationAndBroadcast");
if(mLocationClient.isConnected() && servicesConnected())
{
Log.e(TAG, "going to get last location: "+mLocationClient.getLastLocation());
Intent toBroadcast = new Intent(intentTemplate);
toBroadcast.putExtra(FusedPoller.EXTRA_ERROR,
"Location Provider disabled!");
toBroadcast.putExtra(
FusedPoller.EXTRA_ERROR_PROVIDER_DISABLED, true);
toBroadcast.putExtra(FusedPoller.EXTRA_LASTKNOWN,
mLocationClient.getLastLocation());
sendBroadcast(toBroadcast);
}
else
{
Log.e(TAG, "not going to get last location");
}
}
}
和servicesConnected
方法实现,
/**
* Verify that Google Play services is available before making a request.
*
* @return true if Google Play services is available, otherwise false
*/
private boolean servicesConnected() {
Log.e(TAG, "servicesConnected");
// Check that Google Play services is available
int resultCode =
GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
// If Google Play services is available
if (ConnectionResult.SUCCESS == resultCode) {
// In debug mode, log the status
Log.d(FusedLocationUtils.APPTAG, getString(R.string.play_services_available));
// Continue
return true;
// Google Play services was not available for some reason
} else {
// Display an error dialog
Log.d(FusedLocationUtils.APPTAG, getString(R.string.play_services_unavailable));
Toast.makeText(this, getString(R.string.play_services_unavailable), Toast.LENGTH_SHORT).show();
return false;
}
}
最佳答案
如果您想在后台收听频繁的位置更新(例如,每秒),您应该在 Service
中运行您的代码:
http://developer.android.com/reference/android/app/Service.html
Activity 可以在它们不在前台的任何时间点由 Android 平台结束。
使用服务时,我建议让服务直接实现 LocationListener,而不是服务内部的线程。例如,使用:
public class LocListener extends Service implements com.google.android.gms.location.LocationListener, ...{
我在我的 GPS Benchmark app 中使用了这种直接在服务上使用 LocationClient
和融合位置提供程序实现 LocationListener 的设计。我可以确认即使在屏幕关闭且应用程序在后台运行时这也能正常工作。
如果您想使用融合位置提供程序在后台(例如,每分钟)收听偶尔的位置更新,更好的设计是使用 PendingIntents,使用 LocationClient.requestLocationUpdates(Location Request, PendingIntent callbackIntent)
方法:
来自上面的 Android 文档:
This method is suited for the background use cases, more specifically for receiving location updates, even when the app has been killed by the system. In order to do so, use a PendingIntent for a started service. For foreground use cases, the LocationListener version of the method is recommended, see requestLocationUpdates(LocationRequest, LocationListener).
Any previous LocationRequests registered on this PendingIntent will be replaced.
Location updates are sent with a key of KEY_LOCATION_CHANGED and a Location value on the intent.
有关使用 PendingIntents
在后台运行时获取更新的更详细说明,请参阅 Activity 识别示例:
https://developer.android.com/training/location/activity-recognition.html
此文档的修改摘录如下,由我更改为特定于位置更新。
首先声明Intent:
public class MainActivity extends FragmentActivity implements
ConnectionCallbacks, OnConnectionFailedListener {
...
...
/*
* Store the PendingIntent used to send location updates
* back to the app
*/
private PendingIntent mLocationPendingIntent;
// Store the current location client
private LocationClient mLocationClient;
...
}
像现在一样请求更新,但这次传递待处理的 Intent :
/*
* Create the PendingIntent that Location Services uses
* to send location updates back to this app.
*/
Intent intent = new Intent(
mContext, LocationIntentService.class);
...
//Set up LocationRequest with desired parameter here
...
/*
* Request a PendingIntent that starts the IntentService.
*/
mLocationPendingIntent =
PendingIntent.getService(mContext, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
/*
* Request location updates
*/
mLocationClient.requestLocationUpdates(mLocationRequest, callbackIntent);
Handle Location Updates
To handle the Intent that Location Services sends for each update interval, define an IntentService and its required method onHandleIntent(). Location Services sends out ... updates as Intent objects, using the the PendingIntent you provided when you called requestLocationUpdates(). Since you provided an explicit intent for the PendingIntent, the only component that receives the intent is the IntentService you're defining.
Define the class and the required method onHandleIntent():
/**
* Service that receives Location updates. It receives
* updates in the background, even if the main Activity is not visible.
*/
public class LocationIntentService extends IntentService {
...
/**
* Called when a new location update is available.
*/
@Override
protected void onHandleIntent(Intent intent) {
Bundle b = intent.getExtras();
Location loc = (Location) b.get(LocationClient.KEY_LOCATION_CHANGED);
Log.d(TAG, "Updated location: " + loc.toString());
}
...
}
重要 - 为了尽可能高效,您在 onHandleIntent()
中的代码应尽快返回以允许 IntentService 关闭。来自 IntentService 文档:
This method is invoked on the worker thread with a request to process. Only one Intent is processed at a time, but the processing happens on a worker thread that runs independently from other application logic. So, if this code takes a long time, it will hold up other requests to the same IntentService, but it will not hold up anything else. When all requests have been handled, the IntentService stops itself, so you should not call stopSelf().
我对 IntentService
设计的理解是,您可以在 onHandleIntent()
中生成线程,以避免通过平台调用 onHandleIntent()< 阻止其他位置更新
,请注意该服务将继续运行,直到所有正在运行的线程终止。
关于android - LocationClient 在屏幕灯熄灭时不提供回调,但我的 WakefulThread 按预期完美运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17613888/
我对java有点陌生,所以如果我犯了一个简单的错误,请原谅我,但我不确定我哪里出错了,我收到的错误是“预期的.class,预期的标识符,而不是声明, ';'预期的。”我尝试了不同的方法,并从这些方法中
This question already has answers here: chai test array equality doesn't work as expected (3个答案) 3年前
我正在学习 Java(对不起,我的英语很差,这不是我的母语),当我在 Eclipse (JavaSE-1.7) 中在我输入的每个“try”中执行“try-finally” block 时,会出现以下消
我收到两个错误,指出 token 上的语法错误,ConstructorHeaderName expected instead & token “(”上的语法错误,< expected 在线: mTM.
我找不到错误。 Eclipse 给我这个错误。每个 { } 都是匹配的。请帮忙。 Multiple markers at this line - Syntax error on token “)”,
代码: import java.awt.*; import javax.swing.*; import java.awt.event.*; public class DoubleIt extends
我正在用 python(Vs 代码)编写代码,但出现此错误: Expected ")" Pylance 错误发生在:def main() 我试着运行我的 main 并将它打印到我的屏幕上。我用谷歌搜
我正在尝试按照 documentation 中的建议使用异步函数。但我收到此错误 意外的 token ,预期 ( async function getMoviesFromApi() { try
Closed. This question does not meet Stack Overflow guidelines。它当前不接受答案。 想改善这个问题吗?更新问题,以便将其作为on-topic
Closed. This question does not meet Stack Overflow guidelines。它当前不接受答案。 想改善这个问题吗?更新问题,以便将其作为on-topic
第一行包含一个表示数组长度的整数p。第二行包含用空格分隔的整数,这些整数描述数组中的每个元素。第三行打印一个整数,指示负数组的数量。 package asgn3; import java.util.*
好的,我是初学者,我必须修复此 java 表达式语言代码才能在我的系统 (Windchill) 中工作,但看起来我在语法中遗漏了一些内容: LWCNormalizedObject lwc =
我无法编译我的程序! 我想我缺少一个花括号,但我怎么也看不出在哪里! import javax.swing.*; import java.awt.*;
我的 jQuery 代码有问题,我的 Firebug 向我发出警告:需要选择器。 这是代码: $("img[id$='_tick']").each(function() { $(this).c
我的新类(class) Fountainofyouth 遇到了问题。尝试构建整个项目后,调试器显示 warning: extended initializer lists only available
我已经从 Java 转向 CPP,并且正在努力围绕构造构造函数链进行思考,我认为这是我的问题的根源。 我的头文件如下: public: GuidedTour(); GuidedTour(string
鉴于以下 for(var i=0; i< data.cats.length; i++) list += buildCategories(data.cats[i]); jsLint 告诉我 Expect
我有这个 json,但 Visual Studio Code 在标题中给了我警告。 [ { "title": "Book A", "imageUrl": "https:
我正在尝试编写一个有条件地禁用四个特殊成员函数(复制构造、移动构造、复制赋值和移动赋值)的包装类,下面是我用于测试目的的快速草稿: enum class special_member : uint8_
所以我用 F# 编写了一个非常简单的程序,它应该对 1000 以下的所有 3 和 5 的倍数求和: [1..999] |> List.filter (fun x -> x % 3 = 0 || x %
我是一名优秀的程序员,十分优秀!