我在我的片段(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 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>
让我知道,如果这也适合你:)欢呼
我终于解决了这个问题..
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函数处理。