Przeglądaj źródła

添加推送工具类

tianboguang 3 lat temu
rodzic
commit
8f393c10b9
17 zmienionych plików z 1038 dodań i 0 usunięć
  1. 57 0
      4dkankan-utils-app-push/pom.xml
  2. 199 0
      4dkankan-utils-app-push/src/main/java/com/fdkankan/push/AndroidNotification.java
  3. 6 0
      4dkankan-utils-app-push/src/main/java/com/fdkankan/push/App.java
  4. 95 0
      4dkankan-utils-app-push/src/main/java/com/fdkankan/push/IOSNotification.java
  5. 103 0
      4dkankan-utils-app-push/src/main/java/com/fdkankan/push/PushClient.java
  6. 331 0
      4dkankan-utils-app-push/src/main/java/com/fdkankan/push/PushMessageConfig.java
  7. 86 0
      4dkankan-utils-app-push/src/main/java/com/fdkankan/push/UmengNotification.java
  8. 11 0
      4dkankan-utils-app-push/src/main/java/com/fdkankan/push/android/AndroidBroadcast.java
  9. 22 0
      4dkankan-utils-app-push/src/main/java/com/fdkankan/push/android/AndroidCustomizedcast.java
  10. 15 0
      4dkankan-utils-app-push/src/main/java/com/fdkankan/push/android/AndroidFilecast.java
  11. 16 0
      4dkankan-utils-app-push/src/main/java/com/fdkankan/push/android/AndroidGroupcast.java
  12. 16 0
      4dkankan-utils-app-push/src/main/java/com/fdkankan/push/android/AndroidUnicast.java
  13. 12 0
      4dkankan-utils-app-push/src/main/java/com/fdkankan/push/ios/IOSBroadcast.java
  14. 23 0
      4dkankan-utils-app-push/src/main/java/com/fdkankan/push/ios/IOSCustomizedcast.java
  15. 15 0
      4dkankan-utils-app-push/src/main/java/com/fdkankan/push/ios/IOSFilecast.java
  16. 16 0
      4dkankan-utils-app-push/src/main/java/com/fdkankan/push/ios/IOSGroupcast.java
  17. 15 0
      4dkankan-utils-app-push/src/main/java/com/fdkankan/push/ios/IOSUnicast.java

+ 57 - 0
4dkankan-utils-app-push/pom.xml

@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>4dkankan-utils</artifactId>
+        <groupId>com.fdkankan</groupId>
+        <version>2.0.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>4dkankan-utils-app-push</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-beans</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-core</artifactId>
+            <version>4.0.3</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
+            <version>1.1.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.amazonaws</groupId>
+            <artifactId>aws-java-sdk</artifactId>
+            <version>1.11.327</version>
+        </dependency>
+        <dependency>
+            <groupId>com.sun.mail</groupId>
+            <artifactId>javax.mail</artifactId>
+            <version>1.5.4</version>
+        </dependency>
+    </dependencies>
+
+</project>

+ 199 - 0
4dkankan-utils-app-push/src/main/java/com/fdkankan/push/AndroidNotification.java

