开发环境xcode7.1 运行环境 IOS9.1

IOS的信送简单就是在开开发者管理门户中创建推送证书,然后生成服务器推送证书(服务端代码可以是任意的,我们采用C#来写),App中嵌入推送代码,App安装后允许推送后就可以收到服务端的推送消息了,关于更进一步的原理说明,可以查看官方文档。

 

前提是你已经开通购买了apple的开发者帐户,并且已经有开发证书,能正常创建运行项目到你的iphone上了,如果以前条件不具备,请先参完成以上步骤。

导出证书

打开Mac系统的“钥匙串访问”-“证书助理”-“从证书颁发机构请求证书

wKiom1Yu907zcobtAATUB6Kqd-0667.jpg

输入邮箱和名称,选择“存储到磁盘”

wKiom1Yu94_ysOcmAALbjJL5frU882.jpg

在弹出框中***的名字为RemotePush_CertificateSigningRequest.certSigningRequest请注意,这记住这个名字和保存路径,马上在创建App ID时会用到。

添加App ID

登录apple的开发者门户,进入到“MemberCenter-Certificates,Identifiers&Profiles”-IOSApps下的“Certificates”-Identifiers”-“AppIDs”

wKiom1Yu97yhJvMqAAWXG8XIWjM252.jpg

这时,还有没在xcode下创建自己的项目,所以App IDs下还无法添加对应的App ID,现在先在xcode下创建一个项目,名字叫RemotePushDemo

wKioL1Yu-B2CQQkVAAJ1u8cuosw822.jpg

现在添加一个App ID

wKiom1Yu-CuAg8tBAAV863vfFO4761.jpg

wKioL1Yu-F7iqhMuAALhCZAXPLc168.jpg

wKioL1Yu-F6CBhTQAAQESSecERE706.jpg



然后提交

wKiom1Yu-GiRoMsrAARYS1FyLeo706.jpg

提交成功后,在App IDs中选择刚添加的RemotePush,点击Edit

wKioL1Yu-LKRh3aUAAV4R2a5X3o112.jpg

找到Push Notifications节点,点击CreateCertificate(如果是发布,就先Production SSL Certificate下的Create Certificate)

 wKiom1Yu-JfTKDUHAANVQ5_UNGs608.jpg

选择继续,直到选择上传证书页面,点击选择证书

wKioL1Yu-PPDBFW2AANJcmArvfU254.jpg

这是找到文章开始先择导出的证书RemotePush_CertificateSigningRequest.certSigningRequest,然后点击Generate生成证书

 wKiom1Yu-OPy6kZ1AAR023p074I542.jpg


这时,就可以下载生成的证书了,下载完成后双击安装证书。

wKioL1Yu-S7iEfYpAAPWW8v9glU868.jpg

安装完成后可以钥匙串访问的“登录”下,类型为证书下看到安装的证书了。

wKiom1Yu-TLBPxN7AATHWfK506o055.jpg

选中这张证书,右键,选择导出证书选项,然后在弹出框中输入证书名称,要使用.p12格式,同时,需要输入证书密码,这时一定要记住自己设定的证书密码,这个证书和密码将要在服务端使用。在最后,导出证书时需要系统登录密码,以作验证。

配置Provisioning Profiles,选择Development添加,选择IOS App Development

wKioL1Yu-XyA5yQ4AAdXoapKzJ8294.jpg

要选择自己创建的App ID,然后保存下载,双击安装即可(安装后会自动打开xcode,可以在项目的Build Settings中搜Provisioning Profile的选项目中查看是否安装成功)。

wKioL1Yu-ZiwWjL7AASY2ETkdN0960.jpg

同时,在设置项目的Capabilities开启Remotenotifications

wKioL1Yu-bHgNG06AAMTAdhyncU556.jpg

接下来就开始写swiftapp中的代码了,打开项目的AppDelegate活加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
         
         UIApplication.sharedApplication().applicationIconBadgeNumber=0;
         
         application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: [UIUserNotificationType.Alert,UIUserNotificationType.Sound,UIUserNotificationType.Badge], categories: nil));
         
         return  true
     }
     
     // 8.0 
之后 收到远程推送通知
     func application(application: UIApplication , didReceiveRemoteNotification userInfo: [ NSObject : AnyObject ], fetchCompletionHandler completionHandler: ( UIBackgroundFetchResult ) -> Void ) {
    
     }
     func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
      
     }
     // 注册通知 alert 、 sound 、 badge ( 8.0 之后,必须要添加下面这段代码,否则注册失败)
     func application(application: UIApplication , didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings ) {
         application.registerForRemoteNotifications();
     }    
     
     func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
  
          print(deviceToken); //在输入窗口中查看此值
     }
     func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) {
     
     }


注意认识印的倒数第二个方法的deviceToken,这个值要作为服务端推送的设备值使用,每个设备,每次安装后都有一个唯一的值,同样设备卸载再次安装,此值会变化。

 

接下来是用C#写服务端了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
using  System;
using  System.Collections.Generic;
using  System.IO;
using  System.Linq;
using  System.Net.Security;
using  System.Net.Sockets;
using  System.Security.Authentication;
using  System.Security.Cryptography.X509Certificates;
using  System.Text;
using  System.Threading.Tasks;
  
namespace  ConsoleApplication1
{
     class  Program
     {
         static  void  Main( string [] args)
         {
             while  ( true )
             {
                 pushMessage(Console.ReadLine());
             }
         }
         public  static  void  pushMessage( string  content)
         {         
             string  deviceID =  "deviceToken替换掉这里" ;
             int  port = 2195;
             var  hostname =  "gateway.sandbox.push.apple.com" ;
  
              var  certificatePath =  @"还记得.p12的证书文件吗?替换这里" ;
         
             X509Certificate2 clientCertificate =  new  X509Certificate2(System.IO.File.ReadAllBytes(certificatePath),  "还记得证书密码吗?你设定的,替换这里" );
  
             X509Certificate2Collection certificatesCollection =  new  X509Certificate2Collection(clientCertificate);
  
             TcpClient client =  new  TcpClient(hostname, port);
             SslStream sslStream =  new  SslStream(client.GetStream(),  false new  RemoteCertificateValidationCallback(ValidateServerCertificate),  null );
  
             try
             {
                 sslStream.AuthenticateAsClient(hostname, certificatesCollection, SslProtocols.Tls,  false );
                 MemoryStream memoryStream =  new  MemoryStream();
                 BinaryWriter writer =  new  BinaryWriter(memoryStream);
                 writer.Write(( byte )0);
                 writer.Write(( byte )0);
                 writer.Write(( byte )32);
  
                 writer.Write(HexStringToByteArray(deviceID.ToUpper()));
   
                 String payload =  "{\"aps\":{\"alert\":\""  + content +  "\",\"badge\":10,\"sound\":\"default\"}}" ;
                 var  payloadlength = System.Text.Encoding.UTF8.GetBytes(payload).Length;
                 writer.Write(( byte )0);
                 //writer.Write((byte)payload.Length);
                 writer.Write(( byte )payloadlength);
                 byte [] b1 = System.Text.Encoding.UTF8.GetBytes(payload);
                 writer.Write(b1);
                 writer.Flush();
                 byte [] array = memoryStream.ToArray();
                 sslStream.Write(array);
                 sslStream.Flush();
                 client.Close();
             }
             catch  (System.Security.Authentication.AuthenticationException ex)
             {
                 client.Close();
             }
             catch  (Exception e)
             {
                 client.Close();
             }
         }
  
         private  static  bool  ValidateServerCertificate( object  sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
         {     
             Console.WriteLine(certificate.Subject);         
             return  true ;
         }
  
         public  static  byte [] HexStringToByteArray( string  hex) 
         {
             return  Enumerable.Range(0, hex.Length)
                               .Where(x => x % 2 == 0)
                               .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
                               .ToArray();
         }
  
     }
}

















本文转自桂素伟51CTO博客,原文链接:http://blog.51cto.com/axzxs/1706713 ,如需转载请自行联系原作者