4

GCEエンドポイントのAndroidでFirebase認証ライブラリによって作成されたクライアントトークンを認証しようとしています。Google Cloud Endpointがエンドポイントで非同期コードを実行する

これを行う方法のガイドはhere

を見出すことができる基本的に私は、エンドポイント(即ち、サーバーバックエンドコードではないアンドロイドコード)から、このコードスニペットを呼び出す必要があります。

私はそのコードを実行し、アンドロイドクライアントコードにユーザーを戻したいとしましょう。私はどうしたらいいですか?

これは意味をなさない私のサンプルコードです。しかし、それは私がしたいことを示しています!

@ApiMethod(name = "serverAuth") 
public MyUser serverAuth(@Named("token") String token) { 
    FirebaseAuth.getInstance().verifyIdToken(token) 
      .addOnSuccessListener(new OnSuccessListener<FirebaseToken>() { 
       @Override 
       public void onSuccess(FirebaseToken decodedToken) { 
        String uid = decodedToken.getUid(); 
        String email = decodedToken.getEmail(); 
        String name = decodedToken.getName(); 
        Map<String, Object> claims = decodedToken.getClaims(); 

        String claimString = ""; 

        for (Object claim : claims.values()) { 
         claimString += claims.toString(); 
        } 

        MyUser user = new MyUser(uid, email, name, claimString); 
        //How to return this user? 

       } 
      }); 

    //This is compile error since user varriable does not exist here  
    return user; 

} 

GCEエンドポイントで非同期コードを実行する方法をGoogleで検索しました。しかし、それでどこにもいない。私が得意とするのは、実行されるまでブロックしてからユーザーを返すコード実行に関するものです。しかし、上記のような非同期コードがブロックされるようにコードする方法はありますか?

答えて

4

CountDownLatchは、必要なマジッククラスです。 OnSuccessListenerが実際に完了するまで待ちます。

は、あなたの方法この方法を適応:(私は重要なポイントに集中するために、MyUserとの創造につながるの手順を削除。)

@ApiMethod(name = "serverAuth") 
public MyUser serverAuth(@Named("token") String token) { 
    final List<MyUser> users = new ArrayList<>(); 
    final CountDownLatch cdl = new CountDownLatch(1); 
    FirebaseAuth.getInstance().verifyIdToken(token) 
      .addOnSuccessListener(new OnSuccessListener<FirebaseToken>() { 
       @Override 
       public void onSuccess(FirebaseToken decodedToken) { 
        // ... init uid, email, name and claimString 
        users.add(new MyUser(uid, email, name, claimString)); 
        cdl.countDown(); 
       } 
      }); 
    try { 
     cdl.await(); // This line blocks execution till count down latch is 0 
    } catch (InterruptedException ie) { 

    } 
    if (users.size() > 0) { 
     return users.get(0); 
    } else { 
     return null ; 
    } 
} 

これは、何が必要の基本的なバージョンです。私見、それは2点の以上の改善が必要です。

  • あなたはも考慮に失敗の可能性を取る必要があります。

    FirebaseAuth.getInstance().verifyIdToken(token) 
    .addOnSuccessListener(new OnSuccessListener<FirebaseToken>() { 
        @Override 
        public void onSuccess(FirebaseToken decodedToken) { 
         cdl.countDown(); 
        } 
    }).addOnFailureListener(new OnFailureListener() { 
        @Override 
        public void onFailure(@NonNull Exception e) { 
         // log error, ... 
         cdl.countDown(); 
        } 
    }); 
    
  • ます。また、リスナーのどれが呼び出されていないという可能性を取る必要があります。この状況では、あなたのメソッドは決して戻ってこないでしょう。

    try { 
        // This line blocks execution till count down latch is 0 
        // or after 30 seconds. 
        cdl.await(30l, TimeUnit.SECONDS); 
    } catch (InterruptedException ie) { 
    
    } 
    

それだ:それを回避するには、のawait()メソッドにタイムアウトを設定することができます。これが役立つことを願っています。

+0

ありがとうございます!できます。しかし、私はユーザー変数が最終的なエラーを取得し、設定することはできません。私はそれを回避するためにクラスプライベート変数を宣伝します。これは単なるテストコードなので、乱雑さは許されます。しかし、私はまだ最終変数としてユーザー変数を行うためのより良い方法について聞くことに興味があります。 –

+0

はい、あなたは正しいです - 最終変数の割り当ては禁止されています。十分にテストされていないサンプルをお手数です。しかし、私はクラス変数を使用することが最良の回避策ではないと思います。むしろ「コンテナ」または「ラッパー」を使用したいと思います。私の更新された答えを見てください。 – Benoit

関連する問題