昨天搞了许久的苹果的推送服务,看着文档不是很难。可是很少使用socket发送拼接字节一类的数据。后来找到了javapns,很方便。直接就推送成功了。
本来是想用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];很重要。我看到这恍然大悟。。。。哎