mirror of https://github.com/YTVanced/VancedMicroG
Fix FCM registration for apps using firebase >= 20.1.1
With version 20.1.1 the Firebase Cloud Messaging SDK started to use the Firebase Installations SDK, which affects the FCM registration process. The implementation of FCM registration in microG failed to pass extra parameters that became relevant with the introduction of the Firebase Installations SDK to the FCM registration endpoint. These additional parameters are passed through to the endpoint with an 'X-' prefix.
This commit is contained in:
parent
8eff51cfb6
commit
5146559f89
|
@ -46,6 +46,13 @@ public class HttpFormClient {
|
||||||
try {
|
try {
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
Object objVal = field.get(request);
|
Object objVal = field.get(request);
|
||||||
|
if (field.isAnnotationPresent(RequestContentDynamic.class)) {
|
||||||
|
Map<String, String> contentParams = (Map<String, String>) objVal;
|
||||||
|
for (Map.Entry<String, String> param : contentParams.entrySet()) {
|
||||||
|
appendParam(content, param.getKey(), param.getValue());
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
String value = objVal != null ? String.valueOf(objVal) : null;
|
String value = objVal != null ? String.valueOf(objVal) : null;
|
||||||
Boolean boolVal = null;
|
Boolean boolVal = null;
|
||||||
if (field.getType().equals(boolean.class)) {
|
if (field.getType().equals(boolean.class)) {
|
||||||
|
@ -65,9 +72,7 @@ public class HttpFormClient {
|
||||||
value = valueFromBoolVal(value, boolVal, annotation.truePresent(), annotation.falsePresent());
|
value = valueFromBoolVal(value, boolVal, annotation.truePresent(), annotation.falsePresent());
|
||||||
if (value != null || annotation.nullPresent()) {
|
if (value != null || annotation.nullPresent()) {
|
||||||
for (String key : annotation.value()) {
|
for (String key : annotation.value()) {
|
||||||
if (content.length() > 0)
|
appendParam(content, key, value);
|
||||||
content.append("&");
|
|
||||||
content.append(Uri.encode(key)).append("=").append(Uri.encode(String.valueOf(value)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,6 +114,12 @@ public class HttpFormClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void appendParam(StringBuilder content, String key, String value) {
|
||||||
|
if (content.length() > 0)
|
||||||
|
content.append("&");
|
||||||
|
content.append(Uri.encode(key)).append("=").append(Uri.encode(String.valueOf(value)));
|
||||||
|
}
|
||||||
|
|
||||||
private static <T> T parseResponse(Class<T> tClass, HttpURLConnection connection, String result) throws IOException {
|
private static <T> T parseResponse(Class<T> tClass, HttpURLConnection connection, String result) throws IOException {
|
||||||
Map<String, List<String>> headerFields = connection.getHeaderFields();
|
Map<String, List<String>> headerFields = connection.getHeaderFields();
|
||||||
T response;
|
T response;
|
||||||
|
@ -227,6 +238,11 @@ public class HttpFormClient {
|
||||||
public boolean nullPresent() default false;
|
public boolean nullPresent() default false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
public @interface RequestContentDynamic {
|
||||||
|
}
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.FIELD)
|
@Target(ElementType.FIELD)
|
||||||
public @interface ResponseField {
|
public @interface ResponseField {
|
||||||
|
|
|
@ -264,4 +264,12 @@ public class PackageUtils {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int targetSdkVersion(Context context, String packageName) {
|
||||||
|
try {
|
||||||
|
return context.getPackageManager().getApplicationInfo(packageName, 0).targetSdkVersion;
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,7 +145,7 @@ class PushRegisterHandler extends Handler {
|
||||||
.checkin(LastCheckinInfo.read(context))
|
.checkin(LastCheckinInfo.read(context))
|
||||||
.app(packageName)
|
.app(packageName)
|
||||||
.delete(delete)
|
.delete(delete)
|
||||||
.appid(subdata.getString("appid"), subdata.getString("gmp_app_id")),
|
.extraParams(subdata),
|
||||||
bundle -> sendReply(what, id, replyTo, bundle));
|
bundle -> sendReply(what, id, replyTo, bundle));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,12 +70,16 @@ public class PushRegisterManager {
|
||||||
|
|
||||||
public static void completeRegisterRequest(Context context, GcmDatabase database, String requestId, RegisterRequest request, BundleCallback callback) {
|
public static void completeRegisterRequest(Context context, GcmDatabase database, String requestId, RegisterRequest request, BundleCallback callback) {
|
||||||
if (request.app != null) {
|
if (request.app != null) {
|
||||||
if (request.appSignature == null)
|
|
||||||
request.appSignature = PackageUtils.firstSignatureDigest(context, request.app);
|
|
||||||
if (request.appVersion <= 0)
|
if (request.appVersion <= 0)
|
||||||
request.appVersion = PackageUtils.versionCode(context, request.app);
|
request.appVersion = PackageUtils.versionCode(context, request.app);
|
||||||
if (request.appVersionName == null)
|
if (!request.delete) {
|
||||||
request.appVersionName = PackageUtils.versionName(context, request.app);
|
if (request.appSignature == null) {
|
||||||
|
request.appSignature = PackageUtils.firstSignatureDigest(context, request.app);
|
||||||
|
}
|
||||||
|
request.sdkVersion = PackageUtils.targetSdkVersion(context, request.app);
|
||||||
|
if (!request.hasExtraParam(GcmConstants.EXTRA_APP_VERSION_NAME))
|
||||||
|
request.extraParam(GcmConstants.EXTRA_APP_VERSION_NAME, PackageUtils.versionName(context, request.app));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GcmDatabase.App app = database.getApp(request.app);
|
GcmDatabase.App app = database.getApp(request.app);
|
||||||
|
|
|
@ -20,7 +20,6 @@ import android.app.IntentService;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ApplicationInfo;
|
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
@ -140,7 +139,8 @@ public class PushRegisterService extends IntentService {
|
||||||
.build(Utils.getBuild(context))
|
.build(Utils.getBuild(context))
|
||||||
.sender(intent.getStringExtra(EXTRA_SENDER))
|
.sender(intent.getStringExtra(EXTRA_SENDER))
|
||||||
.checkin(LastCheckinInfo.read(context))
|
.checkin(LastCheckinInfo.read(context))
|
||||||
.app(packageName),
|
.app(packageName)
|
||||||
|
.extraParams(intent.getExtras()),
|
||||||
bundle -> {
|
bundle -> {
|
||||||
Intent outIntent = new Intent(ACTION_C2DM_REGISTRATION);
|
Intent outIntent = new Intent(ACTION_C2DM_REGISTRATION);
|
||||||
outIntent.putExtras(bundle);
|
outIntent.putExtras(bundle);
|
||||||
|
@ -176,7 +176,8 @@ public class PushRegisterService extends IntentService {
|
||||||
.build(Utils.getBuild(this))
|
.build(Utils.getBuild(this))
|
||||||
.sender(intent.getStringExtra(EXTRA_SENDER))
|
.sender(intent.getStringExtra(EXTRA_SENDER))
|
||||||
.checkin(LastCheckinInfo.read(this))
|
.checkin(LastCheckinInfo.read(this))
|
||||||
.app(packageName),
|
.app(packageName)
|
||||||
|
.extraParams(intent.getExtras()),
|
||||||
bundle -> {
|
bundle -> {
|
||||||
Intent outIntent = new Intent(ACTION_C2DM_REGISTRATION);
|
Intent outIntent = new Intent(ACTION_C2DM_REGISTRATION);
|
||||||
outIntent.putExtras(bundle);
|
outIntent.putExtras(bundle);
|
||||||
|
|
|
@ -16,19 +16,24 @@
|
||||||
|
|
||||||
package org.microg.gms.gcm;
|
package org.microg.gms.gcm;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import org.microg.gms.checkin.LastCheckinInfo;
|
import org.microg.gms.checkin.LastCheckinInfo;
|
||||||
import org.microg.gms.common.Build;
|
import org.microg.gms.common.Build;
|
||||||
import org.microg.gms.common.Constants;
|
|
||||||
import org.microg.gms.common.HttpFormClient;
|
import org.microg.gms.common.HttpFormClient;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.microg.gms.common.HttpFormClient.RequestContent;
|
import static org.microg.gms.common.HttpFormClient.RequestContent;
|
||||||
|
import static org.microg.gms.common.HttpFormClient.RequestContentDynamic;
|
||||||
import static org.microg.gms.common.HttpFormClient.RequestHeader;
|
import static org.microg.gms.common.HttpFormClient.RequestHeader;
|
||||||
|
|
||||||
public class RegisterRequest extends HttpFormClient.Request {
|
public class RegisterRequest extends HttpFormClient.Request {
|
||||||
private static final String SERVICE_URL = "https://android.clients.google.com/c2dm/register3";
|
private static final String SERVICE_URL = "https://android.clients.google.com/c2dm/register3";
|
||||||
private static final String USER_AGENT = "Android-GCM/1.3 (%s %s)";
|
private static final String USER_AGENT = "Android-GCM/1.5 (%s %s)";
|
||||||
|
|
||||||
@RequestHeader("Authorization")
|
@RequestHeader("Authorization")
|
||||||
private String auth;
|
private String auth;
|
||||||
|
@ -42,35 +47,26 @@ public class RegisterRequest extends HttpFormClient.Request {
|
||||||
public String appSignature;
|
public String appSignature;
|
||||||
@RequestContent("app_ver")
|
@RequestContent("app_ver")
|
||||||
public int appVersion;
|
public int appVersion;
|
||||||
@RequestContent("app_ver_name")
|
|
||||||
public String appVersionName;
|
|
||||||
@RequestContent("info")
|
@RequestContent("info")
|
||||||
public String info;
|
public String info;
|
||||||
@RequestContent({"sender", "subtype"})
|
@RequestContent("sender")
|
||||||
public String sender;
|
public String sender;
|
||||||
@RequestContent({"X-GOOG.USER_AID", "device"})
|
@RequestContent("device")
|
||||||
public long androidId;
|
public long androidId;
|
||||||
@RequestContent("delete")
|
@RequestContent("delete")
|
||||||
public boolean delete;
|
public boolean delete;
|
||||||
public long securityToken;
|
public long securityToken;
|
||||||
public String deviceName;
|
public String deviceName;
|
||||||
public String buildVersion;
|
public String buildVersion;
|
||||||
@RequestContent("osv")
|
@RequestContent("target_ver")
|
||||||
public int sdkVersion;
|
public Integer sdkVersion;
|
||||||
@RequestContent("gmsv")
|
@RequestContentDynamic
|
||||||
public int gmsVersion;
|
private Map<String, String> extraParams = new LinkedHashMap<>();
|
||||||
@RequestContent("scope")
|
|
||||||
public String scope = "*";
|
|
||||||
@RequestContent("appid")
|
|
||||||
public String appId;
|
|
||||||
@RequestContent("gmp_app_id")
|
|
||||||
public String gmpAppId;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepare() {
|
public void prepare() {
|
||||||
userAgent = String.format(USER_AGENT, deviceName, buildVersion);
|
userAgent = String.format(USER_AGENT, deviceName, buildVersion);
|
||||||
auth = "AidLogin " + androidId + ":" + securityToken;
|
auth = "AidLogin " + androidId + ":" + securityToken;
|
||||||
gmsVersion = Constants.MAX_REFERENCE_VERSION;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public RegisterRequest checkin(LastCheckinInfo lastCheckinInfo) {
|
public RegisterRequest checkin(LastCheckinInfo lastCheckinInfo) {
|
||||||
|
@ -90,17 +86,10 @@ public class RegisterRequest extends HttpFormClient.Request {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RegisterRequest app(String app, String appSignature, int appVersion, String appVersionName) {
|
public RegisterRequest app(String app, String appSignature, int appVersion) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
this.appSignature = appSignature;
|
this.appSignature = appSignature;
|
||||||
this.appVersion = appVersion;
|
this.appVersion = appVersion;
|
||||||
this.appVersionName = appVersionName;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RegisterRequest appid(String appid, String gmpAppId) {
|
|
||||||
this.appId = appid;
|
|
||||||
this.gmpAppId = gmpAppId;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +106,6 @@ public class RegisterRequest extends HttpFormClient.Request {
|
||||||
public RegisterRequest build(Build build) {
|
public RegisterRequest build(Build build) {
|
||||||
deviceName = build.device;
|
deviceName = build.device;
|
||||||
buildVersion = build.id;
|
buildVersion = build.id;
|
||||||
sdkVersion = build.sdk;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,6 +118,31 @@ public class RegisterRequest extends HttpFormClient.Request {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RegisterRequest extraParams(Bundle extraBundle) {
|
||||||
|
for (String key : extraBundle.keySet()) {
|
||||||
|
if (!key.equals(GcmConstants.EXTRA_SENDER) && !key.equals(GcmConstants.EXTRA_DELETE)) {
|
||||||
|
extraParam(key, extraBundle.getString(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegisterRequest extraParam(String key, String value) {
|
||||||
|
// Ignore empty registration extras
|
||||||
|
if (!TextUtils.isEmpty(value)) {
|
||||||
|
extraParams.put(extraParamKey(key), value);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasExtraParam(String key) {
|
||||||
|
return extraParams.containsKey(extraParamKey(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String extraParamKey(String key) {
|
||||||
|
return "X-" + key;
|
||||||
|
}
|
||||||
|
|
||||||
public RegisterResponse getResponse() throws IOException {
|
public RegisterResponse getResponse() throws IOException {
|
||||||
return HttpFormClient.request(SERVICE_URL, this, RegisterResponse.class);
|
return HttpFormClient.request(SERVICE_URL, this, RegisterResponse.class);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue