Android: 如何解决 Google API 服务连接失败?
Android: How to resolve Google API connection fail from a Service?
here是官方指南提供的代码,而这是一个导致问题的片段。
@Override
public void onConnectionFailed(ConnectionResult result) {
if (mResolvingError) {
// Already attempting to resolve an error.
return;
} else if (result.hasResolution()) {
try {
mResolvingError = true;
result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);
} catch (IntentSender.SendIntentException e) {
// There was an error with the resolution intent. Try again.
mGoogleApiClient.connect();
}
} else {
// Show dialog using GooglePlayServicesUtil.getErrorDialog()
mResolvingError = true;
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), this, REQUEST_RESOLVE_ERROR)
.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
mResolvingError = false;
}
});
}
}
如果我在服务中使用它,当您读取作为参数传递给这些函数的变量 this
时,它们需要一个 Activity 类型。
我应该怎么做?这是一项服务。
出于同样的原因,我无法获得 activity 结果
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_RESOLVE_ERROR) {
mResolvingError = false;
if (resultCode == RESULT_OK) {
// Make sure the app is not already connected or attempting to connect
if (!mGoogleApiClient.isConnecting() &&
!mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
}
}
}
}
此答案假定您的服务是 "started" 服务。如果它是绑定服务或意图服务,请在评论中指出,我将更新此处包含的描述和代码。
我建议的解决方案是实施下面显示的 activity 来处理分辨率 UI。用此代码替换服务中的 onConnectionFailed()
方法,将解析处理交给 ResolverActivity
:
@Override
public void onConnectionFailed(ConnectionResult result) {
Intent i = new Intent(this, ResolverActivity.class);
i.putExtra(ResolverActivity.CONNECT_RESULT_KEY, result);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
将下面显示的 activity 添加到您的应用程序。当您的服务中的连接请求失败时,连接结果 Parcelable
将传递给 activity。 activity 处理解析 UI,完成后,returns 将服务状态作为 intent extra。您将需要修改服务 onStartCommand()
中的代码,以检查意图中的额外内容,以确定是否调用它来首次启动服务,或者从 ResolverActivity
接收解析状态.
此方法的增强功能是 post 为 ResolverActivity
发送带有 PendingIntent
的通知,而不是立即启动 activity。这将为用户提供延迟解决连接失败的选项。
public class ResolverActivity extends AppCompatActivity {
public static final String TAG = "ResolverActivity";
public static final String CONNECT_RESULT_KEY = "connectResult";
public static final String CONN_STATUS_KEY = "connectionStatus";
public static final int CONN_SUCCESS = 1;
public static final int CONN_FAILED = 2;
public static final int CONN_CANCELLED = 3;
// Request code to use when launching the resolution activity
private static final int REQUEST_RESOLVE_ERROR = 1111;
private static final String ERROR_CODE_KEY = "errorCode";
private static final String DIALOG_FRAG_TAG = "errorDialog";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "onCreate()");
// No content needed.
//setContentView(R.layout.activity_main);
Intent i = getIntent();
ConnectionResult result = i.getParcelableExtra(CONNECT_RESULT_KEY);
if (result.hasResolution()) {
try {
Log.i(TAG, "Starting error resolution...");
result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);
} catch (IntentSender.SendIntentException e) {
// There was an error with the resolution intent.
sendStatusToService(CONN_FAILED);
finish();
}
} else {
// Show dialog using GooglePlayServicesUtil.getErrorDialog()
ErrorDialogFragment.newInstance(result.getErrorCode())
.show(getSupportFragmentManager(), DIALOG_FRAG_TAG);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent result) {
if (requestCode == REQUEST_RESOLVE_ERROR) {
if (resultCode == RESULT_OK) {
Log.i(TAG, "onActivityResult(): Connection problem resolved");
sendStatusToService(CONN_SUCCESS);
} else {
sendStatusToService(CONN_CANCELLED);
Log.w(TAG, "onActivityResult(): Resolution cancelled");
}
// Nothing more to do in this activity
finish();
}
}
private void sendStatusToService(int status) {
Intent i = new Intent(this, MyGoogleApiService.class);
i.putExtra(CONN_STATUS_KEY, status);
startService(i);
}
// Fragment to display an error dialog
public static class ErrorDialogFragment extends DialogFragment {
public static ErrorDialogFragment newInstance(int errorCode) {
ErrorDialogFragment f = new ErrorDialogFragment();
// Pass the error that should be displayed
Bundle args = new Bundle();
args.putInt(ERROR_CODE_KEY, errorCode);
f.setArguments(args);
return f;
}
@Override
@NonNull
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Get the error code and retrieve the appropriate dialog
int errorCode = getArguments().getInt(ERROR_CODE_KEY);
return GooglePlayServicesUtil.getErrorDialog(
errorCode, getActivity(), REQUEST_RESOLVE_ERROR);
}
@Override
public void onDismiss(DialogInterface dialog) {
Log.i(TAG, "Dialog dismissed");
}
}
}
here是官方指南提供的代码,而这是一个导致问题的片段。
@Override
public void onConnectionFailed(ConnectionResult result) {
if (mResolvingError) {
// Already attempting to resolve an error.
return;
} else if (result.hasResolution()) {
try {
mResolvingError = true;
result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);
} catch (IntentSender.SendIntentException e) {
// There was an error with the resolution intent. Try again.
mGoogleApiClient.connect();
}
} else {
// Show dialog using GooglePlayServicesUtil.getErrorDialog()
mResolvingError = true;
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(), this, REQUEST_RESOLVE_ERROR)
.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
mResolvingError = false;
}
});
}
}
如果我在服务中使用它,当您读取作为参数传递给这些函数的变量 this
时,它们需要一个 Activity 类型。
我应该怎么做?这是一项服务。
出于同样的原因,我无法获得 activity 结果
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_RESOLVE_ERROR) {
mResolvingError = false;
if (resultCode == RESULT_OK) {
// Make sure the app is not already connected or attempting to connect
if (!mGoogleApiClient.isConnecting() &&
!mGoogleApiClient.isConnected()) {
mGoogleApiClient.connect();
}
}
}
}
此答案假定您的服务是 "started" 服务。如果它是绑定服务或意图服务,请在评论中指出,我将更新此处包含的描述和代码。
我建议的解决方案是实施下面显示的 activity 来处理分辨率 UI。用此代码替换服务中的 onConnectionFailed()
方法,将解析处理交给 ResolverActivity
:
@Override
public void onConnectionFailed(ConnectionResult result) {
Intent i = new Intent(this, ResolverActivity.class);
i.putExtra(ResolverActivity.CONNECT_RESULT_KEY, result);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
将下面显示的 activity 添加到您的应用程序。当您的服务中的连接请求失败时,连接结果 Parcelable
将传递给 activity。 activity 处理解析 UI,完成后,returns 将服务状态作为 intent extra。您将需要修改服务 onStartCommand()
中的代码,以检查意图中的额外内容,以确定是否调用它来首次启动服务,或者从 ResolverActivity
接收解析状态.
此方法的增强功能是 post 为 ResolverActivity
发送带有 PendingIntent
的通知,而不是立即启动 activity。这将为用户提供延迟解决连接失败的选项。
public class ResolverActivity extends AppCompatActivity {
public static final String TAG = "ResolverActivity";
public static final String CONNECT_RESULT_KEY = "connectResult";
public static final String CONN_STATUS_KEY = "connectionStatus";
public static final int CONN_SUCCESS = 1;
public static final int CONN_FAILED = 2;
public static final int CONN_CANCELLED = 3;
// Request code to use when launching the resolution activity
private static final int REQUEST_RESOLVE_ERROR = 1111;
private static final String ERROR_CODE_KEY = "errorCode";
private static final String DIALOG_FRAG_TAG = "errorDialog";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "onCreate()");
// No content needed.
//setContentView(R.layout.activity_main);
Intent i = getIntent();
ConnectionResult result = i.getParcelableExtra(CONNECT_RESULT_KEY);
if (result.hasResolution()) {
try {
Log.i(TAG, "Starting error resolution...");
result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);
} catch (IntentSender.SendIntentException e) {
// There was an error with the resolution intent.
sendStatusToService(CONN_FAILED);
finish();
}
} else {
// Show dialog using GooglePlayServicesUtil.getErrorDialog()
ErrorDialogFragment.newInstance(result.getErrorCode())
.show(getSupportFragmentManager(), DIALOG_FRAG_TAG);
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent result) {
if (requestCode == REQUEST_RESOLVE_ERROR) {
if (resultCode == RESULT_OK) {
Log.i(TAG, "onActivityResult(): Connection problem resolved");
sendStatusToService(CONN_SUCCESS);
} else {
sendStatusToService(CONN_CANCELLED);
Log.w(TAG, "onActivityResult(): Resolution cancelled");
}
// Nothing more to do in this activity
finish();
}
}
private void sendStatusToService(int status) {
Intent i = new Intent(this, MyGoogleApiService.class);
i.putExtra(CONN_STATUS_KEY, status);
startService(i);
}
// Fragment to display an error dialog
public static class ErrorDialogFragment extends DialogFragment {
public static ErrorDialogFragment newInstance(int errorCode) {
ErrorDialogFragment f = new ErrorDialogFragment();
// Pass the error that should be displayed
Bundle args = new Bundle();
args.putInt(ERROR_CODE_KEY, errorCode);
f.setArguments(args);
return f;
}
@Override
@NonNull
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Get the error code and retrieve the appropriate dialog
int errorCode = getArguments().getInt(ERROR_CODE_KEY);
return GooglePlayServicesUtil.getErrorDialog(
errorCode, getActivity(), REQUEST_RESOLVE_ERROR);
}
@Override
public void onDismiss(DialogInterface dialog) {
Log.i(TAG, "Dialog dismissed");
}
}
}