@@ -0,0 +1,199 @@
+package com.fdkankan.push;
+
+import com.alibaba.fastjson.JSONObject;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+public abstract class AndroidNotification extends UmengNotification {
+	// Keys can be set in the payload level
+	protected static final HashSet<String> PAYLOAD_KEYS = new HashSet<String>(Arrays.asList(new String[]{
+			"display_type"}));
+	
+	// Keys can be set in the body level
+	protected static final HashSet<String> BODY_KEYS = new HashSet<String>(Arrays.asList(new String[]{
+			"ticker", "title", "text", "builder_id", "icon", "largeIcon", "img", "play_vibrate", "play_lights", "play_sound",
+			"sound", "after_open", "url", "activity", "custom"}));
+
+	public enum DisplayType{
+		NOTIFICATION{public String getValue(){return "notification";}},///通知:消息送达到用户设备后,由友盟SDK接管处理并在通知栏上显示通知内容。
+		MESSAGE{public String getValue(){return "message";}};///消息:消息送达到用户设备后,消息内容透传给应用自身进行解析处理。
+		public abstract String getValue();
+	}
+	public enum AfterOpenAction{
+        go_app,//打开应用
+        go_url,//跳转到URL
+        go_activity,//打开特定的activity
+        go_custom//用户自定义内容。
+	}
+	// Set key/value in the rootJson, for the keys can be set please see ROOT_KEYS, PAYLOAD_KEYS, 
+	// BODY_KEYS and POLICY_KEYS.
+	@Override
+	public boolean setPredefinedKeyValue(String key, Object value) throws Exception {
+		if (ROOT_KEYS.contains(key)) {
+			// This key should be in the root level
+			rootJson.put(key, value);
+		} else if (PAYLOAD_KEYS.contains(key)) {
+			// This key should be in the payload level
+			JSONObject payloadJson = null;
+			if (rootJson.containsKey("payload")) {
+				payloadJson = rootJson.getJSONObject("payload");
+			} else {
+				payloadJson = new JSONObject();
+				rootJson.put("payload", payloadJson);
+			}
+			payloadJson.put(key, value);
+		} else if (BODY_KEYS.contains(key)) {
+			// This key should be in the body level
+			JSONObject bodyJson = null;
+			JSONObject payloadJson = null;
+			// 'body' is under 'payload', so build a payload if it doesn't exist
+			if (rootJson.containsKey("payload")) {
+				payloadJson = rootJson.getJSONObject("payload");
+			} else {
+				payloadJson = new JSONObject();
+				rootJson.put("payload", payloadJson);
+			}
+			// Get body JSONObject, generate one if not existed
+			if (payloadJson.containsKey("body")) {
+				bodyJson = payloadJson.getJSONObject("body");
+			} else {
+				bodyJson = new JSONObject();
+				payloadJson.put("body", bodyJson);
+			}
+			bodyJson.put(key, value);
+		} else if (POLICY_KEYS.contains(key)) {
+			// This key should be in the body level
+			JSONObject policyJson = null;
+			if (rootJson.containsKey("policy")) {
+				policyJson = rootJson.getJSONObject("policy");
+			} else {
+				policyJson = new JSONObject();
+				rootJson.put("policy", policyJson);
+			}
+			policyJson.put(key, value);
+		} else {
+			if (key == "payload" || key == "body" || key == "policy" || key == "extra") {
+				throw new Exception("You don't need to set value for " + key + " , just set values for the sub keys in it.");
+			} else {
+				throw new Exception("Unknown key: " + key);
+			}
+		}
+		return true;
+	}
+	
+	// Set extra key/value for Android notification
+	public boolean setExtraField(String key, String value) throws Exception {
+		JSONObject payloadJson = null;
+		JSONObject extraJson = null;
+		if (rootJson.containsKey("payload")) {
+			payloadJson = rootJson.getJSONObject("payload");
+		} else {
+			payloadJson = new JSONObject();
+			rootJson.put("payload", payloadJson);
+		}
+		
+		if (payloadJson.containsKey("extra")) {
+			extraJson = payloadJson.getJSONObject("extra");
+		} else {
+			extraJson = new JSONObject();
+			payloadJson.put("extra", extraJson);
+		}
+		extraJson.put(key, value);
+		return true;
+	}
+	
+	//
+	public void setDisplayType(DisplayType d) throws Exception {
+		setPredefinedKeyValue("display_type", d.getValue());
+	}
+	///通知栏提示文字
+	public void setTicker(String ticker) throws Exception {
+		setPredefinedKeyValue("ticker", ticker);
+	}
+	///通知标题
+	public void setTitle(String title) throws Exception {
+		setPredefinedKeyValue("title", title);
+	}
+	///通知文字描述
+	public void setText(String text) throws Exception {
+		setPredefinedKeyValue("text", text);
+	}
+	///用于标识该通知采用的样式。使用该参数时, 必须在SDK里面实现自定义通知栏样式。
+	public void setBuilderId(Integer builder_id) throws Exception {
+		setPredefinedKeyValue("builder_id", builder_id);
+	}
+	///状态栏图标ID, R.drawable.[smallIcon],如果没有, 默认使用应用图标。
+	public void setIcon(String icon) throws Exception {
+		setPredefinedKeyValue("icon", icon);
+	}
+	///通知栏拉开后左侧图标ID
+	public void setLargeIcon(String largeIcon) throws Exception {
+		setPredefinedKeyValue("largeIcon", largeIcon);
+	}
+	///通知栏大图标的URL链接。该字段的优先级大于largeIcon。该字段要求以http或者https开头。
+	public void setImg(String img) throws Exception {
+		setPredefinedKeyValue("img", img);
+	}
+	///收到通知是否震动,默认为"true"
+	public void setPlayVibrate(Boolean play_vibrate) throws Exception {
+		setPredefinedKeyValue("play_vibrate", play_vibrate.toString());
+	}
+	///收到通知是否闪灯,默认为"true"
+	public void setPlayLights(Boolean play_lights) throws Exception {
+		setPredefinedKeyValue("play_lights", play_lights.toString());
+	}
+	///收到通知是否发出声音,默认为"true"
+	public void setPlaySound(Boolean play_sound) throws Exception {
+		setPredefinedKeyValue("play_sound", play_sound.toString());
+	}
+	///通知声音,R.raw.[sound]. 如果该字段为空,采用SDK默认的声音
+	public void setSound(String sound) throws Exception {
+		setPredefinedKeyValue("sound", sound);
+	}
+	///收到通知后播放指定的声音文件
+	public void setPlaySound(String sound) throws Exception {
+		setPlaySound(true);
+		setSound(sound);
+	}
+	
+	///点击"通知"的后续行为,默认为打开app。
+	public void goAppAfterOpen() throws Exception {
+		setAfterOpenAction(AfterOpenAction.go_app);
+	}
+	public void goUrlAfterOpen(String url) throws Exception {
+		setAfterOpenAction(AfterOpenAction.go_url);
+		setUrl(url);
+	}
+	public void goActivityAfterOpen(String activity) throws Exception {
+		setAfterOpenAction(AfterOpenAction.go_activity);
+		setActivity(activity);
+	}
+	public void goCustomAfterOpen(String custom) throws Exception {
+		setAfterOpenAction(AfterOpenAction.go_custom);
+		setCustomField(custom);
+	}
+	public void goCustomAfterOpen(JSONObject custom) throws Exception {
+		setAfterOpenAction(AfterOpenAction.go_custom);
+		setCustomField(custom);
+	}
+	
+	///点击"通知"的后续行为,默认为打开app。原始接口
+	public void setAfterOpenAction(AfterOpenAction action) throws Exception {
+		setPredefinedKeyValue("after_open", action.toString());
+	}
+	public void setUrl(String url) throws Exception {
+		setPredefinedKeyValue("url", url);
+	}
+	public void setActivity(String activity) throws Exception {
+		setPredefinedKeyValue("activity", activity);
+	}
+	///can be a string of json
+	public void setCustomField(String custom) throws Exception {
+		setPredefinedKeyValue("custom", custom);
+	}
+	public void setCustomField(JSONObject custom) throws Exception {
+		setPredefinedKeyValue("custom", custom);
+	}
+	
+}

