- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试实现 Google 登录,以便使用电子钱包或付款,并向用户销售产品。我按照 the official guide 中的步骤操作我什至克隆了这个项目,它和我有同样的问题。问题是,当我尝试从 OptionalPendingResult
获取用户信息时,系统抛出一个 IllegalStateException
。
首先,用户必须通过使用以这种方式初始化的 GoogleApiClient
的 Activity:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_checkout);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Wallet.API, new Wallet.WalletOptions.Builder().build())
.build();
showProgressDialog();
itemInfo = getIntent().getParcelableExtra(Constants.EXTRA_ITEM_INFO);
}
之后,我在一个没有 GoogleApiClient
的 Activity 托管的 fragment 中显示了一个 com.google.android.gms.common.SignInButton
,我正在 fragment :
public class LoginFragment extends Fragment implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
public static final int REQUEST_CODE_PICK_ACCOUNT = 1000;
public static final int REQUEST_CODE_RESOLVE_ERR = 1005;
public static final int REQUEST_CODE_SIGN_IN = 1006;
private static final String TAG = "LoginFragment";
private static final String WALLET_SCOPE = "https://www.googleapis.com/auth/payments.make_payments";
private static final String WALLET_SANDBOX_SCOPE = "https://www.googleapis.com/auth/paymentssandbox.make_payments";
@Bind(R.id.sign_in_button)com.google.android.gms.common.SignInButton button;
private ProgressDialog mProgressDialog;
private GoogleApiClient mGoogleApiClient;
private int mLoginAction;
private String userEmail;
public static LoginFragment newInstance(int intentCode) {
LoginFragment fragment = new LoginFragment();
Bundle args = new Bundle();
args.putInt(LoginActivity.EXTRA_ACTION, intentCode);
fragment.setArguments(args);
return fragment;
}
public LoginFragment() {}
@Override public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
if (args != null) {
mLoginAction = args.getInt(LoginActivity.EXTRA_ACTION);
}
if(savedInstanceState != null) {
userEmail = savedInstanceState.getString("email");
}
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestProfile()
.requestScopes(new Scope(WALLET_SCOPE))
// .requestIdToken(getString(R.string.client_id_test))
.build();
mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
}
@Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View v = inflater.inflate(R.layout.fragment_login, container, false);
ButterKnife.bind(this, v);
button.setSize(SignInButton.SIZE_WIDE);
if(savedInstanceState != null && userEmail.isEmpty())
userEmail = savedInstanceState.getString("email");
button.setClickable(true);
return v;
}
@Override public void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
@Override public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("email", userEmail);
}
@Override public void onStop() {
super.onStop();
mGoogleApiClient.disconnect();
}
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_SIGN_IN:
logIn(data);
button.setClickable(true);
break;
case REQUEST_CODE_PICK_ACCOUNT:
if (resultCode == Activity.RESULT_OK) {
userEmail = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
getUsername();
} else if (resultCode == Activity.RESULT_CANCELED) {
showToast(getString(R.string.please_select_account));
}
default:
super.onActivityResult(requestCode, resultCode, data);
break;
}
}
@Override public void onDestroyView() {
super.onDestroyView();
ButterKnife.unbind(this);
mGoogleApiClient = null;
}
@OnClick(R.id.sign_in_button) public void onSignIn() {
if(button.isClickable()) {
button.setClickable(false);
Intent intent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(intent, REQUEST_CODE_SIGN_IN);
}
}
@Override public void onConnected(@Nullable Bundle bundle) {
if (mLoginAction == LoginActivity.Action.LOGOUT) {
logOut();
}
}
@Override public void onConnectionSuspended(int i) {}
@Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
Log.e(TAG, "onConnectionFailed, error code:" + connectionResult.getErrorCode());
switch (connectionResult.getErrorCode()) {
case ConnectionResult.SERVICE_DISABLED:
showToast(getString(R.string.error_gps_service_disabled));
break;
case ConnectionResult.SERVICE_INVALID:
showToast(getString(R.string.error_gps_service_invalid));
break;
case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED:
showToast(getString(R.string.error_gps_service_update));
break;
}
}
private void showToast(String message) {
Toast.makeText(getActivity(), "Failed: " + message, Toast.LENGTH_SHORT).show();
}
private void logIn(Intent data) {
OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
if (opr.isDone()) {
try {
GoogleSignInResult signInResult = opr.get();
GoogleSignInAccount gsa = signInResult.getSignInAccount();
Toast.makeText(getActivity(), getString(R.string.welcome_user, gsa.getDisplayName()),
Toast.LENGTH_LONG).show();
((MultaJustaApp) getActivity().getApplication()).login(gsa.getEmail(), gsa.getIdToken());
success = true;
} catch (IllegalStateException e) {
e.printStackTrace();
showToast(getString(R.string.error_sign_in));
}
} else {
showToast(getString(R.string.network_error));
}
if(success) {
getActivity().setResult(Activity.RESULT_OK);
getActivity().finish();
}
}
}
值得一提的是,在创建 opr 之后,当我在观察变量上检查它时,它有一个 Status{statusCode=INTERNAL_ERROR, resolution=null}
属性,当然还有 opr.get()
被调用 IllegalStateException
被抛出,因为 Result 已被消耗。我已经尝试了所有方法,在我的控制台中启用了 API, keystore 的校验和已启动,并且 apiClient 在请求时已连接。我在模拟器和物理设备上都遇到了问题。我很绝望。我真的很感激任何帮助。
谢谢
最佳答案
首先,你不应该得到 IllegalStateException 除非你在 isDone() 之前调用 opr.get() 或多次调用它(不管它是失败还是成功的结果): https://developers.google.com/android/reference/com/google/android/gms/common/api/OptionalPendingResult.html#get()您能否仔细检查您的代码/在此处粘贴您的确切代码?
其次,INTERNAL_ERROR 最常见的问题是缺少正确的 OAuth2 客户端注册。 (不幸的是,目前状态代码是 INTERNAL_ERROR 8,这没有帮助。)例如看看这个线程: Occured an INTERNAL_ERROR when requestEmail from GoogleSignInOptions Android .由于您已经添加了电子钱包范围,如果缺少 OAuth2 注册,您将在同意对话框中看到“未注册的 Android 应用程序”。 (我在最后附上了截图)
第三,使用 enableAutoManage 可以节省大量样板代码。请查看官方文档: https://developers.google.com/identity/sign-in/android/sign-in(例如,您的 onConnectionFailed 处理程序中的所有错误处理, connect()/disconnect() 都将被自动调用)。并且可以在您的 onActivityResult 中调用 Auth.GoogleSignInApi.silentSignIn()。但获得结果的更简单方法是:
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
关于java - OptionalPendingResult<GoogleSignInResult> 总是抛出 IllegalStateException,原因为 "Result has already been consumed",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35332835/
我正在尝试实现 Google 登录,以便使用电子钱包或付款,并向用户销售产品。我按照 the official guide 中的步骤操作我什至克隆了这个项目,它和我有同样的问题。问题是,当我尝试从 O
我是一名优秀的程序员,十分优秀!