本地通知?

2023-12-08

我的应用程序主要是服务器的客户端,实际上没有连接到互联网。它连接到 Polycom 编解码器并管理 2 个端点之间的视频通话。所以我的应用程序可以发送诸如结束通话、调高音量等命令... 然而我的问题是这样的。当有来电并且应用程序不在前台时,我需要某种通知。 由于服务器无法访问互联网,APNS/推送通知对我不起作用。我已经考虑过做类似的事情this。这似乎让我的客户端保持运行,但是我无法发出警报,因为我的应用程序位于后台。

因此,除了如何解决我的问题的基础知识之外,我的问题是:

我可以使用链接中列出的技术将我的应用程序带到前台吗(执行类似于我下面所做的操作)。我可以从日志中看到这段代码使我的代码保持运行。我知道我的 while 循环不正确,最终我需要 KVO,但无论如何这不应该影响答案。 (我不明白的一件事是,这使我的整个应用程序保持运行,而不是仅运行 bcClient 中的类?)

- (void)applicationDidEnterBackground:(UIApplication *)application
{    
     [bcClient connect];
     bgTask = [app beginBackgroundTaskWithExpirationHandler:expirationHandler];
     
     // Start the long-running task and return immediately.
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  
          while(1) {   
               sleep(3);
               NSLog(@"held join %d",bcClient.heldjoin);

               if (bcClient.heldjoin == 602 || bcClient.heldjoin == 604 || bcClient.heldjoin == 513) {
                    NSLog(@"incoming call");
               }
          }   
     });           
}

如果我无法将我的应用程序带到前台,那么是否可以在本地推送通知(不需要 APNS 服务器)?

我有一种感觉,这一切都是不可能的,但我想我会问。


这是我的答案。这使我的客户端应用程序在后台运行,并在有呼叫时显示通知。

AppDelegate.h

@interface CameleonAppDelegate : NSObject <UIApplicationDelegate> {

    CrestronClient *cClient;
    CrestronControllerValues *CCV;
    RootViewController *rootViewController;
    CrestronValues *crestronValues;

    UIBackgroundTaskIdentifier bgTask;
    dispatch_block_t expirationHandler;
    UIApplication*    app;
    BOOL showedCall;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;

@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
-(void)save;
-(void)load;
- (void)backgroundHandler;
@end

AppDelegate.m(只是didFinishLaunchingWithOptions and applicationDidEnterBackground)

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{    
     app = [UIApplication sharedApplication];
     expirationHandler = ^{

          [app endBackgroundTask:bgTask];
          bgTask = UIBackgroundTaskInvalid;


          bgTask = [app beginBackgroundTaskWithExpirationHandler:expirationHandler];
     };


    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    NSArray *keys = [NSArray arrayWithObjects:@"IPaddress", @"PortNumber",@"IPID", nil];

    NSArray *objs = [NSArray arrayWithObjects:@"10.8.40.64", @"41794",@"3", nil];

    //10.8.30.143       10.8.40.64

    NSDictionary *dict = [NSDictionary dictionaryWithObjects:objs forKeys:keys];

    [defaults registerDefaults:dict];

     CCV = [CrestronControllerValues sharedManager];

    [CCV setIpAddress:[defaults stringForKey:@"IPaddress"]];
    [CCV setPortNumber:[defaults stringForKey:@"PortNumber"]];
    [CCV setIPID:[defaults stringForKey:@"IPID"]];


    cClient = [CrestronClient sharedManager];


     rootViewController = [[RootViewController alloc]initWithNibName:@"RootViewController" bundle:nil];
     self.window.rootViewController = rootViewController;
     [self.window makeKeyAndVisible];   

    return YES;
}


- (void)applicationDidEnterBackground:(UIApplication *)application
{
     showedCall = FALSE;
     BOOL backgroundAccepted = [[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{ [self backgroundHandler]; }];
     if (backgroundAccepted)
     {
          NSLog(@"VOIP backgrounding accepted");
     }


     bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
          [app endBackgroundTask:bgTask];
          bgTask = UIBackgroundTaskInvalid;
     }];


     // Start the long-running task
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

          while (1) {
               sleep(4);
               //NSLog(@"BGTime left: %f", [UIApplication sharedApplication].backgroundTimeRemaining);

               if ([rootViewController isIncomingCall] && showedCall != TRUE) {
                    UILocalNotification *localNotif = [[UILocalNotification alloc] init];
                    if (localNotif) {
                         localNotif.alertBody = [NSString stringWithFormat:@"Incoming Call."];
                         localNotif.alertAction = NSLocalizedString(@"Accept Call", nil);
                         localNotif.soundName = @"alarmsound.caf";
                         localNotif.applicationIconBadgeNumber = 1;
                         [application presentLocalNotificationNow:localNotif];
                         [localNotif release];
                    }
                    showedCall = TRUE;
               }
          }
     });           
}
- (void)backgroundHandler {

     NSLog(@"### -->VOIP backgrounding callback");


     bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
          [app endBackgroundTask:bgTask];
          bgTask = UIBackgroundTaskInvalid;
     }];

     // Start the long-running task 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

          while (1) {
               NSLog(@"BGTime left: %f", [UIApplication sharedApplication].backgroundTimeRemaining);
               [rootViewController isIncomingCall];
               sleep(1);
          }   
     });
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

本地通知? 的相关文章