+ 6 - 0
4dkankan-utils-app-push/src/main/java/com/fdkankan/push/App.java

@@ -0,0 +1,6 @@
+package com.fdkankan.modeling.push;
+
+
+public class App {
+
+}

+ 95 - 0
4dkankan-utils-app-push/src/main/java/com/fdkankan/push/IOSNotification.java

@@ -0,0 +1,95 @@
+package com.fdkankan.push;
+
+import com.alibaba.fastjson.JSONObject;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+public abstract class IOSNotification extends UmengNotification {
+
+	// Keys can be set in the aps level
+	protected static final HashSet<String> APS_KEYS = new HashSet<String>(Arrays.asList(new String[]{
+			"alert", "badge", "sound", "content-available", "url", "mutable-content"
+	}));
+	
+	@Override
+	public boolean setPredefinedKeyValue(String key, Object value) throws Exception {
+		if (ROOT_KEYS.contains(key)) {
+			// This key should be in the root level
+			rootJson.put(key, value);
+		} else if (APS_KEYS.contains(key)) {
+			// This key should be in the aps level
+			JSONObject apsJson = null;
+			JSONObject payloadJson = null;
+			if (rootJson.containsKey("payload")) {
+				payloadJson = rootJson.getJSONObject("payload");
+			} else {
+				payloadJson = new JSONObject();
+				rootJson.put("payload", payloadJson);
+			}
+			if (payloadJson.containsKey("aps")) {
+				apsJson = payloadJson.getJSONObject("aps");
+			} else {
+				apsJson = new JSONObject();
+				payloadJson.put("aps", apsJson);
+			}
+			apsJson.put(key, value);
+		} else if (POLICY_KEYS.contains(key)) {
+			// This key should be in the body level
+			JSONObject policyJson = null;
+			if (rootJson.containsKey("policy")) {
+				policyJson = rootJson.getJSONObject("policy");
+			} else {
+				policyJson = new JSONObject();
+				rootJson.put("policy", policyJson);
+			}
+			policyJson.put(key, value);
+		} else {
+			if (key == "payload" || key == "aps" || key == "policy") {
+				throw new Exception("You don't need to set value for " + key + " , just set values for the sub keys in it.");
+			} else {
+				throw new Exception("Unknownd key: " + key);
+			}
+		}
+		
+		return true;
+	}
+	// Set customized key/value for IOS notification
+	public boolean setCustomizedField(String key, String value) throws Exception {
+		//rootJson.put(key, value);
+		JSONObject payloadJson = null;
+		if (rootJson.containsKey("payload")) {
+			payloadJson = rootJson.getJSONObject("payload");
+		} else {
+			payloadJson = new JSONObject();
+			rootJson.put("payload", payloadJson);
+		}
+		payloadJson.put(key, value);
+		return true;
+	}
+
+	public void setAlert(String token) throws Exception {
+    	setPredefinedKeyValue("alert", token);
+    }
+
+    public void setAlert(String title ,String subtitle , String body, String url) throws Exception{
+		JSONObject object = new JSONObject();
+		object.put("title" , title);
+		object.put("subtitle" , subtitle);
+		object.put("body" , body);
+		setPredefinedKeyValue("alert",object );
+		setPredefinedKeyValue("url", url);
+		setPredefinedKeyValue("mutable-content", 1);
+	}
+	public void setBadge(Integer badge) throws Exception {
+    	setPredefinedKeyValue("badge", badge);
+    }
+	
+	public void setSound(String sound) throws Exception {
+    	setPredefinedKeyValue("sound", sound);
+    }
+	
+	public void setContentAvailable(Integer contentAvailable) throws Exception {
+    	setPredefinedKeyValue("content-available", contentAvailable);
+    }
+}

+ 103 - 0
4dkankan-utils-app-push/src/main/java/com/fdkankan/push/PushClient.java

