All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.leancloud.AVPush Maven / Gradle / Ivy

package cn.leancloud;

import cn.leancloud.callback.SendCallback;
import cn.leancloud.core.PaasClient;
import cn.leancloud.utils.AVUtils;
import cn.leancloud.utils.LogUtil;
import cn.leancloud.utils.StringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable;

import java.util.*;

public class AVPush {
  private static final AVLogger LOGGER = LogUtil.getLogger(AVPush.class);

  private static final String deviceTypeTag = "deviceType";
  private static final Set DEVICE_TYPES = new HashSet();
  static {
    DEVICE_TYPES.add("android");
    DEVICE_TYPES.add("ios");
  }
  private final Set channelSet;
  private AVQuery pushQuery;
  private String cql;
  private long expirationTime;
  private long expirationTimeInterval;
  private final Set pushTarget;
  private final Map pushData;
  private volatile AVObject notification;
  private Date pushDate = null;

  /**
   * Creates a new push notification. The default channel is the empty string, also known as the
   * global broadcast channel, but this value can be overridden using AVPush.setChannel(String),
   * AVPush.setChannels(Collection) or AVPush.setQuery(AVQuery). Before sending the push
   * notification you must call either AVPush.setMessage(String) or AVPush.setData(JSONObject).
   */
  public AVPush() {
    channelSet = new HashSet();
    pushData = new HashMap();
    pushTarget = new HashSet(DEVICE_TYPES);
    pushQuery = AVInstallation.getQuery();
  }

  public Set getChannelSet() {
    return channelSet;
  }

  /**
   * 返回推送后创建的_Notification对象。
   *
   * @return
   */
  public AVObject getNotification() {
    return notification;
  }

  public AVQuery getPushQuery() {
    return pushQuery;
  }

  public Date getPushDate() {
    return pushDate;
  }

  public long getExpirationTime() {
    return expirationTime;
  }

  public long getExpirationTimeInterval() {
    return expirationTimeInterval;
  }

  public Set getPushTarget() {
    return pushTarget;
  }

  public Map getPushData() {
    return pushData;
  }

  /**
   * Sets the channel on which this push notification will be sent. The channel name must start with
   * a letter and contain only letters, numbers, dashes, and underscores. A push can either have
   * channels or a query. Setting this will unset the query.
   */
  public void setChannel(String channel) {
    channelSet.clear();
    channelSet.add(channel);
  }

  /**
   * Sets the collection of channels on which this push notification will be sent. Each channel name
   * must start with a letter and contain only letters, numbers, dashes, and underscores. A push can
   * either have channels or a query. Setting this will unset the query.
   */
  public void setChannels(Collection channels) {
    channelSet.clear();
    channelSet.addAll(channels);
  }

  /**
   * Sets the entire data of the push message. See the push guide for more details on the data
   * format. This will overwrite any data specified in AVPush.setMessage(String).
   *
   * @since 1.4.4
   */
  public void setData(Map data) {
    this.pushData.put("data", data);
  }

  /**
   * Sets the entire data of the push message. See the push guide for more details on the data
   * format. This will overwrite any data specified in AVPush.setMessage(String).
   */
  public void setData(JSONObject data) {
    try {
      Map map = new HashMap();
      Iterator iter = data.keySet().iterator();
      while (iter.hasNext()) {
        String key = (String) iter.next();
        Object value = data.get(key);
        map.put(key, value);
      }
      this.pushData.put("data", map);
    } catch (Exception exception) {
      LOGGER.w(exception);
    }
  }

  private Date expirationDateTime() {
    return new Date(expirationTime);
  }

  /**
   * Set the push date at which the push will be sent.
   *
   * @param date The push date.
   */
  public void setPushDate(Date date) {
    this.pushDate = date;
  }

