|
@ -1,7 +1,7 @@
|
|||
# Vanced MicroG
|
||||
|
||||
![Build Status](https://github.com/YTVanced/VancedMicroG/workflows/Debug%20APK%20Builder/badge.svg)
|
||||
[![Github All Releases](https://img.shields.io/github/downloads/YTVanced/VancedMicroG/total.svg)]() [![Github All Releases](https://img.shields.io/github/release/YTVanced/VancedMicroG.svg)]()
|
||||
[![Github All Releases](https://img.shields.io/github/downloads/YTVanced/VancedMicroG/total.svg)](https://github.com/YTVanced/VancedMicroG/releases) [![Github All Releases](https://img.shields.io/github/release/YTVanced/VancedMicroG.svg)](https://github.com/YTVanced/VancedMicroG/releases)
|
||||
|
||||
microG GmsCore is a FLOSS (Free/Libre Open Source Software) framework to allow applications designed for Google Play Services to run on systems, where Play Services is not available.
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
*/
|
||||
|
||||
buildscript {
|
||||
ext.nlpVersion = '2.0-alpha4'
|
||||
ext.safeParcelVersion = '1.6.0'
|
||||
|
||||
ext.kotlinVersion = '1.3.72'
|
||||
|
@ -46,8 +45,8 @@ allprojects {
|
|||
apply plugin: 'idea'
|
||||
|
||||
group = 'org.microg.gms'
|
||||
version = "0.2.14.204216"
|
||||
ext.appVersionCode = 204215002
|
||||
version = "0.2.16.204713"
|
||||
ext.appVersionCode = 204713001
|
||||
ext.isReleaseVersion = false
|
||||
}
|
||||
|
||||
|
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
|||
#Fri Oct 16 00:14:59 CEST 2020
|
||||
#Sun Dec 27 23:11:46 GMT 2020
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
|
||||
|
|
|
@ -19,10 +19,10 @@ apply plugin: 'kotlin-android'
|
|||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
dependencies {
|
||||
api "org.microg:safe-parcel:$safeParcelVersion"
|
||||
api "org.microg:safe-parcel:1.7.0"
|
||||
|
||||
implementation "androidx.annotation:annotation:$annotationVersion"
|
||||
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.10'
|
||||
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.21'
|
||||
}
|
||||
|
||||
android {
|
||||
|
|
|
@ -46,6 +46,7 @@ public enum GmsService {
|
|||
CREDENTIALS(68, "com.google.android.gms.auth.api.credentials.service.START"),
|
||||
MEASUREMENT(93, "com.google.android.gms.measurement.START"),
|
||||
GASS(116, "com.google.android.gms.gass.START"),
|
||||
IDENTITY_SIGN_IN(212, "com.google.android.gms.auth.api.identity.service.signin.START"),
|
||||
;
|
||||
|
||||
public int SERVICE_ID;
|
||||
|
@ -65,6 +66,15 @@ public enum GmsService {
|
|||
return UNKNOWN;
|
||||
}
|
||||
|
||||
public static GmsService byAction(String action) {
|
||||
for (GmsService service : values()) {
|
||||
for (String serviceAction : service.SECONDARY_ACTIONS) {
|
||||
if (serviceAction.equals(action)) return service;
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
public static String nameFromServiceId(int serviceId) {
|
||||
return byServiceId(serviceId).toString(serviceId);
|
||||
}
|
||||
|
|
|
@ -41,11 +41,11 @@ dependencies {
|
|||
implementation "androidx.mediarouter:mediarouter:1.2.0"
|
||||
implementation "androidx.preference:preference-ktx:$preferenceVersion"
|
||||
|
||||
implementation "androidx.navigation:navigation-fragment-ktx:2.3.1"
|
||||
implementation "androidx.navigation:navigation-ui-ktx:2.3.1"
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.2'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.3.2'
|
||||
|
||||
implementation "androidx.lifecycle:lifecycle-service:$lifecycleVersion"
|
||||
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.10'
|
||||
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.21'
|
||||
implementation project(path: ':play-services-basement')
|
||||
|
||||
api project(':play-services-location-api')
|
||||
|
|
|
@ -80,9 +80,10 @@
|
|||
tools:ignore="ProtectedPermissions" />
|
||||
|
||||
<application
|
||||
android:forceQueryable="true"
|
||||
android:allowBackup="false"
|
||||
android:allowBackup="true"
|
||||
android:fullBackupOnly="true"
|
||||
android:extractNativeLibs="true"
|
||||
android:forceQueryable="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:networkSecurityConfig="@xml/network_security_config">
|
||||
|
@ -144,7 +145,8 @@
|
|||
|
||||
<!-- Cloud Messaging -->
|
||||
<service
|
||||
android:name="org.microg.gms.gcm.PushRegisterService">
|
||||
android:name="org.microg.gms.gcm.PushRegisterService"
|
||||
android:process=":persistent">
|
||||
<intent-filter>
|
||||
<action android:name="com.mgoogle.android.c2dm.intent.REGISTER" />
|
||||
<action android:name="com.mgoogle.android.c2dm.intent.UNREGISTER" />
|
||||
|
@ -153,24 +155,33 @@
|
|||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<receiver android:name="org.microg.gms.gcm.PushRegisterReceiver">
|
||||
<receiver
|
||||
android:name="org.microg.gms.gcm.PushRegisterReceiver"
|
||||
android:process=":persistent">
|
||||
<intent-filter>
|
||||
<action android:name="com.mgoogle.iid.TOKEN_REQUEST" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service android:name="org.microg.gms.gcm.McsService" />
|
||||
<service
|
||||
android:name="org.microg.gms.gcm.McsService"
|
||||
android:process=":persistent" />
|
||||
|
||||
<receiver
|
||||
android:name="org.microg.gms.gcm.SendReceiver">
|
||||
android:name="org.microg.gms.gcm.SendReceiver"
|
||||
android:process=":persistent">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.gcm.intent.SEND" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name="org.microg.gms.gcm.ServiceInfoReceiver" />
|
||||
<receiver
|
||||
android:name="org.microg.gms.gcm.ServiceInfoReceiver"
|
||||
android:process=":persistent" />
|
||||
|
||||
<receiver android:name="org.microg.gms.gcm.TriggerReceiver">
|
||||
<receiver
|
||||
android:name="org.microg.gms.gcm.TriggerReceiver"
|
||||
android:process=":persistent">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
<action android:name="android.intent.action.AIRPLANE_MODE" />
|
||||
|
@ -191,7 +202,9 @@
|
|||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name="org.microg.gms.gcm.UnregisterReceiver">
|
||||
<receiver
|
||||
android:name="org.microg.gms.gcm.UnregisterReceiver"
|
||||
android:process=":persistent">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.PACKAGE_DATA_CLEARED" />
|
||||
<action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
|
||||
|
|
BIN
play-services-core/src/main/ic_launcher-playstore.png
Normal file
After Width: | Height: | Size: 22 KiB |
|
@ -131,7 +131,7 @@ public class ProviderInstallerImpl {
|
|||
// TODO: Move manual loading into helper function (as it is also used in both maps implementations)
|
||||
String primaryCpuAbi = (String) ApplicationInfo.class.getField("primaryCpuAbi").get(otherAppInfo);
|
||||
if (primaryCpuAbi != null) {
|
||||
String path = "lib/" + primaryCpuAbi + "/libconscrypt_jni.so";
|
||||
String path = "lib/" + primaryCpuAbi + "/libconscrypt_gmscore_jni.so";
|
||||
File cacheFile = new File(context.createPackageContext(packageName, 0).getCacheDir().getAbsolutePath() + "/.gmscore/" + path);
|
||||
cacheFile.getParentFile().mkdirs();
|
||||
File apkFile = new File(context.getPackageCodePath());
|
||||
|
@ -144,7 +144,7 @@ public class ProviderInstallerImpl {
|
|||
Log.d(TAG, "Can't load native library: " + path + " does not exist in " + apkFile);
|
||||
}
|
||||
}
|
||||
Log.d(TAG, "Loading conscrypt_jni from " + cacheFile.getPath());
|
||||
Log.d(TAG, "Loading conscrypt_gmscore_jni from " + cacheFile.getPath());
|
||||
System.load(cacheFile.getAbsolutePath());
|
||||
|
||||
Class<NativeCrypto> clazz = NativeCrypto.class;
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.microg.gms.common.PackageUtils;
|
|||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.microg.gms.auth.AuthConstants.DEFAULT_ACCOUNT_TYPE;
|
||||
import static org.microg.gms.auth.AuthConstants.PROVIDER_EXTRA_ACCOUNTS;
|
||||
import static org.microg.gms.auth.AuthConstants.PROVIDER_EXTRA_CLEAR_PASSWORD;
|
||||
import static org.microg.gms.auth.AuthConstants.PROVIDER_METHOD_CLEAR_PASSWORD;
|
||||
|
@ -65,15 +66,20 @@ public class AccountContentProvider extends ContentProvider {
|
|||
if (getContext().checkCallingPermission(Manifest.permission.GET_ACCOUNTS) != PackageManager.PERMISSION_GRANTED)
|
||||
throw new SecurityException("Access denied, missing GET_ACCOUNTS or EXTENDED_ACCESS permission");
|
||||
}
|
||||
if (PROVIDER_METHOD_GET_ACCOUNTS.equals(method) && AuthConstants.DEFAULT_ACCOUNT_TYPE.equals(arg)) {
|
||||
if (PROVIDER_METHOD_GET_ACCOUNTS.equals(method)) {
|
||||
Bundle result = new Bundle();
|
||||
AccountManager am = AccountManager.get(getContext());
|
||||
Account[] accounts = null;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
accounts = am.getAccountsByTypeForPackage(arg, packageName);
|
||||
if (arg != null && (arg.equals(DEFAULT_ACCOUNT_TYPE) || arg.startsWith(DEFAULT_ACCOUNT_TYPE + "."))) {
|
||||
AccountManager am = AccountManager.get(getContext());
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
accounts = am.getAccountsByTypeForPackage(arg, packageName);
|
||||
}
|
||||
if (accounts == null || accounts.length == 0) {
|
||||
accounts = am.getAccountsByType(arg);
|
||||
}
|
||||
}
|
||||
if (accounts == null || accounts.length == 0) {
|
||||
accounts = am.getAccountsByType(arg);
|
||||
if (accounts == null) {
|
||||
accounts = new Account[0];
|
||||
}
|
||||
result.putParcelableArray(PROVIDER_EXTRA_ACCOUNTS, accounts);
|
||||
return result;
|
||||
|
|
|
@ -133,6 +133,13 @@ public class AuthManager {
|
|||
getAccountManager().setUserData(getAccount(), key, value);
|
||||
}
|
||||
|
||||
public boolean accountExists() {
|
||||
for (Account refAccount : getAccountManager().getAccountsByType(accountType)) {
|
||||
if (refAccount.name.equalsIgnoreCase(accountName)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String peekAuthToken() {
|
||||
Log.d(TAG, "peekAuthToken: " + buildTokenKey());
|
||||
return getAccountManager().peekAuthToken(getAccount(), buildTokenKey());
|
||||
|
|
|
@ -93,6 +93,10 @@ public class AuthManagerServiceImpl extends IAuthManagerService.Stub {
|
|||
Bundle result = new Bundle();
|
||||
result.putString(KEY_ACCOUNT_NAME, accountName);
|
||||
result.putString(KEY_ACCOUNT_TYPE, authManager.getAccountType());
|
||||
if (!authManager.accountExists()) {
|
||||
result.putString(KEY_ERROR, "NetworkError");
|
||||
return result;
|
||||
}
|
||||
try {
|
||||
AuthResponse res = authManager.requestAuth(false);
|
||||
if (res.auth != null) {
|
||||
|
|
|
@ -22,9 +22,7 @@ public class CheckinPrefs implements SharedPreferences.OnSharedPreferenceChangeL
|
|||
|
||||
public static CheckinPrefs get(Context context) {
|
||||
if (INSTANCE == null) {
|
||||
if (!context.getPackageName().equals(PackageUtils.getProcessName())) {
|
||||
Log.w("Preferences", CheckinPrefs.class.getName() + " initialized outside main process", new RuntimeException());
|
||||
}
|
||||
PackageUtils.warnIfNotMainProcess(context, CheckinPrefs.class);
|
||||
if (context == null) return new CheckinPrefs(null);
|
||||
INSTANCE = new CheckinPrefs(context.getApplicationContext());
|
||||
}
|
||||
|
|
|
@ -32,13 +32,16 @@ import android.util.Log;
|
|||
|
||||
import androidx.legacy.content.WakefulBroadcastReceiver;
|
||||
|
||||
import com.mgoogle.android.gms.R;
|
||||
import com.google.android.gms.checkin.internal.ICheckinService;
|
||||
|
||||
import org.microg.gms.auth.AuthConstants;
|
||||
import org.microg.gms.common.ForegroundServiceInfo;
|
||||
import org.microg.gms.common.ForegroundServiceContext;
|
||||
import org.microg.gms.gcm.McsService;
|
||||
import org.microg.gms.people.PeopleManager;
|
||||
|
||||
@ForegroundServiceInfo(value = "Google device registration", res = R.string.service_name_checkin)
|
||||
public class CheckinService extends IntentService {
|
||||
private static final String TAG = "GmsCheckinSvc";
|
||||
public static final long MAX_VALID_CHECKIN_AGE = 24 * 60 * 60 * 1000; // 12 hours
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.microg.gms.common;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
|
@ -20,8 +19,6 @@ import androidx.core.app.NotificationCompat;
|
|||
|
||||
import com.mgoogle.android.gms.R;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ForegroundServiceContext extends ContextWrapper {
|
||||
private static final String TAG = "ForegroundService";
|
||||
public static final String EXTRA_FOREGROUND = "foreground";
|
||||
|
@ -33,8 +30,7 @@ public class ForegroundServiceContext extends ContextWrapper {
|
|||
@Override
|
||||
public ComponentName startService(Intent service) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
||||
&& !isIgnoringBatteryOptimizations()
|
||||
&& !isAppOnForeground()) {
|
||||
&& !isIgnoringBatteryOptimizations()) {
|
||||
Log.d(TAG, "Starting in foreground mode.");
|
||||
service.putExtra(EXTRA_FOREGROUND, true);
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
|
@ -52,31 +48,46 @@ public class ForegroundServiceContext extends ContextWrapper {
|
|||
return powerManager.isIgnoringBatteryOptimizations(getPackageName());
|
||||
}
|
||||
|
||||
private boolean isAppOnForeground() {
|
||||
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
|
||||
List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
|
||||
if (appProcesses == null) {
|
||||
return false;
|
||||
}
|
||||
final String packageName = getPackageName();
|
||||
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
|
||||
if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && appProcess.processName.equals(packageName)) {
|
||||
return true;
|
||||
private static String getServiceName(Service service) {
|
||||
String serviceName = null;
|
||||
try {
|
||||
ForegroundServiceInfo annotation = service.getClass().getAnnotation(ForegroundServiceInfo.class);
|
||||
if (annotation != null) {
|
||||
if (annotation.res() != 0) {
|
||||
try {
|
||||
serviceName = service.getString(annotation.res());
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
if (serviceName == null) {
|
||||
serviceName = annotation.value();
|
||||
}
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return false;
|
||||
if (serviceName == null) {
|
||||
serviceName = service.getClass().getSimpleName();
|
||||
}
|
||||
return serviceName;
|
||||
}
|
||||
|
||||
public static void completeForegroundService(Service service, Intent intent, String tag) {
|
||||
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
||||
&& intent != null
|
||||
&& intent.getBooleanExtra(EXTRA_FOREGROUND, false)) {
|
||||
Log.d(tag, "Started in foreground mode.");
|
||||
service.startForeground(tag.hashCode(), buildForegroundNotification(service));
|
||||
String serviceName = getServiceName(service);
|
||||
Log.d(tag, "Started " + serviceName + " in foreground mode.");
|
||||
try {
|
||||
Notification notification = buildForegroundNotification(service, serviceName);
|
||||
service.startForeground(serviceName.hashCode(), notification);
|
||||
Log.d(tag, "Notification: " + notification.toString());
|
||||
} catch (Exception e) {
|
||||
Log.w(tag, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Notification buildForegroundNotification(Context context) {
|
||||
private static Notification buildForegroundNotification(Context context, String serviceName) {
|
||||
Intent notificationIntent = new Intent();
|
||||
notificationIntent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
|
||||
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
@ -89,6 +100,7 @@ public class ForegroundServiceContext extends ContextWrapper {
|
|||
context.getResources().getString(R.string.notification_service_name),
|
||||
NotificationManager.IMPORTANCE_LOW);
|
||||
Channel.setShowBadge(false);
|
||||
Channel.setVibrationPattern(new long[]{0});
|
||||
Channel.setLockscreenVisibility(0);
|
||||
context.getSystemService(NotificationManager.class).createNotificationChannel(Channel);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.common;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface ForegroundServiceInfo {
|
||||
String value();
|
||||
int res() default 0;
|
||||
}
|
|
@ -24,6 +24,7 @@ import android.content.pm.PackageInfo;
|
|||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.Signature;
|
||||
import android.os.Binder;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
|
@ -255,6 +256,36 @@ public class PackageUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public static boolean isPersistentProcess() {
|
||||
String processName = getProcessName();
|
||||
if (processName == null) {
|
||||
Log.w("GmsPackageUtils", "Can't determine process name of current process");
|
||||
return false;
|
||||
}
|
||||
return processName.endsWith(":persistent");
|
||||
}
|
||||
|
||||
public static boolean isMainProcess(Context context) {
|
||||
String processName = getProcessName();
|
||||
if (processName == null) {
|
||||
Log.w("GmsPackageUtils", "Can't determine process name of current process");
|
||||
return false;
|
||||
}
|
||||
return processName.equals(context.getPackageName());
|
||||
}
|
||||
|
||||
public static void warnIfNotPersistentProcess(Class<?> clazz) {
|
||||
if (!isPersistentProcess()) {
|
||||
Log.w("GmsPackageUtils", clazz.getSimpleName() + " initialized outside persistent process", new RuntimeException());
|
||||
}
|
||||
}
|
||||
|
||||
public static void warnIfNotMainProcess(Context context, Class<?> clazz) {
|
||||
if (!isMainProcess(context)) {
|
||||
Log.w("GmsPackageUtils", clazz.getSimpleName() + " initialized outside main process", new RuntimeException());
|
||||
}
|
||||
}
|
||||
|
||||
public static String sha1sum(byte[] bytes) {
|
||||
MessageDigest md;
|
||||
try {
|
||||
|
|
|
@ -53,10 +53,7 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
|
|||
|
||||
public static GcmPrefs get(Context context) {
|
||||
if (INSTANCE == null) {
|
||||
if (!context.getPackageName().equals(PackageUtils.getProcessName())) {
|
||||
Log.w("Preferences", GcmPrefs.class.getName() + " initialized outside main process", new RuntimeException());
|
||||
}
|
||||
if (context == null) return new GcmPrefs(null);
|
||||
PackageUtils.warnIfNotPersistentProcess(GcmPrefs.class);
|
||||
INSTANCE = new GcmPrefs(context.getApplicationContext());
|
||||
}
|
||||
return INSTANCE;
|
||||
|
@ -64,7 +61,6 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
|
|||
|
||||
private boolean gcmLogEnabled = true;
|
||||
private String lastPersistedId = "";
|
||||
private boolean confirmNewApps = false;
|
||||
private boolean gcmEnabled = false;
|
||||
|
||||
private int networkMobile = 0;
|
||||
|
@ -76,19 +72,19 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
|
|||
private int learntMobile = 300000;
|
||||
private int learntOther = 300000;
|
||||
|
||||
private final Context context;
|
||||
private SharedPreferences preferences;
|
||||
private SharedPreferences systemDefaultPreferences;
|
||||
|
||||
private GcmPrefs(Context context) {
|
||||
if (context != null) {
|
||||
preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||
try {
|
||||
systemDefaultPreferences = (SharedPreferences) Context.class.getDeclaredMethod("getSharedPreferences", File.class, int.class).invoke(context, new File("/system/etc/microg.xml"), Context.MODE_PRIVATE);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
update();
|
||||
this.context = context;
|
||||
preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||
try {
|
||||
systemDefaultPreferences = (SharedPreferences) Context.class.getDeclaredMethod("getSharedPreferences", File.class, int.class).invoke(context, new File("/system/etc/microg.xml"), Context.MODE_PRIVATE);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
private boolean getSettingsBoolean(String key, boolean def) {
|
||||
|
@ -101,7 +97,6 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
|
|||
public void update() {
|
||||
gcmEnabled = getSettingsBoolean(PREF_ENABLE_GCM, true);
|
||||
gcmLogEnabled = getSettingsBoolean(PREF_FULL_LOG, true);
|
||||
confirmNewApps = getSettingsBoolean(PREF_CONFIRM_NEW_APPS, false);
|
||||
|
||||
lastPersistedId = preferences.getString(PREF_LAST_PERSISTENT_ID, "");
|
||||
|
||||
|
@ -129,12 +124,49 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
|
|||
}
|
||||
|
||||
public int getHeartbeatMsFor(NetworkInfo info) {
|
||||
return getHeartbeatMsFor(getNetworkPrefForInfo(info), false);
|
||||
return getHeartbeatMsFor(getNetworkPrefForInfo(info));
|
||||
}
|
||||
|
||||
public int getHeartbeatMsFor(String pref, boolean rawRoaming) {
|
||||
if (PREF_NETWORK_ROAMING.equals(pref) && (rawRoaming || networkRoaming != 0)) {
|
||||
return networkRoaming * 60000;
|
||||
public int getMobileInterval() {
|
||||
return networkMobile;
|
||||
}
|
||||
|
||||
public int getWifiInterval() {
|
||||
return networkWifi;
|
||||
}
|
||||
|
||||
public int getRoamingInterval() {
|
||||
return networkRoaming;
|
||||
}
|
||||
|
||||
public int getOtherInterval() {
|
||||
return networkOther;
|
||||
}
|
||||
|
||||
public void setMobileInterval(int value) {
|
||||
this.networkMobile = value;
|
||||
preferences.edit().putString(PREF_NETWORK_MOBILE, Integer.toString(networkMobile)).apply();
|
||||
}
|
||||
|
||||
public void setWifiInterval(int value) {
|
||||
this.networkWifi = value;
|
||||
preferences.edit().putString(PREF_NETWORK_WIFI, Integer.toString(networkWifi)).apply();
|
||||
}
|
||||
|
||||
public void setRoamingInterval(int value) {
|
||||
this.networkRoaming = value;
|
||||
preferences.edit().putString(PREF_NETWORK_ROAMING, Integer.toString(networkRoaming)).apply();
|
||||
}
|
||||
|
||||
public void setOtherInterval(int value) {
|
||||
this.networkOther = value;
|
||||
preferences.edit().putString(PREF_NETWORK_OTHER, Integer.toString(networkOther)).apply();
|
||||
}
|
||||
|
||||
public int getHeartbeatMsFor(String pref) {
|
||||
if (PREF_NETWORK_ROAMING.equals(pref)) {
|
||||
if (networkRoaming != 0) return networkRoaming * 60000;
|
||||
else return learntMobile;
|
||||
} else if (PREF_NETWORK_MOBILE.equals(pref)) {
|
||||
if (networkMobile != 0) return networkMobile * 60000;
|
||||
else return learntMobile;
|
||||
|
@ -201,6 +233,18 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
|
|||
preferences.edit().putInt(PREF_LEARNT_MOBILE, INTERVAL).putInt(PREF_LEARNT_WIFI, INTERVAL).putInt(PREF_LEARNT_OTHER, INTERVAL).apply();
|
||||
}
|
||||
|
||||
public int getLearntMobileInterval() {
|
||||
return learntMobile;
|
||||
}
|
||||
|
||||
public int getLearntWifiInterval() {
|
||||
return learntWifi;
|
||||
}
|
||||
|
||||
public int getLearntOtherInterval() {
|
||||
return learntOther;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
update();
|
||||
|
@ -210,27 +254,23 @@ public class GcmPrefs implements SharedPreferences.OnSharedPreferenceChangeListe
|
|||
return gcmEnabled;
|
||||
}
|
||||
|
||||
public boolean isEnabledFor(NetworkInfo info) {
|
||||
return isEnabled() && info != null && getHeartbeatMsFor(info) >= 0;
|
||||
}
|
||||
|
||||
public static void setEnabled(Context context, boolean newStatus) {
|
||||
boolean changed = GcmPrefs.get(context).isEnabled() != newStatus;
|
||||
PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(GcmPrefs.PREF_ENABLE_GCM, newStatus).apply();
|
||||
public void setEnabled(boolean value) {
|
||||
boolean changed = gcmEnabled != value;
|
||||
preferences.edit().putBoolean(GcmPrefs.PREF_ENABLE_GCM, value).apply();
|
||||
if (!changed) return;
|
||||
if (!newStatus) {
|
||||
if (!value) {
|
||||
McsService.stop(context);
|
||||
} else {
|
||||
context.sendBroadcast(new Intent(TriggerReceiver.FORCE_TRY_RECONNECT, null, context, TriggerReceiver.class));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isGcmLogEnabled() {
|
||||
return gcmLogEnabled;
|
||||
public boolean isEnabledFor(NetworkInfo info) {
|
||||
return isEnabled() && info != null && getHeartbeatMsFor(info) >= 0;
|
||||
}
|
||||
|
||||
public boolean isConfirmNewApps() {
|
||||
return confirmNewApps;
|
||||
public boolean isGcmLogEnabled() {
|
||||
return gcmLogEnabled;
|
||||
}
|
||||
|
||||
public List<String> getLastPersistedIds() {
|
||||
|
|
|
@ -40,10 +40,12 @@ import android.util.Log;
|
|||
|
||||
import androidx.legacy.content.WakefulBroadcastReceiver;
|
||||
|
||||
import com.mgoogle.android.gms.R;
|
||||
import com.squareup.wire.Message;
|
||||
|
||||
import org.microg.gms.checkin.LastCheckinInfo;
|
||||
import org.microg.gms.common.ForegroundServiceContext;
|
||||
import org.microg.gms.common.ForegroundServiceInfo;
|
||||
import org.microg.gms.common.PackageUtils;
|
||||
import org.microg.gms.gcm.mcs.AppData;
|
||||
import org.microg.gms.gcm.mcs.Close;
|
||||
|
@ -106,6 +108,7 @@ import static org.microg.gms.gcm.McsConstants.MSG_OUTPUT_ERROR;
|
|||
import static org.microg.gms.gcm.McsConstants.MSG_OUTPUT_READY;
|
||||
import static org.microg.gms.gcm.McsConstants.MSG_TEARDOWN;
|
||||
|
||||
@ForegroundServiceInfo(value = "Cloud messaging", res = R.string.service_name_mcs)
|
||||
public class McsService extends Service implements Handler.Callback {
|
||||
private static final String TAG = "GmsGcmMcsSvc";
|
||||
|
||||
|
@ -236,7 +239,7 @@ public class McsService extends Service implements Handler.Callback {
|
|||
return false;
|
||||
}
|
||||
// consider connection to be dead if we did not receive an ack within twice the heartbeat interval
|
||||
int heartbeatMs = GcmPrefs.get(context).getHeartbeatMsFor(activeNetworkPref, false);
|
||||
int heartbeatMs = GcmPrefs.get(context).getHeartbeatMsFor(activeNetworkPref);
|
||||
if (heartbeatMs < 0) {
|
||||
closeAll();
|
||||
} else if (SystemClock.elapsedRealtime() - lastHeartbeatAckElapsedRealtime > 2 * heartbeatMs) {
|
||||
|
@ -266,7 +269,7 @@ public class McsService extends Service implements Handler.Callback {
|
|||
public void scheduleHeartbeat(Context context) {
|
||||
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
|
||||
|
||||
int heartbeatMs = GcmPrefs.get(this).getHeartbeatMsFor(activeNetworkPref, false);
|
||||
int heartbeatMs = GcmPrefs.get(this).getHeartbeatMsFor(activeNetworkPref);
|
||||
if (heartbeatMs < 0) {
|
||||
closeAll();
|
||||
}
|
||||
|
|
|
@ -87,8 +87,7 @@ public class PushRegisterManager {
|
|||
if (!request.delete) {
|
||||
if (!prefs.isEnabled() ||
|
||||
(app != null && !app.allowRegister) ||
|
||||
LastCheckinInfo.read(context).lastCheckin <= 0 ||
|
||||
(app == null && prefs.isConfirmNewApps())) {
|
||||
LastCheckinInfo.read(context).lastCheckin <= 0) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(EXTRA_ERROR, ERROR_SERVICE_NOT_AVAILABLE);
|
||||
callback.onResult(bundle);
|
||||
|
|
|
@ -55,8 +55,6 @@ public class GServicesProvider extends ContentProvider {
|
|||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
databaseHelper = new DatabaseHelper(getContext());
|
||||
|
||||
if (CheckinPrefs.get(getContext()).isEnabled()) {
|
||||
getContext().sendOrderedBroadcast(new Intent(getContext(), org.microg.gms.checkin.TriggerReceiver.class), null);
|
||||
}
|
||||
|
@ -64,6 +62,7 @@ public class GServicesProvider extends ContentProvider {
|
|||
getContext().sendBroadcast(new Intent(org.microg.gms.gcm.TriggerReceiver.FORCE_TRY_RECONNECT, null, getContext(), org.microg.gms.gcm.TriggerReceiver.class));
|
||||
}
|
||||
|
||||
databaseHelper = new DatabaseHelper(getContext());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ public class AboutFragment extends AbstractAboutFragment {
|
|||
libraries.add(new AbstractAboutFragment.Library("su.litvak.chromecast.api.v2", "ChromeCast Java API v2", "Apache License 2.0, Vitaly Litvak"));
|
||||
libraries.add(new AbstractAboutFragment.Library("org.conscrypt", "Conscrypt", "Apache License 2.0, The Android Open Source Project"));
|
||||
libraries.add(new AbstractAboutFragment.Library("org.microg.safeparcel", "SafeParcel", "Apache License 2.0, microG Team"));
|
||||
libraries.add(new AbstractAboutFragment.Library("org.microg.nlp.service", "UnifiedNlp", "Apache License 2.0, microG Team"));
|
||||
libraries.add(new AbstractAboutFragment.Library("com.squareup.wire", "Wire Protocol Buffers", "Apache License 2.0, Square Inc."));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,90 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2017 microG 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.ui;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.mgoogle.android.gms.R;
|
||||
|
||||
import org.microg.gms.gcm.GcmPrefs;
|
||||
import org.microg.gms.gcm.McsService;
|
||||
import org.microg.gms.gcm.TriggerReceiver;
|
||||
import org.microg.tools.ui.ResourceSettingsFragment;
|
||||
|
||||
public class GcmAdvancedFragment extends ResourceSettingsFragment {
|
||||
|
||||
private static String[] HEARTBEAT_PREFS = new String[]{GcmPrefs.PREF_NETWORK_MOBILE, GcmPrefs.PREF_NETWORK_ROAMING, GcmPrefs.PREF_NETWORK_WIFI, GcmPrefs.PREF_NETWORK_OTHER};
|
||||
|
||||
public GcmAdvancedFragment() {
|
||||
preferencesResource = R.xml.preferences_gcm_advanced;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
|
||||
super.onCreatePreferences(savedInstanceState, rootKey);
|
||||
for (String pref : HEARTBEAT_PREFS) {
|
||||
findPreference(pref).setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
getPreferenceManager().getSharedPreferences().edit().putString(preference.getKey(), (String) newValue).apply();
|
||||
updateContent();
|
||||
if (newValue.equals("-1") && preference.getKey().equals(McsService.activeNetworkPref)) {
|
||||
McsService.stop(getContext());
|
||||
} else if (!McsService.isConnected(getContext())) {
|
||||
getContext().sendBroadcast(new Intent(TriggerReceiver.FORCE_TRY_RECONNECT, null, getContext(), TriggerReceiver.class));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
updateContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
updateContent();
|
||||
}
|
||||
|
||||
private void updateContent() {
|
||||
GcmPrefs prefs = GcmPrefs.get(getContext());
|
||||
for (String pref : HEARTBEAT_PREFS) {
|
||||
Preference preference = findPreference(pref);
|
||||
int state = prefs.getNetworkValue(pref);
|
||||
if (state == 0) {
|
||||
int heartbeat = prefs.getHeartbeatMsFor(preference.getKey(), true);
|
||||
if (heartbeat == 0) {
|
||||
preference.setSummary(getString(R.string.service_status_enabled_short) + " / " + getString(R.string.gcm_status_pref_default));
|
||||
} else {
|
||||
preference.setSummary(getString(R.string.service_status_enabled_short) + " / " + getString(R.string.gcm_status_pref_default) + ": " + getHeartbeatString(heartbeat));
|
||||
}
|
||||
} else if (state == -1) {
|
||||
preference.setSummary(getString(R.string.service_status_disabled_short));
|
||||
} else {
|
||||
preference.setSummary(getString(R.string.service_status_enabled_short) + " / " + getString(R.string.gcm_status_pref_manual) + ": " + getHeartbeatString(state * 60000));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String getHeartbeatString(int heartbeatMs) {
|
||||
if (heartbeatMs < 120000) {
|
||||
return (heartbeatMs / 1000) + " " + getString(R.string.gcm_status_pref_sec);
|
||||
}
|
||||
return (heartbeatMs / 60000) + " " + getString(R.string.gcm_status_pref_min);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.chimera
|
||||
|
||||
import android.content.ContentProvider
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.database.Cursor
|
||||
import android.database.MatrixCursor
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.core.os.bundleOf
|
||||
import org.microg.gms.DummyService
|
||||
import org.microg.gms.common.GmsService
|
||||
import org.microg.gms.common.RemoteListenerProxy
|
||||
|
||||
class ServiceProvider : ContentProvider() {
|
||||
|
||||
override fun onCreate(): Boolean {
|
||||
Log.d(TAG, "onCreate")
|
||||
return true
|
||||
}
|
||||
|
||||
override fun call(method: String, arg: String?, extras: Bundle?): Bundle? {
|
||||
when (method) {
|
||||
"serviceIntentCall" -> {
|
||||
val serviceAction = extras?.getString("serviceActionBundleKey") ?: return null
|
||||
val ourServiceAction = GmsService.byAction(serviceAction)?.takeIf { it.SERVICE_ID > 0 }?.ACTION ?: serviceAction
|
||||
val context = context!!
|
||||
val intent = Intent(ourServiceAction).apply { `package` = context.packageName }
|
||||
val resolveInfo = context.packageManager.resolveService(intent, 0)
|
||||
if (resolveInfo != null) {
|
||||
intent.setClassName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name)
|
||||
} else {
|
||||
intent.setClass(context, DummyService::class.java)
|
||||
}
|
||||
Log.d(TAG, "$method: $serviceAction -> $intent")
|
||||
return bundleOf(
|
||||
"serviceResponseIntentKey" to intent
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
Log.d(TAG, "$method: $arg, $extras")
|
||||
return super.call(method, arg, extras)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun query(uri: Uri, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, sortOrder: String?): Cursor? {
|
||||
val cursor = MatrixCursor(COLUMNS)
|
||||
Log.d(TAG, "query: $uri")
|
||||
return cursor
|
||||
}
|
||||
|
||||
override fun insert(uri: Uri, values: ContentValues?): Uri? {
|
||||
Log.d(TAG, "insert: $uri, $values")
|
||||
return uri
|
||||
}
|
||||
|
||||
override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<out String>?): Int {
|
||||
Log.d(TAG, "update: $uri, $values, $selection, $selectionArgs")
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
|
||||
Log.d(TAG, "delete: $uri, $selection, $selectionArgs")
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun getType(uri: Uri): String {
|
||||
Log.d(TAG, "getType: $uri")
|
||||
return "vnd.android.cursor.item/com.google.android.gms.chimera"
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "ChimeraServiceProvider"
|
||||
private val COLUMNS = arrayOf("version", "apkPath", "loaderPath", "apkDescStr")
|
||||
}
|
||||
}
|
|
@ -57,24 +57,7 @@ private suspend fun ensureCheckinIsUpToDate(context: Context) {
|
|||
private suspend fun ensureAppRegistrationAllowed(context: Context, database: GcmDatabase, packageName: String) {
|
||||
if (!GcmPrefs.get(context).isEnabled) throw RuntimeException("GCM disabled")
|
||||
val app = database.getApp(packageName)
|
||||
if (app == null && GcmPrefs.get(context).isConfirmNewApps) {
|
||||
val accepted: Boolean = suspendCoroutine { continuation ->
|
||||
val i = Intent(context, AskPushPermission::class.java)
|
||||
i.putExtra(AskPushPermission.EXTRA_REQUESTED_PACKAGE, packageName)
|
||||
i.putExtra(AskPushPermission.EXTRA_RESULT_RECEIVER, object : ResultReceiver(null) {
|
||||
override fun onReceiveResult(resultCode: Int, resultData: Bundle?) {
|
||||
continuation.resume(resultCode == Activity.RESULT_OK)
|
||||
}
|
||||
})
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
|
||||
i.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT)
|
||||
context.startActivity(i)
|
||||
}
|
||||
if (!accepted) {
|
||||
throw RuntimeException("Push permission not granted to app")
|
||||
}
|
||||
} else if (app?.allowRegister == false) {
|
||||
if (app?.allowRegister == false) {
|
||||
throw RuntimeException("Push permission not granted to app")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,23 +22,29 @@ private const val EXTRA_SERVICE_INFO = "org.microg.gms.gcm.SERVICE_INFO"
|
|||
private const val EXTRA_CONFIGURATION = "org.microg.gms.gcm.CONFIGURATION"
|
||||
private const val TAG = "GmsGcmStatusInfo"
|
||||
|
||||
data class ServiceInfo(val configuration: ServiceConfiguration, val connected: Boolean, val startTimestamp: Long) : Serializable
|
||||
data class ServiceInfo(val configuration: ServiceConfiguration, val connected: Boolean, val startTimestamp: Long, val learntMobileInterval: Int, val learntWifiInterval: Int, val learntOtherInterval: Int) : Serializable
|
||||
|
||||
// TODO: Intervals
|
||||
data class ServiceConfiguration(val enabled: Boolean, val confirmNewApps: Boolean) : Serializable {
|
||||
data class ServiceConfiguration(val enabled: Boolean, val mobile: Int, val wifi: Int, val roaming: Int, val other: Int) : Serializable {
|
||||
fun saveToPrefs(context: Context) {
|
||||
GcmPrefs.setEnabled(context, enabled)
|
||||
// TODO: confirm new apps
|
||||
GcmPrefs.get(context).apply {
|
||||
isEnabled = enabled
|
||||
mobileInterval = mobile
|
||||
wifiInterval = wifi
|
||||
roamingInterval = roaming
|
||||
otherInterval = other
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun GcmPrefs.toConfiguration(): ServiceConfiguration = ServiceConfiguration(isEnabled, isConfirmNewApps)
|
||||
private fun GcmPrefs.toConfiguration(): ServiceConfiguration = ServiceConfiguration(isEnabled, mobileInterval, wifiInterval, roamingInterval, otherInterval)
|
||||
|
||||
class ServiceInfoReceiver : BroadcastReceiver() {
|
||||
private fun sendInfoResponse(context: Context) {
|
||||
context.sendOrderedBroadcast(Intent(ACTION_SERVICE_INFO_RESPONSE).apply {
|
||||
setPackage(context.packageName)
|
||||
putExtra(EXTRA_SERVICE_INFO, ServiceInfo(GcmPrefs.get(context).toConfiguration(), McsService.isConnected(context), McsService.getStartTimestamp()))
|
||||
val prefs = GcmPrefs.get(context)
|
||||
putExtra(EXTRA_SERVICE_INFO, ServiceInfo(prefs.toConfiguration(), McsService.isConnected(context), McsService.getStartTimestamp(), prefs.learntMobileInterval, prefs.learntWifiInterval, prefs.learntOtherInterval))
|
||||
}, null)
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@ import androidx.lifecycle.lifecycleScope
|
|||
import kotlinx.coroutines.delay
|
||||
import org.microg.gms.checkin.CheckinPrefs
|
||||
import org.microg.gms.gcm.GcmPrefs
|
||||
import org.microg.gms.gcm.getGcmServiceInfo
|
||||
import org.microg.gms.gcm.setGcmServiceConfiguration
|
||||
|
||||
class ProvisionService : LifecycleService() {
|
||||
private fun Bundle.getBooleanOrNull(key: String): Boolean? {
|
||||
|
@ -29,7 +31,7 @@ class ProvisionService : LifecycleService() {
|
|||
}
|
||||
|
||||
intent?.extras?.getBooleanOrNull("checkin_enabled")?.let { CheckinPrefs.setEnabled(this@ProvisionService, it) }
|
||||
intent?.extras?.getBooleanOrNull("gcm_enabled")?.let { GcmPrefs.setEnabled(this@ProvisionService, it) }
|
||||
intent?.extras?.getBooleanOrNull("gcm_enabled")?.let { setGcmServiceConfiguration(this@ProvisionService, getGcmServiceInfo(this@ProvisionService).configuration.copy(enabled = it)) }
|
||||
// What else?
|
||||
|
||||
delay(2 * 1000) // Wait 2 seconds to give provisioning some extra time
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2020, microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.microg.gms.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.TwoStatePreference
|
||||
import com.mgoogle.android.gms.R
|
||||
import org.microg.gms.gcm.*
|
||||
|
||||
class PushNotificationAdvancedFragment : PreferenceFragmentCompat() {
|
||||
private lateinit var networkMobile: ListPreference
|
||||
private lateinit var networkWifi: ListPreference
|
||||
private lateinit var networkRoaming: ListPreference
|
||||
private lateinit var networkOther: ListPreference
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.preferences_gcm_advanced)
|
||||
}
|
||||
|
||||
override fun onBindPreferences() {
|
||||
networkMobile = preferenceScreen.findPreference(GcmPrefs.PREF_NETWORK_MOBILE) ?: networkMobile
|
||||
networkWifi = preferenceScreen.findPreference(GcmPrefs.PREF_NETWORK_WIFI) ?: networkWifi
|
||||
networkRoaming = preferenceScreen.findPreference(GcmPrefs.PREF_NETWORK_ROAMING) ?: networkRoaming
|
||||
networkOther = preferenceScreen.findPreference(GcmPrefs.PREF_NETWORK_OTHER) ?: networkOther
|
||||
|
||||
networkMobile.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
|
||||
lifecycleScope.launchWhenResumed {
|
||||
(newValue as? String)?.toIntOrNull()?.let {
|
||||
setGcmServiceConfiguration(requireContext(), getGcmServiceInfo(requireContext()).configuration.copy(mobile = it))
|
||||
}
|
||||
updateContent()
|
||||
}
|
||||
true
|
||||
}
|
||||
networkWifi.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
|
||||
lifecycleScope.launchWhenResumed {
|
||||
(newValue as? String)?.toIntOrNull()?.let {
|
||||
setGcmServiceConfiguration(requireContext(), getGcmServiceInfo(requireContext()).configuration.copy(wifi = it))
|
||||
}
|
||||
updateContent()
|
||||
}
|
||||
true
|
||||
}
|
||||
networkRoaming.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
|
||||
lifecycleScope.launchWhenResumed {
|
||||
(newValue as? String)?.toIntOrNull()?.let {
|
||||
setGcmServiceConfiguration(requireContext(), getGcmServiceInfo(requireContext()).configuration.copy(roaming = it))
|
||||
}
|
||||
updateContent()
|
||||
}
|
||||
true
|
||||
}
|
||||
networkOther.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
|
||||
lifecycleScope.launchWhenResumed {
|
||||
(newValue as? String)?.toIntOrNull()?.let {
|
||||
setGcmServiceConfiguration(requireContext(), getGcmServiceInfo(requireContext()).configuration.copy(other = it))
|
||||
}
|
||||
updateContent()
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
updateContent()
|
||||
}
|
||||
|
||||
private fun updateContent() {
|
||||
lifecycleScope.launchWhenResumed {
|
||||
val serviceInfo = getGcmServiceInfo(requireContext())
|
||||
networkMobile.value = serviceInfo.configuration.mobile.toString()
|
||||
networkMobile.summary = getSummaryString(serviceInfo.configuration.mobile, serviceInfo.learntMobileInterval)
|
||||
networkWifi.value = serviceInfo.configuration.wifi.toString()
|
||||
networkWifi.summary = getSummaryString(serviceInfo.configuration.wifi, serviceInfo.learntWifiInterval)
|
||||
networkRoaming.value = serviceInfo.configuration.roaming.toString()
|
||||
networkRoaming.summary = getSummaryString(serviceInfo.configuration.roaming, serviceInfo.learntMobileInterval)
|
||||
networkOther.value = serviceInfo.configuration.other.toString()
|
||||
networkOther.summary = getSummaryString(serviceInfo.configuration.other, serviceInfo.learntOtherInterval)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSummaryString(value: Int, learnt: Int): String = when (value) {
|
||||
-1 -> getString(R.string.service_status_disabled_short)
|
||||
0 -> getString(R.string.service_status_enabled_short) + " / " + getString(R.string.gcm_status_pref_default) + ": " + getHeartbeatString(learnt)
|
||||
else -> getString(R.string.service_status_enabled_short) + " / " + getString(R.string.gcm_status_pref_manual) + ": " + getHeartbeatString(value * 60000)
|
||||
}
|
||||
|
||||
private fun getHeartbeatString(heartbeatMs: Int): String {
|
||||
return if (heartbeatMs < 120000) {
|
||||
(heartbeatMs / 1000).toString() + " " + getString(R.string.gcm_status_pref_sec)
|
||||
} else (heartbeatMs / 60000).toString() + " " + getString(R.string.gcm_status_pref_min)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val HEARTBEAT_PREFS = arrayOf(GcmPrefs.PREF_NETWORK_MOBILE, GcmPrefs.PREF_NETWORK_ROAMING, GcmPrefs.PREF_NETWORK_WIFI, GcmPrefs.PREF_NETWORK_OTHER)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<group android:scaleX="0.0405"
|
||||
android:scaleY="0.0405"
|
||||
android:translateX="13.5"
|
||||
android:translateY="13.5">
|
||||
<path
|
||||
android:pathData="M1388.1,1415.4L1388.1,1415.4c-91.4,84.5 -216.9,133.3 -365.8,133.3c-208.7,0 -399.6,-117.6 -493.3,-304.1c-78.3,-156 -78.3,-339.8 0,-495.7c93.7,-186.6 284.6,-304.3 493.3,-304.3c137.1,-1.6 269.6,49.9 369.4,143.6L1234,745.9c-57,-54.4 -133.1,-84 -211.8,-82.8c-144,0 -266.3,97.2 -309.9,228c-23.1,68.6 -23.1,142.8 0,211.4h0.2c43.8,130.6 165.9,227.8 309.9,227.8c74.4,0 138.2,-19 187.6,-52.6v-0.1c58.2,-38.5 98,-99.2 110.3,-167.7h-298.2V897.2H1543c6.5,36.9 9.5,74.6 9.5,112.2C1552.5,1177.2 1492.5,1319.2 1388.1,1415.4z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
<path
|
||||
android:pathData="M1293.9,595.9m-14.5,0a14.5,14.5 0,1 1,29 0a14.5,14.5 0,1 1,-29 0"
|
||||
android:fillColor="#953A9A"/>
|
||||
<path
|
||||
android:pathData="M1256.2,582.2c-2.7,0 -5.3,-0.7 -7.8,-2.3c-54.3,-34.7 -120.6,-56.3 -186.8,-61c-7.9,-0.6 -13.9,-7.5 -13.4,-15.4c0.6,-7.9 7.4,-13.9 15.4,-13.4c70.9,5 142,28.2 200.3,65.4c6.7,4.3 8.7,13.2 4.4,19.9C1265.6,579.8 1261,582.2 1256.2,582.2z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:startY="536.1355"
|
||||
android:startX="1270.5692"
|
||||
android:endY="536.1355"
|
||||
android:endX="1048.1708"
|
||||
android:type="linear">
|
||||
<item android:offset="4.04912E-7" android:color="#FF953A9A"/>
|
||||
<item android:offset="1" android:color="#FFFF0032"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M663.5,709.5L663.5,709.5L663.5,709.5l-8,10.6l-3.9,5.3l-3.7,5.5c-2.4,3.7 -4.9,7.3 -7.3,11l-6.8,11.3c-1.1,1.9 -2.3,3.8 -3.4,5.7l-3.1,5.8c-2.1,3.9 -4.2,7.8 -6.2,11.7l-5.6,11.9c-0.9,2 -1.9,4 -2.8,6l-2.5,6.1l-5,12.2l-4.4,12.4l-2.2,6.2l-1.9,6.3l-3.8,12.6c-4.5,17 -8.6,34 -11.1,51.4l-1,6.5c-0.3,2.2 -0.7,4.3 -0.9,6.5l-1.5,13.1c-0.2,2.2 -0.5,4.3 -0.7,6.5l-0.4,6.6l-0.9,13.1l-0.1,1.6v1.6l-0.1,3.3l-0.2,6.6l-0.2,6.6c0,2.2 -0.1,4.4 -0.1,6.6l0.3,13.1l0.1,6.6c0.1,2.2 0.3,4.4 0.4,6.6c0.8,17.5 2.6,34.8 5.3,52l2.2,12.9l2.7,12.8c0.2,1.1 0.4,2.1 0.7,3.2l0.8,3.2l1.6,6.3c0.5,2.1 1,4.2 1.6,6.3l1.8,6.3c9.3,33.5 22.7,65.8 39.2,96.2c8.3,15.2 17.6,29.8 27.5,43.9c10,14.1 20.7,27.7 32.2,40.5c46,51.5 103.7,91.8 167.1,117.4l0,0c7.7,3.1 11.4,11.8 8.3,19.5s-11.8,11.4 -19.5,8.3c-0.1,-0.1 -0.3,-0.1 -0.5,-0.2c-66.6,-29.7 -126.2,-74.6 -172.5,-130.3c-11.7,-13.8 -22.3,-28.5 -32.3,-43.6c-9.9,-15.1 -19,-30.7 -27.1,-46.8c-16.1,-32.2 -28.8,-66.2 -37.2,-101.1l-1.6,-6.5c-0.5,-2.2 -0.9,-4.4 -1.4,-6.6l-1.4,-6.6l-0.7,-3.3c-0.2,-1.1 -0.4,-2.2 -0.6,-3.3l-2.3,-13.3l-1.8,-13.3c-2.2,-17.8 -3.4,-35.7 -3.6,-53.5c0,-2.2 -0.1,-4.5 -0.2,-6.7l0.1,-6.7l0.2,-13.4c0,-2.2 0.2,-4.5 0.3,-6.7l0.4,-6.7l0.4,-6.7l0.2,-3.3l0.1,-1.7l0.2,-1.7l1.4,-13.3l0.7,-6.6c0.3,-2.2 0.6,-4.4 1,-6.6l2,-13.2c0.3,-2.2 0.8,-4.4 1.2,-6.6l1.3,-6.6C587.3,830.2 618.1,763.6 663.5,709.5L663.5,709.5L663.5,709.5z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:startY="1073.554"
|
||||
android:startX="870.6317"
|
||||
android:endY="1071.7072"
|
||||
android:endX="555.1798"
|
||||
android:type="linear">
|
||||
<item android:offset="4.04912E-7" android:color="#FF953A9A"/>
|
||||
<item android:offset="1" android:color="#FFFF0032"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M1332.5,1204.5"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="29"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeLineCap="round">
|
||||
<aapt:attr name="android:strokeColor">
|
||||
<gradient
|
||||
android:startY="1204.5"
|
||||
android:startX="1332.5"
|
||||
android:endY="1204.5"
|
||||
android:endX="1332.5"
|
||||
android:type="linear">
|
||||
<item android:offset="4.04912E-7" android:color="#FF953A9A"/>
|
||||
<item android:offset="1" android:color="#FFFF0032"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M912.6,1444.6m-16.5,0a16.5,16.5 0,1 1,33 0a16.5,16.5 0,1 1,-33 0"
|
||||
android:fillColor="#953A9A"/>
|
||||
<path
|
||||
android:pathData="M1543,897.2c-27.8,20 -57.3,51 -65.9,76.6c-6.5,18 -17.4,29.8 -28.3,30.3c-9.6,0 -23,-12.8 -28.4,-30.9c-8.6,-23.9 -23.1,-50.6 -50,-76L1543,897.2L1543,897.2zM1442.6,1039c1.3,6.7 7.3,9.9 14,8.6s11.7,-6.6 10.4,-13.4c-1.3,-6.7 -14.1,-17.6 -14.1,-17.6S1441.2,1032.2 1442.6,1039z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:startY="897.2"
|
||||
android:startX="1456.7"
|
||||
android:endY="1047.8848"
|
||||
android:endX="1456.7"
|
||||
android:type="linear">
|
||||
<item android:offset="4.04912E-7" android:color="#FF953A9A"/>
|
||||
<item android:offset="1" android:color="#FFFF0032"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
</group>
|
||||
</vector>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 5 KiB |
After Width: | Height: | Size: 5 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 11 KiB |
|
@ -52,7 +52,7 @@
|
|||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/gcmAdvancedFragment"
|
||||
android:name="org.microg.gms.ui.GcmAdvancedFragment"
|
||||
android:name="org.microg.gms.ui.PushNotificationAdvancedFragment"
|
||||
android:label="@string/service_name_mcs" />
|
||||
|
||||
<fragment
|
||||
|
|
|
@ -18,14 +18,14 @@
|
|||
<resources>
|
||||
|
||||
<string-array name="gcm_network_config_names" translatables="false">
|
||||
<item>@string/service_status_disabled</item>
|
||||
<item>@string/service_status_default</item>
|
||||
<item>Intervalo de ping: 2 minutos</item>
|
||||
<item>Intervalo de ping: 5 minutos</item>
|
||||
<item>Intervalo de ping: 10 minutos</item>
|
||||
<item>Intervalo de ping: 15 minutos</item>
|
||||
<item>Intervalo de ping: 20 minutos</item>
|
||||
<item>Intervalo de ping: 30 minutos</item>
|
||||
<item>@string/service_status_disabled_short</item>
|
||||
<item>@string/gcm_status_pref_default</item>
|
||||
<item>Intervalo de ping: 2 minutos</item>
|
||||
<item>Intervalo de ping: 5 minutos</item>
|
||||
<item>Intervalo de ping: 10 minutos</item>
|
||||
<item>Intervalo de ping: 15 minutos</item>
|
||||
<item>Intervalo de ping: 20 minutos</item>
|
||||
<item>Intervalo de ping: 30 minutos</item>
|
||||
</string-array>
|
||||
|
||||
</resources>
|
|
@ -59,10 +59,8 @@ Esto puede tardar unos minutos."</string>
|
|||
<string name="perm_extended_access_label">Acceso extendido a los servicios de Google</string>
|
||||
|
||||
<string name="service_name_checkin">Registro de dispositivos Google</string>
|
||||
<string name="service_name_mcs">Google Cloud Messaging</string>
|
||||
<string name="service_name_mcs">Cloud Messaging</string>
|
||||
|
||||
<string name="service_status_disabled">Deshabilitado</string>
|
||||
<string name="service_status_default">Por Defecto</string>
|
||||
<string name="service_status_enabled_short">Encendido</string>
|
||||
<string name="service_status_disabled_short">Apagado</string>
|
||||
|
||||
|
@ -85,7 +83,7 @@ Esto puede tardar unos minutos."</string>
|
|||
<string name="checkin_last_registration">Ultimo registro: <xliff:g example="Yesterday, 02:20 PM">%1$s</xliff:g></string>
|
||||
|
||||
<string name="cond_gcm_bat_title">Optimizaciones de bateria habilitadas</string>
|
||||
<string name="cond_gcm_bat_summary">Has habilitado Google Cloud Messaging pero tienes las optimizacion de bateria activada para los servicios de microG. Para que lleguen las notificaciones deberás deshabilitar la optimización de batería para microG.</string>
|
||||
<string name="cond_gcm_bat_summary">Has habilitado Cloud Messaging pero tienes las optimizacion de bateria activada para los servicios de microG. Para que lleguen las notificaciones deberás deshabilitar la optimización de batería para microG.</string>
|
||||
<string name="cond_gcm_bat_action">Deshabilitar optimizaciones</string>
|
||||
|
||||
<string name="prefs_account">Preferencias de Cuenta</string>
|
||||
|
@ -100,7 +98,7 @@ Esto puede tardar unos minutos."</string>
|
|||
<string name="pref_add_account_title">Cuenta</string>
|
||||
<string name="pref_add_account_summary">Añadir cuenta de Google</string>
|
||||
<string name="pref_gcm_switcher_title">Recibir notificaciones push</string>
|
||||
<string name="pref_gcm_enable_mcs_summary">Google Cloud Messaging es un proveedor de notificaciónes push usado por muchas aplicaciones de terceros. Pará usarlo tienes que activar registro de dispositivos.</string>
|
||||
<string name="pref_gcm_enable_mcs_summary">Cloud Messaging es un proveedor de notificaciónes push usado por muchas aplicaciones de terceros. Pará usarlo tienes que activar registro de dispositivos.</string>
|
||||
|
||||
<string name="pref_about_title">Acerca de Vanced microG</string>
|
||||
<string name="pref_cast_double_fix">Solucion para Cast duplicado</string>
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
<resources>
|
||||
|
||||
<string-array name="gcm_network_config_names" translatables="false">
|
||||
<item>@string/service_status_disabled</item>
|
||||
<item>@string/service_status_default</item>
|
||||
<item>@string/service_status_disabled_short</item>
|
||||
<item>@string/gcm_status_pref_default</item>
|
||||
<item>Ping interval: 2 menit</item>
|
||||
<item>Ping interval: 5 menit</item>
|
||||
<item>Ping interval: 10 menit</item>
|
||||
|
|
|
@ -59,10 +59,8 @@ Ini bisa berlangsung beberapa menit."</string>
|
|||
<string name="perm_extended_access_label">Akses lebih ke layanan Google</string>
|
||||
|
||||
<string name="service_name_checkin">Google device registration</string>
|
||||
<string name="service_name_mcs">Google Cloud Messaging</string>
|
||||
<string name="service_name_mcs">Cloud Messaging</string>
|
||||
|
||||
<string name="service_status_disabled">Dinonaktifkan</string>
|
||||
<string name="service_status_default">Default</string>
|
||||
<string name="service_status_enabled_short">Hidup</string>
|
||||
<string name="service_status_disabled_short">Mati</string>
|
||||
|
||||
|
@ -85,7 +83,7 @@ Ini bisa berlangsung beberapa menit."</string>
|
|||
<string name="checkin_last_registration">Registrasi terakhir: <xliff:g example="Yesterday, 02:20 PM">%1$s</xliff:g></string>
|
||||
|
||||
<string name="cond_gcm_bat_title">Optimisasi baterai diaktifkan</string>
|
||||
<string name="cond_gcm_bat_summary">Anda mengaktifkan Google Cloud Messaging namun mengaktifkan optimisasi baterai untuk layanan utama microG. Untuk mendapatkan notifikasi push anda harus menonaktifkan optimisasi baterai.</string>
|
||||
<string name="cond_gcm_bat_summary">Anda mengaktifkan Cloud Messaging namun mengaktifkan optimisasi baterai untuk layanan utama microG. Untuk mendapatkan notifikasi push anda harus menonaktifkan optimisasi baterai.</string>
|
||||
<string name="cond_gcm_bat_action">Nonaktifkan optimisasi</string>
|
||||
|
||||
<string name="prefs_account">Preferensi akun</string>
|
||||
|
@ -100,7 +98,7 @@ Ini bisa berlangsung beberapa menit."</string>
|
|||
<string name="pref_add_account_title">Akun</string>
|
||||
<string name="pref_add_account_summary">Tambahkan akun Google</string>
|
||||
<string name="pref_gcm_switcher_title">Terima notifikasi push</string>
|
||||
<string name="pref_gcm_enable_mcs_summary">Google Cloud Messaging adalah penyedia notifikasi push yang digunakan pada banyak aplikasi pihak ketiga. Untuk menggunakannya anda harus mengaktifkan device registration.</string>
|
||||
<string name="pref_gcm_enable_mcs_summary">Cloud Messaging adalah penyedia notifikasi push yang digunakan pada banyak aplikasi pihak ketiga. Untuk menggunakannya anda harus mengaktifkan device registration.</string>
|
||||
|
||||
<string name="pref_about_title">Tentang Vanced microG</string>
|
||||
<string name="pref_cast_double_fix">Perbaikan Cast terduplikasi</string>
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
<resources>
|
||||
|
||||
<string-array name="gcm_network_config_names" translatables="false">
|
||||
<item>@string/service_status_disabled</item>
|
||||
<item>@string/service_status_default</item>
|
||||
<item>@string/service_status_disabled_short</item>
|
||||
<item>@string/gcm_status_pref_default</item>
|
||||
<item>Intervallo ping: 2 minuti</item>
|
||||
<item>Intervallo ping: 5 minuti</item>
|
||||
<item>Intervallo ping: 10 minuti</item>
|
||||
|
|
|
@ -59,10 +59,8 @@ Questo potrà richiedere un paio di minuti"</string>
|
|||
<string name="perm_extended_access_label">Estendi accesso ai servizi Google</string>
|
||||
|
||||
<string name="service_name_checkin">Registrazione dispositivo Google</string>
|
||||
<string name="service_name_mcs">Messaggistica Cloud Google</string>
|
||||
<string name="service_name_mcs">Messaggistica Cloud</string>
|
||||
|
||||
<string name="service_status_disabled">Disattivata</string>
|
||||
<string name="service_status_default">Predefinito</string>
|
||||
<string name="service_status_enabled_short">Attiva</string>
|
||||
<string name="service_status_disabled_short">Disattivata</string>
|
||||
|
||||
|
@ -85,7 +83,7 @@ Questo potrà richiedere un paio di minuti"</string>
|
|||
<string name="checkin_last_registration">Ultima registrazione: <xliff:g example="Yesterday, 02:20 PM">%1$s</xliff:g></string>
|
||||
|
||||
<string name="cond_gcm_bat_title">Ottimizzazione batteria attivata</string>
|
||||
<string name="cond_gcm_bat_summary">Hai attivato l\'opzione Messaggistica Cloud Google ma i Servizi Vanced microG risultano al momento limitati dall\'ottimizzazione energetica di sistema. Se desideri ricevere le notifiche push, escludi i microG da questa ottimizzazione.</string>
|
||||
<string name="cond_gcm_bat_summary">Hai attivato l\'opzione Messaggistica Cloud ma i Servizi Vanced microG risultano al momento limitati dall\'ottimizzazione energetica di sistema. Se desideri ricevere le notifiche push, escludi i microG da questa ottimizzazione.</string>
|
||||
<string name="cond_gcm_bat_action">Disattiva ottimizzazione</string>
|
||||
|
||||
<string name="prefs_account">Preferenze account</string>
|
||||
|
@ -100,7 +98,7 @@ Questo potrà richiedere un paio di minuti"</string>
|
|||
<string name="pref_add_account_title">Account</string>
|
||||
<string name="pref_add_account_summary">Aggiungi account Google</string>
|
||||
<string name="pref_gcm_switcher_title">Ricevi notifiche push</string>
|
||||
<string name="pref_gcm_enable_mcs_summary">Messaggistica Cloud Google è un fornitore di notifiche push presente in molte applicazioni di terze parti. Per utilizzarlo è necessario attivare la registrazione del dispositivo.</string>
|
||||
<string name="pref_gcm_enable_mcs_summary">Messaggistica Cloud è un fornitore di notifiche push presente in molte applicazioni di terze parti. Per utilizzarlo è necessario attivare la registrazione del dispositivo.</string>
|
||||
|
||||
<string name="pref_about_title">Informazioni su Vanced microG</string>
|
||||
<string name="pref_cast_double_fix">Correzione cast duplicato</string>
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
<resources>
|
||||
|
||||
<string-array name="gcm_network_config_names" translatables="false">
|
||||
<item>@string/service_status_disabled</item>
|
||||
<item>@string/service_status_default</item>
|
||||
<item>@string/service_status_disabled_short</item>
|
||||
<item>@string/gcm_status_pref_default</item>
|
||||
<item>Интервал пинга: 2 минуты</item>
|
||||
<item>Интервал пинга: 5 минут</item>
|
||||
<item>Интервал пинга: 10 минут</item>
|
||||
|
|
|
@ -59,10 +59,8 @@
|
|||
<string name="perm_extended_access_label">Расширенный доступ к сервисам Google</string>
|
||||
|
||||
<string name="service_name_checkin">Регистрация устройства в Google</string>
|
||||
<string name="service_name_mcs">Google Cloud Messaging</string>
|
||||
<string name="service_name_mcs">Cloud Messaging</string>
|
||||
|
||||
<string name="service_status_disabled">Отключен</string>
|
||||
<string name="service_status_default">По умолчанию</string>
|
||||
<string name="service_status_enabled_short">Вкл</string>
|
||||
<string name="service_status_disabled_short">Выкл</string>
|
||||
|
||||
|
@ -85,7 +83,7 @@
|
|||
<string name="checkin_last_registration">Последняя регистрация: <xliff:g example="Yesterday, 02:20 PM">%1$s</xliff:g></string>
|
||||
|
||||
<string name="cond_gcm_bat_title">Включена экономия заряда батареи</string>
|
||||
<string name="cond_gcm_bat_summary">Вы включили Google Cloud Messaging, но не отключили экономию заряда батареи для Vanced microG. Для корректной работы уведомлений вам нужно отключить экономию заряда батареи.</string>
|
||||
<string name="cond_gcm_bat_summary">Вы включили Cloud Messaging, но не отключили экономию заряда батареи для Vanced microG. Для корректной работы уведомлений вам нужно отключить экономию заряда батареи.</string>
|
||||
<string name="cond_gcm_bat_action">Отключить экономию</string>
|
||||
|
||||
<string name="prefs_account">Настройки аккаунта</string>
|
||||
|
@ -100,7 +98,7 @@
|
|||
<string name="pref_add_account_title">Аккаунт</string>
|
||||
<string name="pref_add_account_summary">Добавить аккаунт Google</string>
|
||||
<string name="pref_gcm_switcher_title">Получать push-уведомления</string>
|
||||
<string name="pref_gcm_enable_mcs_summary">Google Cloud Messaging позволяет получать уведомления от многих приложений. Чтобы использовать GCM, включите регистрацию устройства в Google.</string>
|
||||
<string name="pref_gcm_enable_mcs_summary">Cloud Messaging позволяет получать уведомления от многих приложений. Чтобы использовать GCM, включите регистрацию устройства в Google.</string>
|
||||
|
||||
<string name="pref_about_title">О Vanced microG</string>
|
||||
<string name="pref_cast_double_fix">Исправление двух кнопок трансляции</string>
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
</string-array>
|
||||
|
||||
<string-array name="gcm_network_config_names" translatables="false">
|
||||
<item>@string/service_status_disabled</item>
|
||||
<item>@string/service_status_default</item>
|
||||
<item>@string/service_status_disabled_short</item>
|
||||
<item>@string/gcm_status_pref_default</item>
|
||||
<item>Ping interval: 2 minutes</item>
|
||||
<item>Ping interval: 5 minutes</item>
|
||||
<item>Ping interval: 10 minutes</item>
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#171719</color>
|
||||
</resources>
|
|
@ -59,10 +59,8 @@ This can take a couple of minutes."</string>
|
|||
<string name="perm_extended_access_label">Extended access to Google services</string>
|
||||
|
||||
<string name="service_name_checkin">Google device registration</string>
|
||||
<string name="service_name_mcs">Google Cloud Messaging</string>
|
||||
<string name="service_name_mcs">Cloud Messaging</string>
|
||||
|
||||
<string name="service_status_disabled">Disabled</string>
|
||||
<string name="service_status_default">Default</string>
|
||||
<string name="service_status_enabled_short">On</string>
|
||||
<string name="service_status_disabled_short">Off</string>
|
||||
|
||||
|
@ -85,7 +83,7 @@ This can take a couple of minutes."</string>
|
|||
<string name="checkin_last_registration">Last registration: <xliff:g example="Yesterday, 02:20 PM">%1$s</xliff:g></string>
|
||||
|
||||
<string name="cond_gcm_bat_title">Battery optimizations enabled</string>
|
||||
<string name="cond_gcm_bat_summary">You enabled Google Cloud Messaging but have battery optimizations active for microG Services Core. For push notifications to arrive you should disable battery optimizations.</string>
|
||||
<string name="cond_gcm_bat_summary">You enabled Cloud Messaging but have battery optimizations active for microG Services Core. For push notifications to arrive you should disable battery optimizations.</string>
|
||||
<string name="cond_gcm_bat_action">Disable optimization</string>
|
||||
|
||||
<string name="prefs_account">Account preferences</string>
|
||||
|
@ -100,7 +98,7 @@ This can take a couple of minutes."</string>
|
|||
<string name="pref_add_account_title">Account</string>
|
||||
<string name="pref_add_account_summary">Add Google account</string>
|
||||
<string name="pref_gcm_switcher_title">Receive push notifications</string>
|
||||
<string name="pref_gcm_enable_mcs_summary">Google Cloud Messaging is a push notification provider used by many third-party applications. To use it you must enable device registration.</string>
|
||||
<string name="pref_gcm_enable_mcs_summary">Cloud Messaging is a push notification provider used by many third-party applications. To use it you must enable device registration.</string>
|
||||
|
||||
<string name="pref_about_title">About Vanced microG</string>
|
||||
<string name="pref_cast_double_fix">Cast duplication fix</string>
|
||||
|
|