apns_apn设置 - CSDN
精华内容
参与话题
  • APNs的学习和使用

    千次阅读 2018-04-10 16:29:15
    APNs(英文全称:Apple Push Notification service),中文翻译为:苹果推送通知服务。 该技术由苹果公司提供的APNs服务。苹果推送通知服务的传输和路由的通知从一个给定的供应商给定的设备。通知是由两个主要部分...
        
    APNs(英文全称:Apple Push Notification service),中文翻译为:苹果推送通知服务。 该技术由苹果公司提供的APNs服务。
    苹果推送通知服务的传输和路由的通知从一个给定的供应商给定的设备。通知是由两个主要部分组成的数据:设备令牌和有效载荷的短消息。设备令牌是类似于一个电话号码,它包含的信息,使的APN定位的设备上安装客户端应用程序。APN还用它来验证通知的路由有效载荷是一个JSON定义的属性列表中指定的设备上的应用程序的用户将被提醒。

        APNs在java的使用,这篇文章非常有效

    APNs入门学习和使用

    https://www.jianshu.com/p/bcdf0c609f7d

    作者:Coselding

    基本对着这个就能写出基本的APNs实例,本文主要讨论代码编写过程中出现的问题

        1.java.lang.NoClassDefFoundError: sun/security/ssl/EllipticCurvesExtension

    假如你已经加了java虚拟机参数


    里面的alpn-boot-8.1.12.v20180117.jar是用来替换虚拟机中的jar包的,这时候出了异常,异常信息可能如下:

    [nioEventLoopGroup-2-1] WARN io.netty.handler.ssl.ApplicationProtocolNegotiationHandler - [id: 0x548cffb1, L://*你的ip*/:11364 - R:api.development.push.apple.com/17.188.166.29:443] Failed to select the application-level protocol:
    java.lang.NoClassDefFoundError: sun/security/ssl/EllipticCurvesExtension
    	at sun.security.ssl.ClientHandshaker.getKickstartMessage(ClientHandshaker.java:1526)
    	at sun.security.ssl.Handshaker.kickstart(Handshaker.java:1061)
    	at sun.security.ssl.SSLEngineImpl.kickstartHandshake(SSLEngineImpl.java:734)
    	at sun.security.ssl.SSLEngineImpl.beginHandshake(SSLEngineImpl.java:756)
    	at io.netty.handler.ssl.JdkSslEngine.beginHandshake(JdkSslEngine.java:147)
    	at io.netty.handler.ssl.SslHandler.handshake(SslHandler.java:1360)
    	at io.netty.handler.ssl.SslHandler.channelActive(SslHandler.java:1399)
    	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:223)
    	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:209)
    	at io.netty.channel.AbstractChannelHandlerContext.fireChannelActive(AbstractChannelHandlerContext.java:202)
    	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelActive(DefaultChannelPipeline.java:1322)
    	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:223)
    	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:209)
    	at io.netty.channel.DefaultChannelPipeline.fireChannelActive(DefaultChannelPipeline.java:902)
    	at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.fulfillConnectPromise(AbstractNioChannel.java:311)
    	at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:341)
    	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:627)
    	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:551)
    	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:465)
    	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:437)
    	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:873)
    	at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144)
    	at java.lang.Thread.run(Thread.java:748)
    [nioEventLoopGroup-2-1] INFO com.relayrides.pushy.apns.ApnsClient - Failed to connect.
    java.lang.IllegalStateException: Channel closed before HTTP/2 preface completed.
    	at com.relayrides.pushy.apns.ApnsClient$2.operationComplete(ApnsClient.java:412)
    	at com.relayrides.pushy.apns.ApnsClient$2.operationComplete(ApnsClient.java:404)
    	at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:514)
    	at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:488)
    	at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:427)
    	at io.netty.util.concurrent.DefaultPromise.trySuccess(DefaultPromise.java:111)
    	at io.netty.channel.DefaultChannelPromise.trySuccess(DefaultChannelPromise.java:82)
    	at io.netty.channel.AbstractChannel$CloseFuture.setClosed(AbstractChannel.java:1058)
    	at io.netty.channel.AbstractChannel$AbstractUnsafe.doClose0(AbstractChannel.java:686)
    	at io.netty.channel.AbstractChannel$AbstractUnsafe.close(AbstractChannel.java:664)
    	at io.netty.channel.AbstractChannel$AbstractUnsafe.close(AbstractChannel.java:607)
    	at io.netty.channel.DefaultChannelPipeline$HeadContext.close(DefaultChannelPipeline.java:1276)
    	at io.netty.channel.AbstractChannelHandlerContext.invokeClose(AbstractChannelHandlerContext.java:634)
    	at io.netty.channel.AbstractChannelHandlerContext.close(AbstractChannelHandlerContext.java:618)
    	at io.netty.channel.ChannelOutboundHandlerAdapter.close(ChannelOutboundHandlerAdapter.java:71)
    	at io.netty.channel.AbstractChannelHandlerContext.invokeClose(AbstractChannelHandlerContext.java:634)
    	at io.netty.channel.AbstractChannelHandlerContext.close(AbstractChannelHandlerContext.java:618)
    	at io.netty.handler.ssl.SslHandler$8.operationComplete(SslHandler.java:1437)
    	at io.netty.handler.ssl.SslHandler$8.operationComplete(SslHandler.java:1428)
    	at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:514)
    	at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:488)
    	at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:427)
    	at io.netty.util.concurrent.DefaultPromise.addListener(DefaultPromise.java:170)
    	at io.netty.channel.DefaultChannelPromise.addListener(DefaultChannelPromise.java:93)
    	at io.netty.channel.DefaultChannelPromise.addListener(DefaultChannelPromise.java:28)
    	at io.netty.handler.ssl.SslHandler.safeClose(SslHandler.java:1428)
    	at io.netty.handler.ssl.SslHandler.closeOutboundAndChannel(SslHandler.java:1259)
    	at io.netty.handler.ssl.SslHandler.close(SslHandler.java:449)
    	at io.netty.channel.AbstractChannelHandlerContext.invokeClose(AbstractChannelHandlerContext.java:634)
    	at io.netty.channel.AbstractChannelHandlerContext.close(AbstractChannelHandlerContext.java:618)
    	at io.netty.channel.AbstractChannelHandlerContext.close(AbstractChannelHandlerContext.java:475)
    	at io.netty.handler.ssl.ApplicationProtocolNegotiationHandler.exceptionCaught(ApplicationProtocolNegotiationHandler.java:122)
    	at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:295)
    	at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:274)
    	at io.netty.channel.AbstractChannelHandlerContext.fireExceptionCaught(AbstractChannelHandlerContext.java:266)
    	at io.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:743)
    	at io.netty.channel.AbstractChannelHandlerContext.invokeExceptionCaught(AbstractChannelHandlerContext.java:295)
    	at io.netty.channel.AbstractChannelHandlerContext.notifyHandlerException(AbstractChannelHandlerContext.java:862)
    	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:225)
    	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:209)
    	at io.netty.channel.AbstractChannelHandlerContext.fireChannelActive(AbstractChannelHandlerContext.java:202)
    	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelActive(DefaultChannelPipeline.java:1322)
    	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:223)
    	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:209)
    	at io.netty.channel.DefaultChannelPipeline.fireChannelActive(DefaultChannelPipeline.java:902)
    	at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.fulfillConnectPromise(AbstractNioChannel.java:311)
    	at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:341)
    	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:627)
    	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:551)
    	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:465)
    	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:437)
    	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:873)
    	at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144)
    	at java.lang.Thread.run(Thread.java:748)
    [nioEventLoopGroup-2-1] WARN io.netty.handler.ssl.ApplicationProtocolNegotiationHandler - [id: 0x548cffb1, L:/192.168.2.71:11364 ! R:api.development.push.apple.com/17.188.166.29:443] TLS handshake failed:
    java.nio.channels.ClosedChannelException
    	at io.netty.handler.ssl.SslHandler.channelInactive(...)(Unknown Source)

    每个alpn-boot包都对应一个单独的jdk版本,并且严格对照版本,因此需要找到对应jdk版本的包,下面是包与jdk的对照表:


    具体参照https://www.eclipse.org/jetty/documentation/current/alpn-chapter.html

    看网上说用

    jetty-alpn-agent-2.0.6.jar  
    可以自动选择与jdk版本对应的包

    2.slf4报错

    pushy依赖于slf4j-api的包,但是并没有slf4j的具体实现,因此会出现如下错误:

    SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
    SLF4J: Defaulting to no-operation (NOP) logger implementation
    SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

    这时只需要添加slf4j-simple的依赖就可以了

    <dependency>
    	<groupId>org.slf4j</groupId>
    	<artifactId>slf4j-simple</artifactId>
    	<version>1.7.25</version>
    </dependency>

    3.消息发送阻塞

    	final Future<PushNotificationResponse<SimpleApnsPushNotification>> sendNotificationFuture = apnsClient.sendNotification(pushNotification);
    final PushNotificationResponse<SimpleApnsPushNotification> pushNotificationResponse = future.get();
    

    如果有多条消息发送,在下一条消息发送之前,只能等上一条消息发送之后得到响应才能发送下一条消息,这无疑是相当耗费时间的,如果想并行的发送消息,就是其他文章说的异步回调方式,可以用:

    final PushNotificationResponse<SimpleApnsPushNotification> pushNotificationResponse = future.getNow();
    这样的话不用等消息发送后得到响应才发送下一条消息了


    贴一下项目代码

    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.TimeUnit;
    
    import javax.net.ssl.SSLException;
    
    import com.relayrides.pushy.apns.ApnsClient;
    import com.relayrides.pushy.apns.ApnsClientBuilder;
    import com.relayrides.pushy.apns.PushNotificationResponse;
    import com.relayrides.pushy.apns.util.ApnsPayloadBuilder;
    import com.relayrides.pushy.apns.util.SimpleApnsPushNotification;
    import com.relayrides.pushy.apns.util.TokenUtil;
    
    import io.netty.channel.EventLoopGroup;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.util.concurrent.Future;
    import io.netty.util.concurrent.GenericFutureListener;
    
    public class MyApnsClient {
    	static ApnsClient apnsClient;
    
    	/*
    	 * static URL url = MyApnsClient.class.getClassLoader().getResource("dev.p12");
    	 * static File file = new File(url.getFile());
    	 */
    	public static void main(String[] args) {
    		try {
    			//并行线程数
    			EventLoopGroup loopGroup = new NioEventLoopGroup(4);
    			//建立apns的客户端,可添加自己写的监听类,实现ApnsClientMetricsListener接口
    			apnsClient = new ApnsClientBuilder().setEventLoopGroup(loopGroup)
    					.setMetricsListener(new MyApnsClientListener())
    					.setClientCredentials(new File("G:\\path\\test.p12"), "123456").build();
    			//设置apns服务器host
    			final Future<Void> connectFuture = apnsClient.connect(ApnsClient.DEVELOPMENT_APNS_HOST);
    			// 设置等待时间,可抛出中断异常
    			connectFuture.await();
    			//connectFuture.await(10, TimeUnit.MINUTES);
    			List<SimpleApnsPushNotification> pushNotifications=new ArrayList<SimpleApnsPushNotification>();
    			for(int i=0;i<10;i++) {
    				final SimpleApnsPushNotification pushNotification;
    				{
    					//消息的载体
    					final ApnsPayloadBuilder payloadBuilder = new ApnsPayloadBuilder();
    					payloadBuilder.setAlertBody("hello world");
    					payloadBuilder.setSoundFileName("system_sing.mp3");
    					payloadBuilder.setBadgeNumber(1);
    					payloadBuilder.setContentAvailable(true);
    					final String payload = payloadBuilder.buildWithDefaultMaximumLength();
    					//设备的唯一标识号devicetoken
    					final String token = TokenUtil
    							.sanitizeTokenString("your device token");
    					pushNotification = new SimpleApnsPushNotification(token, null, payload);
    				}
    				pushNotifications.add(pushNotification);
    			}
    			for(SimpleApnsPushNotification pushNotification:pushNotifications) {
    				//发送信息得到回应的实例,是异步的,会立马创建一个实例,但可能是发送未成功的状态
    				final Future<PushNotificationResponse<SimpleApnsPushNotification>> sendNotificationFuture = apnsClient
    						.sendNotification(pushNotification);
    				sendNotificationFuture.addListener(
    						new GenericFutureListener<Future<PushNotificationResponse<SimpleApnsPushNotification>>>() {
    
    							@Override
    							public void operationComplete(
    									Future<PushNotificationResponse<SimpleApnsPushNotification>> future) throws Exception {
    								final PushNotificationResponse<SimpleApnsPushNotification> pushNotificationResponse = future
    										.getNow();
    								if (pushNotificationResponse.isAccepted()) {
    									System.out.println("Push notification accepted by APNs gateway.");
    								} else {
    									System.out.println("Notification rejected by the APNs gateway: "
    											+ pushNotificationResponse.getRejectionReason());
    
    									if (pushNotificationResponse.getTokenInvalidationTimestamp() != null) {
    										System.out.println("\t…and the token is invalid as of "
    												+ pushNotificationResponse.getTokenInvalidationTimestamp());
    									}
    								}
    							}
    						});
    			}
    			final Future<Void> disconnectFuture = apnsClient.disconnect();
    			try {
    				disconnectFuture.await();
    				if (disconnectFuture.isSuccess()) {
    					System.out.println("连接关闭");
    				}
    			} catch (InterruptedException e) {
    				System.out.println("Failed to disconnect APNs , timeout");
    				e.printStackTrace();
    			}
    		} catch (SSLException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		} catch (InterruptedException e) {
    			System.out.println("Failed to connect APNs , timeout");
    			e.printStackTrace();
    		} /*
    			 * catch (ExecutionException e) {
    			 * System.err.println("Failed to send push notification."); if (e.getCause()
    			 * instanceof ClientNotConnectedException) {
    			 * System.out.println("Waiting for client to reconnect…"); try {
    			 * apnsClient.getReconnectionFuture().await(); } catch (InterruptedException e1)
    			 * { System.out.println("Failed to connect APNs , timeout");
    			 * e1.printStackTrace(); } System.out.println("Reconnected."); }
    			 * e.printStackTrace(); }
    			 */
    	}
    
    }

    展开全文
  • APNS

    2019-09-24 00:50:34
    前言:现在第三方推送也很多 ,比如极光,融云,信鸽,其原理也是相同利用APNS推送机制 。 自己做推送的好处:,1.避免device token被第三方泄露,保护手机设备信息,2.第三方部分开始收费,一些免费的以后谁又知道...

    前言:现在第三方推送也很多 ,比如极光,融云,信鸽,其原理也是相同利用APNS推送机制 。

    自己做推送的好处:,1.避免device token被第三方泄露,保护手机设备信息,2.第三方部分开始收费,一些免费的以后谁又知道呢 ,不如自己创建,除了后台麻烦点,需要数据库来存储token相关字段(后台配置部分在最后更新添加),前端实现起来并不复杂 。 对于iOS8.0以后,原生推送实时性很好,也解决了第三方SDK占用存储顾虑,何乐不为呢!

     

    1.APNS的推送机制

    APNs(Apple Push Notification service)是远程推送功能的核心。

    deviceToken是设备的一个标识符,属于你这款APP装在你这个设备上的标识符,即每个APP在每一个不同的设备上都有着不同的deviceToekn,通过注册远程推送服务,APNs会返回给你的APP的deviceToken。

    首先我们看一下苹果官方给出的对ios推送机制的解释。如下图


     

    Provider就是我们自己程序的后台服务器,APNS是Apple Push Notification Service的缩写,也就是苹果的推送服务器。
    上图可以分为三个阶段:
    第一阶段:应用程序的服务器端把要发送的消息、目的iPhone的标识打包,发给APNS。
    第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发送到iPhone。
    第三阶段:iPhone把发来的消息传递给相应的应用程序,并且按照设定弹出Push通知。

    APNS推送通知的详细工作流程
    下面这张图是说明APNS推送通知的详细工作流程:


     

    根据图片我们可以概括一下:
    1、应用程序注册APNS消息推送。
    2、iOS从APNS Server获取devicetoken,应用程序接收device token。
    3、应用程序将device token发送给程序的PUSH服务端程序。
    4、服务端程序向APNS服务发送消息。
    5、APNS服务将消息发送给iPhone应用程序。

    准备工作
    首先要有一台苹果的设备,模拟器是不支持推送的,所以你需要一台iphone,ipod touch或者ipad。

    我们的客户端与苹果服务器之间和我们自己的服务器与苹果服务器之间都需要证书来进行链接。下面我们来开始进入证书的制作过程。

    转载于:https://www.cnblogs.com/developer-qin/p/9007453.html

    展开全文
  • APNS(Apple Push Notification services)

    千次阅读 2019-07-05 13:02:33
    苹果的推送服务APNs基本原理简单来说就是苹果利用自己专门的推送服务器(APNs)接收来自我们自己应用服务器的需要被推送的信息,然后推送到指定的iOS设备上,然后由设备通知到我们的应用程序,设备以通知或者声音的...

    苹果的推送服务APNs基本原理简单来说就是苹果利用自己专门的推送服务器(APNs)接收来自我们自己应用服务器的需要被推送的信息,然后推送到指定的iOS设备上,然后由设备通知到我们的应用程序,设备以通知或者声音的形式通知用户有新的消息。推送的前提是装有我们应用的设备需要向APNs服务器注册,注册成功后APNs服务器会返给我们一个device_token,拿到这个token后我们将这个token发给我们自己的应用服务器,当有需要被推送的消息时,我们的应用服务器会将消息按指定的格式打包,然后结合设备的device_token一并发给APNs服务器,由于我们的应用和APNs维持一个基于TCP的长连接,APNs将新消息推送到我们设备上,然后在屏幕上显示出新消息来。整个过程基本就这样,下面我们看一下设备注册APNs的流程图:

    上图完成了如下步骤:

    1、Device连接APNs服务器并携带设备序列号

    2、连接成功,APNs经过打包和处理产生device_token并返回给注册的Device

    3、Device携带获取的device_token向我们自己的应用服务器注册

     

    推送经过的流程参照下图:

    图中,Provider是指的是我们的应用服务器,APNS 是Apple Push Notification Service(苹果的推送服务器)。

    上图可以分为三个阶段。

    第一阶段:我们的应用服务器把要发送的消息、目的iPhone的标识打包,发给APNS。

    第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发到iPhone。

    第三阶段:iPhone把发来的消息传递给相应的应用程序, 并且按照设定弹出Push通知。

     

    从上图我们可以看到。

    1、首先是应用程序注册消息推送。

    2、 iOS跟APNS Server要deviceToken。应用程序接受deviceToken。

    3、应用程序将deviceToken发送给PUSH服务端程序。

    4、 服务端程序向APNS服务发送消息。

    5、APNS服务将消息发送给iPhone应用程序。

    展开全文
  • APNs初体验

    万次阅读 2011-09-01 15:20:48
    首先,确定你已经有了CSR证书请求、开发证书和App ID。如果你不是第一次开发iOS应用程序,那么你可能已经有了这些东西。那么你可以继续以下的步骤。一、配置App ID登录你的provisioningportal,点击左侧边栏的App ...点

    首先,确定你已经有了CSR证书请求、开发证书和App ID。如果你不是第一次开发iOS应用程序,那么你可能已经有了这些东西。那么你可以继续以下的步骤。

    一、配置App ID

    登录你的provisioningportal,点击左侧边栏的App ID菜单,可以查看你现有的App ID。

    点击打开链接

    图 1-1

    选择一个App ID进行配置。注意列表中有的App ID的Apple Push Notification Service列是灰色的,并且不允许使用Configure按钮。这是因为APNs不支持带统配符的AppID。

    你可以配置现有的App ID,也可以重新创建一个。我们假设是后者。点击New App ID,按照如下截图进行设置:

    点击打开链接

    图 1-2

    注意,在Bundle Seed ID一栏,苹果提供了Team ID的概念,如果你要和其他应用程序共享钥匙串,可以选择一个已经存在的BundleSeed ID。

    点击Submit,马上可以在App ID中看到你新建的PushAppID,点击右边的Configure按钮,进入App ID配置页面:

    点击打开链接

    图 1-3

    勾选“Enable for Apple Push Notification service”,点击“Development Push SSLCertificate”右边的“Configure”按钮。

    在接下来的“Apple Push Notification service SSL Certificate Assistant”页面中,点击Continue按钮。

    然后选择你硬盘上保存的CSR证书请求文件,点击Generate按钮,以生成一个SSL证书。点击download按钮把ssl证书下载到本地 :

    点击打开链接

    图 1-4

    文件名为aps_developer_identity.cer,双击,将证书安装到钥匙串中。这个证书会在你的程序中用到,它允许程序接收 APNs 发送来的推送通知。

    二、创建 Provisioning Profile

    Provisioning Profile用于把ssl证书安装到设备上。点击Provisioning Portal中左侧边栏的Provisioning菜单进入ProvisioningProfile页面。

    用New Profile按钮新建一个Provisioning Profile。

    点击打开链接

    图 2-1

    ProfileName填写PushDeviceProfile,Certificate勾选你所用的开发证书(这个证书将和第三步Code Signing中设置的一致),如果不太清楚,把所有证书勾上即可。AppID栏选择我们前面创建的App ID。Devices勾上用于接收推送通知的设备,也可以把所有设备勾上。

    点击Submit,将创建Profile。等待几秒刷新页面,Download按钮将出现,下载该证书,文件名为 PushDeviceProfile.mobileprovision。把设备连接上Mac,将该mobileprovision文件拖到 Dock 栏的 Xcode 图标,即可在设备上安装该profile。

    三、创建APNs应用程序

    创建Window-based Application,命名为APNsTest。准备一个.wav文件,比如machinegun.wav,拖到Groups& Files的resources组中。

    选择Targets下的APNsTest,打开info窗口,并切换到Properties页。把Indentifier修改为我们前面创建的AppId:com.ydtf.AppID。

    切换到 Build 页,在 search 输入框中键入 Code Signing。在 Any iPhone OS Device 选项,选择正确的profile(请回忆第二步创建Provisioning Profile时选择的证书) ,注意证书和profile是成对使用的,如下图所示 :

    点击打开链接

    图 3-1

    在本例中,我们用于代码签名的profile是前面创建的PushDeviceProfile,使用的证书是Hongyan Yang(正是我们在创建profile时,在Certificates栏中选择的证书,见图2-1)。

    打开APNsTestAppDelegate.m,找到代码“[windowmakeKeyAndVisible];”,在后面加入:

    //注册APNs类型:警告+徽章+声音

    [[UIApplication sharedApplication]

     registerForRemoteNotificationTypes:

     (UIRemoteNotificationTypeAlert|

    UIRemoteNotificationTypeBadge|

    UIRemoteNotificationTypeSound)];

     

    然后实现3个方法:

    // 注册Device token

    - (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {

        NSString *str = [NSString

     stringWithFormat:@"Device Token=%@",deviceToken];

    NSLog(@"%@",str);

    }

    // 注册APNs错误

    - (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {

        NSString *str = [NSString stringWithFormat: @"Error: %@",err];

    NSLog(@"%@",str);

    }

    // 接收推送通知

    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {

    NSString *msg=[NSString stringWithFormat:@"%@",userInfo];

        UIAlertView* alert=[[UIAlertView alloc]initWithTitle:@"通知"

     message:msg delegate:nil

      cancelButtonTitle:@"OK" otherButtonTitles:nil];

    [alert show];

    alert=nil;

    }

    在真实设备上运行程序(不要在模拟器上运行!),iOS会在屏幕出现一个提示框,问你是否同意应用程序APNsTest接收推送通知,当你点击同意后,会在控制台看到输出的Devicetoken:

    DeviceToken=<804d95ab 708a0aad 33a08c1f 00341ae2 3774bcb0 02362e33 9a8535758f36dc90>

    你可以把这个Device token复制下来,等下要用。

    打开设备的“设置->通用”,可以看到所有使用APNs的应用程序列表:

    点击打开链接

    图 3-2

    可以看到,我们的APNsTest程序已经注册了APNs类型:标记、提醒、声音。你可以在这里更改这些设置。

    四、推送通知提供者

    推送通知提供者是一个程序,用于负责和苹果APNs服务器进行SSL通讯,它是实际上的通知发送者。如果你想想用户设备上的应用程序发送消息,实际上是由推送通知提供者进行的。实际上,整个APNs服务由3层应用程序构成:

    推送通知提供者、Apple APNs服务器、iOS客户端。

    苹果APNs服务器位于两者中间,起到一个中间人的角色。提供者向客户端发送消息,必须由APNs服务器来转发。开发人员除了需要实现客户端外,还需要实现提供者的代码。我们前面创建的SSL证书aps_developer_identity.cer,需要在提供者程序中使用,因为与APNs服务器通讯需要一个合法的SSL数字证书。

    如果仅仅是测试,我们可以使用一个其他人已经实现的提供者:

    PushMeBaby,下载地址

    下载后解压缩,实际上得到的是一个Xcode工程。打开PushMeBaby工程,将aps_developer_identity.cer文件导入到Resources文件夹。

    打开ApplicationDelegate.m文件,在init方法找到“self.deviceToken =”一行,将刚才复制的Devicetoken粘贴到这里:

    self.deviceToken = @"804d95ab708a0aad 33a08c1f 00341ae2 3774bcb0 02362e33 9a853575 8f36dc90";

    把“self.payload =”一行中的You got a new message!替换成我们自己的提示信息“收到一条推送通知。”。

    把“self.certificate =”一行中的apns替换成我们自己的SSL文件aps_developer_identity。

    运行PushMeBaby,程序显示如下界面:

    点击打开链接

    图 4-1

    当提示是否允许使用证书时,选择“总是允许”。然后点击Push按钮。

    稍后,你的iPhone/iPod会受到一条推送通知:

    点击打开链接

    图 4-2

    如果你点击“显示”按钮,则会启动APNsTest,并立即显示消息的内容。

    点击打开链接

    图 4-3

    在我们的self.payload中,仅仅使用了两个基本的通知类型:标记(badge)和提醒(alert)。

    self.payload = @"{\"aps\":{\"alert\":\"收到一条推送通知。\",\"badge\":1}}";

    实际上我们也可加上声音(sound)或者是其他自定义的键-值对,唯一的限制是整个payload不能超过256字节:

    self.payload = @"{\"aps\":{\"alert\":\"收到一条推送通知。\",\"badge\":5,\"sound\":\"machinegun.wav\",\"myData\":12345}}";

    还有一个有趣的地方。如果发送通知时,用户的APNsTest已经在当前任务中,那么当用户收到通知时,则忽略通知,并直接在APNsTest程序中呈现如图4-3所示的界面。



    展开全文
  • apns详细过程

    千次阅读 2013-11-15 14:24:12
    https://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/IPhoneOSClientImp/IPhoneOSClientImp.html#//apple_ref/doc/uid/TP40008194-CH103-SW1 ...
  • IOS消息推送之APNS

    万次阅读 多人点赞 2015-12-09 16:32:06
    APNS:Apple Push
  • iOS推送流程(APNS

    千次阅读 2017-12-04 14:33:15
    iOS推送流程(APNS)一、APNS(Apple Push Notification Service)苹果推送通知服务(APNs)是推送通知的网关,iPhone ipad 对于应用程序在后台运行有诸多限制,考虑到手机电池电量,应用不允许在后台进行过多的操作。...
  • APNS推送服务证书制作 图文详解教程

    万次阅读 2014-07-10 14:50:09
    Provider是指某个iPhone软件的Push服务器,APNS是Apple Push Notification Service的缩写,是苹果的服务器。   上图可以分为三个阶段: 第一阶段:应用程序把要发送的消息、目的iPhone的标识打包,发给APNS。  ...
  • APNS工作原理

    2015-03-02 16:23:15
    首先,APNS会对用户进行物理连接认证,和设备令牌认证(简言之就是苹果的服务器检查设备里的证书以确定其为苹果设备); 然后,将服务器的信息接收并且保存在APNS当中,APNS从其中注册的列表中查找该IOS设备(设备...
  • 该重新认识一下APNS推送了

    万次阅读 2016-06-18 18:21:57
    前言:APNs 协议在近两年的 WWDC 上改过两次,2015年12月17日更是推出了革命性的新特性。但在国内传播的博客、面试题里关于APNs的答案全都是旧的、错的。正文:对 APNs 的吐槽APNs 是 Apple Push Notification ...
  • APNs工具App推荐,适合APNs开发使用

    千次阅读 2018-09-14 11:46:28
    APNs工具App推荐,适合APNs开发使用 最近在调试APNs功能时,通过服务器下发消息太慢了,也很麻烦,之前都是自己从网上找APNs服务器代码,用过Java版、C#、Node.js、Python等等,过一段时间会出现项目运行不起来,...
  • apns.jar包用于apns推送

    热门讨论 2020-07-30 23:31:06
    apns.jar包,用于apns推送,直接导入就可以使用了
  • APNS苹果远程推送

    2019-01-02 14:15:20
    什么是APNS? 苹果推送通知服务(APNs)是推送通知的网关,iPhone ipad 对于应用程序在后台运行有诸多限制,考虑到手机电池电量,应用不允许在后台进行过多的操作。因此,当用户切换到其他程序后,原先的程序无法保持...
  • iOS远程推送--APNs详解

    千次阅读 2019-07-20 11:45:17
    iOS远程推送–APNs详解 iOS远程推送,远远不是配置两个证书,集成个SDK那么简单。 本文会从实践出发,结合苹果的官方文档,带你全面的了解苹果APNs服务。除了基础原理和集成方法外,还将详细介绍了APNs服务接口的...
  • 苹果推送服务(APNs)中文文档

    千次阅读 2017-05-12 13:29:43
    工作中需要用到APNs服务,所以打算将APNs的官方文档翻译出来,供有需求的朋友一起参考,水平有限,难免出错,还望不吝赐教。总览本地通知和远程通知本地通知和远程通知就是所谓的两种不同类型的通知,他们的区别在于...
  • IOS推送详解(一)------APNs

    千次阅读 2017-06-03 18:45:45
    博文会分几部分来写,先介绍下APNs,然后介绍协议(新的旧的都说下),然后介绍生成证书,最后上代码。 APNS IOS推送要比安卓推送简单的多,至少它不用咱们自己维护那些连接,IOS推送就是和APNs服务器通信。 每台...
  • APNs入门学习和使用

    千次阅读 2016-12-04 01:13:23
    本文为博主原创,允许转载,但请声明原文地址:http://www.coselding.cn/article/2016/12/01/APNs入门学习和使用/APNs入门学习和使用这篇文章费了我好多心血啊,这都是在我测试了一堆失败的代码,看了大量的博客之后...
  • apns-expiration:过期 A UNIX epoch date expressed in seconds (UTC). This header identifies the date when the notification is no longer valid and can >be discarded. If this value is nonzero, APNs ...
  • 最近公司需要用苹果APNs实现类似微信视频接电话的效果,查看了苹果官网有VOIP这个东西,于是进行了研究开发。 首先总结一下接入流程: 在开发者中心申请对应的证书(推送证书,VOIP证书) IOS 注册推送到APNs(直接...
  • iOS APNs推送常见问题

    2019-05-20 14:04:55
    但是只针对APNs进行总结,自建通道属于公司隐私,如有不同的意见欢迎补充,大家一起探讨。 一、推送消息没收到 1.1 客户端排查 检查设备通知设置,查看自己的应用是否打开了推送消息权限。 检查设备网络设置,有...
1 2 3 4 5 ... 20
收藏数 10,529
精华内容 4,211
关键字:

apns