Я действительно надеюсь, что кто-то может мне помочь.
У меня есть Firebase, установленный в моем приложении для Android, которое отображает веб-представление моего веб-сайта, созданного с помощью CakePHP 3. Уведомления Firebase работают, когда я вручную добавляю токен устройства в базу данных, но мне трудно понять, как я получаю регистрационный токен после входа в систему, так что я могу объединить его с user_id и сохранить их в базе данных.
ОБНОВИТЬ
Код, который у меня есть, теперь может отправить токен на мой PHP-сервер. Если я храню токен прямо в базе данных, он работает нормально, но мне нужно объединить токен с user_id при входе в систему, поэтому мне нужно сохранить токен в сеансе (см. Код PHP ниже), но когда я пытаюсь использовать $session->read('device_id')
это пусто.
Я думаю, что это может иметь какое-то отношение к моему MainActivity webView, удаляющему текущий сеанс PHP, когда он загружает метод onCreate (), но я не уверен.
Вот код для установки токена сессии в 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();
}
}
}
Возможно, слишком поздно, чтобы помочь вам в этом, а также, вероятно, не самый лучший способ сделать это, но наше решение для этого было передать токен вдоль URL-адреса как base64 при вызове веб-просмотра, а затем сохранить его в сеансе … как только логин был выполнен, мы сохранили токен в сеансе зарегистрированному пользователю.
Что-то вроде этого:
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);
Вам нужно будет хранить имя пользователя в месте, где служба может его найти. Допустим, вы используете прослушиватель состояния авторизации (этот код обычно будет где-то в активности, где вы регистрируете пользователя):
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. Я оставлю эту часть в качестве упражнения для читателя, так как она на самом деле просто вызывает тот же код для этого второго потока.
Я знаю, что может быть так поздно, но я искал эту проблему, и в конце концов я нашел решение, которое может быть полезным.
вы можете отправить свой токен как сообщение в URL-адресе, который вы запрашиваете, а затем в своем php вы перехватываете этот параметр записи и помещаете его в сеанс, чтобы при успешном входе в систему вы могли отправить это значение сеанса в базу данных с идентификатором пользователя, что также даст Вы можете связать токен с активной учетной записью, что означает, что если пользователь выйдет и войдет с новой учетной записью, токен будет связан с новым идентификатором пользователя, но вы должны убедиться, что отправленный токен не связан с другим пользователем, и если он подключен Вы должны изменить этот идентификатор пользователя на новый