我无法使用IBM MobileFirst Platform订阅我的应用程序来进行推送通知。 我收到了错误消息
WLPush.isAbleToSubscribe在WLPush.java:414 ::无法订阅, 通知令牌未在服务器上更新
logcat的
05-06 10:20:44.767 20941-20941/com.vdot.pushdemo D/ViewRootImpl﹕ ViewPostImeInputStage ACTION_DOWN
05-06 10:20:44.887 20941-21582/com.vdot.pushdemo D/WLClient﹕ WLClient.createInstance in WLClient.java:213 :: WLClient has already been created.
05-06 10:20:44.917 20941-21582/com.vdot.pushdemo D/GCMClientFactory﹕ GCMClientFactory.getInstance in GCMClientFactory.java:25 :: Using GCMAPIClient
05-06 10:20:44.937 20941-21582/com.vdot.pushdemo W/com.worklight.wlclient.api.WLPush﹕ WLPush.unregisterReceivers in WLPush.java:792 :: unregisterReceivers:Receiver not registered: com.worklight.wlclient.api.WLPush$3@43a3d598
05-06 10:20:44.967 20941-21582/com.vdot.pushdemo D/wl.request﹕ WLRequestSender.run in WLRequestSender.java:40 :: Sending request http://10.136.78.232:10080/MFPushDemo/apps/services/api/AndroidPushDemo/Androidnative/init
05-06 10:20:45.267 20941-21681/com.vdot.pushdemo I/System.out﹕ pool-3-thread-6 calls detatch()
05-06 10:20:45.307 20941-21582/com.vdot.pushdemo D/com.worklight.wlclient.api.WLPush﹕ WLPush.updateToken in WLPush.java:521 :: Registering at the GCM server.
05-06 10:20:45.327 20941-21582/com.vdot.pushdemo D/com.worklight.wlclient.api.WLPush﹕ WLPush.clearSubscribedEventSources in WLPush.java:596 :: Clearing notification subscriptions.
05-06 10:20:45.337 20941-21582/com.vdot.pushdemo D/com.worklight.wlclient.api.WLPush﹕ WLPush.updateSubscribedEventSources in WLPush.java:614 :: Updating notification subscriptions.
05-06 10:20:45.347 20941-21582/com.vdot.pushdemo D/com.worklight.wlclient.api.WLPush﹕ WLPush.clearSubscribedTags in WLPush.java:607 :: Clearing tag notification subscriptions.
05-06 10:20:45.357 20941-21681/com.vdot.pushdemo D/com.demo.push﹕ Mode Connect Success
05-06 10:20:45.367 20941-21582/com.vdot.pushdemo D/com.worklight.wlclient.api.WLPush﹕ WLPush.updateSubscribedTags in WLPush.java:635 :: Updating tag notification subscriptions.
05-06 10:20:45.497 20941-21582/com.vdot.pushdemo D/GCMAPIClient﹕ GCMAPIClient$1.doInBackground in GCMAPIClient.java:45 :: Successfully registered with GCM using Google Play Services. Returned deviceToken:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
05-06 10:20:45.507 20941-21682/com.vdot.pushdemo D/com.demo.push﹕ onReadyToSubscribe
05-06 10:20:50.697 20941-20941/com.vdot.pushdemo D/ViewRootImpl﹕ ViewPostImeInputStage ACTION_DOWN
05-06 10:20:50.827 20941-21582/com.vdot.pushdemo D/WLClient﹕ WLClient.createInstance in WLClient.java:213 :: WLClient has already been created.
05-06 10:20:50.847 20941-21582/com.vdot.pushdemo D/GCMClientFactory﹕ GCMClientFactory.getInstance in GCMClientFactory.java:25 :: Using GCMAPIClient
05-06 10:20:50.857 20941-21582/com.vdot.pushdemo W/com.worklight.wlclient.api.WLPush﹕ WLPush.unregisterReceivers in WLPush.java:792 :: unregisterReceivers:Receiver not registered: com.worklight.wlclient.api.WLPush$3@43a800e0
05-06 10:20:50.877 20941-21582/com.vdot.pushdemo E/com.worklight.wlclient.api.WLPush﹕ WLPush.isAbleToSubscribe in WLPush.java:414 :: Can't subscribe, notification token is not updated on the server
主要活动
package com.vdot.pushdemo;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.worklight.wlclient.WLRequestListener;
import com.worklight.wlclient.api.WLClient;
import com.worklight.wlclient.api.WLEventSourceListener;
import com.worklight.wlclient.api.WLFailResponse;
import com.worklight.wlclient.api.WLOnReadyToSubscribeListener;
import com.worklight.wlclient.api.WLProcedureInvocationData;
import com.worklight.wlclient.api.WLPush;
import com.worklight.wlclient.api.WLPushOptions;
import com.worklight.wlclient.api.WLRequestOptions;
import com.worklight.wlclient.api.WLResponse;
import com.worklight.wlclient.api.WLResponseListener;
public class MainActivity extends Activity {
Button Push;
Button Sub;
Button UnSub;
Button Test;
Button Logout;
WLClient client;
WLPush push;
final String realm = "SampleAppRealm";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Push =(Button) findViewById(R.id.button0);
Sub =(Button) findViewById(R.id.button1);
UnSub =(Button) findViewById(R.id.button2);
Test =(Button) findViewById(R.id.button3);
Logout = (Button) findViewById(R.id.button4);
setupUIEvents();
}
void setupUIEvents(){
Push.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
client = WLClient.createInstance(MainActivity.this);
push = client.getPush();
PushListener listener = new PushListener(PushListener.MODE_CONNECT, MainActivity.this);
push.setOnReadyToSubscribeListener(listener);
client.registerChallengeHandler(new LoginChallengeHandler(realm, "IBM User", MainActivity.this));
client.connect(listener);
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
});
Sub.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
client = WLClient.createInstance(MainActivity.this);
client.getPush().subscribe("myAndroid",new WLPushOptions(), new PushListener(PushListener.MODE_SUBSCRIBE,MainActivity.this));
}
});
UnSub.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
Test.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
client = WLClient.createInstance(MainActivity.this);
PushListener listener = new PushListener(PushListener.MODE_CONNECT, MainActivity.this);
client.registerChallengeHandler(new LoginChallengeHandler(realm, "IBM User", MainActivity.this));
client.connect(listener);
int i = 0;
while (i < 10000)
{
i++;
}
String adapterName = "PushAdapter";
String procedureName = "getSecretData";
WLProcedureInvocationData invocationData =
new WLProcedureInvocationData(adapterName, procedureName);
Object[] parameters = new Object[]{};
invocationData.setParameters(parameters);
WLRequestOptions options = new WLRequestOptions();
options.setTimeout(30000);
client.getInstance().invokeProcedure(invocationData, listener, options);
}
});
Logout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
client = WLClient.createInstance(MainActivity.this);
client.logout(realm,new MyListener());
}
});
}
public class MyListener implements WLRequestListener{
@Override
public void onSuccess(WLResponse wlResponse) {
Log.d("com.demo.push", "Log out success");
}
@Override
public void onFailure(WLFailResponse wlFailResponse) {
Log.d("com.demo.push", "Log out failed");
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onPause() {
super.onPause();
if (push != null)
push.setForeground(false);
}
@Override
protected void onResume() {
super.onResume();
int code = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if(code == ConnectionResult.SERVICE_MISSING || code == ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED || code == ConnectionResult.SERVICE_DISABLED) {
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(code, this, 1);
dialog.show();
}
if (push != null)
push.setForeground(true);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (push != null)
push.unregisterReceivers();
}
}
登录挑战处理程序
package com.vdot.pushdemo;
import android.content.Context;
import android.content.Intent;
import com.worklight.wlclient.api.WLFailResponse;
import com.worklight.wlclient.api.WLProcedureInvocationData;
import com.worklight.wlclient.api.WLRequestOptions;
import com.worklight.wlclient.api.WLResponse;
import com.worklight.wlclient.api.challengehandler.ChallengeHandler;
public class LoginChallengeHandler extends ChallengeHandler {
private String userName;
private Context currentContext;
public LoginChallengeHandler(String realm, String user, Context ctx) {
super(realm);
userName = user;
currentContext = ctx;
}
@Override
public boolean isCustomResponse(WLResponse wlResponse) {
try {
if(wlResponse!= null &&
wlResponse.getResponseJSON()!=null &&
wlResponse.getResponseJSON().isNull("authRequired") != true &&
wlResponse.getResponseJSON().getBoolean("authRequired") == true){
return true;
}
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
@Override
public void handleChallenge(WLResponse wlResponse) {
submitLogin(userName,"dummyPassword");
}
@Override
public void onSuccess(WLResponse wlResponse) {
// activity.Loader("Authenticate","Authentcating via VDOT secure server",false);
if(isCustomResponse(wlResponse))
{
handleChallenge(wlResponse);
}
else
{
submitSuccess(wlResponse);
}
}
@Override
public void onFailure(WLFailResponse wlFailResponse) {
submitFailure(wlFailResponse);
}
public void submitLogin(String userName, String password){
Object[] parameters = new Object[]{userName, password};
WLProcedureInvocationData invocationData = new WLProcedureInvocationData("PushAdapter", "submitAuthentication");
invocationData.setParameters(parameters);
WLRequestOptions options = new WLRequestOptions();
options.setTimeout(30000);
submitAdapterAuthentication(invocationData, options);
}
}
推送监听器
package com.vdot.pushdemo;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.widget.TextView;
import com.worklight.wlclient.api.WLClient;
import com.worklight.wlclient.api.WLEventSourceListener;
import com.worklight.wlclient.api.WLFailResponse;
import com.worklight.wlclient.api.WLOnReadyToSubscribeListener;
import com.worklight.wlclient.api.WLResponse;
import com.worklight.wlclient.api.WLResponseListener;
public class PushListener implements WLOnReadyToSubscribeListener,WLResponseListener,WLEventSourceListener {
public static final int MODE_CONNECT = 0;
public static final int MODE_SUBSCRIBE = 1;
public static final int MODE_UNSUBSCRIBE =2;
private int mode ;
private Context currentContext;
public PushListener(int mode, Context ctx){
this.mode = mode;
currentContext = ctx;
}
@Override
public void onReadyToSubscribe() {
WLClient.getInstance().getPush().registerEventSourceCallback("myAndroid", "PushAdapter","PushEventSource", this );
Log.d("com.demo.push", "onReadyToSubscribe");
}
@Override
public void onReceive(String arg0, String arg1) {
}
@Override
public void onSuccess(WLResponse wlResponse) {
switch (mode){
case MODE_CONNECT:
// connect =true ;
Log.d("com.demo.push", "Mode Connect Success");
break;
case MODE_SUBSCRIBE:
Log.d("com.demo.push", "Mode Subscribe Success ");
break;
case MODE_UNSUBSCRIBE:
// unsubscribe = true;
break;
}
}
@Override
public void onFailure(WLFailResponse wlFailResponse) {
switch (mode){
case MODE_CONNECT:
Log.d("com.demo.push", "Mode Connect Fail");
break;
case MODE_SUBSCRIBE:
Log.d("com.demo.push", "Mode Subscribe Fail");
break;
case MODE_UNSUBSCRIBE:
// unsubscribe = false;
break;
}
}
}
Android Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.vdot.pushdemo" >
<permission android:name="com.vdot.pushdemo.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_TASKS"/>
<uses-permission android:name="com.vdot.pushdemo.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" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<meta-data
android:name="com.parse.push.notification_icon"
android:resource="@drawable/push" />
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="com.vdot.pushdemo.MainActivity.NOTIFICATION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<service android:name="com.worklight.wlclient.push.GCMIntentService" />
<receiver android:name="com.worklight.wlclient.push.WLBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="com.vdot.pushdemo" />
</intent-filter>
<intent-filter>
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.vdot.pushdemo" />
</intent-filter>
</receiver>
</application>
</manifest>
WLCLient.Properties
wlServerProtocol = http
wlServerHost = NG00164378
wlServerPort = 10080
wlServerContext = /MFPushDemo/
wlAppId = AndroidPushDemo
wlAppVersion = 1.0
wlEnvironment = Androidnative
wlUid = wY/mbnwKTDDYQUvuQCdSgg==
wlPlatformVersion = 7.0.0.0
#languagePreferences = Add locales in order of preference (e.g. en, fr, fr-CA)
#For Push Notifications,uncomment below line and assign value to it
GcmSenderId = 64XXXXXXXXXX
身份验证Config.XML
<?xml version="1.0" encoding="UTF-8"?>
<tns:loginConfiguration xmlns:tns="http://www.worklight.com/auth/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<staticResources>
<resource id="subscribeServlet" securityTest="SubscribeServlet">
<urlPatterns>/subscribeSMS*;/receiveSMS*;/ussd*</urlPatterns>
</resource>
</staticResources>
<securityTests>
<mobileSecurityTest name="MySecurityTest">
<testUser realm="SampleAppRealm"/>
<testDeviceId provisioningType="none"/>
</mobileSecurityTest>
<customSecurityTest name="SubscribeServlet">
<test realm="SubscribeServlet" isInternalUserID="true"/>
</customSecurityTest>
</securityTests>
<realms>
<realm name="SampleAppRealm" loginModule="AuthLoginModule">
<className>com.worklight.integration.auth.AdapterAuthenticator</className>
<parameter name="login-function" value="PushAdapter.onAuthRequired"/>
<parameter name="logout-function" value="PushAdapter.onLogout"/>
</realm>
<realm name="SubscribeServlet" loginModule="rejectAll">
<className>com.worklight.core.auth.ext.HeaderAuthenticator</className>
</realm>
</realms>
<loginModules>
<loginModule name="AuthLoginModule">
<className>com.worklight.core.auth.ext.NonValidatingLoginModule</className>
</loginModule>
<loginModule name="requireLogin" expirationInSeconds="-1">
<className>com.worklight.core.auth.ext.SingleIdentityLoginModule</className>
</loginModule>
<loginModule name="rejectAll">
<className>com.worklight.core.auth.ext.RejectingLoginModule</className>
</loginModule>
<!-- Required for Trusteer - wl_basicTrusteerFraudDetectionRealm -->
<!-- loginModule name="trusteerFraudDetectionLogin" expirationInSeconds="300">
<className>com.worklight.core.auth.ext.TrusteerLoginModule</className>
</loginModule-->
<!-- For websphere -->
<!-- loginModule name="WASLTPAModule" expirationInSeconds="-1">
<className>com.worklight.core.auth.ext.WebSphereLoginModule</className>
</loginModule -->
<!-- Login module for User Certificate Authentication -->
<!-- <loginModule name="WLUserCertificateLoginModule" expirationInSeconds="-1">
<className>com.worklight.core.auth.ext.UserCertificateLoginModule</className>
</loginModule> -->
<!-- For enabling SSO with no-provisioning device authentication -->
<!-- <loginModule name="MySSO" ssoDeviceLoginModule="WLDeviceNoProvisioningLoginModule" expirationInSeconds="-1">
<className>com.worklight.core.auth.ext.NonValidatingLoginModule</className>
</loginModule> -->
<!-- For enabling SSO with auto-provisioning device authentication -->
<!-- <loginModule name="MySSO" ssoDeviceLoginModule="WLDeviceAutoProvisioningLoginModule" expirationInSeconds="-1">
<className>com.worklight.core.auth.ext.NonValidatingLoginModule</className>
</loginModule> -->
</loginModules>
</tns:loginConfiguration>
应用程序描述符
<?xml version="1.0" encoding="UTF-8"?>
<nativeAndroidApp id="AndroidPushDemo" platformVersion="7.0.0.00.20150312-0731"
version="1.0" xmlns="http://www.worklight.com/native-android-descriptor" securityTest="MySecurityTest">
<displayName>AndroidPushDemo</displayName>
<description>AndroidPushDemo</description>
<publicSigningKey></publicSigningKey>
<packageName></packageName>
<accessTokenExpiration>3600</accessTokenExpiration>
<userIdentityRealms></userIdentityRealms>
<pushSender key="AIXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" senderId="XXXXXXXXXX"/>
</nativeAndroidApp>
PushAdapter
function onAuthRequired(headers, errorMessage){
WL.Logger.error("onAuthRequired");
errorMessage = errorMessage ? errorMessage : null;
return {
authRequired: true,
errorMessage: errorMessage
};
}
function onLogout(){
WL.Logger.debug("Logged out");
}
function getSecretData(){
WL.Logger.error("getSecretData");
return {
secretData: "A secret data to invoke authentication"
};
}
function submitAuthentication(username, password){
// if (username==="user" && password === "user"){
WL.Logger.error("submitAuthentication");
var userIdentity = {
userId: username,
displayName: username,
attributes: {
foo: "bar"
}
};
WL.Server.setActiveUser("SampleAppRealm", userIdentity);
return {
authRequired: false,
user :userIdentity
};
// }
// return onAuthRequired(null, "Invalid login credentials");
}
WL.Server.createEventSource({
name: 'PushEventSource',
onDeviceSubscribe: 'deviceSubscribeFunc',
onDeviceUnsubscribe: 'deviceUnsubscribeFunc',
securityTest:'MySecurityTest'
});
function deviceSubscribeFunc(userSubscription, deviceSubscription){
WL.Logger.error("deviceSubscribeFunc");
WL.Logger.debug(">> deviceSubscribeFunc");
}
function deviceUnsubscribeFunc(userSubscription, deviceSubscription){
WL.Logger.debug(">> deviceUnsubscribeFunc");
}
function submitNotification(userId, notificationText) {
var userSubscription = WL.Server.getUserNotificationSubscription('PushAdapter.PushEventSource', userId);
if (userSubscription === null) {
return { result: "No subscription found for user :: " + userId };
}
var badgeDigit = 1;
var notification = WL.Server.createDefaultNotification(notificationText, badgeDigit, {custom:"data"});
WL.Server.notifyAllDevices(userSubscription, notification);
return {
result: "Notification sent to user :: " + userId
};
}
答案 0 :(得分:2)
根据文档http://www-01.ibm.com/support/knowledgecenter/SSHS8R_7.0.0/com.ibm.worklight.apiref.doc/html/refjava-worklight-android-native/html/com/worklight/wlclient/api/WLClient.html?lang=en,需要在应用程序主活动的开头调用createinstance()方法。后续调用需要使用getInstance()...在您粘贴的代码中,我看到对createInstance()的多次调用,这可能会覆盖使用令牌更新的先前实例。因此,您可以在后续调用中使用createInstance()和getInstance()。