- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我已经在我现有的应用程序中配置了 GCM,我正在那里接收通知。现在我面临两个问题:1) 当我退出应用程序或应用程序处于后台时,我没有收到通知。 2)我没有在iphone的通知区域收到通知,只有当我的应用程序运行时我才直接在那里收到警报消息。当我下拉通知区域时,我在 xcode 的控制台中收到此消息 “无法连接到 GCM:操作无法完成。(com.google.gcm 错误 2001。)”
我的 PHP 文件在下面
<?php
// Payload data you want to send to iOSdevice(s)
// (it will be accessible via intent extras)
$data = array( 'message' => 'Hello World!');
// The recipient registration tokens for this notification
// http://developer.android.com/google/gcm/
$ids = array( 'kucy6xoUmx********eeRsla' );
// Send a GCM push
sendGoogleCloudMessage( $data, $ids );
function sendGoogleCloudMessage( $data, $ids )
{
// Insert real GCM API key from Google APIs Console
// https://code.google.com/apis/console/
$apiKey = 'AIz******9JA';
// Define URL to GCM endpoint
$url = 'https://gcm-http.googleapis.com/gcm/send';
// Set GCM post variables (device IDs and push payload)
$post = array(
'registration_ids' => $ids,
'data' => $data,
);
// Set CURL request headers (authentication and type)
$headers = array(
'Authorization: key=' . $apiKey,
'Content-Type: application/json'
);
// Initialize curl handle
$ch = curl_init();
// Set URL to GCM endpoint
curl_setopt( $ch, CURLOPT_URL, $url );
// Set request method to POST
curl_setopt( $ch, CURLOPT_POST, true );
// Set our custom headers
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
// Get the response back as string instead of printing it
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
// Set JSON post data
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $post ) );
// Actually send the push
$result = curl_exec( $ch );
// Error handling
if ( curl_errno( $ch ) )
{
echo 'GCM error: ' . curl_error( $ch );
}
// Close curl handle
curl_close( $ch );
// Debug GCM response
echo $result;
}
?>
这是我的 AppDelegate.m 文件
// [START register_for_remote_notifications]
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// [START_EXCLUDE]
_registrationKey = @"onRegistrationCompleted";
_messageKey = @"onMessageReceived";
// Configure the Google context: parses the GoogleService-Info.plist, and initializes
// the services that have entries in the file
NSError* configureError;
[[GGLContext sharedInstance] configureWithError:&configureError];
NSAssert(!configureError, @"Error configuring Google services: %@", configureError);
_gcmSenderID = [[[GGLContext sharedInstance] configuration] gcmSenderID];
// Register for remote notifications
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
// iOS 7.1 or earlier
UIRemoteNotificationType allNotificationTypes =
(UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge);
[application registerForRemoteNotificationTypes:allNotificationTypes];
} else {
// iOS 8 or later
// [END_EXCLUDE]
UIUserNotificationType allNotificationTypes =
(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
UIUserNotificationSettings *settings =
[UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
// [END register_for_remote_notifications]
// [START start_gcm_service]
GCMConfig *gcmConfig = [GCMConfig defaultConfig];
gcmConfig.receiverDelegate = self;
[[GCMService sharedInstance] startWithConfig:gcmConfig];
// [END start_gcm_service]
__weak typeof(self) weakSelf = self;
// Handler for registration token request
_registrationHandler = ^(NSString *registrationToken, NSError *error){
if (registrationToken != nil) {
weakSelf.registrationToken = registrationToken;
NSLog(@"Registration Token: %@", registrationToken);
[weakSelf subscribeToTopic];
NSDictionary *userInfo = @{@"registrationToken":registrationToken};
[[NSNotificationCenter defaultCenter] postNotificationName:weakSelf.registrationKey
object:nil
userInfo:userInfo];
} else {
NSLog(@"Registration to GCM failed with error: %@", error.localizedDescription);
NSDictionary *userInfo = @{@"error":error.localizedDescription};
[[NSNotificationCenter defaultCenter] postNotificationName:weakSelf.registrationKey
object:nil
userInfo:userInfo];
}
};
return YES;
}
- (void)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:_registrationToken
topic:SubscriptionTopic
options:nil
handler:^(NSError *error) {
if (error) {
// Treat the "already subscribed" error more gently
if (error.code == 3001) {
NSLog(@"Already subscribed to %@",
SubscriptionTopic);
} else {
NSLog(@"Subscription failed: %@",
error.localizedDescription);
}
} else {
self.subscribedToTopic = true;
NSLog(@"Subscribed to %@", SubscriptionTopic);
}
}];
}
}
// [START connect_gcm_service]
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Connect to the GCM server to receive non-APNS notifications
[[GCMService sharedInstance] connectWithHandler:^(NSError *error) {
if (error) {
NSLog(@"Could not connect to GCM: %@", error.localizedDescription);
} else {
_connectedToGCM = true;
NSLog(@"Connected to GCM");
// [START_EXCLUDE]
[self subscribeToTopic];
// [END_EXCLUDE]
}
}];
}
// [END connect_gcm_service]
// [START disconnect_gcm_service]
- (void)applicationDidEnterBackground:(UIApplication *)application {
[[GCMService sharedInstance] disconnect];
// [START_EXCLUDE]
_connectedToGCM = NO;
// [END_EXCLUDE]
}
// [END disconnect_gcm_service]
// [START receive_apns_token]
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
// [END receive_apns_token]
// [START get_gcm_reg_token]
// Create a config and set a delegate that implements the GGLInstaceIDDelegate protocol.
GGLInstanceIDConfig *instanceIDConfig = [GGLInstanceIDConfig defaultConfig];
instanceIDConfig.delegate = self;
// Start the GGLInstanceID shared instance with the that config and request a registration
// token to enable reception of notifications
[[GGLInstanceID sharedInstance] startWithConfig:instanceIDConfig];
_registrationOptions = @{kGGLInstanceIDRegisterAPNSOption:deviceToken,
kGGLInstanceIDAPNSServerTypeSandboxOption:@"NO"};
[[GGLInstanceID sharedInstance] tokenWithAuthorizedEntity:_gcmSenderID
scope:kGGLInstanceIDScopeGCM
options:_registrationOptions
handler:_registrationHandler];
// [END get_gcm_reg_token]
}
// [START receive_apns_token_error]
- (void)application:(UIApplication *)application
didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSLog(@"Registration for remote notification failed with error: %@", error.localizedDescription);
// [END receive_apns_token_error]
NSDictionary *userInfo = @{@"error" :error.localizedDescription};
[[NSNotificationCenter defaultCenter] postNotificationName:_registrationKey
object:nil
userInfo:userInfo];
}
// [START ack_message_reception]
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSLog(@"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:_messageKey
object:nil
userInfo:userInfo];
// [END_EXCLUDE]
}
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler {
NSLog(@"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(UIBackgroundFetchResultNoData);
// [END_EXCLUDE]
}
// [END ack_message_reception]
// [START on_token_refresh]
- (void)onTokenRefresh {
// A rotation of the registration tokens is happening, so the app needs to request a new token.
NSLog(@"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]
- (void)willSendDataMessageWithID:(NSString *)messageID error:(NSError *)error {
if (error) {
// Failed to send the message.
} else {
// Will send message, you can save the messageID to track the message
}
}
- (void)didSendDataMessageWithID:(NSString *)messageID {
// Did successfully send message identified by messageID
}
// [END upstream_callbacks]
- (void)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.
}
我不是 php 脚本专家,所以请帮助我解决我的问题。
最佳答案
我已经添加了
'content_available' => true,//to trigger when iOS app is in background
'priority' => 'high',
'notification' => $data,
$data = array( 'message' => 'Hello World!', 'body' => 'Hello World!');
到您的代码。请尝试以下代码;
<?php
// Payload data you want to send to iOSdevice(s)
// (it will be accessible via intent extras)
$data = array( 'message' => 'Hello World!', 'body' => 'Hello World!');
// The recipient registration tokens for this notification
// http://developer.android.com/google/gcm/
$ids = array( 'kucy6xoUmx********eeRsla' );
// Send a GCM push
sendGoogleCloudMessage( $data, $ids );
function sendGoogleCloudMessage( $data, $ids )
{
// Insert real GCM API key from Google APIs Console
// https://code.google.com/apis/console/
$apiKey = 'AIz******9JA';
// Define URL to GCM endpoint
$url = 'https://gcm-http.googleapis.com/gcm/send';
// Set GCM post variables (device IDs and push payload)
$post = array(
'registration_ids' => $ids,
'data' => $data,
'content_available' => true,
'priority' => 'high',
'notification' => $data,
);
// Set CURL request headers (authentication and type)
$headers = array(
'Authorization: key=' . $apiKey,
'Content-Type: application/json'
);
// Initialize curl handle
$ch = curl_init();
// Set URL to GCM endpoint
curl_setopt( $ch, CURLOPT_URL, $url );
// Set request method to POST
curl_setopt( $ch, CURLOPT_POST, true );
// Set our custom headers
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
// Get the response back as string instead of printing it
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
// Set JSON post data
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $post ) );
// Actually send the push
$result = curl_exec( $ch );
// Error handling
if ( curl_errno( $ch ) )
{
echo 'GCM error: ' . curl_error( $ch );
}
// Close curl handle
curl_close( $ch );
// Debug GCM response
echo $result;
}
?>
在IOS端;按照订单GCM Site
编辑 1:您可以尝试发送 ios 通知;
我在上面编辑了你的 php 代码;变化是;
'通知'=> $data,
和
$data = array( 'message' => 'Hello World!', 'body' => 'Hello World!');
关于php - 当应用程序在 iOS 中处于后台模式时未收到 GCM 通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34704736/
对此感到疯狂,真的缺少一些东西。 我有webpack 4.6.0,webpack-cli ^ 2.1.2,所以是最新的。 在文档(https://webpack.js.org/concepts/mod
object Host "os.google.com" { import "windows" address = "linux.google.com" groups = ["linux"] } obj
每当我安装我的应用程序时,我都可以将数据库从 Assets 文件夹复制到 /data/data/packagename/databases/ .到此为止,应用程序工作得很好。 但 10 或 15 秒后
我在 cc 模式缓冲区中使用 hideshow.el 来折叠我不查看的文件部分。 如果能够在 XML 文档中做到这一点就好了。我使用 emacs 22.2.1 和内置的 sgml-mode 进行 xm
已结束。此问题不符合 Stack Overflow guidelines .它目前不接受答案。 我们不允许提出有关书籍、工具、软件库等方面的建议的问题。您可以编辑问题,以便用事实和引用来回答它。 关闭
根据java: public Scanner useDelimiter(String pattern) Sets this scanner's delimiting pattern to a patt
我读过一些关于 PRG 模式以及它如何防止用户重新提交表单的文章。比如this post有一张不错的图: 我能理解为什么在收到 2xx 后用户刷新页面时不会发生表单提交。但我仍然想知道: (1) 如果
看看下面的图片,您可能会清楚地看到这一点。 那么如何在带有其他一些 View 的简单屏幕中实现没有任何弹出/对话框/模式的微调器日期选择器? 我在整个网络上进行了谷歌搜索,但没有找到与之相关的任何合适
我不知道该怎么做,我一直遇到问题。 以下是代码: rows = int(input()) for i in range(1,rows): for j in range(1,i+1):
我想为重写创建一个正则表达式。 将所有请求重写为 index.php(不需要匹配),它不是以/api 开头,或者不是以('.html',或'.js'或'.css'或'.png'结束) 我的例子还是这样
MVC模式代表 Model-View-Controller(模型-视图-控制器) 模式 MVC模式用于应用程序的分层开发 Model(模型) - 模型代表一个存取数据的对象或 JAVA PO
我想为组织模式创建一个 RDF 模式世界。您可能知道,组织模式文档基于层次结构大纲,其中标题是主要的分组实体。 * March auxiliary :PROPERTIES: :HLEVEL: 1 :E
我正在编写一个可以从文件中读取 JSON 数据的软件。该文件包含“person”——一个值为对象数组的对象。我打算使用 JSON 模式验证库来验证内容,而不是自己编写代码。符合代表以下数据的 JSON
假设我有 4 张 table 人 公司 团体 和 账单 现在bills/persons和bills/companys和bills/groups之间是多对多的关系。 我看到了 4 种可能的 sql 模式
假设您有这样的文档: doc1: id:1 text: ... references: Journal1, 2013, pag 123 references: Journal2, 2014,
我有这个架构。它检查评论,目前工作正常。 var schema = { id: '', type: 'object', additionalProperties: false, pro
这可能很简单,但有人可以解释为什么以下模式匹配不明智吗?它说其他规则,例如1, 0, _ 永远不会匹配。 let matchTest(n : int) = let ran = new Rand
我有以下选择序列作为 XML 模式的一部分。理想情况下,我想要一个序列: 来自 my:namespace 的元素必须严格解析。 来自任何其他命名空间的元素,不包括 ##targetNamespace和
我希望编写一个 json 模式来涵盖这个(简化的)示例 { "errorMessage": "", "nbRunningQueries": 0, "isError": Fals
首先,我是 f# 的新手,所以也许答案很明显,但我没有看到。所以我有一些带有 id 和值的元组。我知道我正在寻找的 id,我想从我传入的三个元组中选择正确的元组。我打算用两个 match 语句来做到这
我是一名优秀的程序员,十分优秀!