- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我试过了Google 开发人员的“在 iOS 上设置 GCM 客户端应用程序”。我的应用程序有一个 android 版本,服务器成功向 Android 发送推送通知。在 ios 中,我可以将消息检索到 didRecieveRemoteNotification 函数。打印时如下所示,
aps: {
alert = {
body = tyyy;
title = "2 is going out at 03/24/2016 15:02:48";
};
badge = 2;
sound = default;
}
当应用程序处于前台和后台时,它会收到此消息。当应用程序处于后台时,系统托盘中不显示任何内容。
当应用程序终止并且服务器正在发送推送通知时,我什么也没有收到,也没有显示任何事件。
我的代码如下。
AppDelegate.swift
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, GGLInstanceIDDelegate, GCMReceiverDelegate {
var window: UIWindow?
var connectedToGCM = false
var subscribedToTopic = false
var gcmSenderID: String?
var registrationToken = "AIzaSy-.....-11bSP6v72UvyKY"
var registrationOptions = [String: AnyObject]()
let registrationKey = "onRegistrationCompleted"
let messageKey = "onMessageReceived"
let subscriptionTopic = "/topics/global"
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "APP_RUNNING")
// Override point for customization after application launch.
// [START_EXCLUDE]
// Configure the Google context: parses the GoogleService-Info.plist, and initializes
// the services that have entries in the file
var configureError:NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError)")
gcmSenderID = GGLContext.sharedInstance().configuration.gcmSenderID
// [END_EXCLUDE]
// Register for remote notifications
if #available(iOS 8.0, *) {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
application.registerUserNotificationSettings(settings)
application.registerForRemoteNotifications()
} else {
// Fallback
let types: UIRemoteNotificationType = [.Alert, .Badge, .Sound]
application.registerForRemoteNotificationTypes(types)
}
// [END register_for_remote_notifications]
// [START start_gcm_service]
let gcmConfig = GCMConfig.defaultConfig()
gcmConfig.receiverDelegate = self
GCMService.sharedInstance().startWithConfig(gcmConfig)
// [END start_gcm_service]
application.registerUserNotificationSettings(UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound],categories: nil))
if let options = launchOptions {
if let notification = options[UIApplicationLaunchOptionsLocalNotificationKey] as? UILocalNotification {
if let userInfo = notification.userInfo {
// do something neat here
}
}
}
return true
}
func subscribeToTopic() {
// If the app has a registration token and is connected to GCM, proceed to subscribe to the
// topic
if(registrationToken != "" && connectedToGCM) {
GCMPubSub.sharedInstance().subscribeWithToken(self.registrationToken, topic: subscriptionTopic,
options: nil, handler: {(error:NSError?) -> Void in
if let error = error {
// Treat the "already subscribed" error more gently
if error.code == 3001 {
print("Already subscribed to \(self.subscriptionTopic)")
} else {
print("Subscription failed: \(error.localizedDescription)");
}
} else {
self.subscribedToTopic = true;
NSLog("Subscribed to \(self.subscriptionTopic)");
}
})
}
}
func application( application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken
deviceToken: NSData ) {
// [END receive_apns_token]
// [START get_gcm_reg_token]
// Create a config and set a delegate that implements the GGLInstaceIDDelegate protocol.
let instanceIDConfig = GGLInstanceIDConfig.defaultConfig()
instanceIDConfig.delegate = self
// Start the GGLInstanceID shared instance with that config and request a registration
// token to enable reception of notifications
GGLInstanceID.sharedInstance().startWithConfig(instanceIDConfig)
registrationOptions = [kGGLInstanceIDRegisterAPNSOption:deviceToken,
kGGLInstanceIDAPNSServerTypeSandboxOption:true]
GGLInstanceID.sharedInstance().tokenWithAuthorizedEntity(gcmSenderID,
scope: kGGLInstanceIDScopeGCM, options: registrationOptions, handler: registrationHandler)
// [END get_gcm_reg_token]
}
// [START receive_apns_token_error]
func application( application: UIApplication, didFailToRegisterForRemoteNotificationsWithError
error: NSError ) {
print("Registration for remote notification failed with error: \(error.localizedDescription)")
// [END receive_apns_token_error]
let userInfo = ["error": error.localizedDescription]
NSNotificationCenter.defaultCenter().postNotificationName(
registrationKey, object: nil, userInfo: userInfo)
}
// [START ack_message_reception]
func application( application: UIApplication,
didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
print("Notification received: \(userInfo)")
// This works only if the app started the GCM service
GCMService.sharedInstance().appDidReceiveMessage(userInfo);
// Handle the received message
// [START_EXCLUDE]
NSNotificationCenter.defaultCenter().postNotificationName("reloadTableEvent", object: nil)
NSNotificationCenter.defaultCenter().postNotificationName(messageKey, object: nil,
userInfo: userInfo)
// [END_EXCLUDE]
}
func application( application: UIApplication,
didReceiveRemoteNotification userInfo: [NSObject : AnyObject],
fetchCompletionHandler handler: (UIBackgroundFetchResult) -> Void) {
print("Notification received: \(userInfo)")
// This works only if the app started the GCM service
GCMService.sharedInstance().appDidReceiveMessage(userInfo);
// Handle the received message
// Invoke the completion handler passing the appropriate UIBackgroundFetchResult value
// [START_EXCLUDE]
NSNotificationCenter.defaultCenter().postNotificationName(messageKey, object: nil,
userInfo: userInfo)
handler(UIBackgroundFetchResult.NoData);
// [END_EXCLUDE]
}
// [END ack_message_reception]
func registrationHandler(registrationToken: String!, error: NSError!) {
if (registrationToken != nil) {
self.registrationToken = registrationToken
print("Registration Token: \(registrationToken)")
NSUserDefaults.standardUserDefaults().setValue(registrationToken, forKey: "registrationToken")
self.subscribeToTopic()
let userInfo = ["registrationToken": registrationToken]
NSNotificationCenter.defaultCenter().postNotificationName(
self.registrationKey, object: nil, userInfo: userInfo)
} else {
print("Registration to GCM failed with error: \(error.localizedDescription)")
let userInfo = ["error": error.localizedDescription]
NSNotificationCenter.defaultCenter().postNotificationName(
self.registrationKey, object: nil, userInfo: userInfo)
}
}
// [START on_token_refresh]
func onTokenRefresh() {
// A rotation of the registration tokens is happening, so the app needs to request a new token.
print("The GCM registration token needs to be changed.")
GGLInstanceID.sharedInstance().tokenWithAuthorizedEntity(gcmSenderID,
scope: kGGLInstanceIDScopeGCM, options: registrationOptions, handler: registrationHandler)
}
// [END on_token_refresh]
// [START upstream_callbacks]
func willSendDataMessageWithID(messageID: String!, error: NSError!) {
if (error != nil) {
// Failed to send the message.
} else {
// Will send message, you can save the messageID to track the message
}
}
func didSendDataMessageWithID(messageID: String!) {
// Did successfully send message identified by messageID
}
// [END upstream_callbacks]
func didDeleteMessagesOnServer() {
// Some messages sent to this device were deleted on the GCM server before reception, likely
// because the TTL expired. The client should notify the app server of this, so that the app
// server can resend those messages.
}
func applicationWillResignActive(application: UIApplication) {
// 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.
}
func applicationDidEnterBackground(application: UIApplication) {
NSUserDefaults.standardUserDefaults().setBool(false, forKey: "APP_RUNNING")
// 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.
GCMService.sharedInstance().disconnect()
// [START_EXCLUDE]
self.connectedToGCM = false
// [END_EXCLUDE]
}
func applicationWillEnterForeground(application: UIApplication) {
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "APP_RUNNING")
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(application: UIApplication) {
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "APP_RUNNING")
// 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.
// Connect to the GCM server to receive non-APNS notifications
GCMService.sharedInstance().connectWithHandler({(error:NSError?) -> Void in
if let error = error {
print("Could not connect to GCM: \(error.localizedDescription)")
} else {
self.connectedToGCM = true
print("Connected to GCM")
// [START_EXCLUDE]
self.subscribeToTopic()
// [END_EXCLUDE]
}
})
}
func applicationWillTerminate(application: UIApplication) {
NSUserDefaults.standardUserDefaults().setBool(false, forKey: "APP_RUNNING")
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
func application(application: UIApplication, didReceiveLocalNotification notification: UILocalNotification) {
if let userInfo = notification.userInfo {
NSNotificationCenter.defaultCenter().postNotificationName(
"LoadEventViewController", object: nil, userInfo: userInfo)
}
}
}
ViewController,弹出本地通知
func scheduleLocal(message: String) {
let settings = UIApplication.sharedApplication().currentUserNotificationSettings()
if settings!.types == .None {
let ac = UIAlertController(title: "Can't schedule", message: "Either we don't have permission to schedule notifications, or we haven't asked yet.", preferredStyle: .Alert)
ac.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
presentViewController(ac, animated: true, completion: nil)
return
}
// create a corresponding local notification
let notification = UILocalNotification()
notification.alertBody = message // text that will be displayed in the notification
notification.alertAction = "open" // text that is displayed after "slide to..." on the lock screen - defaults to "slide to view"
notification.fireDate = NSDate(timeIntervalSinceNow: 0) // todo item due date (when notification will be fired)
notification.soundName = UILocalNotificationDefaultSoundName // play default sound
notification.userInfo = ["UUID": 1, ] // assign a unique identifier to the notification so that we can retrieve it later
notification.category = "TODO_CATEGORY"
UIApplication.sharedApplication().scheduleLocalNotification(notification)
}
我有两个问题,
最佳答案
这是您的推送通知 JSON?
aps: { "content-available" = 1; }
如果是,那么您正在发送静默推送。静默推送意味着用户不会收到任何视觉通知,只会调用您应用的应用委托(delegate)回调。删除内容可用标签并改为传递消息文本。
如果应用程序在前台,iOS 不会显示推送通知,而只是调用委托(delegate)。然后您可以显示警报 View 或您喜欢的其他内容。
或者你可以显示这个:https://github.com/avielg/AGPushNote
关于“由用户终止”的状态,这里是 Apple 文档(用于静默推送):
Use this method to process incoming remote notifications for your app. Unlike the application:didReceiveRemoteNotification: method, which is called only when your app is running in the foreground, the system calls this method when your app is running in the foreground or background. In addition, if you enabled the remote notifications background mode, the system launches your app (or wakes it from the suspended state) and puts it in the background state when a remote notification arrives. However, the system does not automatically launch your app if the user has force-quit it. In that situation, the user must relaunch your app or restart the device before the system attempts to launch your app automatically again.
关于ios - 如何在应用程序未运行/应用程序终止时获取推送通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36195624/
我正在尝试将多个值放入数组中。 当我使用时: csvData.push('data[0][index],data[1][index],data[2][index],data[3][index]');
我想在数组声明中直接使用函数 push(),但它不能正常工作。在我的示例中,我的数组返回值 2 : var j = ["b"].push("a"); document.write(j); // ret
我编写了以下Powershell,它为所选文件夹中的所有驱动程序创建了一个bat安装程序,然后应重新启动PC。 New-Item C:\Tools\Drivers\DellLatitude3450.b
例: $ git clone git@gitlab:carlos/test.git Cloning into 'asd'... ssh: connect to host gitlab port 22:
我正在构建一个具有数组类型属性的对象数组: 这里是一些简化的代码: var _data = []; for(var i=0;i<10;i++) { var element = {
我有一个简单的 PHP/MySql 应用程序,它通常会选择几个数据库之一(假设每个客户一个)进行操作。但是,经常调用访问公共(public)数据库的实用程序函数。 我不想在我的代码中散布 USE 子句
我在推送 View Controller 时遇到问题。这就是我所做的:单击一个按钮,我使用这段代码添加了一个模态视图,我工作正常: - (void)addAction:(id)sender {
我想为socket can写一个android系统服务器。我目前正在设计这个,想知道是否有任何方法可以在 Linux/POSIX 套接字上的数据是否可用而无需调用 read() 并随时轮询结果的情况下
我正在编写一个 Bootstrap 站点,我想知道这是否可以接受。该网站看起来像我想要的那样,但我想知道这是否是最佳做法? 我采用的方法是对每两个缺失的列使用 1 个偏
删除远程分支是通过: git push origin :master 如果本地在远程之后,则需要完成: git push --force origin :master 但是强制删除例如master 基
假设我有一个 git 服务器。在每次推送时,我都需要启动一个进程,我可以通过一个钩子(Hook)来完成。 需要将进程的标准输出写入执行推送的 git 客户端。这与 Heroku 或 Openshift
我刚刚开始学习 Git,有些事情我无法解决。在我的 Mac 上本地创建和使用 git 存储库后,我可以将副本推送到其他地方的另一台服务器吗?我在防火墙后面,所以不幸的是我无法从另一台机器运行 git
这个问题在这里已经有了答案: warning: remote HEAD refers to nonexistent ref, unable to checkout (13 个答案) 关闭 7 年前。
我已经安装了 SCM Sync 配置插件(0.0.10)来将我的 jenkins 设置保存在我的 git 存储库中。 我已经设置了 git url 存储库但插件没有提交/推送,请看截图 我试过: 私钥
这可能看起来很矛盾,我知道 secret 变更集是私有(private)的,但是如果我想备份这些 secret 变更集怎么办? 我与一些分支并行工作,有时我想插入一个,而不是其他的。为了实现这一点,我
我正在使用 TortoiseHg用于版本控制。提交到本地后,我推送到远程存储库。如何撤消到特定的提交点? 有三个不同的插入,我想恢复到第一个插入。我读到了 Mercurial 回滚和 hg 撤销 命令
我知道以前有人问过这个问题,但我似乎无法理解这件事...... git checkout master git pull git git checkout feature git rebase ori
下面的代码片段中 return { Push:function ..... 的含义是什么?当我用谷歌搜索时,我发现push()方法将新项目添加到数组的末尾,并返回新的长度。所以我不确定什么是push:
我正在使用 Mercurial 1.6。我有一个带有几个子存储库的存储库 (11)。我想将父存储库推送到默认远程存储库,而不推送子存储库。想要这样做的原因包括: 我使用的是 SSH 存储库,需要很长时
我分配了一个按钮来将 segue 推送到另一个 View Controller ,但是当我执行这部分代码时,我得到以下信息: 2014-02-20 10:44:29.357 nar[20244:70b
我是一名优秀的程序员,十分优秀!