Android: How to resolve Google API connection fail

2019-04-06 07:59发布

here is the code provided by the official guide, while this is a snippet causing problems.

@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;
                    }
                });
    }
}

If I use it in a Service, when you read the variable this passed as argument to those functions, they expect an Activity type. How should I do? It's a Service.

For the same reason I can't get activity result

@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();
        }
    }
}
}

1条回答
Animai°情兽
2楼-- · 2019-04-06 08:51

This answer assumes your service is a "started" service. If it is a bound service or intent service, indicate that in a comment and I'll update the description and code included here.

The solution I suggest is to implement the activity shown below to handle the resolution UI. Replace the onConnectionFailed() method in your service with this code to hand off the resolution processing to the 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);
}

Add the activity shown below to your app. When the connection request in your service fails, the connection result, which is a Parcelable, is passed to the activity. The activity handles the resolution UI and when finished, returns the status to the service as an intent extra. You will need to modify the code in your service's onStartCommand() to examine the extras in the intent to determine if it is being called to start the service for the first time, or to receive resolution status from the ResolverActivity.

An enhancement to this approach would be to post a notification with a PendingIntent for ResolverActivity instead of launching the activity immediately. That would give the user the option of deferring resolution of the connection failure.

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");
        }
    }
}
查看更多
登录 后发表回答