如何将 Firebase 身份验证令牌传递给 webView 并在 Android 上注册通知

icu*_*ham 7 android android-webview firebase firebase-authentication firebase-cloud-messaging

我有一个 Firebase WebApp,它为用户提供信息。除了应用程序之外,我还需要通过 Firebase Cloud Messaging 向使用 Android 应用程序的用户发送推送通知。

目标:用户应该有一次登录应用程序的权限,该应用程序既可以注册他们的通知,又可以通过 WebView 加载 WebApp。

问题:我找不到一种方法可以通过单次登录来实现这一点。在每种情况下,我都需要为本机应用程序登录一次,然后通过 webView 再次登录。


首先,为其他可能正在解决问题的人提供一些参考:

Firebase 身份验证用户界面:https ://firebase.google.com/docs/auth/android/firebaseui

Firebase 数据库:https ://firebase.google.com/docs/database/android/read-and-write

Firebase 云消息传递:https ://firebase.google.com/docs/cloud-messaging/android/topic-messaging

背景:我能够使用 Firebase Auth UI 分别处理每个身份验证以本地处理通知身份验证,然后通过 firebase 服务器处理 webView 身份验证。这有效,但用户体验很差。由于本机身份验证已经提供了一个令牌,因此我应该能够跳过第二阶段并直接让用户登录。这是我尝试过的方法:


第一种方法:

本机登录,然后是 webapp 登录(工作但需要两次登录):按照 Firebase Auth UI 教程,我可以成功登录:

FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
Run Code Online (Sandbox Code Playgroud)

'user' 不为空,可用于从 firebase 数据库读取数据。然后使用主题 ID 订阅每个 FCM 文档的主题。

订阅通知后,我们然后使用以下行建立与 webapp 的连接:

myWebView.loadUrl("https://someproject.appspot.com/index.html");
Run Code Online (Sandbox Code Playgroud)

第二种方法:

使用 myWebView.loadUrl() 传递用户令牌(授权被拒绝)...基于此信息:https ://firebase.google.com/docs/cloud-messaging/auth-server

类似的东西,我希望:

...

FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();

  if (user != null) {

  //get the user id token

  user.getIdToken(true).addOnCompleteListener(new 
  OnCompleteListener<GetTokenResult>() {

    public void onComplete(@NonNull Task<GetTokenResult> task) {

      if (task.isSuccessful()) {

        //here is the idToken

        String idToken = task.getResult().getToken();

  }}}}

HashMap<String, String> map = new HashMap<String, String>();

String bearer = "Bearer " + idToken;

//Create header of the form "Authorization: Bearer <token>"

map.put("Authorization",bearer);

myWebView.loadUrl("https://someproject.appspot.com/index.html", map);

...
Run Code Online (Sandbox Code Playgroud)

*这似乎是最有可能的工作方式,也许我需要添加一些代码服务器端来显式处理请求而不是依赖 onStateChanged 处理程序?还尝试使用 ?auth= 和 ?access_token= 基于:https : //firebase.google.com/docs/database/rest/auth#authenticate_with_an_id_token 在这里在黑暗中进行拍摄......

第三种方法:

打开 webApp 并在授权完成时触发 onAuthStateChanged。(处理程序似乎永远不会触发。我怀疑没有 FirebaseAuth 对象受 webView 影响)

...
//Register a FirebaseAuth Listener

FirebaseAuth.AuthStateListener mAuthListener = new FirebaseAuth.AuthStateListener() {

  @Override

  public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {

    FirebaseUser user = firebaseAuth.getCurrentUser();

    if (user != null) {

      //Register notification subscriptions per tutorial

    }
...
Run Code Online (Sandbox Code Playgroud)

myWebView.loadUrl(" https://someproject.appspot.com/index.html ");


似乎这里有一个最佳实践,但在 firebase 教程中没有得到很好的记录。对于在 Android 上使用 firebase 的人来说,这似乎也是一项典型任务。有人可以提供一种注册通知主题并在一次登录中访问 webApp 的方法吗?我错过了什么?

预期的结果是进行一次登录,然后用户可以访问 Web 应用程序并注册个人推送通知。

Mar*_*ski 2

以下是 React Native 中使用 WebView 进行 Firebase Auth 的解决方案:

import React from 'react'
import WebView from 'react-native-webview'

export default function HomeScreen(props) {
  // props.user represents firebase user
  const apiKey = props.user.toJSON().apiKey
  const authJS = `
        if (!("indexedDB" in window)) {
          alert("This browser doesn't support IndexedDB")
        } else {
          let indexdb = window.indexedDB.open('firebaseLocalStorageDb', 1)
          indexdb.onsuccess = function() {
            let db = indexdb.result
            let transaction = db.transaction('firebaseLocalStorage', 'readwrite')
            let storage = transaction.objectStore('firebaseLocalStorage')
            const request = storage.put({
              fbase_key: "firebase:authUser:${apiKey}:[DEFAULT]",
              value: ${JSON.stringify(props.user.toJSON())}
            });
          }
        }  
      `
  return <WebView
    injectedJavaScriptBeforeContentLoaded={authJS}
    source={{
      uri: 'http://192.168.1.102:3000',
      baseUrl: 'http://192.168.1.102:3000',
    }}
  />
}
Run Code Online (Sandbox Code Playgroud)

Android 中可能需要类似的逻辑(JS 注入)。