天道酬勤,学无止境

Google push notifications java handler

I have subscribed my app to listen to Google push notifications. Channel details was persisted. I can receive notifications from google to my endpoint.

@PostMapping("/google/calendars/")
public void watch(HttpServletRequest request,
  @RequestHeader(value = "X-Goog-Channel-ID", required = false) String googleChannelId,
  @RequestHeader(value = "X-Goog-Channel-Token", required = false) String googleChannelToken,
  @RequestHeader(value = "X-Goog-Channel-Expiration", required = false) String googleChannelExpiration,
  @RequestHeader(value = "X-Goog-Resource-ID", required = false) String googleResourceId,
  @RequestHeader(value = "X-Goog-Resource-URI", required = false) String googleResourceUri,
  @RequestHeader(value = "X-Goog-Resource-State", required = false) String googleResourceState,
  @RequestHeader(value = "X-Goog-Message-Number", required = false) String googleMessageNumber,

Using information was received I can open client to google service. But I do not know how to get changes.

googleChannelId=354a78aa-0cc0-4b5b-96c5-e54e03a51e68
googleChannelToken=<null>
googleChannelExpiration=Sat, 18 Mar 2017 17:01:56 GMT
googleResourceId=eVHbdUeaWhfQPpvJPU7VZRxYzUs
googleResourceUri=https://www.googleapis.com/calendar/v3/calendars/sergii_vlasiuk@ukr.net/events?maxResults=250&alt=json
googleResourceState=exists
googleMessageNumber=403802722

exists means googleResourceId was changed.

Using googleChannelId I load my channel details and open client.


  1. How to use googleResourceId in my pull change request (request example maybe)?
  2. Is it correct understanding: not_exists means resource was deleted; exists means resource was created or edited?

Add details

I've tried

client.events().get(originalCalendarId, googleResourceId).execute()

Where:

  1. client is com.google.api.services.calendar.Calendar object with correct tokens.
  2. ginalCalendarId - is good known google calendar Id, one was used in subscription.
  3. googleResourceId - is from header message X-Goog-Resource-ID value. ->

    404 Not Found { "code" : 404, "errors" : [ { "domain" : "global", "message" : "Not Found", "reason" : "notFound" } ], "message" : "Not Found" }

评论

But I do not know how to get changes.

The Google Calendar API provides push notifications that let you watch for changes to resources. You can use this feature to improve the performance of your application. It allows you to eliminate the extra network and compute costs involved with polling resources to determine if they have changed. Whenever a watched resource changes, the Google Calendar API notifies your application.

Once you have set up watch correctly your application will be informed when there has been a change. You don't need to check for it.

Example

POST https://www.googleapis.com/calendar/v3/calendars/my_calendar@gmail.com/events/watch
Authorization: Bearer auth_token_for_current_user
Content-Type: application/json

{
  "id": "01234567-89ab-cdef-0123456789ab", // Your channel ID.
  "type": "web_hook",
  "address": "https://example.com/notifications", // Your receiving URL.
  ...
  "token": "target=myApp-myCalendarChannelDest", // (Optional) Your channel token.
  "expiration": 1426325213000 // (Optional) Your requested channel expiration time.
  }
}

There is a full article on how to set this up the documentation Push Notifications

Note:

This statement wont work because Events.get requires an event Id as its second parameter not your GoogleResourceId

 client.events().get(originalCalendarId, googleResourceId).execute()

How watch works:

  1. You decide you want to watch for changes on a users events. You create a watch on the events. Google returns to you resourceId this identifies the watch.
  2. A change is made google sends you a notification in the form of a HTTP Post. It contains the resource id from your watch.
  3. You know that the watch with this resource id is liked to a users events. You use your refresh token to gain access to the users account. you do an events list and scan though each of the events looking for which one has changes.

The resource Id can not be used to request events. The watch does not tell you what exactly was changed or when. You have to query the API to find that out.

If Google doesn't have a convenient approach to distinguish which exactly entities have been updated, I suppose we should think about a workaround. In my opinion, getting all the events and updating your database state by traversing and rewriting all the data will lead you to some performance issues.

To address that, I would choose using "etag" value that each event has. Every time an event is updated, the ETag changes(works in CalDav protocol)

http://cdn.nsoftware.com/help/IP9/cs/CalDAV_p_ETag.htm

If you save etag to your database with your event, then once you get the list of events from Google, you can just check etag value and update only the elements that were really changed. That must optimize the part when you update your entries.

