精华内容
下载资源
问答
  • iOS 开发之实现 App 消息推送(最新)

    万次阅读 多人点赞 2014-11-19 21:13:10
    今天就由本菜鸟给大家做一个简单的IOSApp消息推送教程吧!一切从0开始,包括XCode6, IOS8, 以及苹果开发者中心最新如何注册应用,申请证书以及下载配置概要文件,相信很多刚开始接触ios的人会很想了解一下。(ps:...

    好久没有写过博客啦,今天就由本菜鸟给大家做一个简单的IOSApp消息推送教程吧!一切从0开始,包括XCode6, IOS8, 以及苹果开发者中心最新如何注册应用,申请证书以及下载配置概要文件,相信很多刚开始接触ios的人会很想了解一下。(ps:网上看了一下虽然有很多讲述推送的好教程,我也是看着一步步学会的,但是这些教程的时间都是去年或者更早时期的,对引导新手来说不是很合适)

    第一部分

    首先第一步当然是介绍一下苹果的推送机制(APNS)咯(ps:其实每一篇教程都有),先来看一张苹果官方对其推送做出解释的概要图。

    Provider是给你手机应用发出推送消息的服务器,而APNS(Apple Push Notification Service)则是苹果消息推送服务器。你本地的服务器当需要给应用推送一条消息的时候,先要将消息发出到苹果推送服务器,然后再由苹果推送服务器将消息发到安装了该应用的手机。

    接下来再看一张解释图:

     

    根据上图的逻辑我来给大家解释一下:

    1.你的IOS应用需要去注册APNS消息推送功能。

    2.当苹果APNS推送服收到来自你应用的注册消息就会返回一串device token给你(很重要)

    3.将应用收到的device Token传给你本地的Push服务器。

    4.当你需要为应用推送消息的时候,你本地的推送服务器会将消息,以及Device Token打包发送到苹果的APNS服

    5.APNS再将消息推送给目的iphone

     

    第二部分

    1.从证书颁发机构颁发证书

    打开你mac的钥匙串访问: 然后点击钥匙串访问

     

    随后它会弹出一个窗口用户电子邮件信息就填写你苹果开发者账号的名称即可(应该是一个邮件名称),点击保存到磁盘的选

    项,点击继续,显示如下:

     

    点击存储,文件名为:CertificateSigningRequest.certSigningRequest 随后将他放在一个文件夹中我们取名push吧!

     

    第三部分

    访问苹果开发者网址:https://developer.apple.com/

     

    选中MemberCenter选项,进入登陆页面,用你的苹果开发者账号登陆,过一会网页就会自动跳转到下图。

    点击红色所选部分内容进行下一步的操作。

    选择Certificates选项,设置证书,如图所示先解释一下:

     

     

    Development选项的作用顾名思义就是用来作为开发使用的证书,Production选项则是用来发布产品使用的,名称很陌生是不是,之

    前的开发者网页是没有这一选项的,可能是苹果把他修改了,用这个名称更加能让人理解吧(字面上解释就是产品么)。两个选项生

    成证书的步骤是一样的,现在我们使用开发者的选项进行证书的制作,步骤如下:选择Development选项:

     

    点击上面的加号选项,

     

    选择APNS选项(开发么当然是在沙盒环境下了,模拟真实情况),然后Continue

     

    这个AppID我们在下一部分讲如何生成,现在我用的是已经生成好的一个应用ID,继续Continue

     

    这边就要选择在钥匙串访问环节下载下来的CertificateSigningRequest.certSigningRequest文件了,选择并生成:

    点击下载,得到aps_development .cer,保存到push文件中去。

     

    第四部分

    新建一个AppID,选择网页上的AppIDs,然后点击右上角的 “加号”

     

    App的取名只要按照苹果要求的就可以了

     

    然后BundleID是比较重要的,在提交审核以及测试(苹果的TestFlight)和付费环节都需要用到,也只需按照苹果要求来写就好了。

     

    接下来就是对你的应用需要使用苹果的哪些服务进行选择就行了,例如广告,游戏中心,推送,付费等等情况。

    最后选择“Submit”选项,在下一个界面中选择“done”选项,这样我们设置AppID的步骤我们就完成了。


    第五部分:生成Provisioning Profiles

    这个配置概要文件分为两种,一种是为开发使用的,还有一种则是为发布到appStore上面。

    创建发布版的ProvisioningProfile与开发版的流程相同,点击Development然后点击右上角的加号

     

    会进入选择何种配置概要文件的界面:

     

    我们现在时测试,所以选择“IOS App Development”的选项,在下面的Distribution发布选项中有两个选择,“App Store”以及

    “Ad hoc”,你可以根据下面的描述选择你发布所需的选项。点击Continue进入下一步。

    选择你上一步创建的AppID,点击Continue 进行下一步

    选择你的开发者账号,Continue进行下一步

    在这一步上选择你的设备(你只有在这一步上勾选了你的设备,你才能在设备上用这个签名进行调试)。关于如何将你的设备号添加

    进去也是非常简单的,选择左侧的"Devices",然后点击右上角的加号,在随后出来的页面上添加你设备的UUID(在XCode中可以查

    看到)以及name( 可以随便取,自己看的懂就行)然后Register一下,照着流程走到最后一步就完成了。

    好咱们继续回到上面的Provisioning Profile配置环节,当你选好了你的设备后点击“Continue”进入下一页,

     

    输入一个文件名(最好是起的能看懂是干嘛的,当然也可以随便起),点击“Generate”进入下一个页面,在这个页面中就会有一个下

    载按钮让你下载这个文件,我们把它下载下来放在Push文件夹中。

     

    第六部分

    好了,前期的准备工作都已经做完了,现在让我们开始推送吧!(吼吼)

    首先双击我们生成的 “aps_development .cer” 文件,进入钥匙串访问,找到我们的专用秘钥(根据在第二部分中从证书机构颁发证书操作中填写的常用名)

     

    我在第二部分填写的是“silicon”,由于换了一台mac之前安装的没有了,之前没有截图,所以随便找了个图给大家看一下,凭大家的聪明才智应该不难理解吧。

    然后右击导出,会弹出如下所示的图。

     

    将他存储到push文件夹中,命名为“push.p12”,在这一步中导出会让你输入密码并验证,你可以自定义一个密码,例如abc123

    现在push文件夹中应该有几个文件“aps_development .cer” ,"push.p12",“CertificateSigningRequest.certSigningRequest”以及

    刚才下下来的配置概要文件。

     

    接下来我们打开终端将他们生成.pem文件

    1.把aps_development .cer文件生成.pcm文件,cd到push文件夹下

     

    2.把push.p12文件生成为.pem文件

    上边输入的密码则是你导出证书所设的密码,即abc123.接着还会让你输入.pem文件的密码,还是使用abc123好了,防止混淆。

    这样我们在push文件夹中就又得到了两个文件,PushChatCert.pem和PushChatKey.pem。

     

    3.把PushChatCert.pem和PushChatKey.pem合并为一个pem文件,

     

    在push文件夹中又多了一个ck.pem文件,以上我们把需要使用的文件都准备好了

     

    接下来就要测试一下啦,是不是很激动~

    为了测试证书工作的状况,我们可以使用“telnet gateway.sandbox.push.apple.com 2195”来检测一下,如果显示下图则表示成功了。

     

    然后,我们使用我们生成的证书和私钥来设置一个安全的链接去链接苹果服务器

    在终端输入如下命令:openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushChatCert.pem -key PushChatKey.pem

    需要输入密码(abc123 我们刚才所设置的)。

    然后他会返回一系列的数据,这里我就粘贴一部分啦:

     

    CONNECTED(00000003)

    depth=1 /C=US/O=Entrust, Inc./OU=www.entrust.net/rpa is incorporated by reference/OU=(c) 2009 Entrust, Inc./CN=Entrust Certification Authority - L1C

    verify error:num=20:unable to get local issuer certificate

    verify return:0

    ---

    Certificate chain

    。。。。。(省略)

    。。。。。(省略)

    。。。。。(省略)

     

        Start Time: 1416389389

        Timeout   : 300 (sec)

        Verify return code: 0 (ok)

    ---

    测试就到这里啦。。。

     

    第七部分

    1.建立推送项目

     

    //
    //  AppDelegate.m
    //  TestPushNotifiy
    //
    //  Created by silicon on 14-10-30.
    //  Copyright (c) 2014年 silicon. All rights reserved.
    //
    
    #import "AppDelegate.h"
    
    @implementation AppDelegate
    @synthesize mainView = _mainView;
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
        {
            //IOS8
            //创建UIUserNotificationSettings,并设置消息的显示类类型
            UIUserNotificationSettings *notiSettings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIRemoteNotificationTypeSound) categories:nil];
            
            [application registerUserNotificationSettings:notiSettings];
            
        } else{ // ios7
            [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge										 |UIRemoteNotificationTypeSound										 |UIRemoteNotificationTypeAlert)];
        }
        
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        // Override point for customization after application launch.
        self.window.backgroundColor = [UIColor whiteColor];
        [self.window makeKeyAndVisible];
        
        self.mainView = [[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil];
        self.window.rootViewController = self.mainView;
        return YES;
    }
    
    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken{
        NSLog(@"---Token--%@", pToken);
    }
    
    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
        
        NSLog(@"userInfo == %@",userInfo);
        NSString *message = [[userInfo objectForKey:@"aps"]objectForKey:@"alert"];
        
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
        
        [alert show];
    }
    
    - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
    
        NSLog(@"Regist fail%@",error);
    }
    
    - (void)applicationWillResignActive:(UIApplication *)application
    {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    }
    
    - (void)applicationDidEnterBackground:(UIApplication *)application
    {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }
    
    - (void)applicationWillEnterForeground:(UIApplication *)application
    {
        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    }
    
    - (void)applicationDidBecomeActive:(UIApplication *)application
    {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }
    
    - (void)applicationWillTerminate:(UIApplication *)application
    {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }
    
    @end
    

     

    在appdelegate.m中加入以上代码,

     

     

     

    if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
        {
            //IOS8
            //创建UIUserNotificationSettings,并设置消息的显示类类型
            UIUserNotificationSettings *notiSettings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIRemoteNotificationTypeSound) categories:nil];
            
            [application registerUserNotificationSettings:notiSettings];
            
        } else{ // ios7
            [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge										 |UIRemoteNotificationTypeSound										 |UIRemoteNotificationTypeAlert)];
        }

    由于ios8的推送跟ios7及以下的不一样,所以需要加判断来注册消息推送。

    函数:

     

    - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken{
        NSLog(@"---Token--%@", pToken);
    }

     

    会接收来自苹果服务器给你返回的deviceToken,然后你需要将它添加到你本地的推送服务器上。(很重要,决定你的设备能不能接收到推送消息)。

     

    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
        
        NSLog(@"userInfo == %@",userInfo);
        NSString *message = [[userInfo objectForKey:@"aps"]objectForKey:@"alert"];
        
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
        
        [alert show];
    }

     

    这个函数则是当设备接收到来自苹果推送服务器的消息时触发的,用来显示推送消息。

     

     

    - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
    
        NSLog(@"Regist fail%@",error);
    }

    当注册失败时,触发此函数。

     

     

    2.PHP服务端

    将simplepush.php这个推送脚本也放在push文件夹中

     

    <?php
    
    // ??????????deviceToken???????????????
    $deviceToken = 'c95f661371b085e2517b4c12cc76293522775e5fd9bb1dea17dd80fe85583b41';
    
    // Put your private key's passphrase here:
    $passphrase = 'abc123';
    
    // Put your alert message here:
    $message = 'My first push test!';
    
    
    
    $ctx = stream_context_create();
    stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem');
    stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);
    
    // Open a connection to the APNS server
    //??????????
     //$fp = stream_socket_client(?ssl://gateway.push.apple.com:2195?, $err, $errstr, 60, //STREAM_CLIENT_CONNECT, $ctx);
    //?????????????appstore??????
    $fp = stream_socket_client(
    'ssl://gateway.sandbox.push.apple.com:2195', $err,
    $errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
    
    if (!$fp)
    exit("Failed to connect: $err $errstr" . PHP_EOL);
    
    echo 'Connected to APNS' . PHP_EOL;
    
    // Create the payload body
    $body['aps'] = array(
    'alert' => $message,
    'sound' => 'default'
    );
    
    // Encode the payload as JSON
    $payload = json_encode($body);
    
    // Build the binary notification
    $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
    
    // Send it to the server
    $result = fwrite($fp, $msg, strlen($msg));
    
    if (!$result)
    echo 'Message not delivered' . PHP_EOL;
    else
    echo 'Message successfully delivered' . PHP_EOL;
    
    // Close the connection to the server
    fclose($fp);
    ?>

    deviceToken填写你接收到的token,passPhrase则填写你的ck.pem设置的密码。

    此刻就是见证奇迹的时候了,使用终端进入到push文件夹,在终端输入 php simplepush.php

     

    若显示以上提示则表示推送成功了。附上一张成功图。

     

    推送就到这边吧!

    感谢这篇博客的指导:http://blog.csdn.net/showhilllee/article/details/8631734

     

    simplepush.php以及XCode工程我会上传到我的资源里去,大家可以去那边下载。有什么不明白的地方大家可以留言或者私信我,我会第一之间回复的~

     

     

    大家可以关注我的微信公众号与我互动,相关问题也可以直接用公众号联系我:

     

     

     

     

     

     

     

     

     

     

    展开全文
  • 消息推送

    千次阅读 2016-11-16 00:16:01
    消息推送最简单的方法就是使用第三方的,比如现在使用比较多的是小米推送、极光推送,消息推送的技术原理是:移动无线网络长连接移动互联网络的现状因为手机平台本身、电量、网络流量的限制,移动互联网应用在设计上...

    消息推送,即时通信,目的:想办法让服务器能够及时的通知客户端

    消息推送最简单的方法就是使用第三方的,比如现在使用比较多的是小米推送、极光推送,消息推送的技术原理是:移动无线网络长连接

    实现方案

    1、轮询

    客户端每隔一定的时候就向服务器发出请求,获得最新的信息。特点:

    • 如果用在最新新闻通知上,那么效率就比较低了。
    • 技术简单,好现实。

    应用场景:当服务器端的数据以固定的频率更新,比如 股票行情。

    2、发短信

    特点:效率高,最及时,同时,费用也是最高的。
    应用场景:比较土毫的做法,不差钱。

    3、使用第三方的开源项目

    AndroidPN ( android push notify)

    4、使用第三方的API实现推送功能

    小米推送,百度推送、极光推送、个推、微信推送

    实现方式3和4原理上都属于消息推送。

    消息推送 的实现原理:Socket长联接 + 心跳桢

    XMPP 网络上开源的,用于网络聊天的网络协议

    asmack.jar jar包是对xmpp协议的实现

    推送原理

    • xmpp 是一种基于TCP/IP的协议, 这种协议更适合消息发送
    • socket 套接字, 发送和接收网络请求
    • 长连接 keep-alive, 服务器基于长连接找到设备,发送消息
    • 心跳包 , 客户端会定时(30秒一次)向服务器发送一段极短的数据,作为心跳包, 服务器定时收到心跳,证明客户端或者,才会发消息.否则将消息保存起来,等客户端活了之后(重新连接),重新发送.

    客户端轮询(客户端定时主动拉取数据), 浪费流量, 浪费性能
    谷歌推送服务(不能用,被墙了)

    移动互联网络的现状

    因为手机平台本身、电量、网络流量的限制,移动互联网应用在设计上跟传统PC 上的应用很大不一样,需要根据手机本身的特点,尽量的节省电量和流量,同时又要尽可能的保证数据能及时到达客户端。为了解决数据同步的问题,在手机平台上,常用的方法有2种。

    一种是定时去服务器上查询数据,也叫Polling,还有一种手机跟服务器之间维护一个TCP 长连接,当服务器有数据时,实时推送到客户端,也就是我们说的Push。从耗费的电量、流量和数据送达的及时性来说,Push 都会有明显的优势,但Push 的实现和维护成本相对较高。在移动无线网络下维护长连接,相对也有一些技术上的难度

    移动无线网络的特点

    因为IP v4 的IP 量有限,运营商分配给手机终端的IP 是运营商内网的IP,手机要连接Internet,就需要通过运营商的网关做一个网络地址转换(Network Address Translation,NAT)。简单的说运营商的网关需要维护一个外网IP、端口到内网IP、端口的对应关系,以确保内网的手机可以跟Internet 的服务器通讯。

    对于大部分移动无线网络运营商都在链路一段时间没有数据通讯时,会淘汰NAT 表中的对应项,造成链路中断。

    Android 平台上长连接的实现

    为了不让NAT 表失效,我们需要定时的发心跳,以刷新NAT 表项,避免被淘汰。Android 上定时运行任务常用的方法有2种,一种方法用Timer,另一种是AlarmManager。

    Timer

    Android 的Timer 类可以用来计划需要循环执行的任务,Timer 的问题是它需要用WakeLock 让CPU 保持唤醒状态,这样会大量消耗手机电量,大大减短手机待机时间。这种方式不能满足我们的需求。

    AlarmManager

    AlarmManager 是Android 系统封装的用于管理RTC 的模块,RTC (Real Time Clock) 是一个独立的硬件时钟,可以在CPU 休眠时正常运行,在预设的时间到达时,通过中断唤醒CPU。这意味着,如果我们用AlarmManager 来定时执行任务,CPU 可以正常的休眠,只有在需要运行任务时醒来一段很短的时间。极光推送的Android SDK 就是基于这种技术实现的。

    服务器设计

    当有大量的手机终端需要与服务器维持长连接时,对服务器的设计会是一个很大的挑战。假设一台服务器维护10万个长连接,当有1000万用户量时,需要有多达100台的服务器来维护这些用户的长连接,这里还不算用于做备份的服务器,这将会是一个巨大的成本问题。那就需要我们尽可能提高单台服务器接入用户的量,也就是业界已经讨论很久了的C10K 问题。

    上面只是针对极光推送来说,下面是具体的消息推送的一般有的方式:

    通过SMS进行服务器端和客户端的交流通信

    在Android平台上,你可以通过拦截SMS消息并且解析消息内容来了解服务器的意图,可以实现完全的实时操作。但是问题是这个方案的成本相对比较高,且依赖于运营商

    循环主动定时获取

    这种方法需要客户端来做一个定时或者周期性的访问服务器端接口,以获得最新的消息。轮询的频率太慢可能导致某些消息的延迟,太快则会大量消耗网络带宽和电池

    持久连接

    这个方案可以解决由轮询带来的性能问题,但是还是会消耗手机的电池。我们需要开一个服务来保持和服务器端的持久连接(苹果就和谷歌的C2DM是这种机制)。但是对于Android系统,当系统可用资源较低,系统会强制关闭我们的服务或者是应用,这种情况下连接会强制中断。(Apple的推送服务之所以工作的很好,是因为每一台手机仅仅保持一个与服务器之间的连接,事实上C2DM也是这么工作的。即所有的推送服务都是经由一个代理服务器完成的,这种情况下只需要和一台服务器保持持久连接即可。C2DM=Cloud to Device Messaging)。

    相比之下第三种还是最可行的。为软件编写系统服务或开机启动功能;或者如果系统资源较低,服务被关闭后可以在onDestroy ()方法里面再重启该服务,进而实现持久连接的方式。

    C2DM内置于Android的2.2系统上,无法兼容老的1.6到2.1系统;且依赖于Google官方提供的C2DM服务器,由于国内的网络环境,这个服务经常不可用。

    建立在TCP协议之上的XMPP协议,不仅可提供可这种持久连接的功能,能实现服务器和客户机的双工通信,还能不依赖与系统版本和google服务器的限制,提供了比较好的解决方案。

    小米消息推送服务

    目前用的最多的,也是最稳定消息推送服务,http://dev.xiaomi.com/console/appservice/push.html

    极光推送

    展开全文
  • androidpn消息推送

    千次下载 热门讨论 2012-07-04 16:32:15
    androidpn消息推送 其中包含客户端 服务器端包含tomcat和jetty版本
  • Android消息推送

    千次下载 热门讨论 2013-04-17 12:02:48
    Android消息推送 支持离线消息 Android消息推送 支持离线消息
  • 微信小程序 消息推送功能实现详解

    万次阅读 多人点赞 2018-09-05 19:30:57
    比如我们小程序中的客服功能,我不想要使用小程序后台的在线客服功能,但我又想实现客服功能,这个时候微信提供了消息推送功能,在小程序后台的设置,开发设置中,消息推送功能: 点击开启消息推送功能,认证成功...

    在小程序开发中,如果想实现:用户发给小程序的消息以及开发者需要的事件推送,在小程序项目中,我们想要实现这样一个功能,

    比如我们小程序中的客服功能,我不想要使用小程序后台的在线客服功能,但我又想实现客服功能,这个时候微信提供了消息推送功能,在小程序后台的设置,开发设置中,消息推送功能:

    点击开启消息推送功能,认证成功进入到消息推送配置界面:

    这里配置几个参数注意一下:

    URL(服务器地址):这里要填我们要认证token的接口地址,并且是在线上的接口,才能认证成功

    比如我的消息推送认证接口的地址是:http://xxxxxxx/xxxxxx/getProcessRequest.do,下面会编写这个接口认证的代码

    Token(令牌):这个是用户自己添加,不过在小程序后台添加的Token必须与认证接口中的是一致的,这个才能认证成功

     

    下面是Spring mvc 编写的接口代码:

    因为这个接口是GET认证,POST是发送信息所以才会这么编写:

    /**
         * GET:验证token
         * OST:发送数据
         * @param request 作用域
         * @param response 作用域
         * @return  String
         */
        @RequestMapping(value= {"/getProcessRequest"},method= {RequestMethod.GET, RequestMethod.POST})
        @ResponseBody
        public String getProcessRequest(HttpServletRequest request,HttpServletResponse response) {
            boolean isGet=request.getMethod().toLowerCase().equals("get");
            LOGGER.info(isGet+"---------------");
            System.out.println(isGet);
             System.out.println("方法是-------"+isGet);
             if(isGet){//首次验证token
                 // 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。  
                    String signature = request.getParameter("signature");  
                    // 时间戳  
                    String timestamp = request.getParameter("timestamp");  
                    // 随机数  
                    String nonce = request.getParameter("nonce");  
                    // 随机字符串  
                    String echostr = request.getParameter("echostr");  

                    PrintWriter out = null;  
                    try {  
                        out = response.getWriter();  
                        // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,否则接入失败  
                        if (DateUtil.checkSignature(signature, timestamp, nonce)) {  
                            System.out.println("成功");
                            out.print(echostr);
                            
                            out.flush();  //必须刷新
                        } 
                        System.out.println("失败");
                    } catch (IOException e) {  
                        e.printStackTrace();  
                    } finally {  
                        out.close();  
                        out = null; 
                        
                    }  
             }else{// 进入POST聊天处理  
                 System.out.println("进入了聊天界面");
                 LOGGER.info("进入了聊天界面");
                     // 接收消息并返回消息  
                     try {
                         System.out.println("进入这个方法中了:");
                         acceptMessage(request,response);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }  
                   
             }
            return null;

        }

     

    acceptMessage方法: 这个方法是认证成功后也就是POST方法操作能够接收到小程序发来的信息,也可以回信息:

    这里根据小程序信息的格式可以去看小程序API文档,文档地址:

    https://developers.weixin.qq.com/miniprogram/dev/api/custommsg/receive.html#%E6%96%87%E6%9C%AC%E6%B6%88%E6%81%AF

     

    acceptMessage:


        /**
         * 聊天处理方法 发送数据
         * @param request 作用域
         * @param response 作用域
         * @see  Exception
         */
        public void acceptMessage(HttpServletRequest request,HttpServletResponse response) throws Exception{
            
            BufferedReader streamReader = new BufferedReader( new InputStreamReader(request.getInputStream(), "UTF-8"));
            StringBuilder responseStrBuilder = new StringBuilder();
            String inputStr;
            while ((inputStr = streamReader.readLine()) != null)
                responseStrBuilder.append(inputStr);
            
            /*BufferedReader readers = new BufferedReader(new InputStreamReader(request.getInputStream()));*/
            JSONObject jsonObject = JSONObject.fromObject(responseStrBuilder.toString());
            String param= jsonObject.toString();
            System.out.println("转出来的数据:"+param);
            String attribute = jsonObject.get("FromUserName").toString();//发送的openid
    //        String ToUserName = jsonObject.get("ToUserName").toString();//小程序原始id
            String MsgType = jsonObject.get("MsgType").toString(); //用户发送客服信息的类型
            System.out.println("发送数据的类型:"+MsgType);
            System.out.println(MsgType);
            if(MsgType.equals("event")) {
                  Map<String,Object>  text = new HashMap<String, Object>();
                  Feedbacktxt feedbacktxt = new Feedbacktxt();
                  feedbacktxt.setTouser(attribute);
                  feedbacktxt.setMsgtype("text");
                  text.put("content", "你好,欢迎来到这里");
                  feedbacktxt.setText(text);
                  String token = feedbackService.access_token(); //这里是获取接口凭证的接口
                  String url="https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token="+token;
                  JSONObject jsonStrs = JSONObject.fromObject(feedbacktxt);
                  HttpUtils.httpPost(url, jsonStrs.toString());

    获取access_token,接口凭证的api接口文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140183

     

    DateUtil.java:
     


        
          /** 
         * 验证签名 
         * @param signature  验证签名的数据
         * @param timestamp  参数
         * @param nonce  参数
         * @return  boolean
         */  
        public static boolean checkSignature(String signature, String timestamp, String nonce) {  
            
            //TOKEN
            //与token 比较
            String[] arr = new String[] { qurenneng1796789910, timestamp, nonce };  
     
            // 将token、timestamp、nonce三个参数进行字典排序  
            Arrays.sort(arr); 
            
            StringBuilder content = new StringBuilder();  
            
            for (int i = 0; i < arr.length; i++) {  
                content.append(arr[i]);  
            }
            
            MessageDigest md = null;  
            String tmpStr = null;  
      
            try {  
                md = MessageDigest.getInstance("SHA-1");  
                
                // 将三个参数字符串拼接成一个字符串进行sha1加密
                byte[] digest = md.digest(content.toString().getBytes());
                tmpStr = byteToStr(digest); 
            } catch (NoSuchAlgorithmException e) {  
                e.printStackTrace();  
            }  
     
            content = null;  
            // 将sha1加密后的字符串可与signature对比  
            return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;  
        }
        
        
        /** 
         * 将字节数组转换为十六进制字符串 
         *  
         * @param byteArray 
         * @return  String
         */  
        private static String byteToStr(byte[] byteArray) {  
            String strDigest = "";  
            for (int i = 0; i < byteArray.length; i++) {  
                strDigest += byteToHexStr(byteArray[i]);  
            }  
            return strDigest;  
        }  

        
        
        
        /** 
         * 将字节转换为十六进制字符串 
         *  
         * @param mByte 
         * @return  String
         */  
        private static String byteToHexStr(byte mByte) {  
            char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };  
            char[] tempArr = new char[2];  
            tempArr[0] = Digit[(mByte >>> 4) & 0X0F];  
            tempArr[1] = Digit[mByte & 0X0F];  
      
            String s = new String(tempArr);  
            return s;  
        }

    这样就可以实现动态的去发送客服信息,也可以去用代码去实现想要实现的功能,好了微信小程序接口认证就到这里了

    加入群聊

    展开全文
  • Android消息推送:第三方消息推送平台详细解析

    万次阅读 多人点赞 2016-10-19 19:33:50
    消息推送在Android开发中应用的场景是越来越多了,比如说电商产品进行活动宣传、资讯类产品进行新闻推送等等,如下图: 本文将介绍Android中实现消息推送的第三方推送的详细解决方案 阅读本文前,建议先阅读我的写...

    前言

    • 消息推送在Android开发中应用的场景是越来越多了,比如说电商产品进行活动宣传、资讯类产品进行新闻推送等等,如下图:

    推送消息截图

    • 本文将介绍Android中实现消息推送的第三方推送的详细解决方案

    阅读本文前,建议先阅读我写的文章:史上最全解析Android消息推送解决方案


    目录

    目录


    1. 主流的第三方推送平台分类

    • 手机厂商类:小米推送、华为推送。
    • 第三方平台类:友盟推送、极光推送、云巴(基于MQTT)
    • BAT大厂的平台推送:阿里云移动推送、腾讯信鸽推送、百度云推送

    2. 对比其他推送方式的特点

    其他推送方式还有:C2DM、轮询、SMS、MQTT协议、XMPP协议等等,相对于这些推送方式,第三方推送方式的特点分别是:

    • 优点:

      1. 成本低
        上述的推送大多数是免费的,假如自己实现则消耗过多资源(开发成本和后台管理、统计成本)
      2. 消息到达率高
        如果一个手机里有多个App使用了同一家推送服务,那么这些App将共用一条消息通道,即使你家的App推送服务被杀死了,那么只要用户打开了其他集成该推送服务的App,你家的推送就能到达用户
    • 缺点

      1. 安全性低
        使用别人的服务器,所以你懂的。
      2. 服务会被杀死
        由于Android系统的机制,后台推送 Service 会被各种主动的或是被动的行为给杀死,而服务一旦被杀死,意味着就接收不到推送消息。

    3. 第三方推送服务方式的特点

    • 第三方服务基本都具备免费、和到达率高的特点
    • 那么应该如何选择呢?我们来分别看一下第三方推送各种方式的优点:

    3.1 手机厂商推送

    请记住一个潜规则:操作系统是不会杀死属于自己品牌的推送服务。

    1. 手机厂商的推送服务在自家的手机上属于系统级别的服务,这意味着系统不会杀死自家的推送服务
    2. 比如说,Android原生系统是不会杀死C2DM消息推送服务,MIUI系统是不会杀死小米的推送服务。

    当今市场上的Android手机系统份额最高是MIUI系统,即小米(具体排名请看http://www.umindex.com/)

    因为:免费、到达率高且在Android系统市场份额第一的MIUI系统上不被杀死。所以,如果要选择手机厂商的推送服务,请选择小米推送作为第三方平台实现推送服务

    下面一些应用可以从侧面来证明我的推断:

    • 腾讯新闻使用的小米推送,没有使用自己家的信鸽推送
    • 淘宝使用了自家的阿里云推送,同时还集成了小米推送
    • 百度视频爱奇艺使用的是小米推送,没有用自家的百度推送
    • 官网截图 - 集成应用:

    集成应用

    1. 如果希望进一步提高推送的效果,其实可以集成多个手机厂商的推送服务
    2. 比如小米渠道用小米推送,华为渠道用华为推送,但这样的实现成本会大一些

    3.2 第三方平台类

    请记住一个规则:推送系统会共享一条推送渠道

    1. 这意味着假设你接入了友盟推送,而恰好今日头条也接入了友盟。
    2. 有一天你的App被杀死了,但这时用户启动了今日头条,那么推送系统也就会通过共享的推送通道顺便把你推送消息送达到手机上,然后还可能把你的进程也唤醒(被“保活”了)。

    所以说,关于如何选择第三方平台类的推送,推送平台的规模效应就很重要了。
    那如何得知他们的规模和市场份额呢?按个人经验,主要看两点:

    • 问内部的朋友。
    • 看推送平台的合作客户里有哪些大的app - 参考对应官网的合作案例

    3.3 BAT大厂的推送

    BAT大厂其实并没有什么优势,同时谨记:

    • 不要以为用了腾讯信鸽推送,就能占上微信的光保证你的App永远内部被杀死。
    • 说个题外话,手机淘宝除了自家的阿里云的移动推送,同时也使用其它的第三方推送平台啊(比如友盟推送)。

    4. 如何选择第三方平台推送服务?

    • 选择因素
      用户群体属性、实现成本、渠道

    • 具体选择方案

    示意图

    所以,大家可根据自己的使用场景来进行消息推送平台的选择。


    5. 推送消息类别的选择

    5.1 推送消息的类别

    通常第三方推送平台都支持两种推送消息类型:通知栏消息和透传消息。

    • 通知栏消息:该类消息在被送达用户的设备后,直接以系统通知栏的形式展示给用户

    不会继续被传递到App

    • 透传消息:该类消息在被送达用户的设备后,还会继续传递到App
    1. 通过回调App的某个BroadcastReceiver的形式将消息传递到App内部。然后由App决定如何处理和显示这个消息。
    2. 所以透传消息不一定会以系统通知栏的形式进行推送,由程序猿自定义

    5.2 消息类别的区别与特点

    • 二者的区别在于:透传消息在整个消息传递过程中比通知栏消息多了一步-传递到App
    • 通知栏消息的优点:送达率高
      因为透传消息在整个消息传递过程中比通知栏消息多了一步-传递到App,因此透传消息就增加一些被系统限制的概率,给系统杀死的概率就高一些,所以说,通知栏消息比透传消息应该能提供更好的送达率。

    我们来看下小米推送的官方文档描述:

    1. 在一些 Android 系统(如 MIUI)中,受到系统自启动管理设置的限制,应用不能在后台自启动
    2. 在这类系统中,如果在发送消息的时候对应的应用没有被启动,透传类消息将不能顺利送达。
    3. 因此,对于对送达率要求很高的消息,建议尽量采用通知栏提醒的方式推送消息
    • 透传消息的优点:对消息操作程度高 & 自定义程度高
    1. 提供了对消息数据的更灵活的操纵能力。

    App如果仅仅通过通知栏消息,是无法接触到消息数据本身的。

    1. 可自定义通知提醒的样式(包括提示样式、提示形式如声音等等)

    所以大家可以根据不同的使用场景来对推送消息类别进行选择了。


    6. 总结


    请帮顶 / 评论点赞!因为你的鼓励是我写作的最大动力!

    展开全文
  • 前面写过一篇云开发实现小程序订阅消息(模板消息)推送的文章,《借助云开发实现小程序订阅消息和模板消息的推送功能》是有好多同学用的是Java写后台,所以今天就再来写一篇Java后台实现小程序订阅消息推送的文章。...
  • app消息推送及监听系统消息点击

    万次阅读 2020-08-11 15:55:45
    //创建本地消息,这个可以通过判断服务器端是否有新消息推送,获取到推送消息之后,创建本地推送消息 plus.push.addEventListener(“click”, function(msg) { //content: ( String ) 必选 消息显示的内容,在系统...
  • 在Android开发中,消息推送功能的使用非常常见。为了降低开发成本,使用第三方推送是现今较为流行的解决方案。 今天,我将手把手教大家如何在你的应用里集成小米推送 该文档基于小米推送官方Demo,并给出简易推送...
  • 最近需要开发微信和小程序的推送功能,需要用java后台实现推送,自己本身java和小程序都做,所以就自己动手实现下小...我的这个是跑腿抢单推送,当用户新下单时,会给跑腿员推送消息。 下面开始讲解实现步骤 ...
  • 今天下午看了《见证Android消息推送时刻》,决定按照视频所讲演示一遍,作为笔记,一方面供自己翻看查阅,另一方面供大家学习交流。 Android消息推送系列之Android消息推送 参考文档:   Android消息推送  ...
  • 最近公司需要 Android 的消息推送,在网上找了很多消息推送的例子,都是无法运行. 经过一段时间的研究,终于把例子运行起来了。现在共享出来,共同学习。 在 androidpn 的官网下载...
  • 每次看到iOS的远程消息推送,总是感觉很头大,即便后来项目都做完了,还是觉得摸不着远程推送的脉门,网上介绍的资料虽然多如牛毛,但不是写的太简单了,就是写的太详细了,不能一下抓住要点,今天终于能够抽出点...
  • (1)消息推送的作用目前的手机APP多数都具有消息推送的功能。消息推送我认为其作用和价值有二:一是向所有APP用户发布消息公告;二是在业务流中及时向特定用户发出提醒,告知某请求的处理进度。(2)消息推送的方式...
  • 个推 - 消息推送

    千次阅读 2018-09-14 10:40:21
    最近研究了一下个推的消息推送,记录一下。
  • 极光推送,是一个面向普通开发者开放的,免费的第三方消息推送服务。本篇博客将结合案例介绍极光推送自定义消息的使用方法,利用自定义消息实现项目中特定的消息推送需求。
  • 消息推送的实现: 1.打开应用的时候 2.通过plus.push.getClientInfo().clientid获取到clientid 3.接口传到服务器 4.进行判断表里是否存在该条数据,没有就插入,有则不插入,另外关联登录的companyid 5.在...
  • 消息推送方案

    千次阅读 2018-11-09 17:20:29
    对于需要即使通知用户的业务,例如告警等,需要消息推送功能,保证通知的及时性。   应用场景需求 消息推送涉及到消息的发送和接收,即方案既要能在后端中使用,也要能在前端和移动端使用,所以需要能适配java 和...
  • springboot如何集成mqtt消息推送

    万次阅读 热门讨论 2018-06-04 16:12:16
    1.需求分析 近期笔者项目需要用到mqtt实现消息推送,笔者选择emq作为mqtt服务器载体,上篇笔者讲解了如何在linux中安装mqtt服务,安装链接:https://blog.csdn.net/zhangxing52077/article/details/80567270,接下来...
  • uniapp消息推送push

    千次阅读 2020-10-23 10:53:55
    uniapp uni push 消息推送 一、前期准备 1、账号:生成该应用账号进行配置uni push 2、勾选uni push 推送 二、配置uni push 1、配置厂商推送设置 2、配置厂家推送示例:(华为) (1)、为什么要配置厂家...
  • 离线消息推送

    千次阅读 2019-08-30 02:22:48
    离线消息推送,一般采用厂商通道,现在以Hbuilder创建的APP为例,记录下步骤: 1)Hbuilder创建APP。 2)登录http://dev.dcloud.net.cn,开通UniPush推送服务。 3)配置厂商推送设置,需要根据手机的类型,进入...
  • PhoneGap极光推送 cordova消息推送

    千次阅读 2018-04-01 19:21:26
    之前做过一个APP用到了消息推送,最近这个项目又用到了推送。但是由于两个项目间隔4个多月,推送集成、使用方式等都忘了,所以当时又去看了以前项目的源码和一些推送相关的博客,寻找那些蛛丝马迹。突然觉得这样很...
  •  本发明提供一种消息推送实现方法,包括:移动终端上的正向代理服务模块与服务器之间建立长连接;所述正向代理服务模块通过所述长连接转发所述移动终端上的应用与所述服务器之间交互的信息;其中,所述移动终端上的...
  • HBuilder webapp实现消息推送

    千次阅读 热门讨论 2019-02-02 21:51:32
    HBuilder webapp实现消息推送 关于软件的push推送 HBuilder 只提供了二个SDK(小米推送、个推) 因为我使用的是个推所以这篇文章就主要介绍如何使用个推实现消息推送、 1.注册个推 个推官网:...
  • 在好几年前,就已经注意到DDPush这款推送中间件,不过看近来发展也还是停留在V1.0...DDPush 任意门 消息推送 DDPush是什么 DDPush可以做什么 移动互联网消息推送 IM实时消息系统核心组件 物联网设备控制与交互 ...
  • 基于dwr的消息推送java web

    万次阅读 2020-09-27 09:10:49
    pom.xml 加依赖 <!-- https://mvnrepository.com/artifact/org.directwebremoting/dwr --> <dependency> <groupId>org.directwebremoting</groupId> <...3.0.0-RE..
  • App消息推送的原理

    万次阅读 2019-04-29 16:12:06
    Android消息推送原理3.1 操作系统有自身的消息推送功能(系统级别)3.2 三种基本的推送方式:Push、Pull 和 SMS3.3 七种主流的Android消息推送方式 1. 基本概念 目的: 在用户未打开App时,App主动向用户推送...
  • WebSocket与消息推送

    千次阅读 2018-03-02 17:29:53
    WebSocket与消息推送 https://www.cnblogs.com/best/archive/2016/09/12/5695570.html目录一、Socket简介二、WebSocket简介与消息推送三、WebSocket客户端四、WebSocket服务器端五、测试运行六、小结与消息推送框架...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 24,388
精华内容 9,755
关键字:

消息推送