3

我真的希望有人能帮助我。

我在我的 android 应用程序中设置了 Firebase,它显示了我使用 CakePHP 3 构建的网站的 webView。当我手动将设备令牌添加到数据库时,Firebase 通知确实有效,但我发现很难理解的是如何登录后我得到了注册令牌,所以我可以将它与 user_id 合并并将它们保存到数据库中。

更新

我现在拥有的代码能够将令牌发送到我的 PHP 服务器。如果我将令牌直接存储到数据库中它可以正常工作,但我需要在他们登录时将令牌与 user_id 合并,所以我需要将令牌存储在会话中(例如,请参见下面的 PHP 代码)但是当我尝试使用$session->read('device_id')它时是空的。

我认为这可能与我的 MainActivity webView 在加载 onCreate() 方法时删除当前的 PHP 会话有关,但我不确定。

这是在 PHP 中设置会话令牌的代码。

StoreTokenToSession (PHP)

public function index()
{
    $session = $this->request->session();

    if(isset($_GET['device_id']))
    {
        // Store in session until login
        $session->write('device_id', $_GET['device_id']);
    }
}

MainActivity.java

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);
    webView = (WebView) findViewById(R.id.activity_main_webview);

    webSettings = webView.getSettings();
    webSettings.setJavaScriptEnabled(true);

    FirebaseMessaging.getInstance().subscribeToTopic("notifications");
    FirebaseInstanceId.getInstance().getToken();

    if (Build.VERSION.SDK_INT >= 19) {
        webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);

    }
    else if(Build.VERSION.SDK_INT >=11 && Build.VERSION.SDK_INT < 19) {
        webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }

    CookieManager cookieManager = CookieManager.getInstance(); if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
    {
        cookieManager.setAcceptThirdPartyCookies(webView,true);
    }
    else
    {
        cookieManager.setAcceptCookie(true);
    }

    webView.loadUrl("example.com");
}

MyFirebaseInstanceIDService.java

public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {

    private static final String TAG = "MyFirebaseIIDService";

    @Override
    public void onTokenRefresh() {

        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.d(TAG, "Refreshed token: " + refreshedToken);

        sendRegistrationToServer(refreshedToken);
    }

    private void sendRegistrationToServer(String token) {

        OkHttpClient client = new OkHttpClient();

        Request request = new Request.Builder()
            .url("example.com?device_id="+token)
            .build();

        try {
            Response response = client.newCall(request).execute();
            Log.d(TAG, String.valueOf(response));

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
4

3 回答 3

1

可能为时已晚,也可能不是最好的方法,但我们的解决方案是在调用 webview 时将令牌作为 base64 沿 URL 传递,然后将其存储在会话中......登录后,我们将会话中的令牌保存给登录的用户。

像这样的东西:

String kDeviceToken = "https://hostname.com?deviceToken=%s";
String token = SessionManager.getInstance(getApplicationContext()).getFirebaseToken();
byte[] data = token.getBytes("UTF-8");
String base64 = Base64.encodeToString(data, Base64.DEFAULT);
String url = String.format(kDeviceToken, base64);
webView.loadUrl(url);
于 2017-12-01T14:58:56.657 回答
0

您需要将用户名存储在服务可以找到的位置。假设您正在使用身份验证状态侦听器(此代码通常位于您注册用户的活动中的某处):

FirebaseAuth
    .getInstance()
    .addAuthStateListener(new FirebaseAuth.AuthStateListener() {
        public void onAuthStateChanged(FirebaseAuth firebaseAuth) {
            setCurrentUser(firebaseAuth.getCurrentUser().getUid());
            PreferenceManager
            .getDefaultSharedPreferences(this)
            .edit()
            .putString("uid", mUsername)
            .commit();
        }
    });

这会将 uid 存储在共享首选项中,这些首选项在您的应用程序的任何位置都可用。这意味着在您的服务中,您可以检索 uid:

private void sendRegistrationToServer(String token) {
    String uid = PreferenceManager.getDefaultSharedPreferences(this).getString("uid", null);

    OkHttpClient client = new OkHttpClient();

    Request request = new Request.Builder()
        .url("example.com?device_id="+token+"&uid="+uid)
        .build();

    try {
        Response response = client.newCall(request).execute();
        Log.d(TAG, String.valueOf(response));

    } catch (IOException e) {
        e.printStackTrace();
    }
}

所以我们读取 uid,获取令牌并将它们都发送到服务器。

这里有一个潜在的竞争条件:如果第一个令牌在用户登录之前进入,sendRegistrationToServer则还没有 uid。我将把这部分作为练习留给读者,因为它实际上只是为第二个流程调用相同的代码。

于 2016-06-17T04:07:11.730 回答
-1

我知道可能为时已晚,但我正在寻找这个问题,我最终找到了一个可能有用的解决方案。

您可以在请求的 url 中将令牌作为 post 发送,然后在 php 中捕获此 post 参数并将其放入会话中,这样当您成功登录时,您可以使用用户 ID 将此会话值发送到数据库,这也将给出您可以使令牌与活动帐户连接,这意味着如果用户注销并使用新帐户登录,令牌将连接到新用户 ID,但您必须确保发送的令牌未与其他用户连接,并且如果它已连接您必须将此用户 ID 更改为新用户 ID

于 2018-12-09T21:29:32.887 回答