随机推荐

  • 编写 Safari 5.1 脚本来打开选项卡[重复]

    这个问题在这里已经有答案了 可能的重复 使用 AppleScript 在新的 Safari 选项卡中打开 URL 如何告诉 Safari 在当前窗口的新选项卡中打开 URL 这是重复的使用 AppleScript 在新的 Safari 选项
  • Android Studio 链接 OpenCV 静态库

    目前 我正在开发一个使用 OpenCV3 进行实时视频处理 应用一组颜色滤镜 的项目 并且我设法让它与 Java 一起使用 没有任何问题 接下来我尝试做的是通过 NDK 将我所有的 Java 逻辑实现为 C 以提高性能 这样我就不需要来回将
  • 如何向 MySQL 中的现有列添加非空约束

    我有名为 Person 的表名称和以下列名称 P Id int LastName varchar FirstName varchar 我忘记给NOT NULL约束为P Id 现在我尝试使用以下查询添加NOT NULL对名为的现有列的 约束P
  • ContextMenu 命令绑定到父级和自身

    我正在尝试在具有多个命令绑定的 DataGrid 上创建一个上下文菜单 有些必须绑定到本地 ViewModel 即 Row 的 ViewModel 有些必须绑定到父 ViewModel 到目前为止 我没有运气遵循其他解决方案 我只执行子命令
  • keyup、keydown、keypress 和 input 事件之间有什么区别?

    我一直在尝试理解 JavaScriptkeypress keydown keyup and input事件 但我发现它们很令人困惑 有人可以指出确切的差异吗 我还想知道当用户粘贴一段文本时是否会触发所有这些操作 根据jQuery 文档 Th
  • 在android中的谷歌地图上绘制多个标记

    我是android领域的新手 我写了一个安卓应用1将从网络提供商检索纬度和经度值并将其存储在我的本地服务器 LAMP 中 我还创建了一个 MYSQL DB 表 该表有 3 列 lat lon id 其中包含使用网络提供程序检索的值 lat
  • 为什么即使没有任何类声明也需要原型?

    如果我只是这样做 Ex1 include
  • 为什么我会收到 301 重定向到带有斜杠的文件夹名称?

    请求http localhost SAMPLE CODES backbone mysql reading json websites 被重定向如下 gt Request URL http localhost SAMPLE CODES bac
  • 单选按钮 onclick 不起作用

    我有 3 个单选按钮 将根据单击的按钮显示列表中的某些作业 我曾经使用搜索按钮来运行搜索代码 因此 用户将选择一个单选按钮 然后单击搜索 但现在我已经删除了搜索按钮 我希望单选按钮在单击时调用搜索功能 table tr td td tr t
  • 如何使用 Byte Buddy 更改导入?

    我想更改类的导入 以便它们指向不同的包 Byte Buddy 文档没有提供太多关于如何实现这一目标的信息 这是我到目前为止所拥有的 public class ProxyPlugin implements net bytebuddy buil
  • 限时输入? [复制]

    这个问题在这里已经有答案了 我希望能够做的是使用输入向用户询问问题 例如 print some scenario prompt input You have 10 seconds to choose the correct answer n
  • 使用 fileConfig 在 Python 中配置自定义处理程序

    我正在使用配置文件在 Python 应用程序中配置我的记录器 这是文件 loggers keys root logger root level INFO handlers console handlers keys console file
  • 在 SSRS 中分组?

    我是 SSRS 的新手 数据如下所示 它们都来自同一个数据集 就像将 2 列分组一样 即 WrkCrtId Name 显示在它们之上 我已经尝试了一些方法来做到这一点 但仍然失败 我想知道是否有人可以提供帮助 附注下图显示了 2 组 B3
  • 在.NET 6控制台应用程序中读取appsettings.json文件

    如何从appsettings json NET 6 控制台应用程序中的文件 program cs file public class Program private static ManualResetEvent quitEvent new
  • 如何在 Ant 中从逗号分隔的目录列表创建文件集?

    在 Ant 目标中 我获得一个属性 其中包含要包含在进一步操作 复制 过滤等 中的目录列表 它看起来像这样 directories dir1 dir2 dir3 我需要一种方法将此列表转换为选择的文件集或模式集all这些目录中的文件 我知道
  • 转换错误:需要左值作为赋值的左操作数

    所以我正在尝试使用ether aton 它返回一个struct ether addr 我正在尝试将其放入我的struct ether header eptr 来自 net ethernet h ether shost成员 我试过这个 str
  • swift3 日期到数据,数据到日期转换

    我正在努力将 Objective C 中创建的代码更改为 swift3 我想将下面的代码更改为使用 Objective c 创建的 swift3 代码 Objective c NSDate 到 NSData 代码 NSCalendar ca
  • 如何使用 PDFBox 对动态创建的 PDF 文档进行数字签名?

    对不起 我java很差 我哪里不对的地方请指正 我哪里不好的地方请改进 我正在尝试使用 PDFBox 通过以下程序对动态创建的 pdf 进行数字签名 计划中的任务 i 创建 PDF 模板 ii 更新 ByteRange xref start
  • 如何在构建阶段使用其他小部件的约束和大小

    我想确保涵盖所有情况 父窗口小部件读取 并可能使用 子窗口的大小或约束 子部件读取 并可能使用 父部件的大小或约束 子部件读取 并可能使用 另一个子部件的大小或约束 解决方案似乎是 让构建阶段运行 然后构建我想要从中检索数据的小部件的大小和
  • 本地通知?

    我的应用程序主要是服务器的客户端 实际上没有连接到互联网 它连接到 Polycom 编解码器并管理 2 个端点之间的视频通话 所以我的应用程序可以发送诸如结束通话 调高音量等命令 然而我的问题是这样的 当有来电并且应用程序不在前台时 我需要