如何为定位服务实现 onConnectionFailed() 和 onDisconnected()
Posted
技术标签:
【中文标题】如何为定位服务实现 onConnectionFailed() 和 onDisconnected()【英文标题】:How to implement onConnectionFailed() and onDisconnected() for a location service 【发布时间】:2014-04-15 06:53:22 【问题描述】:我正在使用实现com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks
的Service
和
com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener
该服务应该在运行时每分钟将位置更新上传到服务器。我搜索了教程,但找不到适合我的场景的教程。
我不知道如何实现的方法是:
@Override
public void onConnectionFailed(ConnectionResult connectionResult)
...
有一些教程建议使用connectionResult.startResolutionForResult(this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
开始一个活动,但由于这是一个Service
(不是活动),我不能使用这种方法。我想过将Intent
中的connectionResult
发送到活动,但ConnectionResult
不可序列化。
和
@Override
public void onDisconnected()
...
我应该在这里再打电话给LocationClient#connect()
吗?
【问题讨论】:
【参考方案1】:1. 在onConnectionFailed()
:
对于“我想将Intent
中的connectionResult
发送到活动,但ConnectionResult
不可序列化。”我认为没有它可以通过以下方式工作:
您可以返回int
; ErrorCodes
或 Constants
的值是 ConnectionResult
,根据该值,您可以分配进一步的操作,只需将控制权传递给您的活动/应用程序。
发件人:http://developer.android.com/reference/com/google/android/gms/common/ConnectionResult.html
2. 在onDisconnected()
,
您可以通知用户“您不再接收位置更新”或其他自定义消息,具体取决于您的应用,这将提示用户采取行动。
如果您的服务由于某种我们不知道的原因进入onDisconnected()
,再次调用locationClient.connect()
可能无济于事。
在这两种情况下,我们的想法是将控制权传递给您的应用程序,以便在您的活动中的某个位置,它可以作为控制流的决策点。
此外,您还提到“......但我找不到适合我的场景的任何好东西。”因此,稍微准确地描述您的要求可能会对您有所帮助。将相应地编辑我的答案。
如果它向服务器发送位置更新,那么将控制权传递回您的活动/应用程序并提示用户采取行动也会有所帮助。 (例如,检查Settings
是否启用了Location
访问服务)
查找此问题/答案的任何人的当前情况
在com.google.android.gms.location
下不再找到LocationClient,参考:Android play services 6.5: LocationClient is missing
【讨论】:
第 2 点不正确。onDisconnected()
在调用disconnect()
之后不被调用。见here。
@zelanix 感谢您指出这一点,虽然这不是全部错误,但您对引用 onDisconnect()
的行是正确的,我删除了
不,绝对 - 抱歉,措辞有点不公平 - 答案的其余部分看起来不错。我认为 [这个解决方案] (***.com/a/19433291/2433501) 似乎是在onDisconnected()
之后处理重新连接的合理方式。
没关系,好吧,现在不认为这很重要,LocationClient 已被弃用,接口实现 onConnectionFailed()
和 onConnectionSuspended()
@zelanix 您在使用 location 吗?您是否从应用程序访问位置设置? i am trying to achieve this【参考方案2】:
我不确定过去如何,但现在(棉花糖)ConnectionResult 是 Parcelable:
public final class ConnectionResult implements SafeParcelable
了解这一点后,您可以将其发送到 Intent 的附加功能中:
@Override
public void onConnectionFailed(final ConnectionResult result)
Log.w(LOG_TAG, "Connecting to Google Play Services failed. Result=" + result);
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable()
@Override
public void run()
Intent intent = new Intent(context, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(INTENT_EXTRA_CONNECTION_RESULT, connectionResult);
context.startActivity(intent);
);
然后 MainActivity(或任何其他 Activity)可以向用户显示正确的分辨率或对话框消息:
Parcelable connectionResultExtra = activity.getIntent().getParcelableExtra(INTENT_EXTRA_CONNECTION_RESULT);
if (connectionResultExtra != null)
ConnectionResult connectionResult = (ConnectionResult) connectionResultExtra;
if (connectionResult.hasResolution())
try
connectionResult.startResolutionForResult(activity, 1234567890);
catch (IntentSender.SendIntentException e)
Log.e(LOG_TAG, "Unable to resolve ConnectionResult", e);
else
int availabilityCode = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(activity);
if (availabilityCode != 0)
Dialog errorDialog = GoogleApiAvailability.getInstance().getErrorDialog(activity, availabilityCode, 123);
errorDialog.show();
希望对你有帮助。
【讨论】:
【参考方案3】:调用“yourLocationClient.connect()”时会调用“OnConnectionFailed()”方法 并且 LocationClient 无法连接到 Google Play 定位服务。
在“startResolutionForResult(Activity activity, int requestCode)”方法中,第一个参数是一个Activity类,所以UI相关的东西应该在Activity本身上弹出。您应该尝试输入要显示解析结果的 Activity 类的名称。 (我不确定,但你可以试试)
如果第 2 点不起作用,您可以随时向 Activity 发送广播,并附加一个 'int'。这里的 int 表示您在“connectionResult”中遇到的错误类型。
如果您希望您的客户端始终保持连接,您可以在“onDisconnected()”中调用“onConnected()”,但在您明确调用“disconnect()”之前它不会断开连接。
如果您希望即使用户从应用程序托盘关闭应用程序,您的服务也一直运行,请务必选中this 链接。
最重要的:
如果您在应用程序中使用 Google Play 服务,您应该在应用程序第一次启动时检查服务的可用性。甚至在某些服务启动或您将用户带到主活动之前。您可以在任何空白活动/注册后/启动后的活动上执行此操作。
【讨论】:
感谢您的解决方法,谷歌感到羞耻。在谷歌宣布 Android M 之后,这个问题变得更加实际,人们可以在 安装后 禁用权限。【参考方案4】:这里有一个更好的答案:
ConnectionResult 不可打包,但它有一个构造函数,该构造函数接受一个 errorCode 和一个 pendingIntent。这两个都是可以打包的。
所以,为您服务:
private void notifyUiFailedConnection(ConnectionResult result)
Intent intent = new Intent(FIT_NOTIFY_INTENT);
intent.putExtra(FIT_EXTRA_NOTIFY_FAILED_STATUS_CODE, result.getErrorCode());
intent.putExtra(FIT_EXTRA_NOTIFY_FAILED_INTENT, result.getResolution());
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
在你的活动中:
private BroadcastReceiver mFitStatusReceiver = new BroadcastReceiver()
@Override
public void onReceive(Context context, Intent intent)
// Get extra data included in the Intent
if (intent.hasExtra(GoogleFitService.FIT_EXTRA_NOTIFY_FAILED_STATUS_CODE) &&
intent.hasExtra(GoogleFitService.FIT_EXTRA_NOTIFY_FAILED_STATUS_CODE))
//Recreate the connection result
int statusCode = intent.getIntExtra(GoogleFitService.FIT_EXTRA_NOTIFY_FAILED_STATUS_CODE, 0);
PendingIntent pendingIntent = intent.getParcelableExtra(GoogleFitService.FIT_EXTRA_NOTIFY_FAILED_INTENT);
ConnectionResult result = new ConnectionResult(statusCode, pendingIntent);
fitHandleFailedConnection(result);
;
【讨论】:
【参考方案5】:在您的服务中实现 onconnection failed listsner 并覆盖其方法,如下所示:
public class yourService extends Service implements
LocationListener, OnConnectionFailedListener
@Override
public void onConnectionFailed(ConnectionResult arg0)
【讨论】:
这不能回答上面的问题。以上是关于如何为定位服务实现 onConnectionFailed() 和 onDisconnected()的主要内容,如果未能解决你的问题,请参考以下文章