I have a background service that calls GoogleAuthUtl.getTokenWithNotification
and it works properly but I'm trying to implement the callback portion of this function and that isn't working properly.
我有一个后台服务调用GoogleAuthUtl.getTokenWithNotification并且它正常工作,但我正在尝试实现此功能的回调部分,但是无法正常工作。
I've implemented a broadcast receiver and added it to the manifest, I also have an activity in my app. Below are the relevant pieces of code.
我已经实现了一个广播接收器并将其添加到清单中,我的应用程序中也有一个活动。以下是相关的代码段。
GoogleAuthUtil.getTokenWithNotification
GoogleAuthUtil.getTokenWithNotification
GoogleAuthUtil.getTokenWithNotification(this.getContext(), account, "oauth2:" + GmailScopes.GMAIL_SEND, null, new Intent(AuthReceiver.AUTH_INTENT));
AuthReceiver
AuthReceiver
public class AuthReceiver extends BroadcastReceiver
{
public final static String AUTH_INTENT = "com.testoauth.AUTH_INTENT";
public AuthReceiver()
{
}
@Override
public void onReceive(Context context, Intent intent)
{
Log.d("RECEIVER", "Received Auth broadcast.");
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancelAll();
}
}
AndroidManifest
AndroidManifest
<receiver android:name=".AuthReceiver" android:enabled="true" android:exported="true">
<intent-filter>
<action android:name="com.testoauth.AUTH_INTENT" />
</intent-filter>
</receiver>
I have no clue why it is not receiving the broadcast. I don't see any exceptions in the logs and no indication that the receiver was called at all, it won't even break on a breakpoint when debugging. Am I doing something incorrectly?
我不知道为什么它没有收到广播。我没有在日志中看到任何异常,也没有指示接收器被调用,在调试时它甚至不会在断点处中断。我做错了什么吗?
EDIT
编辑
I'm using min sdk 16 and target sdk 25
我正在使用min sdk 16和目标sdk 25
From the GoogleAuthUtil.getTokenWithNotification API documentation:
来自GoogleAuthUtil.getTokenWithNotification API文档:
This method is specifically provided for background tasks. In the event of an error that needs user intervention, this method takes care of pushing relevant notification. After the user addresses the notification, the callback is broadcasted. If the user cancels then the callback is not fired.
此方法专门用于后台任务。如果出现需要用户干预的错误,此方法将负责推送相关通知。在用户解决通知之后,广播回调。如果用户取消,则不会触发回调。
The callback is not fired regardless of the user canceling or not. Aside from the ActivityManager
saying the notification has been displayed (Displayed com.google.android.gms/.auth.uiflows.gettoken.GetTokenActivity
), there is no indication that the specified broadcast intent (in this case com.testoauth.AUTH_INTENT
) has been sent in the logs. The "Received Auth broadcast." message is also absent from the logs.
无论用户是否取消,都不会触发回调。除了ActivityManager说已显示通知(显示com.google.android.gms / .auth.uiflows.gettoken.GetTokenActivity),没有迹象表明指定的广播意图(在本例中为com.testoauth.AUTH_INTENT)已经在日志中发送。 “收到的Auth广播”。日志中也没有消息。
The included SDK example of this functionality (<android-sdk>/extras/google/google_play_services/samples/auth/gau
) doesn't even work.
此功能包含的SDK示例(
4 个解决方案
#1
1
Migrate from GoogleAuthUtil and Plus.API
从GoogleAuthUtil和Plus.API迁移
If you integrated with Google Sign-In in the past using GoogleAuthUtil.getToken or Plus.API, you should migrate to the newest Sign-In API for greater security and a better user experience.
Ref: https://developers.google.com/identity/sign-in/android/migration-guide
Also check this out whether it helps
如果您过去使用GoogleAuthUtil.getToken或Plus.API与Google登录集成,则应迁移到最新的登录API,以获得更高的安全性和更好的用户体验。参考:https://developers.google.com/identity/sign-in/android/migration-guide同时查看这是否有帮助
http://www.programcreek.com/java-api-examples/index.php?source_dir=AndroidAppDeployer-master/AndroidAppDeployer/src/com/appjma/appdeployer/service/DownloadService.java
http://www.programcreek.com/java-api-examples/index.php?source_dir=AndroidAppDeployer-master/AndroidAppDeployer/src/com/appjma/appdeployer/receiver/AuthReceiver.java
#2
1
I tried following errors on Android API 25, but the callback function was never invoked:
我尝试在Android API 25上跟踪错误,但从未调用回调函数:
- No Internet
- 没有互联网
- The user has not logged in yet
- 用户尚未登录
- The user has not given permission to send emails on his/her behalf
- 用户未授权代表他/她发送电子邮件
- Google Play Services is disabled
- Google Play服务已停用
- Google Play Services is out of date
- Google Play服务已过期
If the callback method invocation is not crucial for your use case, you can follow Android Quickstart for Gmail API to send emails on user's behalf in Android. Check Sending Email to create Message. You can also check MyGoogleAuthUtilApplication created using the above tutorials.
如果回调方法调用对您的用例并不重要,您可以按照Android Quickstart for Gmail API在Android中代表用户发送电子邮件。选中发送电子邮件以创建消息。您还可以查看使用上述教程创建的MyGoogleAuthUtilApplication。
Hope this helps.
希望这可以帮助。
#3
1
I have implemented demo i have used latest version auth gradle and its working. Its looks like there might be problem with auth version
我已经实现了演示,我使用了最新版本的auth gradle及其工作原理。它看起来可能与auth版本有问题
public class AuthActivity extends Activity {
private static final int AUTHORIZATION_CODE = 1993;
private static final int ACCOUNT_CODE = 1601;
private AuthPreferences authPreferences;
private AccountManager accountManager;
/**
* change this depending on the scope needed for the things you do in
* doCoolAuthenticatedStuff()
*/
private final String SCOPE = "https://www.googleapis.com/auth/googletalk";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
accountManager = AccountManager.get(this);
authPreferences = new AuthPreferences(this);
if (authPreferences.getUser() != null
&& authPreferences.getToken() != null) {
doCoolAuthenticatedStuff();
} else {
chooseAccount();
}
}
private void doCoolAuthenticatedStuff() {
// TODO: insert cool stuff with authPreferences.getToken()
Log.e("AuthApp", authPreferences.getToken());
clickSendEmail();
}
private void chooseAccount() {
// use https://github.com/frakbot/Android-AccountChooser for
// compatibility with older devices
Intent intent = AccountManager.newChooseAccountIntent(null, null,
new String[] { "com.google" }, false, null, null, null, null);
startActivityForResult(intent, ACCOUNT_CODE);
}
private void requestToken() {
Account userAccount = null;
String user = authPreferences.getUser();
for (Account account : accountManager.getAccountsByType("com.google")) {
if (account.name.equals(user)) {
userAccount = account;
Preferences.setAccount(AuthActivity.this,account.name, account.type);
break;
}
}
accountManager.getAuthToken(userAccount, "oauth2:" + SCOPE, null, this,
new OnTokenAcquired(), null);
}
/**
* call this method if your token expired, or you want to request a new
* token for whatever reason. call requestToken() again afterwards in order
* to get a new token.
*/
private void invalidateToken() {
AccountManager accountManager = AccountManager.get(this);
accountManager.invalidateAuthToken("com.google",
authPreferences.getToken());
authPreferences.setToken(null);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == AUTHORIZATION_CODE) {
requestToken();
} else if (requestCode == ACCOUNT_CODE) {
String accountName = data
.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
authPreferences.setUser(accountName);
// invalidate old tokens which might be cached. we want a fresh
// one, which is guaranteed to work
invalidateToken();
requestToken();
}
}
}
private class OnTokenAcquired implements AccountManagerCallback<Bundle> {
@Override
public void run(AccountManagerFuture<Bundle> result) {
try {
Bundle bundle = result.getResult();
Intent launch = (Intent) bundle.get(AccountManager.KEY_INTENT);
if (launch != null) {
startActivityForResult(launch, AUTHORIZATION_CODE);
} else {
String token = bundle
.getString(AccountManager.KEY_AUTHTOKEN);
authPreferences.setToken(token);
doCoolAuthenticatedStuff();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
private void clickSendEmail()
{
final Account account = Preferences.getAccount(this);
final String token = Preferences.getToken(this);
new Thread(new Runnable()
{
@Override
public void run()
{
try
{
Session session = Session.getDefaultInstance(new Properties(), null);
MimeMessage email = new MimeMessage(session);
email.setFrom(new InternetAddress(account.name));
//TODO: change email address to your email address for testing
email.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress("nasitraj2@gmail.com"));
email.setSubject("TEST OAUTH EMAIL");
email.setText("This is a test");
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
email.writeTo(bytes);
String encodedEmail = Base64.encodeBase64URLSafeString(bytes.toByteArray());
Message message = new Message();
message.setRaw(encodedEmail);
Intent intent = new Intent(AUTH_INTENT);
PendingIntent pendingIntent = PendingIntent.getBroadcast(AuthActivity.this, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
, pendingIntent);
String test = GoogleAuthUtil.getTokenWithNotification(AuthActivity.this, account, "oauth2:" + GmailScopes.GMAIL_SEND, null, intent);
GoogleCredential credential = new GoogleCredential();
credential.setAccessToken(test);
boolean changed = false;
if (!test.equals(token))
{
changed = true;
// Snackbar.make(AuthActivity.this.getView(), "TOKEN CHANGED", Snackbar.LENGTH_LONG).show();
Preferences.setToken(AuthActivity.this, test);
}
Gmail service = new Gmail.Builder(AndroidHttp.newCompatibleTransport(),
AndroidJsonFactory.getDefaultInstance(), credential)
.setApplicationName("Test OAuth").build();
service.users().messages().send("me", message).execute();
String msg = "Email sent";
if (changed)
msg = "TOKEN CHANGED: " + msg;
}
catch (MessagingException e)
{
Log.d( "ERROR", e.getMessage());
}
catch (GoogleJsonResponseException e)
{
if (e.getDetails().getCode() == 401)
{
try
{
Intent intent = new Intent(AUTH_INTENT);
GoogleAuthUtil.clearToken(AuthActivity.this, Preferences.getToken(AuthActivity.this));
GoogleAuthUtil.getTokenWithNotification(AuthActivity.this, account, "oauth2:" + GmailScopes.GMAIL_SEND, null, intent);
}
catch (Exception e1)
{
//ignore
}
}
}
catch (IOException e)
{
// Snackbar.make(AuthActivity.this.getView(), "ERROR", Snackbar.LENGTH_LONG).show();
Log.d( "ERROR", e.getMessage());
}
catch (Exception e)
{
//Snackbar.make(AuthActivity.this.getView(), "ERROR", Snackbar.LENGTH_LONG).show();
Log.d( "ERROR", e.getMessage());
}
}
}).start();
}
}
#4
0
It doesn't appear that anyone can give a proper answer to this question; plenty of absolutely great suggestions on how to work around the issue but nothing answering the actual question. I've come to the conclusion that this must be a bug in either Android or the Google Play Services. Unfortunately I've reported this issue to both the Android issue tracker and the Google Play Services support forum... Both of which point the finger at each other and refuse to even look at the issue.
似乎任何人都无法对这个问题给出正确的答案;关于如何解决这个问题的大量绝对好的建议,但没有回答实际的问题。我得出结论,这必定是Android或Google Play服务中的错误。不幸的是,我已经向Android问题跟踪器和Google Play服务支持论坛报告了这个问题......两者都指向对方,甚至拒绝查看问题。
#1
1
Migrate from GoogleAuthUtil and Plus.API
从GoogleAuthUtil和Plus.API迁移
If you integrated with Google Sign-In in the past using GoogleAuthUtil.getToken or Plus.API, you should migrate to the newest Sign-In API for greater security and a better user experience.
Ref: https://developers.google.com/identity/sign-in/android/migration-guide
Also check this out whether it helps
如果您过去使用GoogleAuthUtil.getToken或Plus.API与Google登录集成,则应迁移到最新的登录API,以获得更高的安全性和更好的用户体验。参考:https://developers.google.com/identity/sign-in/android/migration-guide同时查看这是否有帮助
http://www.programcreek.com/java-api-examples/index.php?source_dir=AndroidAppDeployer-master/AndroidAppDeployer/src/com/appjma/appdeployer/service/DownloadService.java
http://www.programcreek.com/java-api-examples/index.php?source_dir=AndroidAppDeployer-master/AndroidAppDeployer/src/com/appjma/appdeployer/receiver/AuthReceiver.java
#2
1
I tried following errors on Android API 25, but the callback function was never invoked:
我尝试在Android API 25上跟踪错误,但从未调用回调函数:
- No Internet
- 没有互联网
- The user has not logged in yet
- 用户尚未登录
- The user has not given permission to send emails on his/her behalf
- 用户未授权代表他/她发送电子邮件
- Google Play Services is disabled
- Google Play服务已停用
- Google Play Services is out of date
- Google Play服务已过期
If the callback method invocation is not crucial for your use case, you can follow Android Quickstart for Gmail API to send emails on user's behalf in Android. Check Sending Email to create Message. You can also check MyGoogleAuthUtilApplication created using the above tutorials.
如果回调方法调用对您的用例并不重要,您可以按照Android Quickstart for Gmail API在Android中代表用户发送电子邮件。选中发送电子邮件以创建消息。您还可以查看使用上述教程创建的MyGoogleAuthUtilApplication。
Hope this helps.
希望这可以帮助。
#3
1
I have implemented demo i have used latest version auth gradle and its working. Its looks like there might be problem with auth version
我已经实现了演示,我使用了最新版本的auth gradle及其工作原理。它看起来可能与auth版本有问题
public class AuthActivity extends Activity {
private static final int AUTHORIZATION_CODE = 1993;
private static final int ACCOUNT_CODE = 1601;
private AuthPreferences authPreferences;
private AccountManager accountManager;
/**
* change this depending on the scope needed for the things you do in
* doCoolAuthenticatedStuff()
*/
private final String SCOPE = "https://www.googleapis.com/auth/googletalk";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
accountManager = AccountManager.get(this);
authPreferences = new AuthPreferences(this);
if (authPreferences.getUser() != null
&& authPreferences.getToken() != null) {
doCoolAuthenticatedStuff();
} else {
chooseAccount();
}
}
private void doCoolAuthenticatedStuff() {
// TODO: insert cool stuff with authPreferences.getToken()
Log.e("AuthApp", authPreferences.getToken());
clickSendEmail();
}
private void chooseAccount() {
// use https://github.com/frakbot/Android-AccountChooser for
// compatibility with older devices
Intent intent = AccountManager.newChooseAccountIntent(null, null,
new String[] { "com.google" }, false, null, null, null, null);
startActivityForResult(intent, ACCOUNT_CODE);
}
private void requestToken() {
Account userAccount = null;
String user = authPreferences.getUser();
for (Account account : accountManager.getAccountsByType("com.google")) {
if (account.name.equals(user)) {
userAccount = account;
Preferences.setAccount(AuthActivity.this,account.name, account.type);
break;
}
}
accountManager.getAuthToken(userAccount, "oauth2:" + SCOPE, null, this,
new OnTokenAcquired(), null);
}
/**
* call this method if your token expired, or you want to request a new
* token for whatever reason. call requestToken() again afterwards in order
* to get a new token.
*/
private void invalidateToken() {
AccountManager accountManager = AccountManager.get(this);
accountManager.invalidateAuthToken("com.google",
authPreferences.getToken());
authPreferences.setToken(null);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == AUTHORIZATION_CODE) {
requestToken();
} else if (requestCode == ACCOUNT_CODE) {
String accountName = data
.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
authPreferences.setUser(accountName);
// invalidate old tokens which might be cached. we want a fresh
// one, which is guaranteed to work
invalidateToken();
requestToken();
}
}
}
private class OnTokenAcquired implements AccountManagerCallback<Bundle> {
@Override
public void run(AccountManagerFuture<Bundle> result) {
try {
Bundle bundle = result.getResult();
Intent launch = (Intent) bundle.get(AccountManager.KEY_INTENT);
if (launch != null) {
startActivityForResult(launch, AUTHORIZATION_CODE);
} else {
String token = bundle
.getString(AccountManager.KEY_AUTHTOKEN);
authPreferences.setToken(token);
doCoolAuthenticatedStuff();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
private void clickSendEmail()
{
final Account account = Preferences.getAccount(this);
final String token = Preferences.getToken(this);
new Thread(new Runnable()
{
@Override
public void run()
{
try
{
Session session = Session.getDefaultInstance(new Properties(), null);
MimeMessage email = new MimeMessage(session);
email.setFrom(new InternetAddress(account.name));
//TODO: change email address to your email address for testing
email.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress("nasitraj2@gmail.com"));
email.setSubject("TEST OAUTH EMAIL");
email.setText("This is a test");
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
email.writeTo(bytes);
String encodedEmail = Base64.encodeBase64URLSafeString(bytes.toByteArray());
Message message = new Message();
message.setRaw(encodedEmail);
Intent intent = new Intent(AUTH_INTENT);
PendingIntent pendingIntent = PendingIntent.getBroadcast(AuthActivity.this, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
, pendingIntent);
String test = GoogleAuthUtil.getTokenWithNotification(AuthActivity.this, account, "oauth2:" + GmailScopes.GMAIL_SEND, null, intent);
GoogleCredential credential = new GoogleCredential();
credential.setAccessToken(test);
boolean changed = false;
if (!test.equals(token))
{
changed = true;
// Snackbar.make(AuthActivity.this.getView(), "TOKEN CHANGED", Snackbar.LENGTH_LONG).show();
Preferences.setToken(AuthActivity.this, test);
}
Gmail service = new Gmail.Builder(AndroidHttp.newCompatibleTransport(),
AndroidJsonFactory.getDefaultInstance(), credential)
.setApplicationName("Test OAuth").build();
service.users().messages().send("me", message).execute();
String msg = "Email sent";
if (changed)
msg = "TOKEN CHANGED: " + msg;
}
catch (MessagingException e)
{
Log.d( "ERROR", e.getMessage());
}
catch (GoogleJsonResponseException e)
{
if (e.getDetails().getCode() == 401)
{
try
{
Intent intent = new Intent(AUTH_INTENT);
GoogleAuthUtil.clearToken(AuthActivity.this, Preferences.getToken(AuthActivity.this));
GoogleAuthUtil.getTokenWithNotification(AuthActivity.this, account, "oauth2:" + GmailScopes.GMAIL_SEND, null, intent);
}
catch (Exception e1)
{
//ignore
}
}
}
catch (IOException e)
{
// Snackbar.make(AuthActivity.this.getView(), "ERROR", Snackbar.LENGTH_LONG).show();
Log.d( "ERROR", e.getMessage());
}
catch (Exception e)
{
//Snackbar.make(AuthActivity.this.getView(), "ERROR", Snackbar.LENGTH_LONG).show();
Log.d( "ERROR", e.getMessage());
}
}
}).start();
}
}
#4
0
It doesn't appear that anyone can give a proper answer to this question; plenty of absolutely great suggestions on how to work around the issue but nothing answering the actual question. I've come to the conclusion that this must be a bug in either Android or the Google Play Services. Unfortunately I've reported this issue to both the Android issue tracker and the Google Play Services support forum... Both of which point the finger at each other and refuse to even look at the issue.
似乎任何人都无法对这个问题给出正确的答案;关于如何解决这个问题的大量绝对好的建议,但没有回答实际的问题。我得出结论,这必定是Android或Google Play服务中的错误。不幸的是,我已经向Android问题跟踪器和Google Play服务支持论坛报告了这个问题......两者都指向对方,甚至拒绝查看问题。