@@ -0,0 +1,103 @@
+package com.fdkankan.push;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.DefaultHttpClient;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+@Slf4j
+public class PushClient {
+	
+	// The user agent
+	protected final String USER_AGENT = "Mozilla/5.0";
+
+	// This object is used for sending the post request to Umeng
+	protected HttpClient client = new DefaultHttpClient();
+	
+	// The host
+	protected static final String host = "http://msg.umeng.com";
+	
+	// The upload path
+	protected static final String uploadPath = "/upload";
+	
+	// The post path
+	protected static final String postPath = "/api/send";
+
+	public boolean send(UmengNotification msg) throws Exception {
+		String timestamp = Integer.toString((int)(System.currentTimeMillis() / 1000));
+		msg.setPredefinedKeyValue("timestamp", timestamp);
+        String url = host + postPath;
+        String postBody = msg.getPostBody();
+        String sign = DigestUtils.md5Hex(("POST" + url + postBody + msg.getAppMasterSecret()).getBytes("utf8"));
+        url = url + "?sign=" + sign;
+        HttpPost post = new HttpPost(url);
+        post.setHeader("User-Agent", USER_AGENT);
+        StringEntity se = new StringEntity(postBody, "UTF-8");
+        post.setEntity(se);
+        // Send the post request and get the response
+        HttpResponse response = client.execute(post);
+        int status = response.getStatusLine().getStatusCode();
+        log.info("Response Code : " + status);
+        BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
+        StringBuffer result = new StringBuffer();
+        String line = "";
+        while ((line = rd.readLine()) != null) {
+            result.append(line);
+        }
+        log.info(result.toString());
+        if (status == 200) {
+            log.info("Notification sent successfully.");
+        } else {
+            log.info("Failed to send the notification!");
+        }
+        return true;
+    }
+
+	// Upload file with device_tokens to Umeng
+	public String uploadContents(String appkey,String appMasterSecret,String contents) throws Exception {
+		// Construct the json string
+		JSONObject uploadJson = new JSONObject();
+		uploadJson.put("appkey", appkey);
+		String timestamp = Integer.toString((int)(System.currentTimeMillis() / 1000));
+		uploadJson.put("timestamp", timestamp);
+		uploadJson.put("content", contents);
+		// Construct the request
+		String url = host + uploadPath;
+		String postBody = uploadJson.toString();
+		String sign = DigestUtils.md5Hex(("POST" + url + postBody + appMasterSecret).getBytes("utf8"));
+		url = url + "?sign=" + sign;
+		HttpPost post = new HttpPost(url);
+		post.setHeader("User-Agent", USER_AGENT);
+		StringEntity se = new StringEntity(postBody, "UTF-8");
+		post.setEntity(se);
+		// Send the post request and get the response
+		HttpResponse response = client.execute(post);
+		log.info("Response Code : " + response.getStatusLine().getStatusCode());
+		BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
+		StringBuffer result = new StringBuffer();
+		String line = "";
+		while ((line = rd.readLine()) != null) {
+			result.append(line);
+		}
+		log.info(result.toString());
+		// Decode response string and get file_id from it
+		JSONObject respJson = JSONObject.parseObject(result.toString());
+		String ret = respJson.getString("ret");
+		if (!ret.equals("SUCCESS")) {
+			throw new Exception("Failed to upload file");
+		}
+		JSONObject data = respJson.getJSONObject("data");
+		String fileId = data.getString("file_id");
+		// Set file_id into rootJson using setPredefinedKeyValue
+		
+		return fileId;
+	}
+
+}

+ 331 - 0
4dkankan-utils-app-push/src/main/java/com/fdkankan/push/PushMessageConfig.java

