本来是想用netty做的,但是没有成功,我觉得是bytes的发送格式不对,特别是字节数。
主页: http://code.google.com/p/javapns/
使用的前提: http://code.google.com/p/javapns/wiki/GeneralRequirements
推送的简单例子: http://code.google.com/p/javapns/wiki/PushNotificationBasic
主页的wiki里面有不少例子和文档。使用推送的前提是要生成证书和要推送的设备令牌。
设备令牌是客户端程序第一次安装时生成的,apple的文档中有很详细的图,并提交给自己的push server。
apple的文档有c代码的例子,下面是一段从javapns截取的推送代码。
KeyStore ts = KeyStore.getInstance("PKCS12"); ts.load(new FileInputStream("d:/spncert.p12"), "123456".toCharArray()); KeyManagerFactory tmf = KeyManagerFactory.getInstance("SunX509"); tmf.init(ts, "123456".toCharArray()); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(tmf.getKeyManagers(), null, null); SSLSocketFactory factory = sslContext.getSocketFactory(); SSLSocket socket = (SSLSocket) factory.createSocket(host, port); String[] suites = socket.getSupportedCipherSuites(); socket.setEnabledCipherSuites(suites); // start handshake socket.startHandshake(); char[] t = token.toCharArray(); byte[] b = Arrays.toString(t).getBytes(); OutputStream outputstream = socket.getOutputStream(); byte[] deviceTokenAsBytes = new byte[token.length() / 2]; token = token.toUpperCase(); int j = 0; try { for (int i = 0; i < token.length(); i += 2) { String tt = token.substring(i, i + 2); int tmp = Integer.parseInt(tt, 16); deviceTokenAsBytes[j++] = (byte) tmp; } } catch (NumberFormatException e1) { throw new InvalidDeviceTokenFormatException(token, e1.getMessage()); } // Create the ByteArrayOutputStream which will contain the raw interface byte[] payloadAsBytes = payload.getBytes(); int size = (Byte.SIZE / Byte.SIZE) + (Character.SIZE / Byte.SIZE) + deviceTokenAsBytes.length + (Character.SIZE / Byte.SIZE) + payloadAsBytes.length; ByteArrayOutputStream bao = new ByteArrayOutputStream(size); // Write command to ByteArrayOutputStream // 0 = simple // 1 = enhanced byte zeron = 0; bao.write(zeron); // Write the TokenLength as a 16bits unsigned int, in big endian int tl = deviceTokenAsBytes.length; bao.write(intTo2ByteArray(tl)); // Write the Token in bytes bao.write(deviceTokenAsBytes); // Write the PayloadLength as a 16bits unsigned int, in big endian int pl = payloadAsBytes.length; bao.write(intTo2ByteArray(pl)); // Finally write the Payload bao.write(payloadAsBytes); bao.flush(); outputstream.write(bao.toByteArray()); outputstream.flush(); outputstream.close(); } static final byte[] intTo2ByteArray(int value) { int s1 = (value & 0xFF00) >> 8; int s2 = value & 0xFF; return new byte[] { (byte) s1, (byte) s2 }; }
上面代码中的: byte[] deviceTokenAsBytes = new byte[token.length() / 2];很重要。我看到这恍然大悟。。。。哎