QuickBlox通知:推送令牌消失

时间:2015-05-31 15:55:29

标签: android google-cloud-messaging quickblox

我一直在开发一款使用QuickBlox进行聊​​天的Android应用。聊天工作正常,但我在登出用户的推送通知方面遇到了困难。

问题是某些设备有时会停止接收通知。它经常工作几个小时,但然后突然完全停止为该设备工作。完全手动卸载+重新安装(然后将用户再次登录到QuickBlox + GCM)通常可以解决问题。

查看QuickBlox管理面板,我可以看到某些订阅会丢失其推送令牌。

用户1在设备A上注册。推送令牌已消失。 http://i.stack.imgur.com/YUkyw.png

用户1在设备B上注册。推送令牌仍然存在。 http://i.stack.imgur.com/Yu5IQ.png

一旦用户登录QuickBlox,我就会注册GCM + QuickBlox推送消息。此代码主要来自QuickBlox聊天示例。

ChatService:

.bss

PlayServicesHelper:

private void loginToChat(final Context context, final QBUser user, final QBEntityCallback callback)
{
    this.qbChatService.login(user, new QBEntityCallbackImpl()
    {
        @Override
        public void onSuccess()
        {

            checkPlayServices(context);

            try
            {
                qbChatService.startAutoSendPresence(AUTO_PRESENCE_INTERVAL_IN_SECONDS);
            }
            catch (SmackException.NotLoggedInException e)
            {
                e.printStackTrace();
            }

            if (callback != null)
            {
                callback.onSuccess();
            }
        }

        @Override
        public void onSuccess(Object result, Bundle params)
        {
            super.onSuccess(result, params);

            checkPlayServices(context);
        }

        @Override
        public void onError(List errors)
        {
            if (callback != null)
            {
                callback.onError(errors);
            }
        }
    });
}


private void checkPlayServices(Context context)
{
    // Register with GCM after the session has been created
    PlayServicesHelper playServicesHelper = new PlayServicesHelper(context);
    playServicesHelper.checkPlayServices();
}

为了允许用户接收通知,我每次应用程序进入后台时都会将其注销(在BaseActivity中使用onStop),然后在应用程序恢复时重新登录(然后再次启动PlayServicesHelper)。

public class PlayServicesHelper
{
private static final String PROPERTY_APP_VERSION = "appVersion";
private static final String PROPERTY_REG_ID = "registration_id";
private static final String TAG = "PlayServicesHelper";
private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;

private GoogleCloudMessaging googleCloudMessaging;
private Context activity;
private String regId;

private String projectNumber;

public PlayServicesHelper(Context activity)
{
    this.activity = activity;
    this.projectNumber = activity.getString(R.string.gcm_project_number);
    checkPlayService();
}

private void checkPlayService()
{
    // Check device for Play Services APK. If check succeeds, proceed with
    // GCM registration.
    if (checkPlayServices())
    {
        googleCloudMessaging = GoogleCloudMessaging.getInstance(activity);
        regId = getRegistrationId();

        if (regId.isEmpty())
        {
            registerInBackground();
        }
    }
    else
    {
        Log.i(TAG, "No valid Google Play Services APK found.");
    }
}

/**
 * Check the device to make sure it has the Google Play Services APK. If
 * it doesn't, display a dialog that allows users to download the APK from
 * the Google Play Store or enable it in the device's system settings.
 */
public boolean checkPlayServices()
{
    int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(activity);
    if (resultCode != ConnectionResult.SUCCESS)
    {
        if (GooglePlayServicesUtil.isUserRecoverableError(resultCode))
        {
            GooglePlayServicesUtil.getErrorDialog(resultCode, activity, PLAY_SERVICES_RESOLUTION_REQUEST).show();
        }
        return false;
    }
    return true;
}

/**
 * Gets the current registration ID for application on GCM service.
 * <p/>
 * If result is empty, the app needs to register.
 *
 * @return registration ID, or empty string if there is no existing
 * registration ID.
 */
private String getRegistrationId()
{
    final SharedPreferences prefs = getGCMPreferences();
    String registrationId = prefs.getString(PROPERTY_REG_ID, "");
    if (registrationId.isEmpty())
    {
        Log.i(TAG, "Registration not found.");
        return "";
    }
    // Check if app was updated; if so, it must clear the registration ID
    // since the existing regID is not guaranteed to work with the new
    // app version.
    int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);