@@ -0,0 +1,331 @@
+package com.fdkankan.push;
+
+
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.push.android.*;
+import com.fdkankan.push.ios.*;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Date;
+
+@Slf4j
+public class PushMessageConfig {
+	private String appkey = null;
+	private String appMasterSecret = null;
+	private String timestamp = null;
+	private PushClient client = new PushClient();
+
+	public static final String ANDROID_KEY = "5ee71c03dbc2ec076dd488cb";
+	public static final String ANDROID_SECRET = "gzw4r8frbhq6eigxrvgjkdrm7wgtu83g";
+	public static final String IOS_KEY = "5ee71ca9978eea081640f22a";
+	public static final String IOS_SECRET = "tpuhyojch16pcha2qmpidlbnzkielv9w";
+
+	//转台双目使用
+	public static final String ANDROID_KEY_Z = "60efd777a6f90557b7b97c25";
+	public static final String ANDROID_SECRET_Z = "ll85ov3qzeuas0ig7cw0v5bgzq1bdl07";
+	public static final String IOS_KEY_Z = "60efd7c9a6f90557b7b97d10";
+	public static final String IOS_SECRET_Z = "li62b5f3d9kn8idvy6qva3c5gyidmqwl";
+
+	public PushMessageConfig(String key, String secret) {
+		try {
+			appkey = key;
+			appMasterSecret = secret;
+		} catch (Exception e) {
+			e.printStackTrace();
+			System.exit(1);
+		}
+	}
+	
+	public void sendAndroidBroadcast() throws Exception {
+		AndroidBroadcast broadcast = new AndroidBroadcast(appkey,appMasterSecret);
+		broadcast.setTicker( "Android broadcast ticker");
+		broadcast.setTitle(  "中文的title");
+		broadcast.setText(   "Android broadcast text");
+		broadcast.goAppAfterOpen();
+		broadcast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		// TODO Set 'production_mode' to 'false' if it's a test device. 
+		// For how to register a test device, please see the developer doc.
+		broadcast.setProductionMode();
+		// Set customized fields
+		broadcast.setExtraField("test", "helloworld");
+		//厂商通道相关参数
+		broadcast.setChannelActivity("your channel activity");
+		broadcast.setChannelProperties("abc");
+		client.send(broadcast);
+	}
+	
+	public void sendAndroidUnicast(String token, String ticker, String title, String text, String url) throws Exception {
+		AndroidUnicast unicast = new AndroidUnicast(appkey,appMasterSecret);
+		// TODO Set your device token
+		unicast.setDeviceToken(token);
+		unicast.setTicker(ticker);
+		unicast.setTitle(title);
+		unicast.setText(text);
+		unicast.goUrlAfterOpen(url);
+		unicast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		// TODO Set 'production_mode' to 'false' if it's a test device. 
+		// For how to register a test device, please see the developer doc.
+		unicast.setProductionMode();
+		// Set customized fields
+		unicast.setExtraField("test", "helloworld");
+		unicast.setChannelActivity("com.fdage.eight.module.EightPushMsgHandlerActivity");
+//		unicast.setChannelProperties("abc");
+
+		client.send(unicast);
+	}
+
+	//转台相机
+	public void sendAndroidUnicast2(String token, String ticker, String title, String text, String url) throws Exception {
+		AndroidUnicast unicast = new AndroidUnicast(appkey,appMasterSecret);
+		// TODO Set your device token
+		unicast.setDeviceToken(token);
+		unicast.setTicker(ticker);
+		unicast.setTitle(title);
+		unicast.setText(text);
+		unicast.goUrlAfterOpen(url);
+		unicast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		// TODO Set 'production_mode' to 'false' if it's a test device.
+		// For how to register a test device, please see the developer doc.
+		unicast.setProductionMode();
+		// Set customized fields
+		unicast.setExtraField("test", "helloworld");
+		unicast.setChannelActivity("io.github.zileyuan.umeng_analytics_push.OfflineNotifyClickActivity");
+//		unicast.setChannelProperties("abc");
+
+		client.send(unicast);
+	}
+	
+	public void sendAndroidGroupcast() throws Exception {
+		AndroidGroupcast groupcast = new AndroidGroupcast(appkey,appMasterSecret);
+		/*  TODO
+		 *  Construct the filter condition:
+		 *  "where": 
+		 *	{
+    	 *		"and": 
+    	 *		[
+      	 *			{"tag":"test"},
+      	 *			{"tag":"Test"}
+    	 *		]
+		 *	}
+		 */
+		JSONObject filterJson = new JSONObject();
+		JSONObject whereJson = new JSONObject();
+		JSONArray tagArray = new JSONArray();
+		JSONObject testTag = new JSONObject();
+		JSONObject TestTag = new JSONObject();
+		testTag.put("tag", "test");
+		TestTag.put("tag", "Test");
+		tagArray.add(testTag);
+		tagArray.add(TestTag);
+		whereJson.put("and", tagArray);
+		filterJson.put("where", whereJson);
+
+		groupcast.setFilter(filterJson);
+		groupcast.setTicker( "Android groupcast ticker");
+		groupcast.setTitle(  "中文的title");
+		groupcast.setText(   "Android groupcast text");
+		groupcast.goAppAfterOpen();
+		groupcast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		groupcast.setChannelActivity("your channel activity");
+		// TODO Set 'production_mode' to 'false' if it's a test device. 
+		// For how to register a test device, please see the developer doc.
+		groupcast.setProductionMode();
+		//厂商通道相关参数
+		groupcast.setChannelActivity("your channel activity");
+		groupcast.setChannelProperties("abc");
+		client.send(groupcast);
+	}
+	
+	public void sendAndroidCustomizedcast() throws Exception {
+		AndroidCustomizedcast customizedcast = new AndroidCustomizedcast(appkey,appMasterSecret);
+		// TODO Set your alias here, and use comma to split them if there are multiple alias.
+		// And if you have many alias, you can also upload a file containing these alias, then 
+		// use file_id to send customized notification.
+		customizedcast.setAlias("alias", "alias_type");
+		customizedcast.setTicker( "Android customizedcast ticker");
+		customizedcast.setTitle(  "中文的title");
+		customizedcast.setText(   "Android customizedcast text");
+		customizedcast.goAppAfterOpen();
+		customizedcast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		// TODO Set 'production_mode' to 'false' if it's a test device. 
+		// For how to register a test device, please see the developer doc.
+		customizedcast.setProductionMode();
+		//厂商通道相关参数
+		customizedcast.setChannelActivity("your channel activity");
+		customizedcast.setChannelProperties("abc");
+		client.send(customizedcast);
+	}
+	
+	public void sendAndroidCustomizedcastFile() throws Exception {
+		AndroidCustomizedcast customizedcast = new AndroidCustomizedcast(appkey,appMasterSecret);
+		// TODO Set your alias here, and use comma to split them if there are multiple alias.
+		// And if you have many alias, you can also upload a file containing these alias, then 
+		// use file_id to send customized notification.
+		String fileId = client.uploadContents(appkey,appMasterSecret,"aa"+"\n"+"bb"+"\n"+"alias");
+		customizedcast.setFileId(fileId, "alias_type");
+		customizedcast.setTicker( "Android customizedcast ticker");
+		customizedcast.setTitle(  "中文的title");
+		customizedcast.setText(   "Android customizedcast text");
+		customizedcast.goAppAfterOpen();
+		customizedcast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		// TODO Set 'production_mode' to 'false' if it's a test device. 
+		// For how to register a test device, please see the developer doc.
+		customizedcast.setProductionMode();
+		//厂商通道相关参数
+		customizedcast.setChannelActivity("your channel activity");
+		customizedcast.setChannelProperties("abc");
+		client.send(customizedcast);
+	}
+	
+	public void sendAndroidFilecast() throws Exception {
+		AndroidFilecast filecast = new AndroidFilecast(appkey,appMasterSecret);
+		// TODO upload your device tokens, and use '\n' to split them if there are multiple tokens 
+		String fileId = client.uploadContents(appkey,appMasterSecret,"aa"+"\n"+"bb");
+		filecast.setFileId( fileId);
+		filecast.setTicker( "Android filecast ticker");
+		filecast.setTitle(  "中文的title");
+		filecast.setText(   "Android filecast text");
+		filecast.goAppAfterOpen();
+		filecast.setDisplayType(AndroidNotification.DisplayType.NOTIFICATION);
+		//厂商通道相关参数
+		filecast.setChannelActivity("your channel activity");
+		filecast.setChannelProperties("abc");
+		client.send(filecast);
+	}
+	
+	public void sendIOSBroadcast() throws Exception {
+		IOSBroadcast broadcast = new IOSBroadcast(appkey,appMasterSecret);
+        //alert值设置为字符串
+		//broadcast.setAlert("IOS 广播测试");
+		//alert的值设置为字典
+//		broadcast.setAlert("今日天气" , "" , "今日可能下雨🌂");
+		broadcast.setBadge( 0);
+		broadcast.setSound( "default");
+		// TODO set 'production_mode' to 'true' if your app is under production mode
+		broadcast.setTestMode();
+		// Set customized fields
+		broadcast.setCustomizedField("test", "helloworld");
+		client.send(broadcast);
+	}
+	
+	public void sendIOSUnicast(String token, String title ,String subtitle , String body, String url) throws Exception {
+		IOSUnicast unicast = new IOSUnicast(appkey,appMasterSecret);
+		// TODO Set your device token
+		unicast.setDeviceToken(token);
+		//alert值设置为字符串
+		//unicast.setAlert("IOS 单播测试");
+		//alert的值设置为字典
+		unicast.setAlert(title, subtitle, body, url);
+//		unicast.setBadge( 0);
+		unicast.setSound( "default");
+		// TODO set 'production_mode' to 'true' if your app is under production mode
+		unicast.setProductionMode();
+//		unicast.setTestMode();
+		unicast.setDescription(title);
+		unicast.setExpireTime(DateUtil.formatTime(DateUtil.offsetDay(new Date(), 1)));
+		// Set customized fields
+//		unicast.setCustomizedField("url", url);
+		client.send(unicast);
+	}
+
+	
+	public void sendIOSGroupcast() throws Exception {
+		IOSGroupcast groupcast = new IOSGroupcast(appkey,appMasterSecret);
+		/*  TODO
+		 *  Construct the filter condition:
+		 *  "where": 
+		 *	{
+    	 *		"and": 
+    	 *		[
+      	 *			{"tag":"iostest"}
+    	 *		]
+		 *	}
+		 */
+		JSONObject filterJson = new JSONObject();
+		JSONObject whereJson = new JSONObject();
+		JSONArray tagArray = new JSONArray();
+		JSONObject testTag = new JSONObject();
+		testTag.put("tag", "iostest");
+		tagArray.add(testTag);
+		whereJson.put("and", tagArray);
+		filterJson.put("where", whereJson);
+		log.info(filterJson.toString());
+		
+		// Set filter condition into rootJson
+		groupcast.setFilter(filterJson);
+		//groupcast.setAlert("IOS 组播测试");
+		//alert的值设置为字典
+//		groupcast.setAlert("今日天气" , "subtitle" , "今日可能下雨🌂");
+		groupcast.setBadge( 0);
+		groupcast.setSound( "default");
+		// TODO set 'production_mode' to 'true' if your app is under production mode
+		groupcast.setTestMode();
+		client.send(groupcast);
+	}
+	
+	public void sendIOSCustomizedcast() throws Exception {
+		IOSCustomizedcast customizedcast = new IOSCustomizedcast(appkey,appMasterSecret);
+		// TODO Set your alias and alias_type here, and use comma to split them if there are multiple alias.
+		// And if you have many alias, you can also upload a file containing these alias, then 
+		// use file_id to send customized notification.
+		customizedcast.setAlias("alias", "alias_type");
+		//customizedcast.setAlert("IOS 个性化测试");
+		//alert的值设置为字典
+//		customizedcast.setAlert("今日天气" , "" , "今日可能下雨🌂");
+		customizedcast.setBadge( 0);
+		customizedcast.setSound( "default");
+		// TODO set 'production_mode' to 'true' if your app is under production mode
+		customizedcast.setTestMode();
+		client.send(customizedcast);
+	}
+	
+	public void sendIOSFilecast() throws Exception {
+		IOSFilecast filecast = new IOSFilecast(appkey,appMasterSecret);
+		// TODO upload your device tokens, and use '\n' to split them if there are multiple tokens 
+		String fileId = client.uploadContents(appkey,appMasterSecret,"aa"+"\n"+"bb");
+		filecast.setFileId( fileId);
+		//filecast.setAlert("IOS 文件播测试");
+		//alert的值设置为字典
+//		filecast.setAlert("今日天气" , "" , "今日可能下雨🌂");
+		filecast.setBadge( 0);
+		filecast.setSound( "default");
+		// TODO set 'production_mode' to 'true' if your app is under production mode
+		filecast.setTestMode();
+		client.send(filecast);
+	}
+	
+	public static void main(String[] args) {
+		// TODO set your appkey and master secret here
+		//安卓
+//		Demo demo = new Demo(ANDROID_KEY, ANDROID_SECRET);
+		//ios
+		PushMessageConfig pushMessageConfig = new PushMessageConfig(IOS_KEY, IOS_SECRET);
+		try {
+//			demo.sendAndroidUnicast("AneqkEZahjbW3cF7gu8juNYqz54ZFfK7kjMpTOiQL9dl",
+//					"测试项目计算完成", "四维看看Pro", "您上传的测试项目计算完成,点击查看",
+//					"https://test.4dkankan.com/smobile.html?m=t-e9uHHdn");
+			pushMessageConfig.sendIOSUnicast("ec61a2aa52673c96c12024e07ce267e391ca560e0c60f15ee09e65c8843ef7f4",
+					"四维看看Pro", "测试项目计算完成", "您上传的测试项目计算完成,点击查看",
+					"https://test.4dkankan.com/smobile.html?m=t-e9uHHdn");
+			/* TODO these methods are all available, just fill in some fields and do the test
+			 * demo.sendAndroidCustomizedcastFile();
+			 * demo.sendAndroidBroadcast();
+			 * demo.sendAndroidGroupcast();
+			 * demo.sendAndroidCustomizedcast();
+			 * demo.sendAndroidFilecast();
+			 * 
+			 * demo.sendIOSBroadcast();
+			 * demo.sendIOSUnicast();
+			 * demo.sendIOSGroupcast();
+			 * demo.sendIOSCustomizedcast();
+			 * demo.sendIOSFilecast();
+			 */
+		} catch (Exception ex) {
+			ex.printStackTrace();
+		}
+	}
+	
+
+}