  /**
   * Sets a UNIX epoch timestamp at which this notification should expire, in seconds (UTC). This
   * notification will be sent to devices which are either online at the time the notification is
   * sent, or which come online before the expiration time is reached. Because device clocks are not
   * guaranteed to be accurate, most applications should instead use
   * AVPush.setExpirationTimeInterval(long).
   */
  public void setExpirationTime(long time) {
    this.expirationTime = time;
  }

  /**
   * Sets the time interval after which this notification should expire, in seconds. This
   * notification will be sent to devices which are either online at the time the notification is
   * sent, or which come online within the given number of seconds of the notification being
   * received by AVOSCloud's server. An interval which is less than or equal to zero indicates that
   * the message should only be sent to devices which are currently online.
   */
  public void setExpirationTimeInterval(long timeInterval) {
    this.expirationTimeInterval = timeInterval;
  }

  /**
   * Sets the message that will be shown in the notification. This will overwrite any data specified
   * in AVPush.setData(JSONObject).
   */
  public void setMessage(String message) {
    pushData.clear();
    Map map = AVUtils.createStringObjectMap("alert", message);
    pushData.put("data", map);
  }

  public void setPushToAndroid(boolean pushToAndroid) {
    if (pushToAndroid) {
      this.pushTarget.add("android");
    } else {
      this.pushTarget.remove("android");
    }
  }

  public void setPushToIOS(boolean pushToIOS) {
    if (pushToIOS) {
      this.pushTarget.add("ios");
    } else {
      this.pushTarget.remove("ios");
    }
  }

  public void setPushToWindowsPhone(boolean pushToWP) {
    if (pushToWP) {
      this.pushTarget.add("wp");
    } else {
      this.pushTarget.remove("wp");
    }
  }

  /**
   * Sets the query for this push for which this push notification will be sent. This query will be
   * executed in the AVOSCloud cloud; this push notification will be sent to Installations which
   * this query yields. A push can either have channels or a query. Setting this will unset the
   * channels.
   *
   * @param query A query to which this push should target. This must be a AVInstallation query.
   */
  public void setQuery(AVQuery query) {
    this.pushQuery = query;
  }

  /**
   * 可以通过 cql来针对push进行筛选
   *
   * 请注意cql 的主体应该是_Installation表
   *
   * 请在设置cql的同时,不要设置pushTarget(ios,android,wp)
   *
   * @param cql
   * @since 2.6.7
   */
  public void setCloudQuery(String cql) {
    this.cql = cql;
  }

  /**
   * Clears both expiration values, indicating that the notification should never expire.
   */
  public void clearExpiration() {
    expirationTime = 0L;
    expirationTimeInterval = 0L;
  }

  /**
   * Sends this push notification while blocking this thread until the push notification has
   * successfully reached the AVOSCloud servers. Typically, you should use AVPush.sendInBackground()
   * instead of this, unless you are managing your own threading.
   */
  public void send() {
    sendInBackground().blockingFirst();
  }

  /**
   * Sends this push notification in a background thread. This is preferable to using send(), unless
   * your code is already running from a background thread.
   */
  public Observable sendInBackground() {
    try {
      Map map = postDataMap();
      return PaasClient.getPushClient().sendPushRequest(map);
    } catch (Exception ex) {
      return Observable.error(ex);
    }
  }

  private Map pushChannelsData() {
    return AVUtils.createStringObjectMap("channels", channelSet);
  }

