由于 iOS 框架不允许本地通知在发布之前执行代码,因此我正在寻找一种在越狱设备上实现它的方法。
更新
好吧,我已经设法创建了一个在启动时启动并保持自身运行的守护进程。
但是,发布通知需要 UIApplication 对象。根据documentation此单例由 UIApplicationMain() 方法创建,对于常规应用程序,该方法由 main() 调用。由于我希望通知由守护程序发布,因此单例为 nil。
我可以创建 UIApplication 的实例吗?或者以其他方式发布通知?
我试过调用 UIApplicationMain() 然后在应用程序委托(delegate)中发布通知,并终止应用程序,但这会暂时显示黑屏;我猜它正在启动应用程序。此外,当应用程序无法启动时(当手机尚未完全启动时),它会导致守护程序崩溃。
这里是代码草图
int main(){
if(launchedBySpringBoard || launchedBynotification)
UIApplicationMain(...);
else if(launchedByDaeamon)
StartRunLoop();
}
void triggerdByRunLoopEveryXhours(){
downloadData();
if(isNewData())
postNotification();
}
最佳答案
... Or post the notification any other way?
是。您可以使用触发通知的后台(启动)守护进程(不一定 UILocalNotification)使它工作。当通知向用户显示警报时,您的守护程序可以决定打开(或不打开)普通 UI 应用程序。
This is the best tutorial I've found .启动守护进程在手机启动时启动,并一直作为非图形后台进程运行。从那里,您可以安排检查更新。 (我有一个 HelloDaemon 类,它在 run: 方法中完成所有工作):
int main(int argc, char *argv[]) {
@autoreleasepool {
HelloDaemon* daemon = [[HelloDaemon alloc] init];
// start a timer so that the process does not exit.
NSTimer* timer = [[NSTimer alloc] initWithFireDate: [NSDate date]
interval: 1.0
target: daemon
selector: @selector(run:)
userInfo: nil
repeats: NO];
NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer: timer forMode: NSDefaultRunLoopMode];
[runLoop run];
}
return 0;
}
守护进程可以正常使用 NSTimer,因此请安排另一个计时器(在 run: 内)检查更新,以便随时下载。
如果守护进程决定应该通知用户,那么您可以:
1) 打开完整的 UI 应用程序。
#include <dlfcn.h>
#define SBSERVPATH "/System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices"
-(void) openApp {
// the SpringboardServices.framework private framework can launch apps,
// so we open it dynamically and find SBSLaunchApplicationWithIdentifier()
void* sbServices = dlopen(SBSERVPATH, RTLD_LAZY);
int (*SBSLaunchApplicationWithIdentifier)(CFStringRef identifier, Boolean suspended) = dlsym(sbServices, "SBSLaunchApplicationWithIdentifier");
int result = SBSLaunchApplicationWithIdentifier(CFSTR("com.mycompany.AppName"), false);
dlclose(sbServices);
}
此代码需要 com.apple.springboard.launchapplications 权限,您的守护程序才能成功使用它。 See here for adding an entitlement .您需要一个 entitlements.xml 文件用于您的守护程序可执行文件,如下所示:
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.springboard.launchapplications</key>
<true/>
</dict>
</plist>
2) 显示 simple alert window从您的守护程序,通知用户该事件,并提示他们打开 UI 应用
#include "CFUserNotification.h"
-(void) showAlert {
NSMutableDictionary* dict = [NSMutableDictionary dictionary];
[dict setObject: @"Alert!" forKey: (__bridge NSString*)kCFUserNotificationAlertHeaderKey];
[dict setObject: @"Updates Ready!" forKey: (__bridge NSString*)kCFUserNotificationAlertMessageKey];
[dict setObject: @"View" forKey:(__bridge NSString*)kCFUserNotificationDefaultButtonTitleKey];
[dict setObject: @"Cancel" forKey:(__bridge NSString*)kCFUserNotificationAlternateButtonTitleKey];
SInt32 error = 0;
CFUserNotificationRef alert =
CFUserNotificationCreate(NULL, 0, kCFUserNotificationPlainAlertLevel, &error, (__bridge CFDictionaryRef)dict);
CFOptionFlags response;
// we block, waiting for a response, for up to 10 seconds
if((error) || (CFUserNotificationReceiveResponse(alert, 10, &response))) {
NSLog(@"alert error or no user response after 10 seconds");
} else if((response & 0x3) == kCFUserNotificationAlternateResponse) {
// user clicked on Cancel ... just do nothing
NSLog(@"cancel");
} else if((response & 0x3) == kCFUserNotificationDefaultResponse) {
// user clicked on View ... so, open the UI App
NSLog(@"view");
[self openApp];
}
CFRelease(alert);
}
您需要一个 CFUserNotification.h header 才能按照我上面的方式使用代码。你可以通过谷歌搜索找到一个,或see one here .这older wiki document还显示了一些关于在 iOS 应用程序中使用 CFUserNotification 的有用信息。
answer I linked to from KennyTM above还展示了如何使警报弹出窗口显示,即使设备已锁定也是如此。
关于ios - 在越狱设备上本地拉取通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15025174/
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
有人知道在发布新版本的Ruby和Rails时收到电子邮件的方法吗?他们有邮件列表,RubyonRails有一个推特,但我不想听到那些随之而来的喧嚣,我只想知道什么时候发布新版本,尤其是那些有安全修复的版本。 最佳答案 从therailsblog获取提要.http://weblog.rubyonrails.org/feed/atom.xml 关于ruby-on-rails-如何在发布新的Ruby或Rails版本时收到通知?,我们在StackOverflow上找到一个类似的问题:
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
Devise是一个Ruby库,它为我提供了这个User类:classUser当写入:confirmable时,注册时会发送一封确认邮件。上周我不得不批量创建300个用户,所以我在恢复之前注释掉了:confirmable几分钟。现在我正在为用户批量创建创建一个UI,因此我需要即时添加/删除:confirmable。(我也可以直接修改Devise的源码,但我宁愿不去调和它)问题:如何即时添加/删除:confirmable? 最佳答案 WayneConrad的解决方案:user=User.newuser.skip_confirmation
print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上