如果在使用 IBM MobileFirst Platform 7.0 关闭应用程序时收到推送通知,则不会由 onMessage 处理
push notifications not handled by onMessage if received when app closed using IBM MobileFirst Platform 7.0
我们正在使用 MFP 7.0.0.00-20150907-1450 并构建针对 iOS 和 Android.
的混合应用程序
我们正在使用 "send bulk messages" REST API 发送广播消息。
我们已经在我们的应用程序中实现了 WL.Client.Push.onMessage
,只要应用程序在收到通知时是 运行,它就会处理消息。
如果应用程序在通知到达 phone 时关闭,消息负载似乎没有到达我们的 onMessage
实现。
此行为在 iOS 和 Android 之间是相同的。
我怀疑在我们的 onMessage
函数被分配和 MFP 框架试图将消息传递到我们的应用程序之间存在时间问题。
一些关于我们如何在应用程序关闭时收到消息的情况下处理消息的指示会很棒!
(以下是我们设置的一些细节。)
我们正在使用 Angular 并且 在我们的主应用程序模块中有 这个:
if (angular.isDefined(window.WL) && angular.isDefined(window.WL.Client.Push)) {
window.WL.Client.Push.onMessage = function (props, payload) {
console.log('Received push notification in client', JSON.stringify(props), JSON.stringify(payload));
$rootScope.$broadcast('pushNotification', props, payload);
};
}
在 onMessage
的文档中注意到这个 ("You must declare it outside any function.") 之后,我将作业移到了 JavaScript 文件的顶部,甚至在 IIFE 之外。这个函数似乎没有被调用,当然没有日志记录并且变量仍然未定义:
var lastPushMessage;
function pushMessageRecorder(props, payload) {
lastPushMessage = {
props: props,
payload: payload
};
console.log('MFP: push received: ' + JSON.stringify(lastPushMessage, null, 2));
}
WL.Client.Push.onMessage = pushMessageRecorder;
我们的安全测试(用户无需登录,只需使用我们的密钥打包一个应用程序):
<customSecurityTest name="customTests">
<test realm="wl_antiXSRFRealm" step="1" />
<test realm="wl_authenticityRealm" step="1" />
<test realm="wl_remoteDisableRealm" step="1" />
<test realm="wl_directUpdateRealm" mode="perSession" step="1" />
<test realm="wl_anonymousUserRealm" isInternalUserID="true" step="1" />
<test realm="wl_deviceNoProvisioningRealm" isInternalDeviceID="true" step="2" />
</customSecurityTest>
看来我已经成功了。
(大多数情况下。如果应用不是 运行 并且用户滑动通知,或直接从启动器打开应用,则通知 still 不会显示在应用程序。)
有两件事需要做:
- 必须完成对
WL.Client.Push.onMessage
的分配 "outside of any function"
native/res/values/strings.xml
中字符串 "app_name" 的值似乎用于从推送服务定位应用程序并确保消息通过
第二点对我来说仍然没有真正意义,但看起来 AndroidManifest.xml
中的 intent-filter 操作 android:name
值是使用这些值构建的:
{AndroidManifest.xml:/manifest[@package]}.{res/values/strings.xml:/resources/string[@name="app_name"]}.NOTIFICATION
由于 app_name
值用于构建通知限定符,因此它不能有任何空格,这对于显示在 phone 上的应用程序名称来说不太好。
我通过向 strings.xml
文件添加另一个变量来解决这个问题(尽管我也可以在 AndroidManifest.xml
中硬编码名称,然后使用该变量作为我的标签.
这是有效的:
res/values/strings.xml
:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">MyApp</string>
<string name="app_label">My App</string>
<string name="push_notification_title">My App</string>
<!-- ... -->
</resources>
AndroidManifest.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.MyProject" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19"/>
<supports-screens android:smallScreens="false" android:normalScreens="true" android:largeScreens="false"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Push permissions -->
<permission android:name="com.MyProject.permission.C2D_MESSAGE" android:protectionLevel="signature"/>
<uses-permission android:name="com.MyProject.permission.C2D_MESSAGE"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.USE_CREDENTIALS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application android:label="@string/app_label" android:icon="@drawable/icon">
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
<activity android:name=".MyApp" android:label="@string/app_name" android:configChanges="orientation|keyboardHidden|screenSize" android:launchMode="singleTask" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:screenOrientation="portrait" android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="com.MyProject.MyApp.NOTIFICATION"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<!-- Preference Activity -->
<activity android:name="com.worklight.common.WLSettingActivity" android:label="Worklight Settings"/>
<!-- UI Activity for displaying native dialogs -->
<activity android:name="com.worklight.wlclient.ui.UIActivity"/>
<!-- Push service -->
<!-- In order to use the c2dm library, an application must declare a class with the name C2DMReceiver, in its own package, extending com.google.android.c2dm.C2DMBaseReceiver
It must also include this section in the manifest, replacing "com.google.android.apps.chrometophone" with its package name. -->
<service android:name=".GCMIntentService"/>
<service android:name=".ForegroundService"/>
<!-- Only google service can send data messages for the app. If permission is not set - any other app can generate it -->
<receiver android:name="com.worklight.androidgap.push.WLBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND">
<!-- Receive the actual message -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE"/>
<category android:name="com.MyProject"/>
</intent-filter>
<!-- Receive the registration id -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION"/>
<category android:name="com.MyProject"/>
</intent-filter>
</receiver>
</application>
</manifest>
我们正在使用 MFP 7.0.0.00-20150907-1450 并构建针对 iOS 和 Android.
的混合应用程序
我们正在使用 "send bulk messages" REST API 发送广播消息。
我们已经在我们的应用程序中实现了 WL.Client.Push.onMessage
,只要应用程序在收到通知时是 运行,它就会处理消息。
如果应用程序在通知到达 phone 时关闭,消息负载似乎没有到达我们的 onMessage
实现。
此行为在 iOS 和 Android 之间是相同的。
我怀疑在我们的 onMessage
函数被分配和 MFP 框架试图将消息传递到我们的应用程序之间存在时间问题。
一些关于我们如何在应用程序关闭时收到消息的情况下处理消息的指示会很棒!
(以下是我们设置的一些细节。)
我们正在使用 Angular 并且 在我们的主应用程序模块中有 这个:
if (angular.isDefined(window.WL) && angular.isDefined(window.WL.Client.Push)) {
window.WL.Client.Push.onMessage = function (props, payload) {
console.log('Received push notification in client', JSON.stringify(props), JSON.stringify(payload));
$rootScope.$broadcast('pushNotification', props, payload);
};
}
在 onMessage
的文档中注意到这个 ("You must declare it outside any function.") 之后,我将作业移到了 JavaScript 文件的顶部,甚至在 IIFE 之外。这个函数似乎没有被调用,当然没有日志记录并且变量仍然未定义:
var lastPushMessage;
function pushMessageRecorder(props, payload) {
lastPushMessage = {
props: props,
payload: payload
};
console.log('MFP: push received: ' + JSON.stringify(lastPushMessage, null, 2));
}
WL.Client.Push.onMessage = pushMessageRecorder;
我们的安全测试(用户无需登录,只需使用我们的密钥打包一个应用程序):
<customSecurityTest name="customTests">
<test realm="wl_antiXSRFRealm" step="1" />
<test realm="wl_authenticityRealm" step="1" />
<test realm="wl_remoteDisableRealm" step="1" />
<test realm="wl_directUpdateRealm" mode="perSession" step="1" />
<test realm="wl_anonymousUserRealm" isInternalUserID="true" step="1" />
<test realm="wl_deviceNoProvisioningRealm" isInternalDeviceID="true" step="2" />
</customSecurityTest>
看来我已经成功了。
(大多数情况下。如果应用不是 运行 并且用户滑动通知,或直接从启动器打开应用,则通知 still 不会显示在应用程序。)
有两件事需要做:
- 必须完成对
WL.Client.Push.onMessage
的分配 "outside of any function" native/res/values/strings.xml
中字符串 "app_name" 的值似乎用于从推送服务定位应用程序并确保消息通过
第二点对我来说仍然没有真正意义,但看起来 AndroidManifest.xml
中的 intent-filter 操作 android:name
值是使用这些值构建的:
{AndroidManifest.xml:/manifest[@package]}.{res/values/strings.xml:/resources/string[@name="app_name"]}.NOTIFICATION
由于 app_name
值用于构建通知限定符,因此它不能有任何空格,这对于显示在 phone 上的应用程序名称来说不太好。
我通过向 strings.xml
文件添加另一个变量来解决这个问题(尽管我也可以在 AndroidManifest.xml
中硬编码名称,然后使用该变量作为我的标签.
这是有效的:
res/values/strings.xml
:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">MyApp</string>
<string name="app_label">My App</string>
<string name="push_notification_title">My App</string>
<!-- ... -->
</resources>
AndroidManifest.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.MyProject" android:versionCode="1" android:versionName="1.0">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="19"/>
<supports-screens android:smallScreens="false" android:normalScreens="true" android:largeScreens="false"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- Push permissions -->
<permission android:name="com.MyProject.permission.C2D_MESSAGE" android:protectionLevel="signature"/>
<uses-permission android:name="com.MyProject.permission.C2D_MESSAGE"/>
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.USE_CREDENTIALS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application android:label="@string/app_label" android:icon="@drawable/icon">
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
<activity android:name=".MyApp" android:label="@string/app_name" android:configChanges="orientation|keyboardHidden|screenSize" android:launchMode="singleTask" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:screenOrientation="portrait" android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="com.MyProject.MyApp.NOTIFICATION"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<!-- Preference Activity -->
<activity android:name="com.worklight.common.WLSettingActivity" android:label="Worklight Settings"/>
<!-- UI Activity for displaying native dialogs -->
<activity android:name="com.worklight.wlclient.ui.UIActivity"/>
<!-- Push service -->
<!-- In order to use the c2dm library, an application must declare a class with the name C2DMReceiver, in its own package, extending com.google.android.c2dm.C2DMBaseReceiver
It must also include this section in the manifest, replacing "com.google.android.apps.chrometophone" with its package name. -->
<service android:name=".GCMIntentService"/>
<service android:name=".ForegroundService"/>
<!-- Only google service can send data messages for the app. If permission is not set - any other app can generate it -->
<receiver android:name="com.worklight.androidgap.push.WLBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND">
<!-- Receive the actual message -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE"/>
<category android:name="com.MyProject"/>
</intent-filter>
<!-- Receive the registration id -->
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION"/>
<category android:name="com.MyProject"/>
</intent-filter>
</receiver>
</application>
</manifest>