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