问题描述
|
有谁知道是否有Java客户端框架/ API来调用Windows Phone推送通知服务?我知道有一个JavaPNS项目,该项目特定于Apple PNS。
我正在寻找与Windows Phone类似的东西。
有什么帮助吗?
解决方法
Java-mpns似乎与您要寻找的内容接近。
https://github.com/notnoop/java-mpns
,我已经使用Spring和Apache Commons HTTP Client开发了一种解决方案,用于使用WNS(Windows Notification Push Service)发送RAW消息。
在pom.xml上插入以下依赖项:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.2.1</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.12</version>
</dependency>
以及以下关于applicationContext.xml的行
<bean class=\"java.lang.String\" id=\"authenticateUrlPostWNS\">
<constructor-arg>
<value>https://login.live.com/accesstoken.srf</value>
</constructor-arg>
</bean>
<util:map id=\"authenticateWNSHeaders\">
<entry key=\"Content-Type\" value=\"application/x-www-form-urlencoded\" />
</util:map>
<util:map id=\"authenticateWNSPostParams\">
<entry key=\"grant_type\" value=\"client_credentials\" />
<entry key=\"client_id\" value=\"ms-app://\" />
<entry key=\"client_secret\" value=\"\" />
<entry key=\"scope\" value=\"notify.windows.com\" />
</util:map>
<util:map id=\"sendMessageWNSHeaders\">
<entry key=\"X-WNS-Type\" value=\"wns/raw\" />
<entry key=\"Content-Type\" value=\"application/octet-stream\" />
<entry key=\"X-WNS-RequestForStatus\" value=\"true\" />
<entry key=\"X-NotificationClass\" value=\"3\" />
</util:map>
*请记住填写client_id和client_secret
在我的项目中,我将实现分为四个类,下面将对其进行描述
OAuthToken用于存储和格式化访问令牌:
public class OAuthToken {
private String token;
private String tokenType;
public OAuthToken(String token,String tokenType) {
super();
this.token = token;
this.tokenType = tokenType;
}
public String getAuthorization() {
return StringUtils.capitalize(tokenType) + \" \" + token;
}
}
HttpClientFactory(如下所示)用于在您发送消息时创建新的客户端。如果您重复使用同一HttpClient发送消息,则发送第二条消息后WNS超时。我不知道为什么会这样,但是当我停止重用客户端时,它就解决了。
@Service
public class HttpClientFactory {
private static final int TIMEOUT = 20 * 1000;
public HttpClient create() {
SystemDefaultHttpClient httpClient = new SystemDefaultHttpClient();
httpClient.getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,TIMEOUT);
httpClient.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT,TIMEOUT);
httpClient.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler(NumberUtils.INTEGER_ZERO,false));
return httpClient;
}
}
这是一个基类,您可以根据需要将所有代码下拉到WindowsPushNotificationMediator
public abstract class AbstractCloudMediator {
private static final Logger LOG = Logger.getLogger(AbstractCloudMediator.class.getSimpleName());
@Autowired
private HttpClientFactory clientFactory;
@Autowired
protected ObjectMapper mapper;
public abstract boolean sendMessage(Jogador destinatario,Action mensagem);
protected String postToString(HttpPost post) throws IOException,ClientProtocolException {
HttpResponse response = executeMethod(post);
return responseToString(response);
}
protected String responseToString(HttpResponse response) throws IOException {
InputStream conteudoResposta = response.getEntity().getContent();
try {
return IOUtils.toString(conteudoResposta);
} finally {
IOUtils.closeQuietly(conteudoResposta);
}
}
protected HttpResponse executeMethod(HttpPost post) throws IOException,ClientProtocolException {
LOG.info(\"posting to... \" + post);
return clientFactory.create().execute(post);
}
}
下一堂课应该做主要工作,但请记住创建一个cloudMessagingDAO
来检索和存储您的访问令牌。
您应将类Jogador
替换为另一个包含客户端URL的类,该类用于向Windows Phone设备发送消息。
@Service(SharedConstants.WINDOWS_CLOUD_BEAN)
public class WindowsPushNotificationMediator extends AbstractCloudMediator { // NO_UCD (test only)
private static final Logger LOG = Logger.getLogger(WindowsPushNotificationMediator.class.getName());
private static final String KEY_ACCESS_TOKEN = \"access_token\";
private static final String KEY_TOKEN_TYPE = \"token_type\";
@Resource(name = \"authenticateWNSHeaders\")
private Map<String,String> authenticateWNSHeaders;
@Resource(name = \"authenticateWNSPostParams\")
private Map<String,String> authenticateWNSPostParams;
@Resource(name = \"sendMessageWNSHeaders\")
private Map<String,String> sendMessageWNSHeaders;
@Autowired
@Qualifier(\"authenticateUrlPostWNS\")
private String authenticateUrlPostWNS;
@Autowired
private CloudMessagingDAO cloudMessagingDAO;
private OAuthToken oathToken;
@Override
public boolean sendMessage(Jogador destinatario,Action mensagem) {
try {
OAuthToken token = getToken();
String jsonString = mapper.writeValueAsString(mensagem);
StringEntity entity = new StringEntity(jsonString,Consts.UTF_8);
return sendMessage(destinatario,entity,token);
} catch (IOException e) {
LOG.log(Level.SEVERE,e.getMessage(),e);
throw new RuntimeException(e);
}
}
private boolean sendMessage(Jogador destinatario,HttpEntity entity,OAuthToken token) throws IOException {
HttpPost post = new HttpPost(destinatario.getCloudMessagingInfo());// this is the client url
post.addHeader(\"Authorization\",token.getAuthorization());
addPostHeaders(post,sendMessageWNSHeaders);
post.setEntity(entity);
HttpResponse response = executeMethod(post);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED) {
return sendMessage(destinatario,getNewToken());
}
Header[] allHeaders = response.getAllHeaders();
StringBuilder builder = new StringBuilder();
for (Header header : allHeaders) {
builder.append(header.getName() + \": \" + header.getValue());
builder.append(\'\\n\');
}
LOG.info(builder.toString());
return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK;
}
private void addPostHeaders(HttpPost post,Map<String,String> postHeaders) {
for (String key : postHeaders.keySet()) {
post.addHeader(key,postHeaders.get(key));
}
}
private OAuthToken getToken() throws IOException {
if (oathToken == null) {
//You should store your access token,so you can reuse it until it expires
String token = cloudMessagingDAO.getValue(KEY_ACCESS_TOKEN);
String tokenType = cloudMessagingDAO.getValue(KEY_TOKEN_TYPE);
if (StringUtils.isNotBlank(token) && StringUtils.isNotBlank(tokenType)) {
return oathToken = new OAuthToken(token,tokenType);
}
return getNewToken();
}
return oathToken;
}
private OAuthToken getNewToken() throws IOException {
HttpPost post = new HttpPost(authenticateUrlPostWNS);
addPostHeaders(post,authenticateWNSHeaders);
List<NameValuePair> params = new ArrayList<>();
for (String key : authenticateWNSPostParams.keySet()) {
params.add(new BasicNameValuePair(key,authenticateWNSPostParams.get(key)));
}
post.setEntity(new UrlEncodedFormEntity(params));
HttpResponse response = executeMethod(post);
String conteudo = responseToString(response);
LOG.info(conteudo);
if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
throw new NegocioException(\"Falha ao autenticar no serviço: \" + conteudo);
}
@SuppressWarnings(\"unchecked\")
Map<String,String> resultMap = mapper.readValue(conteudo,HashMap.class);
cloudMessagingDAO.setValues(resultMap);
return oathToken = new OAuthToken(resultMap.get(KEY_ACCESS_TOKEN),resultMap.get(KEY_TOKEN_TYPE));
}
}