+ 86 - 0
4dkankan-utils-app-push/src/main/java/com/fdkankan/push/UmengNotification.java

@@ -0,0 +1,86 @@
+package com.fdkankan.push;
+
+import com.alibaba.fastjson.JSONObject;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+public abstract class UmengNotification {
+	// This JSONObject is used for constructing the whole request string.
+	protected final JSONObject rootJson = new JSONObject();
+	
+	
+	// The app master secret
+	protected String appMasterSecret;
+	
+	// Keys can be set in the root level
+	protected static final HashSet<String> ROOT_KEYS = new HashSet<String>(Arrays.asList(new String[]{
+			"appkey", "timestamp", "type", "device_tokens", "alias", "alias_type", "file_id", 
+			"filter", "production_mode", "feedback", "description", "thirdparty_id" , "mipush" , "mi_activity" , "channel_properties"}));
+	
+	// Keys can be set in the policy level
+	protected static final HashSet<String> POLICY_KEYS = new HashSet<String>(Arrays.asList(new String[]{
+			"start_time", "expire_time", "max_send_num"
+	}));
+	
+	// Set predefined keys in the rootJson, for extra keys(Android) or customized keys(IOS) please 
+	// refer to corresponding methods in the subclass.
+	public abstract boolean setPredefinedKeyValue(String key, Object value) throws Exception;
+	public void setAppMasterSecret(String secret) {
+		appMasterSecret = secret;
+	}
+	
+	public String getPostBody(){
+		return rootJson.toString();
+	}
+	
+	protected final String getAppMasterSecret(){
+		return appMasterSecret;
+	}
+	
+	protected void setProductionMode(Boolean prod) throws Exception {
+    	setPredefinedKeyValue("production_mode", prod.toString());
+    }
+
+	///正式模式
+    public void setProductionMode() throws Exception {
+    	setProductionMode(true);
+    }
+
+    ///测试模式
+    public void setTestMode() throws Exception {
+    	setProductionMode(false);
+    }
+
+    ///发送消息描述,建议填写。
+    public void setDescription(String description) throws Exception {
+    	setPredefinedKeyValue("description", description);
+    }
+
+    ///定时发送时间,若不填写表示立即发送。格式: "YYYY-MM-DD hh:mm:ss"。
+    public void setStartTime(String startTime) throws Exception {
+    	setPredefinedKeyValue("start_time", startTime);
+    }
+    ///消息过期时间,格式: "YYYY-MM-DD hh:mm:ss"。
+    public void setExpireTime(String expireTime) throws Exception {
+    	setPredefinedKeyValue("expire_time", expireTime);
+    }
+    ///发送限速,每秒发送的最大条数。
+    public void setMaxSendNum(Integer num) throws Exception {
+    	setPredefinedKeyValue("max_send_num", num);
+    }
+
+    //厂商弹窗activity
+	public void setChannelActivity(String activity) throws Exception{
+       setPredefinedKeyValue("mipush", "true");
+       setPredefinedKeyValue("mi_activity",activity );
+	}
+
+	//厂商属性配置
+	public void setChannelProperties(String xiaoMiChannelId) throws Exception{
+		JSONObject object = new JSONObject();
+		object.put("xiaomi_channel_id" , xiaoMiChannelId);
+		setPredefinedKeyValue("channel_properties", object);
+	}
+
+}

