android - com.google.android.gms.auth.UserRecoverableAuthException:NeedPermission
问题描述
在 Android 中使用 OAuth2.0 发送带有 GMail 的邮件,引发异常 com.google.android.gms.auth.UserRecoverableAuthException: Need Permission for business G-suit 帐户,并且可以正常使用普通 gmail 帐户
如下所示初始化 Google API 客户端。
GoogleAccountCredential mCredential;
String[] SCOPES = {
GmailScopes.GMAIL_LABELS,
GmailScopes.GMAIL_COMPOSE,
GmailScopes.GMAIL_INSERT,
GmailScopes.GMAIL_MODIFY,
GmailScopes.GMAIL_READONLY,
GmailScopes.MAIL_GOOGLE_COM
};
初始化凭证和服务对象。
mCredential = GoogleAccountCredential.usingOAuth2(
getApplicationContext(), Arrays.asList(SCOPES))
.setBackOff(new ExponentialBackOff());
// 使用 GMail OAuth 发送邮件的异步任务
private class MakeRequestTask extends AsyncTask {
private com.google.api.services.gmail.Gmail mService = null;
private Exception mLastError = null;
private View view = sendFabButton;
public MakeRequestTask(GoogleAccountCredential credential) {
HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
mService = new com.google.api.services.gmail.Gmail.Builder(
transport, jsonFactory, credential)
.setApplicationName(getResources().getString(R.string.app_name))
.build();
}
@Override
protected String doInBackground(Void... params) {
try {
return getDataFromApi();
} catch (Exception e) {
mLastError = e;
cancel(true);
return null;
}
}
private String getDataFromApi() throws IOException {
// getting Values for to Address, from Address, Subject and Body
String user = "me";
String to = Utils.getString(edtToAddress);
String from = mCredential.getSelectedAccountName();
String subject = Utils.getString(edtSubject);
String body = Utils.getString(edtMessage);
MimeMessage mimeMessage;
String response = "";
try {
mimeMessage = createEmail(to, from, subject, body);
response = sendMessage(mService, user, mimeMessage);
} catch (MessagingException e) {
e.printStackTrace();
}
return response;
}
// Method to send email
private String sendMessage(Gmail service,
String userId,
MimeMessage email)
throws MessagingException, IOException {
Message message = createMessageWithEmail(email);
// GMail's official method to send email with oauth2.0
message = service.users().messages().send(userId, message).execute();
System.out.println("Message id: " + message.getId());
System.out.println(message.toPrettyString());
return message.getId();
}
// Method to create email Params
private MimeMessage createEmail(String to,
String from,
String subject,
String bodyText) throws MessagingException {
Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
MimeMessage email = new MimeMessage(session);
InternetAddress tAddress = new InternetAddress(to);
InternetAddress fAddress = new InternetAddress(from);
email.setFrom(fAddress);
email.addRecipient(javax.mail.Message.RecipientType.TO, tAddress);
email.setSubject(subject);
// Create Multipart object and add MimeBodyPart objects to this object
Multipart multipart = new MimeMultipart();
// Changed for adding attachment and text
// This line is used for sending only text messages through mail
// email.setText(bodyText);
BodyPart textBody = new MimeBodyPart();
textBody.setText(bodyText);
multipart.addBodyPart(textBody);
if (!(activity.fileName.equals(""))) {
// Create new MimeBodyPart object and set DataHandler object to this object
MimeBodyPart attachmentBody = new MimeBodyPart();
String filename = activity.fileName; // change accordingly
DataSource source = new FileDataSource(filename);
attachmentBody.setDataHandler(new DataHandler(source));
attachmentBody.setFileName(filename);
multipart.addBodyPart(attachmentBody);
}
// Set the multipart object to the message object
email.setContent(multipart);
return email;
}
private Message createMessageWithEmail(MimeMessage email)
throws MessagingException, IOException {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
email.writeTo(bytes);
String encodedEmail = Base64.encodeBase64URLSafeString(bytes.toByteArray());
Message message = new Message();
message.setRaw(encodedEmail);
return message;
}
@Override
protected void onPreExecute() {
mProgress.show();
}
@Override
protected void onPostExecute(String output) {
mProgress.hide();
if (output == null || output.length() == 0) {
showMessage(view, "No results returned.");
} else {
showMessage(view, output);
}
}
@Override
protected void onCancelled() {
mProgress.hide();
if (mLastError != null) {
if (mLastError instanceof GooglePlayServicesAvailabilityIOException) {
showGooglePlayServicesAvailabilityErrorDialog(
((GooglePlayServicesAvailabilityIOException) mLastError)
.getConnectionStatusCode());
} else if (mLastError instanceof UserRecoverableAuthIOException) {
startActivityForResult(
((UserRecoverableAuthIOException) mLastError).getIntent(),
Utils.REQUEST_AUTHORIZATION);
} else {
showMessage(view, "The following error occurred:\n" + mLastError.getMessage());
Log.v("Error", mLastError.getMessage());
}
} else {
showMessage(view, "Request Cancelled.");
}
}
}
如果是商业帐户,它正在转移到 oncancelled() 方法并抛出
com.google.android.gms.auth.UserRecoverableAuthException:NeedPermission
解决方案
您的身份验证令牌已过期,您需要再次向 Google 进行身份验证。捕获 UserRecoverableAuthException 并在 Exception 对象上调用 getIntent 以获取身份验证 Intent。然后再次启动 Activity 进行身份验证。参考
try {
// Your code
...
} catch (UserRecoverableAuthIOException e) {
startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
}
推荐阅读
- python - 如何查找和附加列表中存在的字典值
- winapi - FlashWindow之后,点击窗口,任务栏保持高亮(橙色)
- spring-bean - Mule 4 中的 Groovy 类
- node.js - 在节点js中获取foreach循环之外的数组元素
- javascript - 如何在不重新加载页面的情况下将服务器端重定向到其他页面并且仍然将 URL 保留在 Nextjs 应用程序中?
- react-native - 尝试在 React-Native 中创建多项选择时出错
- python - ndarray 按索引从另一个数组中的条件删除行
- c# - 在 C# 中将大文本从胡言乱语转换为希伯来语
- typescript - 如何在 TypeScript 中正确使用扩展实例?
- python - Python 等到 os.system 结束