Android Firebase Service未获得SharedPreferences值

问题描述 投票:0回答:2

我在我的片段(Kotlin)上设置sharedPreferences值,然后我想在我的FirebaseMessagingService(Java)上使用这个值。当我设置值并销毁应用程序并再次打开时,我的片段没有任何问题。我可以看到设定值。所以我确信我的片段更新了sharedPreferences值。但是当我尝试在FirebaseMessagingService上使用该值时,我总是得到默认值。

在这里我如何设置kotlin类:

sharedPref = activity?.getSharedPreferences("com.xxx.xxx.xxx",Context.MODE_PRIVATE)!!

private fun sharedPrefWrite(boolean: Boolean){
    with (sharedPref?.edit()) {
        this!!.putBoolean("notf", boolean)
        apply()
    }
}

这很好用。

以下是我在FirebaseMessagingService上获取此数据的方法:

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
    preferences = getApplicationContext().getSharedPreferences("com.xxx.xxx.xxx",Context.MODE_PRIVATE);
    if(preferences.getBoolean("notf",true))
    sendNotification(remoteMessage.getNotification().getBody());
}

并始终服务发送通知。

我没有在我的活动上启动这项服务,它只在Manifest.xml上的Application标签之下;

     <service android:name="com.xxx.xxx.xxx.newsFirebaseMessagingService">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>

关于为何我无法获得这个价值的任何建议?谢谢

编辑:

我刚做了几次调试,当应用程序恢复时(在前台),firebase服务正确获取值。但是如果应用程序在后台(onPause)或应用程序被破坏,服务无法从SharedPreferences获取正确的数据。

编辑2

我从FirebaseMessagingService中删除了onMessageReceived函数,并将该应用程序重新安装到我的设备上,当应用程序被销毁时,我收到通知,即使没有'onMessageReceived'...

最后的编辑

解决方法如下

android firebase service kotlin sharedpreferences
2个回答
0
投票

我遇到了类似的问题,并不是Android api中的所有内容都在我的FirebaseMessagingService中正常工作。

我认为这可能与从Oreo及更高版本运行后台服务的限制有关,而FCM消息与那些https://developer.android.com/about/versions/oreo/background#services不同

我猜你只在Android> = 8上遇到这个问题,对吧?

所以我现在所做的是两段代码,分别用于Oreo之前和Oreo-and-newer,从我的onMessageReceived运行

@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
        val body = remoteMessage.getNotification().getBody()
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            scheduleJobService(body);
        } else {
            runIntentService(body);
        }
}

然后在runIntentService中我只是启动一个Intent服务(我想你知道怎么做),但这只能在pre-Oreo之前工作,因为上面提到的限制

在Android 8及更高版本上,您需要安排JobService或实现自己的自定义BroadcastReceiver ...

我选择了JobService,因为它对我来说比较容易,而且我不介意等待Android安排我的工作,我做的是:

@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
private fun scheduleNotificationJobService(body: String) {
    val serviceName = ComponentName(getPackageName(),
            NotificationJobService::class.java.name)

    val scheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler

    val notificationInfoBundle = PersistableBundle()
    notificationInfoBundle.putString(Constants.EXTRA_NOTIF_BODY, body)

    val builder = JobInfo.Builder(JOB_ID, serviceName)
            .setOverrideDeadline(0)
            .setExtras(notificationInfoBundle)
    val notificationInfo = builder.build()
    scheduler.schedule(notificationInfo)
}

然后你的工作服务看起来像这样:

@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
class NotificationJobService : JobService() {

    override fun onStopJob(params: JobParameters?): Boolean {}

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun onStartJob(params: JobParameters?): Boolean {
        params?.extras?.let {
            val body = it.getString(Constants.EXTRA_NOTIF_BODY)
            val preferences = getApplicationContext().getSharedPreferences("com.xxx.xxx.xxx",Context.MODE_PRIVATE)
            if(preferences.getBoolean("notf",true)){
                sendNotification(body);
            }
        }
        return false
    }
}

记得在AndroidManifest.xml中声明它

    <service android:name=".push.NotificationJobService"
        android:permission="android.permission.BIND_JOB_SERVICE">
    </service>

让我知道,如果这也适合你:)欢呼


-1
投票

我终于解决了这个问题..

FCM(Firebase云消息传递)中有两种类型的消息:

显示消息:仅当您的应用程序位于前台时,这些消息才会触发onMessageReceived()回调

数据消息:即使您的应用处于前台/后台/已杀死,这些消息也会触发onMessageReceived()回调

所以我必须为我的应用发布数据消息。通常它就是这样做的;

POST https://fcm.googleapis.com/fcm/send

Key: Content-Type, Value: application/json
Key: Authorization, Value: key=<your-server-key>

身体使用主题

{
   "to": "/topics/my_topic",
   "data": {
    "my_custom_key": "my_custom_value",
    "my_custom_key2": true
    }
}

但是这不再有效(错误401)..对于这种情况会有Auth问题beacuse FCM现在使用OAUTH 2

所以我读了firebase documentation并根据文档发布数据消息的新方法是;

POST: https://fcm.googleapis.com/v1/projects/YOUR_FIREBASEDB_ID/messages:send

Key: Content-Type, Value: application/json

验证

Bearer YOUR_TOKEN 

身体

{
   "message":{
    "topic" : "xxx",
    "data" : {
         "body" : "This is a Firebase Cloud Messaging Topic Message!",
         "title" : "FCM Message"
          }
      }
 }

在url中有Database Id,您可以在firebase控制台上找到它。 (去项目安排)

现在让我们拿走我们的令牌(它只有1小时有效):

首先在Firebase控制台中,打开“设置”>“服务帐户”。单击生成新私钥,安全地存储包含密钥的JSON文件。我需要这个JSON文件来手动授权服务器请求。我下载了它。

然后我创建一个node.js项目并使用此函数获取我的令牌;

var PROJECT_ID = 'YOUR_PROJECT_ID';
var HOST = 'fcm.googleapis.com';
var PATH = '/v1/projects/' + PROJECT_ID + '/messages:send';
var MESSAGING_SCOPE = 'https://www.googleapis.com/auth/firebase.messaging';
var SCOPES = [MESSAGING_SCOPE];

  router.get('/', function(req, res, next) {
      res.render('index', { title: 'Express' });
      getAccessToken().then(function(accessToken) {
        console.log("TOKEN: "+accessToken)
      })

    });

function getAccessToken() {
return new Promise(function(resolve, reject) {
    var key = require('./YOUR_DOWNLOADED_JSON_FILE.json');
    var jwtClient = new google.auth.JWT(
        key.client_email,
        null,
        key.private_key,
        SCOPES,
        null
    );
    jwtClient.authorize(function(err, tokens) {
        if (err) {
            reject(err);
            return;
        }
        resolve(tokens.access_token);
    });
});
}

现在我在我的帖子请求中使用此标记。然后我发布我的数据消息,它现在由我的应用程序onMessageReceived函数处理。

© www.soinside.com 2019 - 2024. All rights reserved.