android - IBM MobileFirst - 无法订阅,通知 token 未在服务器上更新

标签 android ibm-mobilefirst mobilefirst-server

我无法为使用 IBM MobileFirst Platform 构建的应用程序订阅推送通知。 我收到错误消息

WLPush.isAbleToSubscribe in WLPush.java:414 :: Can't subscribe, notification token is not updated on the server

日志猫

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

主要 Activity

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 list

<?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

认证配置.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>

推送适配器

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
    };
}

最佳答案

根据文档 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() 方法需要在应用程序的主要 Activity 开始时调用。后续调用需要使用 getInstance() ...在您粘贴的代码中我看到多次调用 createInstance() 这可能会覆盖使用 token 更新的先前实例。因此,您可以使用一次 createInstance() 并在后续调用中使用 getInstance()。

关于android - IBM MobileFirst - 无法订阅,通知 token 未在服务器上更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30079686/

相关文章:

android - 避免标记(Google Maps for Android API V2)在点击时以 map 为中心

ios - IBM Worklight - 是否可以在没有 Mac 和 Xcode 的情况下在 iPhone 设备上部署应用程序?

ibm-mobilefirst - 尝试将 .wlapp 文件部署到 Tomcat 时,MobileFirst 7.0 服务器卡住 "Deploying"

java - 未找到架构 'ADAPTER_CONTENT'、版本 'mfp_default_schema' 的 ID 为 '1.0' 的配置

java - IBM 工作灯 6.1 - "Ecma Error: TypeError: Cannot call property <function> in object"

tomcat - 使用 updateApplicationServer ANT 任务在 Tomcat 上更新 WAR 文件似乎需要重新启动应用程序服务器?

android - 绘制镜像的qlabel

java - 在 Android 中创建简单对话框的快捷方式

android - 在应用程序模块和库模块中包含相同的 jar 库

javascript - 如何为工作海报 REST 调用定义 MFP javascript 适配器?