+ 11 - 0
4dkankan-utils-app-push/src/main/java/com/fdkankan/push/android/AndroidBroadcast.java

@@ -0,0 +1,11 @@
+package com.fdkankan.push.android;
+
+import com.fdkankan.push.AndroidNotification;
+
+public class AndroidBroadcast extends AndroidNotification {
+	public AndroidBroadcast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "broadcast");	
+	}
+}

+ 22 - 0
4dkankan-utils-app-push/src/main/java/com/fdkankan/push/android/AndroidCustomizedcast.java

@@ -0,0 +1,22 @@
+package com.fdkankan.push.android;
+
+import com.fdkankan.push.AndroidNotification;
+
+public class AndroidCustomizedcast extends AndroidNotification {
+	public AndroidCustomizedcast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "customizedcast");	
+	}
+	
+	public void setAlias(String alias,String aliasType) throws Exception {
+    	setPredefinedKeyValue("alias", alias);
+    	setPredefinedKeyValue("alias_type", aliasType);
+    }
+			
+	public void setFileId(String fileId,String aliasType) throws Exception {
+    	setPredefinedKeyValue("file_id", fileId);
+    	setPredefinedKeyValue("alias_type", aliasType);
+    }
+
+}

+ 15 - 0
4dkankan-utils-app-push/src/main/java/com/fdkankan/push/android/AndroidFilecast.java

