Клиентская структура Java / API для вызова службы push-уведомлений Windows phone - PullRequest
4 голосов
/ 25 мая 2011

Кто-нибудь знает, существует ли клиентская среда Java / API для вызова службы push-уведомлений Windows phone?Я знаю, что существует проект JavaPNS , специфичный для Apple PNS.Я ищу что-то похожее на это, но только для Windows Phone.

Любая помощь?

Ответы [ 2 ]

2 голосов
/ 15 апреля 2012

Java-mpns кажется близким к тому, что вы ищете.

https://github.com/notnoop/java-mpns

1 голос
/ 05 августа 2014

Я разработал решение с использованием Spring и Apache Commons HTTP Client для отправки RAW-сообщений с помощью WNS (Windows Notification Push Service)

Вставьте эти зависимости в ваш 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, entity, 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));
    }
}
...