Push Notification(三)

本文介绍如何通过JavaPNS实现自定义推送消息内容,并在iOS应用中解析这些内容以实现特定功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

点击push notification 消息进入应用,直接跳转到相应页面!

最近有遇到了上面这个常见的需求:

网上找了一些方法,觉得这篇博客模块化方式最好,这里搬运过来,并且针对JavaPNS,来说明实现思路。相对于Push Notification(一) 改动不大:

1、以javapns搭建的服务端为例,需要定制化地对payload进行封装;

2、手机端对服务端发送的payload进行解析

3、要确定好协议,即payload(在手机端为userInfo)的封装内容

本文使用的方法定制性比较好,前提是一定要和服务器确定好协议1、需要手机push的视图控制器的名称,如下面的HSFeedsViewController  2、HSFeedsViewController中定义的属性;

推送过程结束后,也就完成了将服务端封装的ID和type,赋值给HSFeedsViewController的ID与type属性,至于要用这两个属性干啥就看具体需求了,如作为网络请求的参数,页面直接显示该参数指定的内容。

服务端

选用javapns作为推送框架的服务端,之前的博客中是这样的写的:
import java.util.ArrayList;  
import java.util.List;  
  
import javapns.notification.AppleNotificationServer;  
import javapns.notification.AppleNotificationServerBasicImpl;  
import javapns.notification.PayloadPerDevice;  
import javapns.notification.PushNotificationPayload;  
import javapns.notification.transmission.NotificationProgressListener;  
import javapns.notification.transmission.NotificationThread;  
import javapns.notification.transmission.NotificationThreads;  
  
public class testClass {  
    public static void main(String[] args){    
        String keystore = "cer/aps_developer_identity.p12";//p12证书路径和证书名    
        String password = "证书密码"; // 证书密码    
        String token = "64位十六进制数";// device token    
        boolean production = false; // 设置true为正式服务地址,false为开发者地址    
        int threadThreads = 10; // 线程数    
    try {    
            // 建立与Apple服务器连接    
            AppleNotificationServer server = new AppleNotificationServerBasicImpl(keystore, password, production  );    
        List<PayloadPerDevice> list = new ArrayList<PayloadPerDevice>();    
        PushNotificationPayload payload = new PushNotificationPayload();    
        <span style="color:#3366ff;">payload.addAlert("TV请求视频通话");    
        payload.addSound("default");// 声音    
        payload.addBadge(1);//图标小红圈的数值    
        //payload.addCustomDictionary("url","www.baidu.com");//添加字典用途不明暂时干掉,干掉后测试没有影响结果  </span>  
        PayloadPerDevice pay = new PayloadPerDevice(payload,token);// 将要推送的消息和手机唯一标识绑定    
        list.add(pay);    
        
            NotificationThreads work = new NotificationThreads(server,list,threadThreads);//     
        work.setListener(DEBUGGING_PROGRESS_LISTENER);// 对线程的监听,一定要加上这个监听    
        work.start(); // 启动线程    
        work.waitForAllThreads();// 等待所有线程启动完成    
        
     } catch (Exception e) {    
        e.printStackTrace();    
            }    
    }    
      
    public static final NotificationProgressListener DEBUGGING_PROGRESS_LISTENER = new NotificationProgressListener() {    
        public void eventThreadStarted(NotificationThread notificationThread) {    
            System.out.println("   [EVENT]: thread #" + notificationThread.getThreadNumber() + " started with " + " devices beginning at message id #" + notificationThread.getFirstMessageIdentifier());    
        }    
        public void eventThreadFinished(NotificationThread thread) {    
            System.out.println("   [EVENT]: thread #" + thread.getThreadNumber() + " finished: pushed messages #" + thread.getFirstMessageIdentifier() + " to " + thread.getLastMessageIdentifier() + " toward "+ " devices");    
        }    
        public void eventConnectionRestarted(NotificationThread thread) {    
            System.out.println("   [EVENT]: connection restarted in thread #" + thread.getThreadNumber() + " because it reached " + thread.getMaxNotificationsPerConnection() + " notifications per connection");    
        }    
        public void eventAllThreadsStarted(NotificationThreads notificationThreads) {    
            System.out.println("   [EVENT]: all threads started: " + notificationThreads.getThreads().size());    
        }    
        public void eventAllThreadsFinished(NotificationThreads notificationThreads) {    
            System.out.println("   [EVENT]: all threads finished: " + notificationThreads.getThreads().size());    
        }    
        public void eventCriticalException(NotificationThread notificationThread, Exception exception) {    
            System.out.println("   [EVENT]: critical exception occurred: " + exception);    
        }    
     };    
}  