@@ -0,0 +1,15 @@
+package com.fdkankan.push.android;
+
+import com.fdkankan.push.AndroidNotification;
+
+public class AndroidFilecast extends AndroidNotification {
+	public AndroidFilecast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "filecast");	
+	}
+	
+	public void setFileId(String fileId) throws Exception {
+    	setPredefinedKeyValue("file_id", fileId);
+    }
+}

+ 16 - 0
4dkankan-utils-app-push/src/main/java/com/fdkankan/push/android/AndroidGroupcast.java

@@ -0,0 +1,16 @@
+package com.fdkankan.push.android;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.push.AndroidNotification;
+
+public class AndroidGroupcast extends AndroidNotification {
+	public AndroidGroupcast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "groupcast");	
+	}
+	
+	public void setFilter(JSONObject filter) throws Exception {
+    	setPredefinedKeyValue("filter", filter);
+    }
+}

+ 16 - 0
4dkankan-utils-app-push/src/main/java/com/fdkankan/push/android/AndroidUnicast.java

@@ -0,0 +1,16 @@
+package com.fdkankan.push.android;
+
+import com.fdkankan.push.AndroidNotification;
+
+public class AndroidUnicast extends AndroidNotification {
+	public AndroidUnicast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "unicast");	
+	}
+	
+	public void setDeviceToken(String token) throws Exception {
+    	setPredefinedKeyValue("device_tokens", token);
+    }
+
+}

+ 12 - 0
4dkankan-utils-app-push/src/main/java/com/fdkankan/push/ios/IOSBroadcast.java

@@ -0,0 +1,12 @@
+package com.fdkankan.push.ios;
+
+import com.fdkankan.push.IOSNotification;
+
+public class IOSBroadcast extends IOSNotification {
+	public IOSBroadcast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "broadcast");	
+		
+	}
+}

+ 23 - 0
4dkankan-utils-app-push/src/main/java/com/fdkankan/push/ios/IOSCustomizedcast.java

@@ -0,0 +1,23 @@
+package com.fdkankan.push.ios;
+
+
+import com.fdkankan.push.IOSNotification;
+
+public class IOSCustomizedcast extends IOSNotification {
+	public IOSCustomizedcast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "customizedcast");	
+	}
+	
+	public void setAlias(String alias,String aliasType) throws Exception {
+    	setPredefinedKeyValue("alias", alias);
+    	setPredefinedKeyValue("alias_type", aliasType);
+    }
+		
+	public void setFileId(String fileId, String aliasType) throws Exception {
+		setPredefinedKeyValue("file_id", fileId);
+		setPredefinedKeyValue("alias_type", aliasType);
+	}
+
+}

+ 15 - 0
4dkankan-utils-app-push/src/main/java/com/fdkankan/push/ios/IOSFilecast.java

@@ -0,0 +1,15 @@
+package com.fdkankan.push.ios;
+
+import com.fdkankan.push.IOSNotification;
+
+public class IOSFilecast extends IOSNotification {
+	public IOSFilecast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "filecast");	
+	}
+	
+	public void setFileId(String fileId) throws Exception {
+    	setPredefinedKeyValue("file_id", fileId);
+    }
+}

+ 16 - 0
4dkankan-utils-app-push/src/main/java/com/fdkankan/push/ios/IOSGroupcast.java

@@ -0,0 +1,16 @@
+package com.fdkankan.push.ios;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.push.IOSNotification;
+
+public class IOSGroupcast extends IOSNotification {
+	public IOSGroupcast(String appkey,String appMasterSecret) throws Exception {
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "groupcast");	
+	}
+	
+	public void setFilter(JSONObject filter) throws Exception {
+    	setPredefinedKeyValue("filter", filter);
+    }
+}

+ 15 - 0
4dkankan-utils-app-push/src/main/java/com/fdkankan/push/ios/IOSUnicast.java

@@ -0,0 +1,15 @@
+package com.fdkankan.push.ios;
+
+import com.fdkankan.push.IOSNotification;
+
+public class IOSUnicast extends IOSNotification {
+	public IOSUnicast(String appkey,String appMasterSecret) throws Exception{
+			setAppMasterSecret(appMasterSecret);
+			setPredefinedKeyValue("appkey", appkey);
+			this.setPredefinedKeyValue("type", "unicast");	
+	}
+	
+	public void setDeviceToken(String token) throws Exception {
+    	setPredefinedKeyValue("device_tokens", token);
+    }
+}