资源说明:[UNMAINTAINED] A Java library for implementing the third-party application server component of the Android Cloud to Device Messaging (C2DM) framework.
# C2DM4j [![No Maintenance Intended](http://unmaintained.tech/badge.svg)](http://unmaintained.tech/) [![Build Status](https://travis-ci.org/drbild/c2dm4j.png?branch=master)](https://travis-ci.org/drbild/c2dm4j) NOTE: The library has been deprecated since [GCM](https://developers.google.com/cloud-messaging/) replaced [C2DM](http://code.google.com/android/c2dm/). C2DM4j is a Java library for implementing the third-party application server component of the [Android Cloud to Device Messaging (C2DM) framework](http://code.google.com/android/c2dm/). It implements features like automated retries with exponential backoff and supports both synchronous and asynchronous workflows. The asynchronous flow is extensible via response handlers. C2DM4j is released under the [Apache 2.0 license](http://www.apache.org/licenses/LICENSE-2.0). See the Usage section below for instructions or browse the [javadocs](http://drbild.github.com/c2dm4j/apidocs/index.html). ## Downloads C2DM4j is available from Maven Central and as a jar file. + Maven Central:+ Jar: [c2dm4j-1.0.2.jar](http://github.com/downloads/drbild/c2dm4j/c2dm4j-1.0.2.jar) ([javadoc](http://github.com/downloads/drbild/c2dm4j/c2dm4j-1.0.2-javadoc.jar)) ([source](http://github.com/downloads/drbild/c2dm4j/c2dm4j-1.0.2-sources.jar)) ## Dependencies C2DM4j uses the following libraries: + [Apache HttpComponents](https://hc.apache.org/) + [SLF4J](http://www.slf4j.org/) + [Google Guava](http://code.google.com/p/guava-libraries/) + [Apache Commons IO](http://commons.apache.org/io/) ## Changelog + 1.0.2 (June 2, 2012) + zero the message delay after dequeuing (David R. Bild, reported by Noriaki Kadota) + 1.0.1 (March 23, 2012) + use UTF-8 encoding for the body of POST requests sent to C2DM (Noriaki Kadota) + fix project url in pom.xml (David R. Bild) ## Usage C2DM4j supports two workflow flows, synchronous and asynchronous. In the synchronous flow, the application thread submitting a message is used to deliver the message to the C2DM service and no error-handling or retrying is done automatically. Most users will want the asynchronous flow, in which the application thread submits a message to a queue and a background thread delivers the message to C2DM and can automatically respond to errors and retries. The final response is still available to the submitting application thread via a [Future](http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Future.html). Example code follows. Browse the [javadocs](http://drbild.github.com/c2dm4j/apidocs/index.html). #### Synchronous Quickstart (most users will want the asynchronous quickstart) The synchronous flow is easy to setup and use, but doesn't automatically handle any errors. First, configure the `C2dmManager`. ```java /* Read the C2DM authentication token from a file */ AuthTokenProvider provider = new FileAuthTokenProvider("/var/myservice/authtoken.dat"); /* Create an HttpClient instance. This HttpClient implementation is not * thread-safe, so concurrent calls to C2dmManager.pushMessage() are not allowed. */ HttpClient client = new DefaultHttpClient(); /* Create the C2DM Manager */ C2dmManager manager = new DefaultC2dmManager(client, provider); ``` Then send a message to a client. ```java /* Build message */ Message message = new MessageBuilder().collapseKey("myCollapseKey") .delayWhileIdle(true) .registrationId("registrationKeyFromClient") .put("myKey", "myValue") .build(); /* Send to C2DM, ignoring the response */ manager.pushMessage(message); ``` To handle errors, check the response. ```java /* Send to C2DM, checking the response */ Response response = manager.pushMessage(message); switch (response.getResponseType()) { case Success: // Do nothing break; case ServiceUnavailable: // TODO: Backoff and try again break; /* TODO: Handle remaining ResponseType values */ default: break; } ``` #### Asynchronous Flow Quickstart The asynchronous flow is similar, but a `ScheduledExecutorService` instance is needed to do message delivery in the background and the `HttpClient` instance must be thread-safe. This flow will automatically handle exponential backoff and retries for service unavailable and quota exceeded errors, handle per-device exponential backoff and retries for device quota exceeded errors, and will respect `Retry-After` headers on service unavailable errors. First, configure the `AsyncC2DMManager`. ```java /* Create an executor backed by MAX_THREADS threads */ int MAX_THREADS = 8; ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(MAX_THREADS); /* Create a thread-safe (up to MAX_THREADS) HttpClient instance */ ThreadSafeClientConnManager connManager = new ThreadSafeClientConnManager(); conmManager.setMaxTotal(MAX_THREADS); connManager.setDefaultMaxPerRoute(MAX_THREADS); HttpClient client = new DefaultHttpClient(connManager); /* Read the C2DM authentication token from a file */ AuthTokenProvider provider = new FileAuthTokenProvider("/var/myservice/authtoken.dat"); /* Create AsyncC2dmManager instance */ AsyncC2dmManager manager = AsyncC2dmManagerFactory.create(client, provider, executor); ``` Then send a message to a client. ```java /* Build message */ Message message = new MessageBuilder().collapseKey("myCollapseKey") .delayWhileIdle(true) .registrationId("registrationKeyFromClient") .put("myKey", "myValue") .build(); /* Send to C2DM, ignoring the response */ manager.pushMessage(message); ``` To handle errors not taken care of automatically, check the response. ```java /* Send to C2DM, checking the response via the Future */ Future org.whispercomm.c2dm4j c2dm4j 1.0.2 future = manager.pushMessage(message); /* When ready to wait on the response, make a blocking call to future.get() */ Response response = future.get(); // Blocks until response is available switch(response.getResponseType()) { case Success: // do nothing break; case InvalidRegistration: // TODO: client has unregistered, so remove break; /* TODO: Handle remaining ResponseType values */ default: break; } ``` #### Authentication Token Provider C2DM uses the [Google ClientLogin API](http://code.google.com/apis/accounts/docs/AuthForInstalledApps.html) for authentication. An authentication token obtained from Google must be attached to each request. Google may change the token at any time by attaching a new token to a response. C2DM4j obtains and persists tokens via an `AuthTokenProvider` . The default provider is `FileAuthTokenProvider`, which stores the authentication token in a UTF8-encoded file. Initialize a token file by saving the initial authentication token obtained from Google into a file. Then create an instance of `AuthTokenProvider`: ```java String authTokenFilename = "/var/myservice/authtoken.dat"; AuthTokenProvider provider = new FileAuthTokenProvider(authTokenFilename); ``` The contents of `"/var/myservice/authtoken.dat"` will be used as the initial token and any changes will be persisted to the same file. #### C2DM Message A message to be pushed to a client is represented by a `Message` instance. This instance contains the meta-data needed by the C2DM service + the registration id of the client + the collapse key + the delay-while-idle flag and the data to be delivered to the client + key-value pairs. A `Message` instance can be built from the `MessageBuilder` class. The class can be cloned, to allow initial partial configuration. ```java /* Prepare the default message builder */ MessageBuilder default = new MessageBuilder().collapseKey("a").delayWhileIdle(true); /* Use a clone to build up a specific message */ MessageBuilder builder = new MessageBuilder(default).registrationId("registrationKeyFromClient") .put("myKey", "myValue"); /* Get the immutable message instance */ Message message = builder.build(); ``` #### Custom Asynchronous Handlers The asynchronous flow can be extended by registering additional `MessageFilter`, `ResponseHandler`, and `ThrowableHandler` instances with the `AsyncC2dmManager` instance. A simple example follows. See the code for [`DeviceBackoffThrottle`](https://github.com/drbild/c2dm4j/blob/master/src/main/java/org/whispercomm/c2dm4j/async/handler/DeviceBackoffThrottle.java) and [`GlobalBackoffThrottle`](https://github.com/drbild/c2dm4j/blob/master/src/main/java/org/whispercomm/c2dm4j/async/handler/GlobalBackoffThrottle.java) for more detailed examples. Create the `AsyncC2dmManager` instance with a custom set of `AsyncHandlers`. ```java /* Create a handler to unregister a client on a InvalidRegistration error */ MyClientDatastore clientDatastore; // Assume this was instantiated elsewhere ResponseHandler invalidRegHandler = new ResponseHandler () { @Override public void handleResponse(Context context) { Response response = context.unwrap(); // Don't retry, just return the error to the future context.setDecision(ResultDecision.RETURN); // Unregister from the client data store clientDatastore.unregister(response.getMessage().getRegistrationId()); } }; /* Create a set of handlers already populated with those for automatic exponential * backoff and retry and add the custom handler. */ AsyncHandlers handlers = AsyncHandlersFactory.create(); handlers.appendResponseHandler(ResponseType.InvalidRegistration, invalidRegHandler); /* Create AsyncC2dmManager instance. * client, provider, and executor are created as in the default asynchronous flow example */ AsyncC2dmManager manager = AsyncC2dmManagerFactory.create(client, provider, handlers, executor); ``` ## Contributions Contributions are welcome. Please submit them as pull requests on [GitHub](http://github.com/drbild/c2dm4j). ## Development C2DM4j uses Maven as its build tool. Source code resides in the `src/main/java/` directory. Unit tests reside in the `src/test/java` directory. To run the unit tests, execute `mvn test`. To develop in Eclipse, create the `.classpath` and `.project` files by executing `mvn eclipse:eclipse`. Then import the project into your workspace. ##Authors **David Bild** + [http://www.davidbild.org](http://www.davidbild.org) + [http://github.com/drbild](http://github.com/drbild) ##License Copyright 2012 The Regents of the University of Michigan Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with the License. You may obtain a copy of the License from the LICENSE.txt file or at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
本源码包内暂不包含可直接显示的源代码文件,请下载源码包。