我肯定有答案,但我似乎找不到。大多数例子都是使用传统的HTTP FireBase调用(2年前),但我想使用新的v1HTTP API。我可以让它在应用程序运行在前台(谁没有),但不在后台或应用程序不运行时工作。更复杂的是,我们也支持iOS,因此相同的消息必须同时适用于这两个方面。
其他一些我想做的事情要非常清楚:
-
如果应用程序在前台,FireBase服务工作正常,我会收到通知并获取数据。我稍后再显示代码
-
如果应用程序没有运行,当我单击系统托盘中的通知时,我希望能够从通知中获取数据并进行处理。不工作。
-
如果应用程序在后台运行,当我单击系统托盘中的通知时,我希望能够从通知中获取数据并进行处理。不工作。
我怀疑我在androidmanifest.xml和/或实际消息中的设置有问题,但是我尝试了大量的变化,但没有成功。
首先,我当前正在从FireBase向设备发送的消息:
{
"message":{
"token":"mynastylongdevicetoken...",
"data":{
"State":"Whatever",
},
"notification":{
"title":"New Info",
"body":"A new info has been dispatched to you"
},
"android": {
"notification": {
"click_action": ".StartActivity"
}
}
}
}
请注意上述消息-我尝试了“单击”操作的各种组合,例如“StartActivity”“.StartActivity”“.SplashActivity”“SplashActivity”。
这是基于来自FireBase的最新文档:
https://firebase.google.com/docs/cloud-messaging/migrate-v1
和
https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#AndroidNotification
现在我的
AndroidManifest.xml
. 这有点复杂,因为我已经实现了一些deeplink,我更愿意为此重用相同的活动,但是如果我需要创建一个新的deeplink,就这样吧。目前我有两个主要的入口点活动。一个用于被调用的发射器
SplashActivity
它用来抛出一个飞溅的图像和一个用于深度链接的
StartActivity
. 以下是两种情况的XML:
<activity
android:name="com.mycompany.SplashActivity"
android:configChanges="orientation|keyboardHidden|screenSize|keyboard|navigation"
android:label="@string/app_name"
android:launchMode="singleTask"
android:theme="@style/Theme.Splash" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.mycompany.StartActivity"
android:configChanges="orientation|keyboardHidden|screenSize|keyboard|navigation"
android:label="StartActivity"
android:launchMode="singleTask"
android:windowSoftInputMode="stateHidden" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="@string/launch_protocol" android:host="deeplink1"/>
<data android:scheme="@string/launch_protocol" android:host="deeplink2"/>
<data android:scheme="@string/launch_protocol" android:host="deeplink3"/>
<data android:scheme="@string/launch_protocol" android:host="deeplink4"/>
</intent-filter>
</activity>
现在是源代码。我有两个主要的“块”代码。第一个是标准的FireBase消息服务代码,当应用程序位于前台时,该代码可以工作:
public class MyCompanyFirebaseMessagingService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
// Check if message contains a data payload.
if (remoteMessage.getData().size() > 0) {
String test = remoteMessage.getData().get("State");
}
}
和
public class MyCompanyInstanceIDService extends FirebaseInstanceIdService {
public void sendNotification ( ) {
String token = FirebaseInstanceId.getInstance().getToken();
if (!Utilities.stringIsBlank(token)) {
// Register with our server
}
}
}
以及androidmanifest.xml引用:
<service android:name="com.mycompany.MyCompanyMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name="com.mycompany.MyCompanyInstanceIDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
我把第二部分放在两个前导活动的创建中,试图从创建活动的额外意图中提取数据。我没有看到任何数据通过这个机制进入,许多其他stackoverflows都建议它应该(它们通常超过一年,可能不适用于API的v1?)。以下是它的示例:
protected void onCreate(Bundle savedInstanceState)
{
if (getIntent().getExtras() != null) {
String test = getIntent().getExtras().getString("State", "");
}
}
在这个问题上,我已经看到了无数其他的堆积如山的东西,但都没有成功。如果你想的话,我可以列出来-也许我错过了什么?点击率最高的人(224000)没有帮助。
事先谢谢!
更新
感谢鲍勃的帮助。只是想标记这些变化,这样其他人就不会以Android处理这种奇怪的方式丢失(iOS似乎没有这样的问题,幸运的是他们)。
首先
androidmanifest.xml文件
如答案所示,现在有了一个新的意向过滤器:
<activity
android:name="com.mycompany.SplashActivity"
android:configChanges="orientation|keyboardHidden|screenSize|keyboard|navigation"
android:label="@string/app_name"
android:launchMode="singleTask"
android:theme="@style/Theme.Splash" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="com.mycompany.NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name="com.mycompany.StartActivity"
android:configChanges="orientation|keyboardHidden|screenSize|keyboard|navigation"
android:label="StartActivity"
android:launchMode="singleTask"
android:windowSoftInputMode="stateHidden" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="@string/launch_protocol" android:host="deeplink1"/>
<data android:scheme="@string/launch_protocol" android:host="deeplink2"/>
<data android:scheme="@string/launch_protocol" android:host="deeplink3"/>
<data android:scheme="@string/launch_protocol" android:host="deeplink4"/>
</intent-filter>
</activity>
代码在
onCreate()
. 只需要检查一下
Intent
对于
extras
如果应用程序没有运行或不在后台。在前景中时
public void onMessageReceived(RemoteMessage remoteMessage)
只有消息中有通知时才会调用。如果您只是数据,或者像我一样,使用额外数据通知,则必须同时实现
OnCuto()
意图和
onMessageReceived()
在上面的FireBase服务中。
新消息如下:
{
"message":{
"token":"mynastylongdevicetoken...",
"data":{
"State":"Whatever",
},
"notification":{
"title":"New Info",
"body":"A new info has been dispatched to you"
},
"android": {
"notification": {
"click_action": "com.mycompany.NOTIFICATION_CLICK"
}
}
}
}
最后,如果应用程序还没有运行,我就无法通过从工具栏中选择应用程序(当它有通知指示时)来获取通知。不知道这是不是我想要的行为,还是我在某个地方搞砸了。
最后,我想把当前正在运行的
Activity
如果应用程序已经在运行前台或后台,或者如果没有,则启动应用程序。为此,我必须将以下内容添加到目标活动的onCreate()中以接收通知:
protected void onCreate(Bundle savedInstanceState)
{
if (getIntent().getExtras() != null) {
String test = getIntent().getExtras().getString("State", "");
}
// If this activity is the root activity of the task, the app is not running
if (isTaskRoot()) {
setContentView(R.layout.activity_splash);
}
else
finish();
}
基本上它会检查
飞溅活性
是根,这意味着它是唯一的活动(新的开始)或不是(应用程序已经运行)。如果是这样的话,它就会完成并向前拉应用程序。
令我惊讶的是,在谷歌产品(Android)上使用谷歌产品(FireBase)有多么困难,而在iOS(我被告知)上,这一切都很容易建立起来。