Add GCM register API client

Add generic HttpFormClient
This commit is contained in:
mar-v-in 2015-02-22 17:13:35 +01:00
parent d3f7688516
commit bc532d132c
4 changed files with 293 additions and 0 deletions

View File

@ -0,0 +1,152 @@
/*
* Copyright 2013-2015 µg Project Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.
*/
package org.microg.gms.common;
import android.net.Uri;
import android.util.Log;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpFormClient {
private static final String TAG = "GmsHttpFormClient";
public static <T> T request(String url, Request request, Class<T> tClass) throws IOException {
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("POST");
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
StringBuilder content = new StringBuilder();
request.prepare();
for (Field field : request.getClass().getDeclaredFields()) {
try {
field.setAccessible(true);
String value = String.valueOf(field.get(request));
if (field.isAnnotationPresent(RequestHeader.class)) {
for (String key : field.getAnnotation(RequestHeader.class).value()) {
connection.setRequestProperty(key, value);
}
} else if (field.isAnnotationPresent(RequestContent.class)) {
for (String key : field.getAnnotation(RequestHeader.class).value()) {
if (content.length() > 0)
content.append("&");
content.append(Uri.encode(key)).append("=").append(Uri.encode(value));
}
}
} catch (Exception ignored) {
}
}
Log.d(TAG, "-- Request --\n" + content);
OutputStream os = connection.getOutputStream();
os.write(content.toString().getBytes());
os.close();
if (connection.getResponseCode() != 200) {
throw new IOException(connection.getResponseMessage());
}
String result = new String(Utils.readStreamToEnd(connection.getInputStream()));
Log.d(TAG, "-- Response --\n" + result);
return parseResponse(tClass, result);
}
private static <T> T parseResponse(Class<T> tClass, String result) {
T response;
try {
response = tClass.getConstructor().newInstance();
} catch (Exception e) {
return null;
}
String[] entries = result.split("\n");
for (String s : entries) {
String[] keyValuePair = s.split("=", 2);
String key = keyValuePair[0].trim();
String value = keyValuePair[1].trim();
try {
for (Field field : tClass.getDeclaredFields()) {
if (field.isAnnotationPresent(ResponseField.class) &&
key.equals(field.getAnnotation(ResponseField.class).value())) {
if (field.getType().equals(String.class)) {
field.set(response, value);
} else if (field.getType().equals(boolean.class)) {
field.setBoolean(response, value.equals("1"));
} else if (field.getType().equals(long.class)) {
field.setLong(response, Long.parseLong(value));
} else if (field.getType().equals(int.class)) {
field.setInt(response, Integer.parseInt(value));
}
}
}
} catch (Exception e) {
Log.w(TAG, e);
}
}
return response;
}
public static <T> void requestAsync(final String url, final Request request, final Class<T> tClass,
final Callback<T> callback) {
new Thread(new Runnable() {
@Override
public void run() {
try {
callback.onResponse(request(url, request, tClass));
} catch (Exception e) {
callback.onException(e);
}
}
}).start();
}
public static abstract class Request {
protected void prepare() {
}
}
public interface Callback<T> {
void onResponse(T response);
void onException(Exception exception);
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface RequestHeader {
public String[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface RequestContent {
public String[] value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ResponseField {
public String value();
}
}

View File

@ -0,0 +1,22 @@
/*
* Copyright 2013-2015 µg Project Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.
*/
package org.microg.gms.gcm;
public class Constants {
public static final String REGISTER_URL = "https://android.clients.google.com/c2dm/register3";
}

View File

@ -0,0 +1,95 @@
/*
* Copyright 2013-2015 µg Project Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.
*/
package org.microg.gms.gcm;
import org.microg.gms.checkin.LastCheckinInfo;
import org.microg.gms.common.Build;
import org.microg.gms.common.HttpFormClient;
import java.io.IOException;
import static org.microg.gms.common.HttpFormClient.RequestContent;
import static org.microg.gms.common.HttpFormClient.RequestHeader;
public class RegisterRequest extends HttpFormClient.Request {
private static final String USER_AGENT = "Android-GCM/1.3 (%s %s)";
@RequestHeader("Authorization")
private String auth;
@RequestHeader("User-Agent")
private String userAgent;
@RequestHeader("app")
@RequestContent("app")
public String app;
@RequestContent("cert")
public String appSignature;
@RequestContent("app_ver")
public int appVersion;
@RequestContent("info")
public String info;
@RequestContent("sender")
public String sender;
@RequestContent({"X-GOOG.USER_AID", "device"})
public long androidId;
public long securityToken;
public String deviceName;
public String buildVersion;
@Override
public void prepare() {
userAgent = String.format(USER_AGENT, deviceName, buildVersion);
auth = "AidLogin " + androidId + ":" + securityToken;
}
public RegisterRequest checkin(LastCheckinInfo lastCheckinInfo) {
androidId = lastCheckinInfo.androidId;
securityToken = lastCheckinInfo.securityToken;
return this;
}
public RegisterRequest app(String app, String appSignature, int appVersion) {
this.app = app;
this.appSignature = appSignature;
this.appVersion = appVersion;
return this;
}
public RegisterRequest info(String info) {
this.info = info;
return this;
}
public RegisterRequest sender(String sender) {
this.sender = sender;
return this;
}
public RegisterRequest build(Build build) {
deviceName = build.device;
buildVersion = build.id;
return this;
}
public RegisterResponse getResponse() throws IOException {
return HttpFormClient.request(Constants.REGISTER_URL, this, RegisterResponse.class);
}
public void getResponseAsync(HttpFormClient.Callback<RegisterResponse> callback) {
HttpFormClient.requestAsync(Constants.REGISTER_URL, this, RegisterResponse.class, callback);
}
}

View File

@ -0,0 +1,24 @@
/*
* Copyright 2013-2015 µg Project Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.
*/
package org.microg.gms.gcm;
import static org.microg.gms.common.HttpFormClient.ResponseField;
public class RegisterResponse {
@ResponseField("token")
public String token;
}