  private Map postDataMap() throws AVException {
    Map map = new HashMap();

    if (pushQuery != null) {
      if (pushTarget.size() == 0) {
        pushQuery.whereNotContainedIn(deviceTypeTag, DEVICE_TYPES);
      } else if (pushTarget.size() == 1) {
        pushQuery.whereEqualTo(deviceTypeTag, pushTarget.toArray()[0]);
      }
      Map pushParameters = pushQuery.assembleParameters();
      if (pushParameters.keySet().size() > 0 && !StringUtil.isEmpty(cql)) {
        throw new IllegalStateException("You can't use AVQuery and Cloud query at the same time.");
      }
      for (String k : pushParameters.keySet()) {
        map.put(k, JSON.parse(pushParameters.get(k)));
      }
    }
    if (!StringUtil.isEmpty(cql)) {
      map.put("cql", cql);
    }
    if (channelSet.size() > 0) {
      map.putAll(pushChannelsData());
    }

    if (this.expirationTime > 0) {
      map.put("expiration_time", this.expirationDateTime());
    }
    if (this.expirationTimeInterval > 0) {
      map.put("push_time", StringUtil.stringFromDate(new Date()));
      map.put("expiration_interval", new Long(this.expirationTimeInterval));
    }
    if (this.pushDate != null) {
      map.put("push_time", StringUtil.stringFromDate(pushDate));
    }

    map.putAll(pushData);
    return map;
  }

  /**
   * Sends this push notification in a background thread. This is preferable to using send(), unless
   * your code is already running from a background thread.
   *
   * @param callback callback.done(e) is called when the send completes.
   */
  public void sendInBackground(final SendCallback callback) {
    sendInBackground().subscribe(new Observer() {
      @Override
      public void onSubscribe(Disposable disposable) {

      }

      @Override
      public void onNext(JSONObject jsonObject) {
        notification = new AVObject("_Notification");
        notification.resetServerData(jsonObject.getInnerMap());
        if (null != callback) {
          callback.internalDone(null);
        }
      }

      @Override
      public void onError(Throwable throwable) {
        if (null != callback) {
          callback.internalDone(new AVException(throwable));
        }
      }

      @Override
      public void onComplete() {

      }
    });
  }

  /**
   * A helper method to concisely send a push to a query. This method is equivalent to
   *
   * 
   * AVPush push = new AVPush();
   * push.setData(data);
   * push.setQuery(query);
   * push.sendInBackground(callback);
   * 
* * @param data The entire data of the push message. See the push guide for more details on the * data format. * @param query A AVInstallation query which specifies the recipients of a push. * @param callback callback.done(e) is called when the send completes. */ public static void sendDataInBackground(JSONObject data, AVQuery query, final SendCallback callback) { AVPush push = new AVPush(); push.setData(data); push.setQuery(query); push.sendInBackground(callback); } /** * A helper method to concisely send a push to a query. This method is equivalent to * *
   * AVPush push = new AVPush();
   * push.setData(data);
   * push.setQuery(query);
   * push.sendInBackground(callback);
   * 
* * @param data The entire data of the push message. See the push guide for more details on the * data format. * @param query A AVInstallation query which specifies the recipients of a push. * */ public static Observable sendDataInBackground(JSONObject data, AVQuery query) { AVPush push = new AVPush(); push.setData(data); push.setQuery(query); return push.sendInBackground(); } /** * A helper method to concisely send a push message to a query. This method is equivalent to * *
   * AVPush push = new AVPush();
   * push.setMessage(message);
   * push.setQuery(query);
   * push.sendInBackground();
   * 
* * @param message The message that will be shown in the notification. * @param query A AVInstallation query which specifies the recipients of a push. */ public static Observable sendMessageInBackground(String message, AVQuery query) { AVPush push = new AVPush(); push.setMessage(message); push.setQuery(query); return push.sendInBackground(); } /** * A helper method to concisely send a push message to a query. This method is equivalent to * *
   * AVPush push = new AVPush();
   * push.setMessage(message);
   * push.setQuery(query);
   * push.sendInBackground(callback);
   * 
* * @param message The message that will be shown in the notification. * @param query A AVInstallation query which specifies the recipients of a push. * @param callback callback.done(e) is called when the send completes. */ public static void sendMessageInBackground(String message, AVQuery query, final SendCallback callback) { AVPush push = new AVPush(); push.setMessage(message); push.setQuery(query); push.sendInBackground(callback); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy