17

をトリガではありません。アンドロイドGoogleAuthUtil.getTokenWithNotification意図コールバックは、私が<code>GoogleAuthUtl.getTokenWithNotification</code>を呼び出し、それが正常に動作しますが、私は、この関数のコールバック部分を実装しようとしていると、それが正常に動作していないバックグラウンドサービスを持っている

私は放送受信機を導入し、マニフェストにそれを追加しました、私はまた私のアプリで活性を有しています。以下に関連するコードを示します。

GoogleAuthUtil.getTokenWithNotification

GoogleAuthUtil.getTokenWithNotification(this.getContext(), account, "oauth2:" + GmailScopes.GMAIL_SEND, null, new Intent(AuthReceiver.AUTH_INTENT)); 

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

<receiver android:name=".AuthReceiver" android:enabled="true" android:exported="true"> 
    <intent-filter> 
     <action android:name="com.testoauth.AUTH_INTENT" /> 
    </intent-filter> 
</receiver> 

なぜ私は放送を受信して​​いないのか分からない。ログに例外が表示されず、レシーバーがまったく呼び出されていないという表示もありません。デバッグ時にブレークポイントを破ることさえありません。間違って何かしていますか?

私は分のSDK 16とターゲットSDK GoogleAuthUtil.getTokenWithNotification APIドキュメントから25

使用してい

EDIT:

この方法は、特にバックグラウンド・タスクのために設けられています。 ユーザー介入が必要なエラーのイベントでは、このメソッドは関連する通知をプッシュすることを に注意します。ユーザーが 通知を指定すると、コールバックがブロードキャストされます。ユーザーが をキャンセルした場合、コールバックは起動されません。

キャンセルするユーザーとは関係なく、コールバックは発生しません。通知が表示されたことを示すActivityManagerDisplayed com.google.android.gms/.auth.uiflows.gettoken.GetTokenActivity)を除いて、指定されたブロードキャストインテント(この場合はcom.testoauth.AUTH_INTENT)がログに送信されたことは示されません。 「受信したAuthブロードキャスト」。メッセージはログにも存在しません。

この機能の付属SDKの例(<android-sdk>/extras/google/google_play_services/samples/auth/gau)は機能しません。

+0

この問題の解決方法を見つけましたか?私は同じことを試みたが、それはまた私のために働いていない。 – Emanuel

+0

@Emanuel残念ながら、いいえ、私はしていません。 – vane

+0

'AuthReceiver.AUTH_INTENT =" com.testoauth.AUTH_INTENT ";'を確認するだけです。 *** /// ***おそらく無関係です:暗黙的なインテントを使用しないでください。各新しいプラットフォームのリリースには制限があります(現在はAndroid Oです)(https://developer.android.com/preview/features /background.html#broadcasts)、あなたのケースには暗黙のインテントはまったく必要ありません。 'new Intent(context、com.package.AuthReceiver.class)'を作成するだけです。 –

答えて

0

誰でもこの質問に適切な回答を与えることはできません。問題を回避する方法については絶対に素晴らしい提案がたくさんありますが、実際の質問には何も答えません。 AndroidやGoogle Playサービスのバグでなければならないという結論に至りました。申し訳ありませんが、この問題はAndroidの問題追跡ツールとGoogle Playサービスのサポートフォーラムの両方に報告されています...どちらも指を指していて、問題を見ることも拒否しています。

1

あなたがGoogleAuthUtil.getTokenやPlus.APIを使用して、過去にGoogleログイン中に統合する場合は、セキュリティを強化するために、最新のサインインAPIに移行する必要があり

GoogleAuthUtilとPlus.APIから移行優れたユーザーエクスペリエンスを提供します。
参考:https://developers.google.com/identity/sign-in/android/migration-guide

また、それは、私は、Android API 25で次のエラーを試してみましたが、コールバック関数だった

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

+0

私が前に試した2つの例で、どちらもうまくいきません。私はこれがGoogle Playサービスの実際のバグだと思っています。 Plus.APIについては、私が理解していることは、ユーザーがGoogleにログインし、自分のアカウントの特定の側面にアクセスできるようにしているのに対し、私は作成するだけのアプリですが、電子メールを送信し、 GoogleAuthUtilを使用すると、接続されたアプリと、ユーザーのGoogleアカウントにアクセスする必要があるものを表示できます。 – vane

1

に役立つかどうか、これをチェック決して呼び出されません:

  • ないインターネットユーザーはまだ
  • ログインしていない
  • ユーザーは、Googleがサービスを再生
  • 彼/彼女に代わって電子メールを送信する権限を与えられていないが、Googleがサービスを再生
  • 無効になって出ています日付の

コールバックメソッドの呼び出しは、あなたのユースケースのために重要ではない場合、あなたはまた、中にユーザーに代わって電子メールを送信するAndroid Quickstart for Gmail APIに従うことができます礼拝堂。メッセージを作成するにはSending Emailをチェックしてください。 上記のチュートリアルを使用して作成したMyGoogleAuthUtilApplicationを確認することもできます。

希望します。

+0

この方法の問題は、Gmail APIの例が、Androidで利用できないlibにあるMimeMessageに依存しているか、少なくともlibがAndroid用であるかどうかがあまり明確でないことです。 – vane

+0

はい、私はMimeMessageのライブラリを見つけることに問題がありました。最後に、 "https://mvnrepository.com/artifact/com.sun.mail/android-mail" < - このライブラリは私のために働いていました。私のGitHubプロジェクトをチェックすることができます。 – BhalchandraSW

+0

これをテストしたところ、電子メールを送信するのに最適な解決策ですが、私は移行する予定ですが、それでもコールバックの問題は解決しません。私がこれを使用する場合、私はまだ壊れたコールバックを持っているか、自分の通知を作成し、アンドロイド内蔵のものを使用しないでください。 – vane

1

私はdemoを実装しました。私は最新バージョンの認証とその動作を使用しています。認証バージョンに問題があるようです。

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("[email protected]")); 
        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(); 
    } 
} 
+0

これは私の問題を解決するものではありません。 'AccountManager.getAuthToken'はフォアグラウンド操作のみです。私は 'GoogleAuthUtil.getTokenWithNotification'を使用する必要があります。なぜなら、バックグラウンドでサービス内で行われているため、ステータスバーに通知を出し、getAuthTokenはそうでないからです。 – vane

+0

ああ、今はあまりにも遅い夜です。私は明日のサービスを確認します。しかし、私は1つの質問がある、あなたはそれを必要としないトークンを取得するために1回のみAccountManagerを使用する必要があります。あなたがUIからトークンを取るなら、それはあなたには良いことではありませんか?また、どのようにユーザーがアカウントを選択することができますか? –

+0

いいえ、バックグラウンドサービスでトークンをチェックする必要があります。これは、サービスが後で呼び出される前に、Googleアカウント設定からアプリの承認を削除した場合に通知をユーザーに表示できるようにするためです。それ以外の場合、トークンはもはや有効ではないため、トークンの使用に失敗します。 – vane

関連する問題