红色的代码是推送的主要内容(然后在手机端的userInfo字段可以收取以便后面解析,这是后话),注意,推送的内容可以包括:1)推送消息的具体内容 2)推送消息的提示音类型 3)应用图标左上角表示消息数量的数字 4)自定义内容
自定义内容的实现方法就是上面被注释掉的那句
payload.addCustomDictionary("url","www.baidu.com");
该方法可以有3个重载方法
payload.addCustomDictionary(String key, int value);
payload.addCustomDictionary(String key, String value);
payload.addCustomDictionary(String key, List value);

这个消息会以键值对的方式传到手机端, 所以如果想要向手机端发送什么自定义的键值对,用这种方法就可以了
如想要手机端接收的userInfo为如下内容:

userInfo:{

    class = HSFeedsViewController;

    property =     {

        ID = 123;

        type = 12;

    };

}

只需要在封装时使用下面的语句即可

List<HashMap<String,String>> propertyList = new ArrayList<HashMap<String,String>>();
	    HashMap myMap  = new HashMap();
	    myMap.put("ID", "123");
	    myMap.put("type", "12");
	    propertyList.add(myMap);
	    
	    payload.addCustomDictionary("class", "HSFeedsViewController");
	    payload.addCustomDictionary("property",propertyList );

可能看着挺麻烦的,但是没有办法,addCustomDictionary不能直接将HashMap发送,只能将HashMap的内容装好后,放在一个List中,发出去即可。


手机端


然而由于List是一个数组,所以手机端接收到的内容其实是

userInfo:{

    class = HSFeedsViewController;

    property =    (

 {

        ID = 123;

        type = 12;

     }

    );

}

property对应的value是一个数组,我们要在手机端做一下简单的处理就好:取数组的第一个元素,重新封装为一个dictionary。
==============================================分割线===============================================
下面引用这篇博客的内容,并稍加改动

HSFeedsViewController.h:

  • 进入该界面需要传的属性

1
2
3
4
5
6
7
@interface HSFeedsViewController : UIViewController
// 注:根据下面的两个属性,可以从服务器获取对应的频道列表数据
/** 频道ID */
@property (nonatomic, copy) NSString *ID;
/** 频道type */
@property (nonatomic, copy) NSString *type;
@end

AppDelegate.m:

  • 推送过来的消息规则

1
2
3
4
5
6
7
8
// 这个规则肯定事先跟服务端沟通好,跳转对应的界面需要对应的参数
NSDictionary *userInfo = @{
                            @ "class" : @ "HSFeedsViewController" ,
                            @ "property" : @{
                                         @ "ID" : @ "123" ,
                                         @ "type" : @ "12"
                                    }
                            };
  • 接收推送消息

1
2
3
4
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
     [self push:userInfo];
}
  • 跳转界面

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
- (void)push:(NSDictionary *)params
{
     // 类名
     NSString *class =[NSString stringWithFormat:@ "%@" , params[@ "class" ]];
     const char *className = [class cStringUsingEncoding:NSASCIIStringEncoding];
     // 从一个字串返回一个类
     Class newClass = objc_getClass(className);
     if  (!newClass)
     {
         // 创建一个类
         Class superClass = [NSObject class];
         newClass = objc_allocateClassPair(superClass, className, 0);
         // 注册你创建的这个类
         objc_registerClassPair(newClass);
     }
     // 创建对象
     id instance = [[newClass alloc] init];
     // 对该对象赋值属性
     NSDictionary * propertys = params[@ "property" ];
     [propertys enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
         // 检测这个对象是否存在该属性
         if  ([self checkIsExistPropertyWithInstance:instance verifyPropertyName:key]) {
             // 利用kvc赋值
             [instance setValue:obj forKey:key];
         }
     }];
     // 获取导航控制器
     UITabBarController *tabVC = (UITabBarController *)self.window.rootViewController;
     UINavigationController *pushClassStance = (UINavigationController *)tabVC.viewControllers[tabVC.selectedIndex];
     // 跳转到对应的控制器
     [pushClassStance pushViewController:instance animated:YES];
}
  • 检测对象是否存在该属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- (BOOL)checkIsExistPropertyWithInstance:(id)instance verifyPropertyName:(NSString *)verifyPropertyName
{
     unsigned int outCount, i;
     // 获取对象里的属性列表
     objc_property_t * properties = class_copyPropertyList([instance
                                                            class], &outCount);
     for  (i = 0; i < outCount; i++) {
         objc_property_t property =properties[i];
         //  属性名转成字符串
         NSString *propertyName = [[NSString alloc] initWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
         // 判断该属性是否存在
         if  ([propertyName isEqualToString:verifyPropertyName]) {
             free(properties);
             return  YES;
         }
     }
     free(properties);
     return  NO;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值