Google supports etag. You can find it here:

https://developers.google.com/google-apps/calendar/v3/reference/events/list

{
  "kind": "calendar#events",
  "etag": etag,
  "summary": string,
  "description": string,
  "updated": datetime,
  "timeZone": string,
  "accessRole": string,
  "defaultReminders": [
    {
      "method": string,
      "minutes": integer
    }
  ],
  "nextPageToken": string,
  "nextSyncToken": string,
  "items": [
    events Resource
  ]
}

UPDATED:

There is a more convenient way to perform synchronization. You can use Incremental synchronization approach. Incremental sync allows you to retrieve all the resources that have been modified since the last sync request.

https://developers.google.com/google-apps/calendar/v3/sync#initial_full_sync

You just need to save sync token every time you update data and use it in the request to get new data. In this case you will get only data that was modified.

Calendar.Events.List request = client.events().list("primary");
request.setSyncToken(syncToken);

If you call then:

events = request.execute();
List<Event> items = events.getItems();

You will get only the data that was updated.

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • Android doesn't receive push notification from Parse Push when app is closed
    When I am testing the Parse Push to my Android phones the push notification come through as long as the app runs. If the app is closed: I just get a message saying <App name> has stopped. - I don't receive any of the pushes - but still got the stop notification popup. I have followed the Quickstart guide from Parse step by step. <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.ostsia.ostsia"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK
  • GCM将通知推送到具有content_available的iOS(无法从非活动状态调用)(GCM push notification to iOS with content_available (not working to invoke from inactive state))
    问题 我正在开发基于Java REST的Web服务,在该服务中,我试图通过Google Cloud Messaging将消息从Java API发送到iOS设备。 出于学习目的,我使用了适用于iOS的Google示例代码,并且能够在应用程序处于前台状态时发送消息,但在应用程序处于后台状态时无法正常工作。 我尝试了“ content_available”标志的几种变体,这些标志负责从后台调用应用程序。 当应用程序处于前台时,它运行良好。 我正在尝试在后台运行应用程序时显示通知。 HttpClient client = new DefaultHttpClient(); HttpPost post = null; try { post = new HttpPost("https://android.googleapis.com/gcm/send"); } catch (URISyntaxException e) { // TODO Auto-generated catch block e.printStackTrace(); } String regisID="My_iOS_Registration_Id-GVnH1gEsJ"; List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1); List
  • GCM push notification to iOS with content_available (not working to invoke from inactive state)
    I am working on Java REST based web service in which I am trying to send messages from a Java API to an iOS device through Google Cloud Messaging. For learning purposes I have used google sample code for iOS and I am able to send messages when the app is in the foreground but it is not working when the app is in the background. I have tried several variations of the "content_available" flag that is responsible for invoking the app from the background. It is working nicely when the app is in foreground. I am trying to show notifications when the app is in the background. HttpClient client = new
  • Parse Push “No Activity Found” on opening Push Notification
    I made an app using Parse as backend. I am able to get the notification but when i tap on it, the app crashes. Here are the java and XML files. AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="chipset.lugmnotifier"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission
  • 在打开推送通知时解析推送“未找到活动”(Parse Push “No Activity Found” on opening Push Notification)
    问题 我使用 Parse 作为后端制作了一个应用程序。 我能够收到通知,但是当我点击它时,应用程序崩溃了。 这是 java 和 XML 文件。 AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="chipset.lugmnotifier"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android
  • react native - not receiving notification when app is killed/not started
    I am using react-native-firebase@4.2.0 for push notifications. When app is open on screen, I receive the notification via onNotification and an alert as intended by my code. PROBLEM 1 When app is in background (not killed), I receive the notification in status bar but on tapping it, it just gets dismissed and app is not opened. I also get this error in android logcat: 06-21 17:26:03.892 5926 8672 D RNFMessagingService: onMessageReceived event received 06-21 17:26:03.913 5926 8600 E ReactNativeJS: No task registered for key RNFirebaseBackgroundMessage --------- beginning of crash 06-21 17:26:03
  • 当应用程序关闭时,Android 不会收到来自 Parse Push 的推送通知(Android doesn't receive push notification from Parse Push when app is closed)
    问题 当我测试解析推送到我的 Android 手机时,只要应用程序运行,推送通知就会出现。 如果应用程序已关闭:我只会收到一条消息,指出<App name> has stopped. - 我没有收到任何推送 - 但仍然收到停止通知弹出窗口。 我一步一步地遵循了 Parse 的快速入门指南。 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.ostsia.ostsia"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission
  • Fcm integration getting the exception
    I am working on the FCM integration but getting the java.lang.ClassNotFoundException: Didn't find class "service.MyFirebaseMessagingService" on path: DexPathList[[zip file "/data/app/com.rk.servicepractise-2/base.apk"],nativeLibraryDirectories=[/vendor/lib64, /system/lib64]] I have searched it about but did not get the proper solution yet,Please check my code below and let me know where am i doing wrong? Please check my classes and manifest file with gradle, Please help me to short out from this problem. My first class that is the MyFirebaseInstanceIDService which extends
  • Firebase Messaging on Android suddenly started crashing when message received
    Currently using react native, react-native-firebase, and react-native-push-notification. Everything was fine until suddenly today firebase messaging started causing the app to crash. The error message is the following: Process: com.packagename, PID: 30087 java.lang.AbstractMethodError: abstract method "com.google.android.gms.tasks.Task com.google.firebase.iid.WithinAppServiceBinder$IntentHandler.zza(android.content.Intent)" at com.google.firebase.iid.WithinAppServiceBinder.zza(com.google.firebase:firebase-iid@@20.2.2:9) at com.google.firebase.iid.zzaw.zza(com.google.firebase:firebase-iid@@20.2
  • Fcm 集成获得异常(Fcm integration getting the exception)
    问题 我正在处理FCM集成,但得到java.lang.ClassNotFoundException: Didn't find class "service.MyFirebaseMessagingService" on path: DexPathList[[zip file "/data/app/com.rk.servicepractise-2/base.apk"],nativeLibraryDirectories=[/vendor/lib64, /system/lib64]] 我已经搜索过,但还没有得到正确的解决方案,请检查下面的代码,让我知道我做错了什么? 请使用gradle检查我的classes和manifest文件,请帮我解决这个问题。 我的第一个类是扩展FirebaseInstanceIdService类的MyFirebaseInstanceIDService public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService { private static final String TAG = "MyFirebaseIIDService"; @Override public void onTokenRefresh() { //Getting registration token
  • WakefulBroadcastReceiver onReceive 不触发android GCM(WakefulBroadcastReceiver onReceive not triggering android GCM)
    问题 我在 Android 中实现了GCM通知,一切正常。 我正在使用 Google Cloud Messaging Service 通过 PHP 服务器向手机发送通知。 一周左右后,我再次在手机上安装了该应用程序并将测试通知发送到我的手机上,但我什么也没收到。 PHP 脚本运行没有任何错误, success=1并且 GCM 响应中没有 cononical id。 WakufulBroadcastReceiver不会在 android 应用程序中触发。 这是我正在使用的完整代码: GcmBroadcastReceiver.java public class GcmBroadcastReceiver extends WakefulBroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { Log.d("", "In Receive Method of Broadcast Receiver"); ComponentName cn = new ComponentName(context.getPackageName(), GcmMessageHandler.class.getName()); startWakefulService(context, intent
  • Unable to start receiver com.google.firebase.iid.FirebaseInstanceIdInternalReceiver
    My app integrates FCM to receive push notifications and it works okay. However, I am facing issue that on installation it crashes randomly. It is very random and occurring on OS 6.0+ devices till latest but randomly occurs. Code wise, in service class only show notification code is written and added service in manifest. I am getting below exception on app loads Fatal Exception: java.lang.RuntimeException: Unable to start receiver com.google.firebase.iid.FirebaseInstanceIdInternalReceiver: java.lang.IllegalStateException: Not allowed to start service Intent { act=com.google.firebase.INSTANCE_ID
  • Exception when sending broadcast to ComponentInfo
    I have a receiver for Google cloud message, it's registered in AndroidManifest.xml: <receiver android:name="com.app.android.push.HSPushReceiver" android:permission="com.google.android.c2dm.permission.SEND" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> <action android:name="com.google.android.c2dm.intent.REGISTER" /> <category android:name="com.app.android" /> </intent-filter> </receiver> I can receive message when the app is in foreground or
  • 当应用程序在iOS中处于后台模式时,无法接收GCM通知(GCM Notifications not receiving when app is in background mode in 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 ) {
  • 如何修复此错误:“ android.app.RemoteServiceException:错误的通知从程序包中发布”(How to fix this bug : “android.app.RemoteServiceException: Bad notification posted from package”)
    问题 崩溃信息为: android.app.RemoteServiceException: Bad notification posted from package com.xx.xx: Couldn't create icon: StatusBarIcon(pkg=com.xx.xx user=0 id=0x7f02035c level=0 visible=true num=0 ) android.app.ActivityThread$H.handleMessage(ActivityThread.java:1372) android.os.Handler.dispatchMessage(Handler.java:102) android.os.Looper.loop(Looper.java:136) android.app.ActivityThread.main(ActivityThread.java:5139) java.lang.reflect.Method.invokeNative(Native Method) java.lang.reflect.Method.invoke(Method.java:515) com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:796) com
  • 向 ComponentInfo 发送广播时出现异常(Exception when sending broadcast to ComponentInfo)
    问题 我有一个谷歌云消息接收器,它在 AndroidManifest.xml 中注册: <receiver android:name="com.app.android.push.HSPushReceiver" android:permission="com.google.android.c2dm.permission.SEND" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE" /> <action android:name="com.google.android.c2dm.intent.REGISTRATION" /> <action android:name="com.google.android.c2dm.intent.REGISTER" /> <category android:name="com.app.android" /> </intent-filter> </receiver> 当应用程序在前台或被杀死时,我可以收到消息。 但是,如果我使用通知启动 IntentService,然后将主要活动滑开,然后如果我发送通知,则会出现以下崩溃: 08-29 15:29:37
  • GcmBroadcastReceiver IllegalStateException: Not allowed to start service Intent
    I am working on FCM Push notification in Android, where I am getting this exception: GcmBroadcastReceiver IllegalStateException: Not allowed to start service Intent I have searched many question in this forum, but still didn't got help for solving it. My Log and Manifest patch is also given below. Manifest: <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android
  • 带有PHP的GCM(Google云消息传递)(GCM with PHP (Google Cloud Messaging))
    问题 更新:不建议使用GCM,请使用FCM 如何将新的Google Cloud Messaging集成到PHP后端? 回答1 此代码将通过PHP CURL将GCM消息发送到多个注册ID。 // Payload data you want to send to Android device(s) // (it will be accessible via intent extras) $data = array('message' => 'Hello World!'); // The recipient registration tokens for this notification // https://developer.android.com/google/gcm/ $ids = array('abc', 'def'); // Send push notification via Google Cloud Messaging sendPushNotification($data, $ids); function sendPushNotification($data, $ids) { // Insert real GCM API key from the Google APIs Console // https://code.google.com/apis/console/
  • ios Google Cloud Messaging (GCM) not receiving remote notifications
    Problem: iOS isn't receiving any remote notifications from GCM, but can't find any information relating to why this would be the case. First time implementing push notifications, not sure what the cause of problem is. Situation: I am currently working on the iOS version of an app that uses GCM for push notifications. Notifications are being received fine on Android, however, it doesn't appear to be receiving at all on iOS. When I run the application, the console shows me that everything is fine, has a token, connected to GCM and subscribed to topics app[579:45511] Registration Token
  • ios Google Cloud Messaging (GCM) 未收到远程通知(ios Google Cloud Messaging (GCM) not receiving remote notifications)
    问题 问题: iOS 没有收到来自 GCM 的任何远程通知,但找不到任何有关为什么会出现这种情况的信息。 第一次实现推送通知,不确定问题的原因是什么。 情况: 我目前正在开发使用 GCM 进行推送通知的应用程序的 iOS 版本。 在 Android 上可以很好地接收通知,但是,在 iOS 上似乎根本没有接收到通知。 当我运行应用程序时,控制台向我显示一切正常,有一个令牌,连接到 GCM 并订阅了主题 app[579:45511] 注册令牌:bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1pLTQ/8t-5QNiXbYwZYEWiSFD-frQKlsV8lgI 应用程序[579:45511] 连接到 GCM app[579:45511] 已经订阅/topics/global 但是它没有收到任何通知,当我拉下通知中心或拉起控制中心时,控制台中会出现以下消息 app[579:45511] 无法连接到 GCM:操作无法完成。 (com.google.gcm 错误 2001。) 除了提到... /// 缺少密钥对。 kGGLInstanceIDOperationErrorCodeMissingKeyPair = 2001, 另一方面,当我使用多任务功能将其发送到后台并将其带回来时,我又得到了这个: 应用程序[579:45511] 连接到 GCM app