具有SOCKS支持的APNS Java简单实现(Apple推送通知服务)

时间:2014-01-22 11:17:37

标签: java ios apple-push-notifications socks

我一直在寻找一种易于集成,简单轻便的APNS(Apple推送通知服务)Java实现。

2个java库(同样?)受欢迎:

  • javapns
  • java的APNS。

两者都非常臃肿且整合起来很复杂,尽管它们(通常)声称它非常简单。两个库都声称SOCKS代理支持,但我没有设法使它工作,并在几个小时后挖掘源代码并做了很多尝试我正在寻找另一种解决方案。

任何人都有Java简单的实现吗?我认为应该可以只在一个类中提供functionnality。 请注意我需要SOCKS代理支持。

1 个答案:

答案 0 :(得分:0)

我终于编写了自己的单一类实现,用于通过APNS发送通知。

以下是代码,希望它有所帮助。 请注意,通知的有效负载格式(标题,文本,声音等)不在此处,也不是用于发送到许多智能手机的排队。 此实现可以使用或不使用SOCKS代理,请参阅代码以获取详细信息。

public class APNSHelper
{
private static SSLContext sslContext;
private static SSLSocketFactory sslSocketFactory;
private static SSLSocket sslSocket; 
private static DataOutputStream dataOutputStream;

private static final String KEYSTORE_TYPE = "PKCS12";
private static final String KEY_ALGORITHM = "sunx509";
private final static byte COMMAND = 0;

private static long lastSucessfulSocketUsageMillis = 0L;

private static void initSSL() throws Exception
{
    Logger.debug("ApnsHelper.initSSL() begin");
    try
    {
        FileInputStream stream = new FileInputStream(Constants.IOS_CERTIFICATE_PATH);
        final KeyStore lks = KeyStore.getInstance(KEYSTORE_TYPE);
        lks.load(stream, Constants.IOS_CERTIFICATE_PASSWORD.toCharArray());
        final KeyManagerFactory lkmf = KeyManagerFactory.getInstance(KEY_ALGORITHM);
        lkmf.init(lks, Constants.IOS_CERTIFICATE_PASSWORD.toCharArray());
        final TrustManagerFactory ltmf = TrustManagerFactory.getInstance(KEY_ALGORITHM);
        ltmf.init((KeyStore)null);
        sslContext = SSLContext.getInstance("TLS");
        sslContext.init(lkmf.getKeyManagers(), ltmf.getTrustManagers(), null);
        sslSocketFactory = sslContext.getSocketFactory();
    }
    catch(Exception e)
    {
        Logger.error("ApnsHelper.initSSL: " + e);
        throw e;
    }
    Logger.debug("ApnsHelper.initSSL() end");
}

private static Socket getSocket() throws Exception
{
    Logger.debug("ApnsHelper.getSocket() begin");

    if (sslSocketFactory == null) initSSL();

    if (sslSocket != null)
    {
        try
        {
            dataOutputStream.close();
            sslSocket.close();
        }
        catch(Exception e)
        {
            Logger.error("ApnsHelper.getSocket(): closing sslSocket: " + e);
        }
        dataOutputStream = null;
        sslSocket = null;
    }

    try
    {
        Socket infraSocket = null;
        if (Constants.IOS_PUSH_SOCKS_PROXY_HOST != null && Constants.IOS_PUSH_SOCKS_PROXY_HOST.length() > 0)
        {
            Logger.debug("ApnsHelper.getSocket(): with SOCKS PROXY=" + Constants.IOS_PUSH_SOCKS_PROXY_HOST + ":" + Constants.IOS_PUSH_SOCKS_PROXY_PORT);

            InetSocketAddress proxyAddr = new InetSocketAddress(Constants.IOS_PUSH_SOCKS_PROXY_HOST, Constants.IOS_PUSH_SOCKS_PROXY_PORT);
            Proxy proxy = new Proxy(Proxy.Type.SOCKS, proxyAddr);
            infraSocket = new Socket(proxy);
        }
        else
        {
            Logger.debug("ApnsHelper.getSocket(): NO proxy");

            // NO SOCKS version
            infraSocket = new Socket();
        }

        InetSocketAddress targetAddr = new InetSocketAddress(Constants.IOS_PUSH_GATEWAY_HOST, Constants.IOS_PUSH_GATEWAY_PORT);
        infraSocket.connect(targetAddr);
        sslSocket = (SSLSocket) sslSocketFactory.createSocket(infraSocket, Constants.IOS_PUSH_GATEWAY_HOST, Constants.IOS_PUSH_GATEWAY_PORT, true);

        Logger.debug("ApnsHelper.getSocket(): starting SSL handshake");
        sslSocket.startHandshake();
        Logger.debug("ApnsHelper.getSocket(): ended SSL handshake");
    }
    catch(Exception e)
    {
        Logger.error("ApnsHelper.getSocket(): " + e);
        throw e;
    }

    Logger.debug("ApnsHelper.getSocket() end");

    return sslSocket;
}

private static int hexValue(final char c) throws Exception
{
    if ('0' <= c && c <= '9') return (c - '0');
    if ('a' <= c && c <= 'f') return (c - 'a') + 10;
    if ('A' <= c && c <= 'F') return (c - 'A') + 10;

    Logger.error("Invalid hex char='" + c + "'");
    throw new Exception("Invalid hex char='" + c + "'");
}

public static synchronized void apnsPush(String mobileUIDID, String payLoad)
{
    Logger.debug("ApnsHelper.apnsPush(mobileUIDID=" + mobileUIDID + ", payLoad=" + payLoad+ ") begin");

    int ltries = 0;
    while( ltries < 3)
    {
        try
        {
            if (sslSocket == null || lastSucessfulSocketUsageMillis + Constants.IOS_PUSH_STALLED_MAX_TIME < System.currentTimeMillis())
            {
                getSocket();
            }
            dataOutputStream = new DataOutputStream(new BufferedOutputStream(sslSocket.getOutputStream()));

            byte[] lpayLoad = payLoad.getBytes("UTF-8");
            final byte[] deviceId = new byte[mobileUIDID.length() / 2];
            for (int i = 0; i < deviceId.length; i++) deviceId[i] = (byte) ((hexValue(mobileUIDID.charAt(2*i)) * 16 + hexValue(mobileUIDID.charAt(2*i + 1))));

            dataOutputStream.writeByte(COMMAND);
            dataOutputStream.writeShort(deviceId.length);
            dataOutputStream.write(deviceId);
            dataOutputStream.writeShort(lpayLoad.length);
            dataOutputStream.write(lpayLoad);

            dataOutputStream.flush();
            lastSucessfulSocketUsageMillis = System.currentTimeMillis();
            Logger.debug("ApnsHelper.apnsPush(): sent message, mobileUIDID=" + mobileUIDID + ", payLoad=" + payLoad);
            break;
        }
        catch(Exception e)
        {
            Logger.error("ApnsHelper.apnsPush(): " + e);
            ltries++;
        }
    }
    Logger.debug("ApnsHelper.apnsPush(mobileUIDID=" + mobileUIDID + ", payLoad=" + payLoad+ ") end");
}

} }“

相关问题