    int currentVersion = getAppVersionCode();
    if (registeredVersion != currentVersion)
    {
        Log.i(TAG, "App version changed.");
        return "";
    }
    return registrationId;
}

/**
 * Registers the application with GCM servers asynchronously.
 * <p/>
 * Stores the registration ID and app versionCode in the application's
 * shared preferences.
 */
private void registerInBackground()
{
    new AsyncTask<Void, Void, String>()
    {
        @Override
        protected String doInBackground(Void... params)
        {
            String msg = "";
            try
            {
                if (googleCloudMessaging == null)
                {
                    googleCloudMessaging = GoogleCloudMessaging.getInstance(activity);
                }
                regId = googleCloudMessaging.register(projectNumber);
                msg = "Device registered, registration ID=" + regId;

                // You should send the registration ID to your server over HTTP, so it
                // can use GCM/HTTP or CCS to send messages to your app.
                Handler h = new Handler(activity.getMainLooper());
                h.post(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        subscribeToPushNotifications(regId);
                    }
                });

                // Persist the regID - no need to register again.
                storeRegistrationId(regId);
            }
            catch (IOException ex)
            {
                msg = "Error :" + ex.getMessage();
                // If there is an error, don't just keep trying to register.
                // Require the user to click a button again, or perform
                // exponential back-off.
            }
            return msg;
        }

        @Override
        protected void onPostExecute(String msg)
        {
            Log.i(TAG, msg + "\n");
        }
    }.execute(null, null, null);
}

/**
 * @return Application's {@code SharedPreferences}.
 */
private SharedPreferences getGCMPreferences()
{
    return activity.getSharedPreferences(activity.getPackageName(), Context.MODE_PRIVATE);
}

/**
 * Subscribe to Push Notifications
 *
 * @param regId registration ID
 */
private void subscribeToPushNotifications(String regId)
{
    String deviceId;

    final TelephonyManager mTelephony = (TelephonyManager) activity.getSystemService(Context.TELEPHONY_SERVICE);
    if (mTelephony.getDeviceId() != null)
    {
        deviceId = mTelephony.getDeviceId();
    }
    else
    {
        deviceId = Settings.Secure.getString(activity.getContentResolver(), Settings.Secure.ANDROID_ID);
    }

    QBMessages.subscribeToPushNotificationsTask(regId, deviceId, QBEnvironment.PRODUCTION, new QBEntityCallbackImpl<ArrayList<QBSubscription>>()
    {
        @Override
        public void onSuccess(ArrayList<QBSubscription> qbSubscriptions, Bundle bundle)
        {

        }

        @Override
        public void onError(List<String> strings)
        {

        }
    });
}

/**
 * Stores the registration ID and app versionCode in the application's
 * {@code SharedPreferences}.
 *
 * @param regId registration ID
 */
private void storeRegistrationId(String regId)
{
    final SharedPreferences prefs = getGCMPreferences();
    int appVersion = getAppVersionCode();
    SharedPreferences.Editor editor = prefs.edit();
    editor.putString(PROPERTY_REG_ID, regId);
    editor.putInt(PROPERTY_APP_VERSION, appVersion);
    editor.apply();
}

private int getAppVersionCode()
{
    try
    {
        PackageInfo packageInfo = this.activity.getPackageManager().getPackageInfo(this.activity.getPackageName(), 0);
        return packageInfo.versionCode;
    }
    catch (PackageManager.NameNotFoundException e)
    {
        return 0;
    }
}
}

该应用程序还使用Parse(使用GCM)进行推送通知,但是当我禁用Parse时,问题似乎仍然存在。

问题可能是由于一个用户同时在多个设备上注册了吗?频繁安装应用程序(无需手动删除以前的安装)会导致此行为吗?

1 个答案:

答案 0 :(得分:1)

如果2个用户使用同一设备

,则推送令牌可能会消失

例如,用户1订阅了推送deviceA

然后用户2订阅了推送deviceA(同一设备)

此后只有用户2接收推送,而不是用户1

你的案子中是否有机会拥有这样的逻辑?