gpt4 book ai didi

android - LocationClient 在屏幕灯熄灭时不提供回调,但我的 WakefulThread 按预期完美运行

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:25:11 27 4
gpt4 key购买 nike

检索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) 方法:

https://developer.android.com/reference/com/google/android/gms/location/LocationClient.html#requestLocationUpdates(com.google.android.gms.location.LocationRequest,%20android.app.PendingIntent)

来自上面的 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 文档:

http://developer.android.com/reference/android/app/IntentService.html#onHandleIntent(android.content.Intent)

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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com