2 * Copyright 2011 Google Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.google.ipc.invalidation.ticl.android.c2dm;
20 import com.google.common.base.Preconditions;
21 import com.google.ipc.invalidation.external.client.SystemResources.Logger;
22 import com.google.ipc.invalidation.external.client.android.service.AndroidLogger;
24 import android.app.Service;
25 import android.content.Intent;
27 import org.json.JSONException;
28 import org.json.JSONObject;
31 * Represents a C2DM observer that gets notifications whenever the
32 * application receives a C2DM message or something changes regarding C2DM registration status.
34 * An observer may have its own unique filter so that not all messages are dispatched to all
37 public class C2DMObserver {
40 private static final Logger logger = AndroidLogger.forTag("C2DMObserver");
42 /** JSON key name for the observer class name string value */
43 private static final String KEY_CLASS = "class";
45 /** JSON key name for the filter field name string value */
46 private static final String KEY_FILTER_KEY = "filterKey";
48 /** JSON key name for the value field string value */
49 private static final String KEY_FILTER_VALUE = "filterValue";
51 /** JSON kye name for the handle wake lock boolean field */
52 private static final String KEY_HANDLE_WAKE_LOCK = "handleWakeLock";
54 /** Service class that handles messages for this observer */
55 private final Class<? extends Service> messageService;
57 /** Select field name (or {@code null} if none) */
58 private final String selectKey;
60 /** Select field value (or {@code null} if none) */
61 private final String selectValue;
63 /** {@code true} if the observer handles the wake lock */
64 private final boolean handleWakeLock;
67 * Creates a new observer using the state stored within the provided JSON object (normally
68 * created by {@link #toJSON()}.
70 static C2DMObserver createFromJSON(JSONObject json) {
72 // Extract instance state value from the appropriate JSON fields.
73 String canonicalClassString = json.getString(KEY_CLASS);
74 Class<? extends Service> clazz =
75 Class.forName(canonicalClassString).asSubclass(Service.class);
76 String filterKey = json.has(KEY_FILTER_KEY) ? json.getString(KEY_FILTER_KEY) : null;
77 String filterValue = json.has(KEY_FILTER_VALUE) ? json.getString(KEY_FILTER_VALUE) : null;
78 Boolean handleWakeLock =
79 json.has(KEY_HANDLE_WAKE_LOCK) && json.getBoolean(KEY_HANDLE_WAKE_LOCK);
80 return new C2DMObserver(clazz, filterKey, filterValue, handleWakeLock);
81 } catch (JSONException e) {
82 logger.severe("Unable to parse observer. Source: %s", json);
83 } catch (ClassNotFoundException e) {
84 logger.severe("Unable to parse observer. Class not found. Source: %s", json);
90 * Creates a new observer from the extra values contained in the provided intent.
92 static C2DMObserver createFromIntent(Intent intent) {
93 String canonicalClassString = intent.getStringExtra(C2DMessaging.EXTRA_CANONICAL_CLASS);
95 // Extract observer state from the intent built by the C2DM manager.
96 Class<? extends Service> clazz =
97 Class.forName(canonicalClassString).asSubclass(Service.class);
98 String filterKey = intent.getStringExtra(C2DMessaging.EXTRA_FILTER_KEY);
99 String filterValue = intent.getStringExtra(C2DMessaging.EXTRA_FILTER_VALUE);
100 boolean handleWakeLock = intent.getBooleanExtra(C2DMessaging.EXTRA_HANDLE_WAKELOCK, false);
101 return new C2DMObserver(clazz, filterKey, filterValue, handleWakeLock);
102 } catch (ClassNotFoundException e) {
103 logger.severe("Unable to register observer class %s", canonicalClassString);
109 * Creates a new observer for the provided service, selection criteria, and wake lock behavior.
112 C2DMObserver(Class<? extends Service> messageService, String selectKey, String selectValue,
113 boolean handleWakeLock) {
114 Preconditions.checkNotNull(messageService);
115 this.messageService = messageService;
116 this.selectKey = selectKey;
117 this.selectValue = selectValue;
118 this.handleWakeLock = handleWakeLock;
122 * Returns the JSON object representation of the observer state.
124 JSONObject toJSON() {
126 JSONObject json = new JSONObject();
127 json.put(KEY_CLASS, messageService.getCanonicalName());
128 json.put(KEY_FILTER_KEY, selectKey);
129 json.put(KEY_FILTER_VALUE, selectValue);
130 json.put(KEY_HANDLE_WAKE_LOCK, handleWakeLock);
132 } catch (JSONException e) {
133 logger.severe("Unable to create JSON object from observer %s", toString());
139 * Returns {@code true} if the provided intent matches the selection criteria for this
142 boolean matches(Intent intent) {
143 if (selectKey == null) {
146 if (intent.hasExtra(selectKey)) {
147 return selectValue == null || selectValue.equals(intent.getStringExtra(selectKey));
152 Class<?> getObserverClass() {
153 return messageService;
157 String getFilterKey() {
162 String getFilterValue() {
167 boolean isHandleWakeLock() {
168 return handleWakeLock;
172 public boolean equals(Object o) {
176 if (o == null || getClass() != o.getClass()) {
179 C2DMObserver that = (C2DMObserver) o;
180 if (!messageService.equals(that.messageService)) {
183 if (selectKey != null ? !selectKey.equals(that.selectKey) : that.selectKey != null) {
186 if (selectValue != null ? !selectValue.equals(that.selectValue) : that.selectValue
190 return handleWakeLock == that.handleWakeLock;
194 public int hashCode() {
195 int result = messageService.hashCode();
196 result = 31 * result + (selectKey != null ? selectKey.hashCode() : 0);
197 result = 31 * result + (selectValue != null ? selectValue.hashCode() : 0);
198 result = 31 * result + (handleWakeLock ? 1 : 0);
203 public String toString() {
204 return "C2DMObserver{" + "mClass=" + messageService + ", mFilterKey='" + selectKey + '\''
205 + ", mFilterValue='" + selectValue + '\'' + ", mHandleWakeLock=" + handleWakeLock + '}';