Major changes to core and settings ui

This commit is contained in:
Marvin W 2020-07-26 11:59:27 +02:00
parent aae974ec5b
commit 396965f407
No known key found for this signature in database
GPG Key ID: 072E9235DB996F2A
68 changed files with 1712 additions and 964 deletions

View File

@ -73,7 +73,7 @@ public class ForegroundServiceContext extends ContextWrapper {
return new Notification.Builder(context, channel.getId())
.setOngoing(true)
.setContentTitle("Running in background")
//.setSmallIcon(R.drawable.gcm_bell)
//.setSmallIcon(R.drawable.ic_cloud_bell)
.build();
}
}

View File

@ -15,6 +15,8 @@
*/
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
configurations {
mapboxImplementation
@ -58,6 +60,8 @@ dependencies {
implementation "androidx.navigation:navigation-ui:$navigationVersion"
implementation "androidx.navigation:navigation-fragment-ktx:$navigationVersion"
implementation "androidx.navigation:navigation-ui-ktx:$navigationVersion"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
}
android {
@ -87,6 +91,7 @@ android {
sourceSets {
main {
java.srcDirs += 'src/main/protos-java'
java.srcDirs += 'src/main/kotlin'
}
}

View File

@ -29,24 +29,22 @@ public abstract class SwitchBarResourceSettingsFragment extends ResourceSettings
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
AbstractSettingsActivity activity = (AbstractSettingsActivity) getActivity();
switchBar = activity.getSwitchBar();
switchBar.show();
switchCompat = switchBar.getSwitch();
// switchBar = activity.getSwitchBar();
// switchBar.show();
// switchCompat = switchBar.getSwitch();
}
@Override
public void onDestroyView() {
super.onDestroyView();
switchBar.hide();
// switchBar.hide();
}
@Override
public void onResume() {
super.onResume();
if (!listenerSetup) {
switchBar.addOnSwitchChangeListener(this);
// switchBar.addOnSwitchChangeListener(this);
listenerSetup = true;
}
}
@ -54,7 +52,7 @@ public abstract class SwitchBarResourceSettingsFragment extends ResourceSettings
@Override
public void onPause() {
if (listenerSetup) {
switchBar.removeOnSwitchChangeListener(this);
// switchBar.removeOnSwitchChangeListener(this);
listenerSetup = false;
}
super.onPause();

View File

@ -16,12 +16,13 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorAccent"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#ffffff"
android:fillColor="#FF000000"
android:pathData="M14,10H2V12H14V10M14,6H2V8H14V6M2,16H10V14H2V16M21.5,11.5L23,13L16,20L11.5,15.5L13,14L16,17L21.5,11.5Z" />
</vector>
</vector>

View File

@ -106,15 +106,15 @@
android:allowBackup="false"
android:extractNativeLibs="false"
android:icon="@mipmap/ic_core_service_app"
android:label="@string/gms_app_name">
android:label="@string/gms_app_name"
android:theme="@style/Theme.AppCompat.DayNight">
<meta-data
android:name="fake-signature"
android:value="@string/fake_signature" />
<!-- Location -->
<activity android:name="org.microg.nlp.ui.BackendSettingsActivity"
android:theme="@style/Theme.AppCompat.DayNight" />
<activity android:name="org.microg.nlp.ui.BackendSettingsActivity" />
<activity
android:name="org.microg.gms.ui.PlacePickerActivity"
@ -261,6 +261,7 @@
<service android:name="org.microg.gms.droidguard.DroidGuardService">
<intent-filter>
<action android:name="com.google.android.gms.droidguard.service.START" />
<action android:name="com.google.android.gms.droidguard.service.PING" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
@ -410,8 +411,7 @@
android:name="org.microg.gms.ui.SettingsActivity"
android:icon="@mipmap/ic_microg_settings"
android:label="@string/gms_settings_name"
android:roundIcon="@mipmap/ic_microg_settings"
android:theme="@style/Theme.AppCompat.DayNight">
android:roundIcon="@mipmap/ic_microg_settings">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@ -423,13 +423,18 @@
</intent-filter>
</activity>
<activity
android:name="org.microg.gms.ui.SettingsDashboardActivity"
android:icon="@mipmap/ic_microg_settings"
android:label="Legacy microG Settings"
android:roundIcon="@mipmap/ic_microg_settings" />
<!-- microG Settings embedded in System Settings on SDK 23 and newer -->
<activity-alias
android:name="org.microg.gms.ui.SettingsActivityLink"
android:icon="@drawable/microg_light_color_24"
android:label="@string/gms_settings_name"
android:targetActivity="org.microg.gms.ui.SettingsActivity"
android:theme="@style/Theme.AppCompat.DayNight">
android:targetActivity="org.microg.gms.ui.SettingsActivity">
<intent-filter>
<action android:name="com.android.settings.action.EXTRA_SETTINGS" />
</intent-filter>
@ -452,52 +457,25 @@
<activity
android:name="org.microg.gms.ui.AboutFragment$AsActivity"
android:label="@string/pref_about_title"
android:theme="@style/Theme.AppCompat.DayNight" />
<activity
android:name="org.microg.gms.ui.CheckinFragment$AsActivity"
android:label="@string/service_name_checkin"
android:theme="@style/Theme.AppCompat.DayNight" />
<activity
android:name="org.microg.gms.ui.GcmFragment$AsActivity"
android:label="@string/service_name_mcs"
android:theme="@style/Theme.AppCompat.DayNight" />
<activity
android:name="org.microg.gms.ui.GcmAdvancedFragment$AsActivity"
android:label="@string/service_name_mcs"
android:theme="@style/Theme.AppCompat.DayNight" />
<activity
android:name="org.microg.gms.ui.GcmAppFragment$AsActivity"
android:label="@string/service_name_mcs"
android:theme="@style/Theme.AppCompat.DayNight" />
android:label="@string/pref_about_title" />
<activity
android:name="org.microg.gms.ui.GoogleMoreFragment$AsActivity"
android:label="@string/gms_settings_name"
android:theme="@style/Theme.AppCompat.DayNight" />
android:label="@string/gms_settings_name" />
<activity
android:name="org.microg.gms.ui.SafetyNetFragment$AsActivity"
android:label="@string/service_name_snet"
android:theme="@style/Theme.AppCompat.DayNight" />
android:label="@string/service_name_snet" />
<activity
android:name="org.microg.gms.ui.SafetyNetAdvancedFragment$AsActivity"
android:label="@string/service_name_snet"
android:theme="@style/Theme.AppCompat.DayNight" />
android:label="@string/service_name_snet" />
<activity
android:name="org.microg.gms.ui.SelfCheckFragment$AsActivity"
android:label="@string/self_check_title"
android:theme="@style/Theme.AppCompat.DayNight" />
android:label="@string/self_check_title" />
<activity
android:name="org.microg.gms.ui.AccountSettingsActivity"
android:theme="@style/Theme.AppCompat.DayNight">
<activity android:name="org.microg.gms.ui.AccountSettingsActivity">
<intent-filter>
<action android:name="com.google.android.gms.accountsettings.ACCOUNT_PREFERENCES_SETTINGS" />
<action android:name="com.google.android.gms.accountsettings.PRIVACY_SETTINGS" />
@ -507,9 +485,7 @@
</intent-filter>
</activity>
<activity
android:name="org.microg.gms.ui.LocationSettingsActivity"
android:theme="@style/Theme.AppCompat.DayNight">
<activity android:name="org.microg.gms.ui.LocationSettingsActivity">
<intent-filter>
<action android:name="com.google.android.gms.location.settings.LOCATION_HISTORY" />
<action android:name="com.google.android.location.settings.LOCATION_REPORTING_SETTINGS" />

View File

@ -33,8 +33,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static org.microg.gms.checkin.TriggerReceiver.PREF_ENABLE_CHECKIN;
public class CheckinManager {
private static final long MIN_CHECKIN_INTERVAL = 3 * 60 * 60 * 1000; // 3 hours
@ -43,7 +41,7 @@ public class CheckinManager {
LastCheckinInfo info = LastCheckinInfo.read(context);
if (!force && info.lastCheckin > System.currentTimeMillis() - MIN_CHECKIN_INTERVAL)
return null;
if (!PreferenceManager.getDefaultSharedPreferences(context).getBoolean(PREF_ENABLE_CHECKIN, false))
if (!CheckinPrefs.get(context).isEnabled())
return null;
List<CheckinClient.Account> accounts = new ArrayList<CheckinClient.Account>();
AccountManager accountManager = AccountManager.get(context);

View File

@ -0,0 +1,47 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.checkin;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
public class CheckinPrefs implements SharedPreferences.OnSharedPreferenceChangeListener {
public static final String PREF_ENABLE_CHECKIN = "checkin_enable_service";
private static CheckinPrefs INSTANCE;
public static CheckinPrefs get(Context context) {
if (INSTANCE == null) {
if (context == null) return new CheckinPrefs(null);
INSTANCE = new CheckinPrefs(context.getApplicationContext());
}
return INSTANCE;
}
private SharedPreferences preferences;
private boolean checkinEnabled = false;
private CheckinPrefs(Context context) {
if (context != null) {
preferences = PreferenceManager.getDefaultSharedPreferences(context);
preferences.registerOnSharedPreferenceChangeListener(this);
update();
}
}
private void update() {
checkinEnabled = preferences.getBoolean(PREF_ENABLE_CHECKIN, false);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
update();
}
public boolean isEnabled() {
return checkinEnabled;
}
}

View File

@ -34,8 +34,6 @@ import org.microg.gms.common.ForegroundServiceContext;
import org.microg.gms.gcm.McsService;
import org.microg.gms.people.PeopleManager;
import static org.microg.gms.checkin.TriggerReceiver.PREF_ENABLE_CHECKIN;
public class CheckinService extends IntentService {
private static final String TAG = "GmsCheckinSvc";
public static final String BIND_ACTION = "com.google.android.gms.checkin.BIND_TO_SERVICE";
@ -58,7 +56,7 @@ public class CheckinService extends IntentService {
protected void onHandleIntent(Intent intent) {
try {
ForegroundServiceContext.completeForegroundService(this, intent, TAG);
if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean(PREF_ENABLE_CHECKIN, false)) {
if (CheckinPrefs.get(this).isEnabled()) {
LastCheckinInfo info = CheckinManager.checkin(this, intent.getBooleanExtra(EXTRA_FORCE_CHECKIN, false));
if (info != null) {
Log.d(TAG, "Checked in as " + Long.toHexString(info.androidId));

View File

@ -31,7 +31,6 @@ import static org.microg.gms.checkin.CheckinService.EXTRA_FORCE_CHECKIN;
public class TriggerReceiver extends WakefulBroadcastReceiver {
private static final String TAG = "GmsCheckinTrigger";
public static final String PREF_ENABLE_CHECKIN = "checkin_enable_service";
private static final long REGULAR_CHECKIN_INTERVAL = 12 * 60 * 60 * 1000; // 12 hours
@Override
@ -40,7 +39,7 @@ public class TriggerReceiver extends WakefulBroadcastReceiver {
boolean force = "android.provider.Telephony.SECRET_CODE".equals(intent.getAction());
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean(PREF_ENABLE_CHECKIN, false) || force) {
if (CheckinPrefs.get(context).isEnabled() || force) {
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction()) &&
LastCheckinInfo.read(context).lastCheckin > System.currentTimeMillis() - REGULAR_CHECKIN_INTERVAL) {
return;

View File

@ -80,6 +80,7 @@ public class SafetyNetClientServiceImpl extends ISafetyNetService.Stub {
bundle.putString("contentBinding", attestation.getPayloadHashBase64());
RemoteDroidGuardConnector.Result dg = conn.guard("attest", Long.toString(LastCheckinInfo.read(context).androidId), bundle);
if (!SafetyNetPrefs.get(context).isOfficial() || dg != null && dg.getStatusCode() == 0 && dg.getResult() != null) {
Log.d(TAG, dg == null ? "No dg result" : ("Status: " + dg.getStatusCode() + ", error:" + dg.getErrorMsg()));
if (dg != null && dg.getStatusCode() == 0 && dg.getResult() != null) {
attestation.setDroidGaurdResult(Base64.encodeToString(dg.getResult(), Base64.NO_WRAP + Base64.NO_PADDING + Base64.URL_SAFE));
}

View File

@ -1,60 +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.os.Bundle;
import android.preference.PreferenceManager;
import androidx.fragment.app.Fragment;
import com.google.android.gms.R;
import org.microg.tools.ui.AbstractSettingsActivity;
import org.microg.tools.ui.SwitchBarResourceSettingsFragment;
import static org.microg.gms.checkin.TriggerReceiver.PREF_ENABLE_CHECKIN;
public class CheckinFragment extends SwitchBarResourceSettingsFragment {
public CheckinFragment() {
preferencesResource = R.xml.preferences_checkin;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
switchBar.setChecked(PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean(PREF_ENABLE_CHECKIN, false));
}
@Override
public void onSwitchBarChanged(boolean isChecked) {
PreferenceManager.getDefaultSharedPreferences(getContext()).edit().putBoolean(PREF_ENABLE_CHECKIN, isChecked).apply();
}
public static class AsActivity extends AbstractSettingsActivity {
public AsActivity() {
showHomeAsUp = true;
}
@Override
protected Fragment getFragment() {
return new CheckinFragment();
}
}
}

View File

@ -94,15 +94,4 @@ public class GcmAdvancedFragment extends ResourceSettingsFragment {
}
return (heartbeatMs / 60000) + " minutes";
}
public static class AsActivity extends AbstractSettingsActivity {
public AsActivity() {
showHomeAsUp = true;
}
@Override
protected Fragment getFragment() {
return new GcmAdvancedFragment();
}
}
}

View File

@ -1,224 +0,0 @@
package org.microg.gms.ui;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.text.format.DateUtils;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import com.google.android.gms.R;
import org.microg.gms.gcm.GcmDatabase;
import org.microg.gms.gcm.PushRegisterManager;
import org.microg.tools.ui.AbstractSettingsActivity;
import org.microg.tools.ui.ResourceSettingsFragment;
import java.util.List;
import static android.text.format.DateUtils.FORMAT_SHOW_TIME;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
public class GcmAppFragment extends ResourceSettingsFragment {
public static final String EXTRA_PACKAGE_NAME = "package_name";
public static final String PREF_WAKE_FOR_DELIVERY = "gcm_app_wake_for_delivery";
public static final String PREF_ALLOW_REGISTER = "gcm_app_allow_register";
public static final String PREF_REGISTER_DETAILS = "gcm_app_register_details";
public static final String PREF_MESSAGE_DETAILS = "gcm_app_message_details";
protected String packageName;
private String appName;
private GcmDatabase database;
public GcmAppFragment() {
preferencesResource = R.xml.preferences_gcm_app_detail;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
packageName = getArguments().getString(EXTRA_PACKAGE_NAME);
AbstractSettingsActivity activity = (AbstractSettingsActivity) getActivity();
if (packageName != null && activity != null) {
activity.setCustomBarLayout(R.layout.app_bar);
try {
PackageManager pm = activity.getPackageManager();
ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
((ImageView) activity.findViewById(R.id.app_icon)).setImageDrawable(pm.getApplicationIcon(info));
appName = pm.getApplicationLabel(info).toString();
((TextView) activity.findViewById(R.id.app_name)).setText(appName);
View view = activity.findViewById(R.id.app_bar);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", packageName, null);
intent.setData(uri);
getContext().startActivity(intent);
}
});
view.setClickable(true);
} catch (Exception e) {
appName = packageName;
((TextView) activity.findViewById(R.id.app_name)).setText(packageName);
}
}
database = new GcmDatabase(getContext());
updateAppDetails();
}
@Override
public void onPause() {
super.onPause();
database.close();
}
@Override
public void onResume() {
super.onResume();
if (database != null) {
updateAppDetails();
}
}
private void updateAppDetails() {
GcmDatabase.App app = database.getApp(packageName);
if (app == null) {
getActivity().finish();
return;
}
PreferenceScreen root = getPreferenceScreen();
SwitchPreference wakeForDelivery = (SwitchPreference) root.findPreference(PREF_WAKE_FOR_DELIVERY);
wakeForDelivery.setChecked(app.wakeForDelivery);
wakeForDelivery.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (newValue instanceof Boolean) {
database.setAppWakeForDelivery(packageName, (Boolean) newValue);
return true;
}
return false;
}
});
SwitchPreference allowRegister = (SwitchPreference) root.findPreference(PREF_ALLOW_REGISTER);
allowRegister.setChecked(app.allowRegister);
allowRegister.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (newValue instanceof Boolean) {
if (!(boolean) newValue) {
final List<GcmDatabase.Registration> registrations = database.getRegistrationsByApp(packageName);
if (!registrations.isEmpty()) {
showUnregisterConfirm(registrations, getString(R.string.gcm_unregister_after_deny_message));
}
}
database.setAppAllowRegister(packageName, (Boolean) newValue);
return true;
}
return false;
}
});
Preference registerDetails = root.findPreference(PREF_REGISTER_DETAILS);
final List<GcmDatabase.Registration> registrations = database.getRegistrationsByApp(packageName);
if (registrations.isEmpty()) {
registerDetails.setTitle("");
registerDetails.setSelectable(false);
registerDetails.setSummary(R.string.gcm_not_registered);
} else {
StringBuilder sb = new StringBuilder();
for (GcmDatabase.Registration registration : registrations) {
if (sb.length() != 0) sb.append("\n");
if (registration.timestamp == 0) {
sb.append(getString(R.string.gcm_registered));
} else {
sb.append(getString(R.string.gcm_registered_since, DateUtils.getRelativeDateTimeString(getContext(), registration.timestamp, MINUTE_IN_MILLIS, WEEK_IN_MILLIS, FORMAT_SHOW_TIME)));
}
}
registerDetails.setTitle(R.string.gcm_unregister_app);
registerDetails.setSummary(sb.toString());
registerDetails.setSelectable(true);
registerDetails.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showUnregisterConfirm(registrations, getString(R.string.gcm_unregister_confirm_message));
return true;
}
});
}
Preference messageDetails = root.findPreference(PREF_MESSAGE_DETAILS);
if (app.totalMessageCount == 0) {
messageDetails.setSummary(R.string.gcm_no_message_yet);
} else {
String s = getString(R.string.gcm_messages_counter, app.totalMessageCount, app.totalMessageBytes);
if (app.lastMessageTimestamp != 0) {
s += "\n" + getString(R.string.gcm_last_message_at, DateUtils.getRelativeDateTimeString(getContext(), app.lastMessageTimestamp, MINUTE_IN_MILLIS, WEEK_IN_MILLIS, FORMAT_SHOW_TIME));
}
messageDetails.setSummary(s);
}
}
private void showUnregisterConfirm(final List<GcmDatabase.Registration> registrations, String unregisterConfirmDesc) {
new AlertDialog.Builder(getContext())
.setTitle(getString(R.string.gcm_unregister_confirm_title, appName))
.setMessage(unregisterConfirmDesc)
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
new Thread(new Runnable() {
@Override
public void run() {
for (GcmDatabase.Registration registration : registrations) {
PushRegisterManager.unregister(getContext(), registration.packageName, registration.signature, null, null);
}
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
updateAppDetails();
}
});
}
}).start();
}
})
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// Do nothing
}
}).show();
}
public static class AsActivity extends AbstractSettingsActivity {
public AsActivity() {
showHomeAsUp = true;
}
@Override
protected Fragment getFragment() {
GcmAppFragment fragment = new GcmAppFragment();
fragment.setArguments(getIntent().getExtras());
return fragment;
}
}
}

View File

@ -1,240 +0,0 @@
/*
* Copyright (C) 2013-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.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.text.format.DateUtils;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
import androidx.preference.PreferenceViewHolder;
import com.google.android.gms.R;
import org.microg.gms.gcm.GcmDatabase;
import org.microg.gms.gcm.GcmPrefs;
import org.microg.gms.gcm.McsConstants;
import org.microg.gms.gcm.McsService;
import org.microg.gms.gcm.TriggerReceiver;
import org.microg.tools.ui.AbstractSettingsActivity;
import org.microg.tools.ui.DimmableIconPreference;
import org.microg.tools.ui.SwitchBarResourceSettingsFragment;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import static android.text.format.DateUtils.FORMAT_SHOW_TIME;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
public class GcmFragment extends SwitchBarResourceSettingsFragment {
public static final String PREF_GCM_STATUS = "pref_gcm_status";
public static final String PREF_GCM_APPS = "gcm_apps";
private GcmDatabase database;
private final int MENU_ADVANCED = Menu.FIRST;
public GcmFragment() {
preferencesResource = R.xml.preferences_gcm;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
switchBar.setChecked(GcmPrefs.get(getContext()).isEnabled());
}
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
super.onCreatePreferences(savedInstanceState, rootKey);
database = new GcmDatabase(getContext());
updateContent();
}
@Override
public void onResume() {
super.onResume();
updateContent();
}
@Override
public void onPause() {
super.onPause();
database.close();
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.add(0, MENU_ADVANCED, 0, R.string.menu_advanced);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_ADVANCED:
Intent intent = new Intent(getContext(), GcmAdvancedFragment.AsActivity.class);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onSwitchBarChanged(boolean isChecked) {
getPreferenceManager().getSharedPreferences().edit().putBoolean(GcmPrefs.PREF_ENABLE_GCM, isChecked).apply();
if (!isChecked) {
McsService.stop(getContext());
} else {
getContext().sendBroadcast(new Intent(TriggerReceiver.FORCE_TRY_RECONNECT, null, getContext(), TriggerReceiver.class));
}
updateContent();
}
private static void addPreferencesSorted(List<Preference> prefs, PreferenceGroup container) {
// If there's some items to display, sort the items and add them to the container.
Collections.sort(prefs, new Comparator<Preference>() {
@Override
public int compare(Preference lhs, Preference rhs) {
return lhs.getTitle().toString().toLowerCase().compareTo(rhs.getTitle().toString().toLowerCase());
}
});
for (Preference entry : prefs) {
container.addPreference(entry);
}
}
private void updateContent() {
PreferenceScreen root = getPreferenceScreen();
if (McsService.isConnected()) {
root.findPreference(PREF_GCM_STATUS).setSummary(getString(R.string.gcm_state_connected, DateUtils.getRelativeTimeSpanString(McsService.getStartTimestamp(), System.currentTimeMillis(), 0)));
} else {
root.findPreference(PREF_GCM_STATUS).setSummary(getString(R.string.gcm_state_disconnected));
}
PreferenceCategory appList = (PreferenceCategory) root.findPreference(PREF_GCM_APPS);
appList.removeAll();
List<GcmDatabase.App> list = database.getAppList();
if (!list.isEmpty()) {
List<Preference> appListPrefs = new ArrayList<>();
PackageManager pm = getContext().getPackageManager();
for (GcmDatabase.App app : list) {
try {
pm.getApplicationInfo(app.packageName, 0);
appListPrefs.add(new GcmAppPreference(getPreferenceManager().getContext(), app));
} catch (PackageManager.NameNotFoundException e) {
final List<GcmDatabase.Registration> registrations = database.getRegistrationsByApp(app.packageName);
if (registrations.isEmpty()) {
database.removeApp(app.packageName);
} else {
appListPrefs.add(new GcmAppPreference(getPreferenceManager().getContext(), app));
}
}
}
addPreferencesSorted(appListPrefs, appList);
} else {
// If there's no item to display, add a "None" item.
Preference banner = new Preference(getPreferenceManager().getContext());
banner.setLayoutResource(R.layout.list_no_item);
banner.setTitle(R.string.list_no_item_none);
banner.setSelectable(false);
appList.addPreference(banner);
}
}
public static class GcmAppPreference extends DimmableIconPreference implements Preference.OnPreferenceClickListener {
private GcmDatabase database;
private GcmDatabase.App app;
public GcmAppPreference(Context context, GcmDatabase.App app) {
super(context);
this.app = app;
this.database = new GcmDatabase(context);
setKey(app.packageName);
PackageManager packageManager = context.getPackageManager();
try {
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(app.packageName, 0);
setTitle(packageManager.getApplicationLabel(applicationInfo));
setIcon(packageManager.getApplicationIcon(applicationInfo));
} catch (PackageManager.NameNotFoundException e) {
setTitle(app.packageName);
setIcon(android.R.drawable.sym_def_app_icon);
}
setOnPreferenceClickListener(this);
updateViewDetails();
}
private void updateViewDetails() {
if (database.getRegistrationsByApp(app.packageName).isEmpty()) {
setSummary(R.string.gcm_not_registered);
} else if (app.lastMessageTimestamp > 0) {
setSummary(getContext().getString(R.string.gcm_last_message_at, DateUtils.getRelativeDateTimeString(getContext(), app.lastMessageTimestamp, MINUTE_IN_MILLIS, WEEK_IN_MILLIS, FORMAT_SHOW_TIME)));
} else {
setSummary(R.string.gcm_no_message_yet);
}
database.close();
}
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
updateViewDetails();
super.onBindViewHolder(view);
}
@Override
public boolean onPreferenceClick(Preference preference) {
Intent intent = new Intent(getContext(), GcmAppFragment.AsActivity.class);
intent.putExtra(GcmAppFragment.EXTRA_PACKAGE_NAME, app.packageName);
getContext().startActivity(intent);
return true;
}
}
public static class AsActivity extends AbstractSettingsActivity {
public AsActivity() {
showHomeAsUp = true;
}
@Override
protected Fragment getFragment() {
return new GcmFragment();
}
}
}

View File

@ -1,82 +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 android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.google.android.gms.R;
import org.microg.gms.snet.SafetyNetPrefs;
import org.microg.tools.ui.AbstractSettingsActivity;
import org.microg.tools.ui.SwitchBarResourceSettingsFragment;
public class SafetyNetFragment extends SwitchBarResourceSettingsFragment {
private final int MENU_ADVANCED = Menu.FIRST;
public SafetyNetFragment() {
preferencesResource = R.xml.preferences_snet;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setHasOptionsMenu(true);
switchBar.setChecked(SafetyNetPrefs.get(getContext()).isEnabled());
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.add(0, MENU_ADVANCED, 0, R.string.menu_advanced);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_ADVANCED:
Intent intent = new Intent(getContext(), SafetyNetAdvancedFragment.AsActivity.class);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onSwitchBarChanged(boolean isChecked) {
SafetyNetPrefs.get(getContext()).setEnabled(isChecked);
}
public static class AsActivity extends AbstractSettingsActivity {
public AsActivity() {
showHomeAsUp = true;
}
@Override
protected Fragment getFragment() {
return new SafetyNetFragment();
}
}
}

View File

@ -1,112 +1,34 @@
/*
* Copyright (C) 2013-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.os.Bundle;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.NavController;
import androidx.navigation.fragment.NavHostFragment;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.google.android.gms.R;
import org.microg.gms.gcm.GcmDatabase;
import org.microg.gms.gcm.GcmPrefs;
import org.microg.gms.snet.SafetyNetPrefs;
//import org.microg.nlp.Preferences;
import org.microg.tools.ui.AbstractDashboardActivity;
import org.microg.tools.ui.ResourceSettingsFragment;
public class SettingsActivity extends AppCompatActivity {
private AppBarConfiguration appBarConfiguration;
import static org.microg.gms.checkin.TriggerReceiver.PREF_ENABLE_CHECKIN;
public class SettingsActivity extends AbstractDashboardActivity {
public SettingsActivity() {
preferencesResource = R.xml.preferences_start;
addCondition(Conditions.GCM_BATTERY_OPTIMIZATIONS);
addCondition(Conditions.PERMISSIONS);
private NavController getNavController() {
return ((NavHostFragment)getSupportFragmentManager().findFragmentById(R.id.navhost)).getNavController();
}
@Override
protected Fragment getFragment() {
return new FragmentImpl();
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_root_activity);
appBarConfiguration = new AppBarConfiguration.Builder(getNavController().getGraph()).build();
NavigationUI.setupActionBarWithNavController(this, getNavController(), appBarConfiguration);
}
public static class FragmentImpl extends ResourceSettingsFragment {
public static final String PREF_ABOUT = "pref_about";
public static final String PREF_GCM = "pref_gcm";
public static final String PREF_SNET = "pref_snet";
// public static final String PREF_UNIFIEDNLP = "pref_unifiednlp";
public static final String PREF_CHECKIN = "pref_checkin";
public FragmentImpl() {
preferencesResource = R.xml.preferences_start;
}
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
super.onCreatePreferences(savedInstanceState, rootKey);
updateDetails();
}
@Override
public void onResume() {
super.onResume();
updateDetails();
}
private void updateDetails() {
findPreference(PREF_ABOUT).setSummary(getString(R.string.about_version_str, AboutFragment.getSelfVersion(getContext())));
if (GcmPrefs.get(getContext()).isEnabled()) {
GcmDatabase database = new GcmDatabase(getContext());
int regCount = database.getRegistrationList().size();
database.close();
findPreference(PREF_GCM).setSummary(getString(R.string.abc_capital_on) + " / " + getResources().getQuantityString(R.plurals.gcm_registered_apps_counter, regCount, regCount));
} else {
findPreference(PREF_GCM).setSummary(R.string.abc_capital_off);
}
if (SafetyNetPrefs.get(getContext()).isEnabled()) {
String snet_info = "";
if (SafetyNetPrefs.get(getContext()).isOfficial()) {
snet_info = getString(R.string.pref_snet_status_official_info);
} else if (SafetyNetPrefs.get(getContext()).isSelfSigned()) {
snet_info = getString(R.string.pref_snet_status_self_signed_info);
} else if (SafetyNetPrefs.get(getContext()).isThirdParty()) {
snet_info = getString(R.string.pref_snet_status_third_party_info);
}
findPreference(PREF_SNET).setSummary(getString(R.string.service_status_enabled) + " / " + snet_info);
} else {
findPreference(PREF_SNET).setSummary(R.string.service_status_disabled);
}
// Preferences unifiedNlPrefs = new Preferences(getContext());
// int backendCount = TextUtils.isEmpty(unifiedNlPrefs.getLocationBackends()) ? 0 :
// Preferences.splitBackendString(unifiedNlPrefs.getLocationBackends()).length;
// backendCount += TextUtils.isEmpty(unifiedNlPrefs.getGeocoderBackends()) ? 0 :
// Preferences.splitBackendString(unifiedNlPrefs.getGeocoderBackends()).length;
// findPreference(PREF_UNIFIEDNLP).setSummary(getResources().getQuantityString(R.plurals.pref_unifiednlp_summary, backendCount, backendCount));
boolean checkinEnabled = PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean(PREF_ENABLE_CHECKIN, false);
findPreference(PREF_CHECKIN).setSummary(checkinEnabled ? R.string.service_status_enabled : R.string.service_status_disabled);
}
@Override
public boolean onSupportNavigateUp() {
return NavigationUI.navigateUp(getNavController(), appBarConfiguration) || super.onSupportNavigateUp();
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2013-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 androidx.fragment.app.Fragment;
import com.google.android.gms.R;
//import org.microg.nlp.Preferences;
import org.microg.tools.ui.AbstractDashboardActivity;
public class SettingsDashboardActivity extends AbstractDashboardActivity {
public SettingsDashboardActivity() {
preferencesResource = R.xml.preferences_start;
addCondition(Conditions.GCM_BATTERY_OPTIMIZATIONS);
addCondition(Conditions.PERMISSIONS);
}
@Override
protected Fragment getFragment() {
return new SettingsFragment();
}
}

View File

@ -0,0 +1,97 @@
package org.microg.gms.ui;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.navigation.fragment.NavHostFragment;
import com.google.android.gms.R;
import org.microg.gms.checkin.CheckinPrefs;
import org.microg.gms.gcm.GcmDatabase;
import org.microg.gms.gcm.GcmPrefs;
import org.microg.gms.snet.SafetyNetPrefs;
import org.microg.tools.ui.ResourceSettingsFragment;
public class SettingsFragment extends ResourceSettingsFragment {
public static final String PREF_ABOUT = "pref_about";
public static final String PREF_GCM = "pref_gcm";
public static final String PREF_SNET = "pref_snet";
public static final String PREF_UNIFIEDNLP = "pref_unifiednlp";
public static final String PREF_CHECKIN = "pref_checkin";
public SettingsFragment() {
preferencesResource = R.xml.preferences_start;
}
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
super.onCreatePreferences(savedInstanceState, rootKey);
updateDetails();
}
@Override
public void onResume() {
super.onResume();
updateDetails();
}
private void updateDetails() {
findPreference(PREF_ABOUT).setSummary(getString(R.string.about_version_str, AboutFragment.getSelfVersion(getContext())));
findPreference(PREF_ABOUT).setOnPreferenceClickListener(preference -> {
NavHostFragment.findNavController(SettingsFragment.this).navigate(R.id.openAbout);
return true;
});
if (GcmPrefs.get(getContext()).isEnabled()) {
GcmDatabase database = new GcmDatabase(getContext());
int regCount = database.getRegistrationList().size();
database.close();
findPreference(PREF_GCM).setSummary(getString(R.string.service_status_enabled_short) + " - " + getResources().getQuantityString(R.plurals.gcm_registered_apps_counter, regCount, regCount));
} else {
findPreference(PREF_GCM).setSummary(R.string.service_status_disabled_short);
}
findPreference(PREF_GCM).setOnPreferenceClickListener(preference -> {
NavHostFragment.findNavController(SettingsFragment.this).navigate(R.id.openGcmSettings);
return true;
});
if (SafetyNetPrefs.get(getContext()).isEnabled()) {
String snet_info = "";
if (SafetyNetPrefs.get(getContext()).isOfficial()) {
snet_info = getString(R.string.pref_snet_status_official_info);
} else if (SafetyNetPrefs.get(getContext()).isSelfSigned()) {
snet_info = getString(R.string.pref_snet_status_self_signed_info);
} else if (SafetyNetPrefs.get(getContext()).isThirdParty()) {
snet_info = getString(R.string.pref_snet_status_third_party_info);
}
findPreference(PREF_SNET).setSummary(getString(R.string.service_status_enabled_short));
} else {
findPreference(PREF_SNET).setSummary(R.string.service_status_disabled_short);
}
findPreference(PREF_SNET).setOnPreferenceClickListener(preference -> {
NavHostFragment.findNavController(SettingsFragment.this).navigate(R.id.openSafetyNetSettings);
return true;
});
// Preferences unifiedNlPrefs = new Preferences(getContext());
// int backendCount = TextUtils.isEmpty(unifiedNlPrefs.getLocationBackends()) ? 0 :
// Preferences.splitBackendString(unifiedNlPrefs.getLocationBackends()).length;
// backendCount += TextUtils.isEmpty(unifiedNlPrefs.getGeocoderBackends()) ? 0 :
// Preferences.splitBackendString(unifiedNlPrefs.getGeocoderBackends()).length;
// findPreference(PREF_UNIFIEDNLP).setSummary(getResources().getQuantityString(R.plurals.pref_unifiednlp_summary, backendCount, backendCount));
findPreference(PREF_UNIFIEDNLP).setOnPreferenceClickListener(preference -> {
NavHostFragment.findNavController(SettingsFragment.this).navigate(R.id.openUnifiedNlpSettings);
return true;
});
boolean checkinEnabled = CheckinPrefs.get(getContext()).isEnabled();
findPreference(PREF_CHECKIN).setSummary(checkinEnabled ? R.string.service_status_enabled_short : R.string.service_status_disabled_short);
findPreference(PREF_CHECKIN).setOnPreferenceClickListener(preference -> {
NavHostFragment.findNavController(SettingsFragment.this).navigate(R.id.openCheckinSettings);
return true;
});
}
}

View File

@ -1,18 +0,0 @@
package org.microg.gms.ui;
import androidx.fragment.app.Fragment;
import org.microg.nlp.ui.BackendDetailsFragment;
import org.microg.nlp.ui.BackendListFragment;
import org.microg.tools.ui.AbstractSettingsActivity;
public class UnifiedBackendDetailsActivity extends AbstractSettingsActivity {
public UnifiedBackendDetailsActivity() {
showHomeAsUp = true;
}
@Override
protected Fragment getFragment() {
return new BackendDetailsFragment();
}
}

View File

@ -1,32 +0,0 @@
package org.microg.gms.ui;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import org.microg.nlp.ui.BackendListFragment;
import org.microg.tools.ui.AbstractSettingsActivity;
public class UnifiedBackendListActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
} catch (Exception e) {
Log.w("GmsCoreSettingUi", e);
}
getSupportFragmentManager().beginTransaction().add(new BackendListFragment(), null).commit();
}
@Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
}

View File

@ -0,0 +1,24 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.ui
import android.content.Context
import android.util.DisplayMetrics
import android.widget.ImageView
import androidx.preference.Preference
import androidx.preference.PreferenceViewHolder
class AppIconPreference(context: Context) : Preference(context) {
override fun onBindViewHolder(holder: PreferenceViewHolder?) {
super.onBindViewHolder(holder)
val icon = holder?.findViewById(android.R.id.icon)
if (icon is ImageView) {
icon.adjustViewBounds = true
icon.scaleType = ImageView.ScaleType.CENTER_INSIDE
icon.maxHeight = (32.0 * context.resources.displayMetrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT).toInt()
}
}
}

View File

@ -0,0 +1,45 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.ui
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.preference.PreferenceManager
import com.google.android.gms.R
import com.google.android.gms.databinding.DeviceRegistrationFragmentBinding
import org.microg.gms.checkin.CheckinPrefs
import org.microg.gms.checkin.CheckinPrefs.PREF_ENABLE_CHECKIN
import org.microg.gms.checkin.TriggerReceiver
class DeviceRegistrationFragment : Fragment(R.layout.device_registration_fragment) {
private lateinit var binding: DeviceRegistrationFragmentBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = DeviceRegistrationFragmentBinding.inflate(inflater, container, false)
binding.switchBarCallback = object : PreferenceSwitchBarCallback {
override fun onChecked(newStatus: Boolean) {
PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(PREF_ENABLE_CHECKIN, newStatus).commit()
if (newStatus) {
requireContext().sendOrderedBroadcast(Intent(requireContext(), TriggerReceiver::class.java), null)
}
binding.checkinEnabled = newStatus
}
}
return binding.root
}
override fun onResume() {
super.onResume()
lifecycleScope.launchWhenResumed {
binding.checkinEnabled = CheckinPrefs.get(context).isEnabled
}
}
}

View File

@ -0,0 +1,57 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.ui
import android.os.Bundle
import android.os.Handler
import android.text.format.DateUtils
import androidx.preference.Preference
import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceFragmentCompat
import com.google.android.gms.R
import org.microg.gms.checkin.CheckinPrefs
import org.microg.gms.checkin.LastCheckinInfo
class DeviceRegistrationPreferencesFragment : PreferenceFragmentCompat() {
private lateinit var statusCategory: PreferenceCategory
private lateinit var status: Preference
private val handler = Handler()
private val updateRunnable = Runnable { updateStatus() }
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.preferences_device_registration)
}
override fun onBindPreferences() {
statusCategory = preferenceScreen.findPreference("prefcat_device_registration_status") ?: statusCategory
status = preferenceScreen.findPreference("pref_device_registration_status") ?: status
}
override fun onResume() {
super.onResume()
updateStatus()
}
override fun onPause() {
super.onPause()
handler.removeCallbacks(updateRunnable)
}
private fun updateStatus() {
handler.postDelayed(updateRunnable, UPDATE_INTERVAL)
statusCategory.isVisible = CheckinPrefs.get(context).isEnabled
val checkinInfo = LastCheckinInfo.read(requireContext())
status.summary = if (checkinInfo.lastCheckin > 0) {
"Last registration: " + DateUtils.getRelativeTimeSpanString(checkinInfo.lastCheckin, System.currentTimeMillis(), 0)
} else {
"Not registered"
}
}
companion object {
private const val UPDATE_INTERVAL = 1000L
}
}

View File

@ -0,0 +1,10 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.ui
interface PreferenceSwitchBarCallback {
fun onChecked(newStatus: Boolean)
}

View File

@ -0,0 +1,115 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.ui
import android.os.Bundle
import android.text.format.DateUtils
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.os.bundleOf
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.preference.Preference
import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceFragmentCompat
import com.google.android.gms.R
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.microg.gms.gcm.GcmDatabase
class PushNotificationAllAppsFragment : PreferenceFragmentCompat() {
private lateinit var database: GcmDatabase
private lateinit var registered: PreferenceCategory
private lateinit var unregistered: PreferenceCategory
private lateinit var registeredNone: Preference
private lateinit var unregisteredNone: Preference
private lateinit var progress: Preference
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
database = GcmDatabase(context)
}
override fun onResume() {
super.onResume()
updateContent()
}
override fun onPause() {
super.onPause()
database.close()
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.preferences_push_notifications_all_apps)
registered = preferenceScreen.findPreference("prefcat_push_apps_registered") ?: registered
unregistered = preferenceScreen.findPreference("prefcat_push_apps_unregistered") ?: unregistered
registeredNone = preferenceScreen.findPreference("pref_push_apps_registered_none") ?: registeredNone
unregisteredNone = preferenceScreen.findPreference("pref_push_apps_unregistered_none") ?: unregisteredNone
progress = preferenceScreen.findPreference("pref_push_apps_all_progress") ?: progress
}
private fun updateContent() {
lifecycleScope.launchWhenResumed {
val context = requireContext()
val apps = withContext(Dispatchers.IO) {
val res = database.appList.map { app ->
try {
app to context.packageManager.getApplicationInfo(app.packageName, 0)
} catch (ignored: Exception) {
app to null
}
}.map { (app, applicationInfo) ->
val pref = AppIconPreference(context)
pref.title = applicationInfo?.loadLabel(context.packageManager) ?: app.packageName
pref.summary = when {
app.lastMessageTimestamp > 0 -> getString(R.string.gcm_last_message_at, DateUtils.getRelativeTimeSpanString(app.lastMessageTimestamp))
else -> null
}
pref.icon = applicationInfo?.loadIcon(context.packageManager)
?: AppCompatResources.getDrawable(context, android.R.mipmap.sym_def_app_icon)
pref.onPreferenceClickListener = Preference.OnPreferenceClickListener {
findNavController().navigate(R.id.openGcmAppDetailsFromAll, bundleOf(
"package" to app.packageName
))
true
}
pref.key = "pref_push_app_" + app.packageName
pref to (database.getRegistrationsByApp(app.packageName))
}.sortedBy {
it.first.title.toString().toLowerCase()
}.mapIndexed { idx, pair ->
pair.first.order = idx
pair
}
database.close()
res
}
registered.removeAll()
registered.isVisible = true
unregistered.removeAll()
unregistered.isVisible = true
var hadRegistered = false
var hadUnregistered = false
for (pair in apps) {
if (pair.second.isEmpty()) {
unregistered.addPreference(pair.first)
hadUnregistered = true
} else {
registered.addPreference(pair.first)
hadRegistered = true
}
}
registeredNone.isVisible = !hadRegistered
unregisteredNone.isVisible = !hadUnregistered
if (!hadRegistered) registered.addPreference(registeredNone)
if (!hadUnregistered) unregistered.addPreference(unregisteredNone)
progress.isVisible = false
}
}
}

View File

@ -0,0 +1,58 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.ui
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.content.res.AppCompatResources
import androidx.fragment.app.Fragment
import androidx.fragment.app.findFragment
import androidx.lifecycle.lifecycleScope
import com.google.android.gms.R
import com.google.android.gms.databinding.PushNotificationAppFragmentBinding
class PushNotificationAppFragment : Fragment(R.layout.push_notification_fragment) {
lateinit var binding: PushNotificationAppFragmentBinding
val packageName: String?
get() = arguments?.getString("package")
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = PushNotificationAppFragmentBinding.inflate(inflater, container, false)
binding.callbacks = object : PushNotificationAppFragmentCallbacks {
override fun onAppClicked() {
val intent = Intent()
intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
val uri: Uri = Uri.fromParts("package", packageName, null)
intent.data = uri
context!!.startActivity(intent)
}
}
childFragmentManager.findFragmentById(R.id.sub_preferences)?.arguments = arguments
return binding.root
}
override fun onResume() {
super.onResume()
lifecycleScope.launchWhenResumed {
val pm = requireContext().packageManager
val applicationInfo = packageName?.let { pm.getApplicationInfo(it, 0) }
binding.appName = applicationInfo?.loadLabel(pm)?.toString() ?: packageName
binding.appIcon = applicationInfo?.loadIcon(pm)
?: AppCompatResources.getDrawable(requireContext(), android.R.mipmap.sym_def_app_icon)
}
}
}
interface PushNotificationAppFragmentCallbacks {
fun onAppClicked()
}

View File

@ -0,0 +1,134 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.ui
import android.os.Bundle
import android.text.format.DateUtils
import androidx.appcompat.app.AlertDialog
import androidx.lifecycle.lifecycleScope
import androidx.preference.Preference
import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.TwoStatePreference
import com.google.android.gms.R
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.microg.gms.gcm.GcmDatabase
import org.microg.gms.gcm.PushRegisterManager
class PushNotificationAppPreferencesFragment : PreferenceFragmentCompat() {
private lateinit var wakeForDelivery: TwoStatePreference
private lateinit var allowRegister: TwoStatePreference
private lateinit var status: Preference
private lateinit var unregister: Preference
private lateinit var unregisterCat: PreferenceCategory
private lateinit var database: GcmDatabase
private val packageName: String?
get() = arguments?.getString("package")
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.preferences_push_notifications_app)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
database = GcmDatabase(context)
}
override fun onBindPreferences() {
wakeForDelivery = preferenceScreen.findPreference("pref_push_app_wake_for_delivery") ?: wakeForDelivery
allowRegister = preferenceScreen.findPreference("pref_push_app_allow_register") ?: allowRegister
unregister = preferenceScreen.findPreference("pref_push_app_unregister") ?: unregister
unregisterCat = preferenceScreen.findPreference("prefcat_push_app_unregister") ?: unregisterCat
status = preferenceScreen.findPreference("pref_push_app_status") ?: status
wakeForDelivery.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
database.setAppWakeForDelivery(packageName, newValue as Boolean)
database.close()
true
}
allowRegister.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
val enabled = newValue as? Boolean ?: return@OnPreferenceChangeListener false
if (!enabled) {
val registrations = packageName?.let { database.getRegistrationsByApp(it) } ?: emptyList()
if (registrations.isNotEmpty()) {
showUnregisterConfirm(R.string.gcm_unregister_after_deny_message)
}
}
database.setAppAllowRegister(packageName, enabled)
database.close()
true
}
unregister.onPreferenceClickListener = Preference.OnPreferenceClickListener {
showUnregisterConfirm(R.string.gcm_unregister_confirm_message)
true
}
}
private fun showUnregisterConfirm(unregisterConfirmDesc: Int) {
val pm = requireContext().packageManager
val applicationInfo = packageName?.let { pm.getApplicationInfo(it, 0) }
AlertDialog.Builder(requireContext())
.setTitle(getString(R.string.gcm_unregister_confirm_title, applicationInfo?.loadLabel(pm)
?: packageName))
.setMessage(unregisterConfirmDesc)
.setPositiveButton(android.R.string.yes) { _, _ -> unregister() }
.setNegativeButton(android.R.string.no) { _, _ -> }.show()
}
private fun unregister() {
lifecycleScope.launchWhenResumed {
withContext(Dispatchers.IO) {
for (registration in database.getRegistrationsByApp(packageName)) {
PushRegisterManager.unregister(context, registration.packageName, registration.signature, null, null)
}
}
updateDetails()
}
}
override fun onResume() {
super.onResume()
updateDetails()
}
private fun updateDetails() {
lifecycleScope.launchWhenResumed {
val app = packageName?.let { database.getApp(it) }
wakeForDelivery.isChecked = app?.wakeForDelivery ?: true
allowRegister.isChecked = app?.allowRegister ?: true
val registrations = packageName?.let { database.getRegistrationsByApp(it) } ?: emptyList()
unregisterCat.isVisible = registrations.isNotEmpty()
val sb = StringBuilder()
if ((app?.totalMessageCount ?: 0L) == 0L) {
sb.append(getString(R.string.gcm_no_message_yet))
} else {
sb.append(getString(R.string.gcm_messages_counter, app?.totalMessageCount, app?.totalMessageBytes))
if (app?.lastMessageTimestamp != 0L) {
sb.append("\n").append(getString(R.string.gcm_last_message_at, DateUtils.getRelativeDateTimeString(context, app?.lastMessageTimestamp ?: 0L, DateUtils.MINUTE_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, DateUtils.FORMAT_SHOW_TIME)))
}
}
for (registration in registrations) {
sb.append("\n")
if (registration.timestamp == 0L) {
sb.append(getString(R.string.gcm_registered))
} else {
sb.append(getString(R.string.gcm_registered_since, DateUtils.getRelativeDateTimeString(context, registration.timestamp, DateUtils.MINUTE_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, DateUtils.FORMAT_SHOW_TIME)))
}
}
status.summary = sb.toString()
database.close()
}
}
override fun onPause() {
super.onPause()
database.close()
}
}

View File

@ -0,0 +1,72 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.ui
import android.content.Intent
import android.os.Bundle
import android.view.*
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.preference.*
import com.google.android.gms.R
import com.google.android.gms.databinding.PushNotificationFragmentBinding
import org.microg.gms.checkin.CheckinPrefs
import org.microg.gms.gcm.GcmPrefs
import org.microg.gms.gcm.McsService
import org.microg.gms.gcm.TriggerReceiver
class PushNotificationFragment : Fragment(R.layout.push_notification_fragment) {
lateinit var binding: PushNotificationFragmentBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = PushNotificationFragmentBinding.inflate(inflater, container, false)
binding.switchBarCallback = object : PreferenceSwitchBarCallback {
override fun onChecked(newStatus: Boolean) {
PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(GcmPrefs.PREF_ENABLE_GCM, newStatus).apply()
if (!newStatus) {
McsService.stop(context)
} else {
requireContext().sendBroadcast(Intent(TriggerReceiver.FORCE_TRY_RECONNECT, null, context, TriggerReceiver::class.java))
}
binding.gcmEnabled = newStatus
}
}
return binding.root
}
override fun onResume() {
super.onResume()
lifecycleScope.launchWhenResumed {
binding.gcmEnabled = GcmPrefs.get(context).isEnabled
binding.checkinEnabled = CheckinPrefs.get(context).isEnabled
}
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
menu.add(0, MENU_ADVANCED, 0, R.string.menu_advanced)
super.onCreateOptionsMenu(menu, inflater)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
MENU_ADVANCED -> {
findNavController().navigate(R.id.openGcmAdvancedSettings)
true
}
else -> super.onOptionsItemSelected(item)
}
}
companion object {
private const val MENU_ADVANCED = Menu.FIRST
}
}

View File

@ -0,0 +1,121 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.ui
import android.os.Bundle
import android.os.Handler
import android.text.format.DateUtils
import androidx.core.os.bundleOf
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.preference.Preference
import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceFragmentCompat
import com.google.android.gms.R
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.microg.gms.gcm.GcmDatabase
import org.microg.gms.gcm.GcmPrefs
import org.microg.gms.gcm.McsService
class PushNotificationPreferencesFragment : PreferenceFragmentCompat() {
private lateinit var pushStatusCategory: PreferenceCategory
private lateinit var pushStatus: Preference
private lateinit var pushApps: PreferenceCategory
private lateinit var pushAppsAll: Preference
private lateinit var pushAppsNone: Preference
private lateinit var database: GcmDatabase
private val handler = Handler()
private val updateRunnable = Runnable { updateStatus() }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
database = GcmDatabase(context)
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.preferences_push_notifications)
}
override fun onBindPreferences() {
pushStatusCategory = preferenceScreen.findPreference("prefcat_push_status") ?: pushStatusCategory
pushStatus = preferenceScreen.findPreference("pref_push_status") ?: pushStatus
pushApps = preferenceScreen.findPreference("prefcat_push_apps") ?: pushApps
pushAppsAll = preferenceScreen.findPreference("pref_push_apps_all") ?: pushAppsAll
pushAppsNone = preferenceScreen.findPreference("pref_push_apps_none") ?: pushAppsNone
pushAppsAll.onPreferenceClickListener = Preference.OnPreferenceClickListener {
findNavController().navigate(R.id.openAllGcmApps)
true
}
}
override fun onResume() {
super.onResume()
updateStatus()
updateContent()
}
override fun onPause() {
super.onPause()
database.close()
handler.removeCallbacks(updateRunnable)
}
private fun updateStatus() {
handler.postDelayed(updateRunnable, UPDATE_INTERVAL)
pushStatusCategory.isVisible = GcmPrefs.get(context).isEnabled
pushStatus.summary = if (McsService.isConnected()) {
"Connected since: " + DateUtils.getRelativeTimeSpanString(McsService.getStartTimestamp(), System.currentTimeMillis(), 0)
} else {
"Disconnected"
}
}
private fun updateContent() {
lifecycleScope.launchWhenResumed {
val context = requireContext()
val (apps, showAll) = withContext(Dispatchers.IO) {
val apps = database.appList.sortedByDescending { it.lastMessageTimestamp }
val res = apps.map { app ->
try {
app to context.packageManager.getApplicationInfo(app.packageName, 0)
} catch (ignored: Exception) {
null
}
}.filterNotNull().take(3).mapIndexed { idx, (app, applicationInfo) ->
val pref = AppIconPreference(context)
pref.order = idx
pref.title = applicationInfo.loadLabel(context.packageManager)
pref.icon = applicationInfo.loadIcon(context.packageManager)
pref.onPreferenceClickListener = Preference.OnPreferenceClickListener {
findNavController().navigate(R.id.openGcmAppDetails, bundleOf(
"package" to app.packageName
))
true
}
pref.key = "pref_push_app_" + app.packageName
pref
}.let { it to (it.size < apps.size) }
database.close()
res
}
pushAppsAll.isVisible = showAll
pushApps.removeAll()
for (app in apps) {
pushApps.addPreference(app)
}
if (showAll) {
pushApps.addPreference(pushAppsAll)
} else if (apps.isEmpty()) {
pushApps.addPreference(pushAppsNone)
}
}
}
companion object {
private const val UPDATE_INTERVAL = 1000L
}
}

View File

@ -0,0 +1,61 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.ui
import android.os.Bundle
import android.view.*
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.google.android.gms.R
import com.google.android.gms.databinding.SafetyNetFragmentBinding
import org.microg.gms.checkin.CheckinPrefs
import org.microg.gms.snet.SafetyNetPrefs
class SafetyNetFragment : Fragment(R.layout.safety_net_fragment) {
private lateinit var binding: SafetyNetFragmentBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = SafetyNetFragmentBinding.inflate(inflater, container, false)
binding.switchBarCallback = object : PreferenceSwitchBarCallback {
override fun onChecked(newStatus: Boolean) {
SafetyNetPrefs.get(requireContext()).isEnabled = newStatus
binding.safetynetEnabled = newStatus
}
}
return binding.root
}
override fun onResume() {
super.onResume()
binding.checkinEnabled = CheckinPrefs.get(requireContext()).isEnabled
binding.safetynetEnabled = SafetyNetPrefs.get(requireContext()).isEnabled
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
menu.add(0, MENU_ADVANCED, 0, R.string.menu_advanced)
super.onCreateOptionsMenu(menu, inflater)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
MENU_ADVANCED -> {
findNavController().navigate(R.id.openSafetyNetAdvancedSettings)
true
}
else -> super.onOptionsItemSelected(item)
}
}
companion object {
private const val MENU_ADVANCED = Menu.FIRST
}
}

View File

@ -0,0 +1,17 @@
/*
* SPDX-FileCopyrightText: 2020, microG Project Team
* SPDX-License-Identifier: Apache-2.0
*/
package org.microg.gms.ui
import android.os.Bundle
import androidx.preference.PreferenceFragmentCompat
import com.google.android.gms.R
class SafetyNetPreferencesFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.preferences_safetynet)
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 169 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 791 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 586 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -1,13 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:pathData="M16,12A2,2 0 0,1 18,10A2,2 0 0,1 20,12A2,2 0 0,1 18,14A2,2 0 0,1 16,12M10,12A2,2
0 0,1 12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12M4,12A2,2 0 0,1
6,10A2,2 0 0,1 8,12A2,2 0 0,1 6,14A2,2 0 0,1 4,12Z" />
</vector>
</vector>

View File

@ -2,6 +2,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorAccent"
android:viewportWidth="24"
android:viewportHeight="24">
@ -10,4 +11,4 @@
<path
android:fillColor="#ff000000"
android:pathData="M15,12 C17.21,12,19,10.21,19,8 S17.21,4,15,4 S11,5.79,11,8 S12.79,12,15,12 Z M6,10 L6,7 L4,7 L4,10 L1,10 L1,12 L4,12 L4,15 L6,15 L6,12 L9,12 L9,10 L6,10 Z M15,14 C12.33,14,7,15.34,7,18 L7,20 L23,20 L23,18 C23,15.34,17.67,14,15,14 Z" />
</vector>
</vector>

View File

@ -1,13 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorAccent"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:pathData="M4,3C2.89,3 2,3.89 2,5V15A2,2 0 0,0 4,17H12V22L15,19L18,22V17H20A2,2 0 0,0
22,15V8L22,6V5A2,2 0 0,0
20,3H16V3H4M12,5L15,7L18,5V8.5L21,10L18,11.5V15L15,13L12,15V11.5L9,10L12,8.5V5M4,5H9V7H4V5M4,9H7V11H4V9M4,13H9V15H4V13Z" />
</vector>
</vector>

View File

@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorAccent"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:pathData="M 12 4 C 9.11 4 6.5996094 5.6392969 5.3496094 8.0292969 C 2.3396094 8.3592969 0 10.9 0 14 A 6 6 0 0 0 6 20 L 19 20 A 5 5 0 0 0 24 15 C 24 12.36 21.949609 10.219297 19.349609 10.029297 C 18.669609 6.5892969 15.64 4 12 4 z M 12 7.5 A 0.5 0.5 0 0 1 12.5 8 L 12.5 8.5390625 C 13.92 8.7790625 15 10.015 15 11.5 L 15 14.5 L 16.5 16 L 7.5 16 L 9 14.5 L 9 11.5 C 9 10.015 10.08 8.7790625 11.5 8.5390625 L 11.5 8 A 0.5 0.5 0 0 1 12 7.5 z M 11 16.5 L 13 16.5 A 1 1 0 0 1 12 17.5 A 1 1 0 0 1 11 16.5 z"/>
</vector>
android:pathData="M 12 4 C 9.11 4 6.5996094 5.6392969 5.3496094 8.0292969 C 2.3396094 8.3592969 0 10.9 0 14 A 6 6 0 0 0 6 20 L 19 20 A 5 5 0 0 0 24 15 C 24 12.36 21.949609 10.219297 19.349609 10.029297 C 18.669609 6.5892969 15.64 4 12 4 z M 12 7.5 A 0.5 0.5 0 0 1 12.5 8 L 12.5 8.5390625 C 13.92 8.7790625 15 10.015 15 11.5 L 15 14.5 L 16.5 16 L 7.5 16 L 9 14.5 L 9 11.5 C 9 10.015 10.08 8.7790625 11.5 8.5390625 L 11.5 8 A 0.5 0.5 0 0 1 12 7.5 z M 11 16.5 L 13 16.5 A 1 1 0 0 1 12 17.5 A 1 1 0 0 1 11 16.5 z" />
</vector>

View File

@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorAccent"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:pathData="M10,17.25V14H3V10H10V6.75L15.25,12L10,17.25M8,2H17A2,2 0 0,1 19,4V20A2,2 0 0,1 17,22H8A2,2 0 0,1 6,20V16H8V20H17V4H8V8H6V4A2,2 0 0,1 8,2Z"/>
</vector>
android:pathData="M10,17.25V14H3V10H10V6.75L15.25,12L10,17.25M8,2H17A2,2 0 0,1 19,4V20A2,2 0 0,1 17,22H8A2,2 0 0,1 6,20V16H8V20H17V4H8V8H6V4A2,2 0 0,1 8,2Z" />
</vector>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2019, The Android Open Source Project
~ SPDX-FileCopyrightText: 2020, microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:tint="?attr/colorAccent"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M9.71,18.71l-1.42,-1.42l5.3,-5.29l-5.3,-5.29l1.42,-1.42l6.7,6.71z" />
</vector>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2019, The Android Open Source Project
~ SPDX-FileCopyrightText: 2020, microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorAccent"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z" />
</vector>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2019, The Android Open Source Project
~ SPDX-FileCopyrightText: 2020, microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorAccent"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M12,11.5A2.5,2.5 0 0,1 9.5,9A2.5,2.5 0 0,1 12,6.5A2.5,2.5 0 0,1 14.5,9A2.5,2.5 0 0,1 12,11.5M12,2A7,7 0 0,0 5,9C5,14.25 12,22 12,22C12,22 19,14.25 19,9A7,7 0 0,0 12,2Z" />
</vector>

View File

@ -48,7 +48,7 @@
android:layout_width="36dip"
android:layout_height="36dip"
android:scaleType="fitCenter"
android:src="@drawable/gcm_bell"
android:src="@drawable/ic_cloud_bell"
android:tint="?attr/colorAccent">
</ImageView>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2020, microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="checkinEnabled"
type="boolean" />
<variable
name="switchBarCallback"
type="org.microg.gms.ui.PreferenceSwitchBarCallback" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
layout="@layout/preference_switch_bar"
app:callback="@{switchBarCallback}"
app:checked="@{checkinEnabled}"
app:description='@{"Register device"}'
app:enabled="@{true}" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/sub_preferences"
android:name="org.microg.gms.ui.DeviceRegistrationPreferencesFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
</layout>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2020, microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<View xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="0dp" />

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2020, microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ProgressBar
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="true" />
</LinearLayout>

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2020, microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="checked"
type="boolean" />
<variable
name="enabled"
type="boolean" />
<variable
name="description"
type="String" />
<variable
name="callback"
type="org.microg.gms.ui.PreferenceSwitchBarCallback" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:clickable="@{enabled}"
android:focusable="@{enabled}"
android:gravity="center"
android:onClick="@{(v) -> callback.onChecked(!Boolean.valueOf(checked))}"
android:orientation="horizontal"
android:paddingStart="?attr/listPreferredItemPaddingStart"
android:paddingLeft="?attr/listPreferredItemPaddingLeft"
android:paddingEnd="?attr/listPreferredItemPaddingEnd"
android:paddingRight="?attr/listPreferredItemPaddingRight"
app:backgroundColorAttr="@{checked ? androidx.appcompat.R.attr.colorControlActivated : (enabled ? androidx.appcompat.R.attr.colorButtonNormal : androidx.appcompat.R.attr.colorControlHighlight)}"
tools:background="?attr/colorControlActivated">
<TextView
android:id="@android:id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="2"
android:paddingStart="56dp"
android:paddingLeft="56dp"
android:text="@{description}"
android:textAppearance="?attr/textAppearanceListItem"
android:textColor="?android:attr/textColorPrimaryInverse"
tools:text="Enabled" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/switch_widget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@null"
android:checked="@{checked}"
android:enabled="@{enabled}"
app:onCheckedChangeListener="@{(v, newStatus) -> callback.onChecked(newStatus)}"
app:thumbTint="?android:attr/textColorPrimaryInverse"
app:trackTint="?android:attr/textColorSecondaryInverse"
tools:checked="true" />
</LinearLayout>
</layout>

View File

@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2020, microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="appName"
type="String" />
<variable
name="appIcon"
type="android.graphics.drawable.Drawable" />
<variable
name="callbacks"
type="org.microg.gms.ui.PushNotificationAppFragmentCallbacks" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:paddingStart="?attr/listPreferredItemPaddingStart"
android:paddingLeft="?attr/listPreferredItemPaddingLeft"
android:paddingTop="24dp"
android:paddingEnd="?attr/listPreferredItemPaddingEnd"
android:paddingRight="?attr/listPreferredItemPaddingRight"
android:paddingBottom="16dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:gravity="center_horizontal"
android:onClick='@{() -> callbacks.onAppClicked()}'
android:orientation="vertical">
<ImageView
android:id="@+id/icon"
android:layout_width="48dp"
android:layout_height="48dp"
android:antialias="true"
android:scaleType="fitCenter"
android:src="@{appIcon}"
tools:src="@android:mipmap/sym_def_app_icon" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:ellipsize="marquee"
android:gravity="center"
android:singleLine="false"
android:text='@{appName}'
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
android:textColor="?android:attr/textColorPrimary"
android:textSize="20sp"
tools:text="@tools:sample/lorem" />
</LinearLayout>
</RelativeLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/sub_preferences"
android:name="org.microg.gms.ui.PushNotificationAppPreferencesFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
</layout>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2020, microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="gcmEnabled"
type="boolean" />
<variable
name="checkinEnabled"
type="boolean" />
<variable
name="switchBarCallback"
type="org.microg.gms.ui.PreferenceSwitchBarCallback" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
layout="@layout/preference_switch_bar"
app:callback="@{switchBarCallback}"
app:checked="@{gcmEnabled}"
app:description='@{"Receive push notifications"}'
app:enabled="@{checkinEnabled}" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/sub_preferences"
android:name="org.microg.gms.ui.PushNotificationPreferencesFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
</layout>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2020, microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="checkinEnabled"
type="boolean" />
<variable
name="safetynetEnabled"
type="boolean" />
<variable
name="switchBarCallback"
type="org.microg.gms.ui.PreferenceSwitchBarCallback" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
layout="@layout/preference_switch_bar"
app:callback="@{switchBarCallback}"
app:checked="@{safetynetEnabled}"
app:description='@{"Allow device attestation"}'
app:enabled="@{checkinEnabled}" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/sub_preferences"
android:name="org.microg.gms.ui.SafetyNetPreferencesFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"/>
</LinearLayout>
</layout>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2020, microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/navhost"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_settings" />
</LinearLayout>

View File

@ -0,0 +1,152 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_settings"
app:startDestination="@id/settingsFragment">
<fragment
android:id="@+id/settingsFragment"
android:name="org.microg.gms.ui.SettingsFragment"
android:label="@string/gms_settings_name">
<action
android:id="@+id/openUnifiedNlpSettings"
app:destination="@id/nav_unlp"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
<action
android:id="@+id/openSelfcheck"
app:destination="@id/selfcheckFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
<action
android:id="@+id/openCheckinSettings"
app:destination="@id/checkinFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
<action
android:id="@+id/openGcmSettings"
app:destination="@id/gcmFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
<action
android:id="@+id/openSafetyNetSettings"
app:destination="@id/safetyNetFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
<action
android:id="@+id/openMoreGoogleSettings"
app:destination="@id/googleMoreFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
<action
android:id="@+id/openAbout"
app:destination="@id/aboutFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
</fragment>
<fragment
android:id="@+id/selfcheckFragment"
android:name="org.microg.gms.ui.SelfCheckFragment"
android:label="@string/self_check_title" />
<fragment
android:id="@+id/checkinFragment"
android:name="org.microg.gms.ui.DeviceRegistrationFragment"
android:label="@string/service_name_checkin"
tools:layout="@layout/device_registration_fragment" />
<fragment
android:id="@+id/gcmFragment"
android:name="org.microg.gms.ui.PushNotificationFragment"
android:label="@string/service_name_mcs"
tools:layout="@layout/push_notification_fragment">
<action
android:id="@+id/openGcmAppDetails"
app:destination="@id/gcmAppFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
<action
android:id="@+id/openAllGcmApps"
app:destination="@id/gcmAllAppsFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
<action
android:id="@+id/openGcmAdvancedSettings"
app:destination="@id/gcmAdvancedFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
</fragment>
<fragment
android:id="@+id/gcmAllAppsFragment"
android:name="org.microg.gms.ui.PushNotificationAllAppsFragment"
android:label="Apps using push notifications">
<action
android:id="@+id/openGcmAppDetailsFromAll"
app:destination="@id/gcmAppFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
</fragment>
<fragment
android:id="@+id/gcmAppFragment"
android:name="org.microg.gms.ui.PushNotificationAppFragment"
android:label="@string/service_name_mcs"
tools:layout="@layout/push_notification_app_fragment">
<argument
android:name="package"
app:argType="string" />
</fragment>
<fragment
android:id="@+id/gcmAdvancedFragment"
android:name="org.microg.gms.ui.GcmAdvancedFragment"
android:label="@string/service_name_mcs" />
<fragment
android:id="@+id/safetyNetFragment"
android:name="org.microg.gms.ui.SafetyNetFragment"
android:label="@string/service_name_snet">
<action
android:id="@+id/openSafetyNetAdvancedSettings"
app:destination="@id/safetyNetAdvancedFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
</fragment>
<fragment
android:id="@+id/safetyNetAdvancedFragment"
android:name="org.microg.gms.ui.SafetyNetAdvancedFragment"
android:label="@string/service_name_snet" />
<fragment
android:id="@+id/googleMoreFragment"
android:name="org.microg.gms.ui.GoogleMoreFragment"
android:label="@string/gms_settings_name" />
<include app:graph="@navigation/nav_unlp" />
<fragment
android:id="@+id/aboutFragment"
android:name="org.microg.gms.ui.AboutFragment"
android:label="@string/prefcat_about" />
</navigation>

View File

@ -61,6 +61,8 @@ This can take a couple of minutes."</string>
<string name="service_status_enabled">Enabled</string>
<string name="service_status_automatic">Automatic</string>
<string name="service_status_manual">Manual</string>
<string name="service_status_enabled_short">On</string>
<string name="service_status_disabled_short">Off</string>
<string name="menu_advanced">Advanced</string>
<string name="list_no_item_none">None</string>

View File

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<Preference
android:selectable="false"
android:summary="@string/pref_checkin_enable_summary"/>
</PreferenceScreen>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2017, microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<PreferenceCategory
android:key="prefcat_device_registration_status"
android:layout="@layout/preference_category_no_label">
<Preference
android:key="pref_device_registration_status"
android:selectable="false"
android:title="Status"
tools:summary="Last registration: 13 hours ago" />
</PreferenceCategory>
<PreferenceCategory android:layout="@layout/preference_category_no_label">
<Preference
android:icon="@drawable/ic_info_outline"
android:selectable="false"
android:summary="@string/pref_checkin_enable_summary" />
</PreferenceCategory>
</PreferenceScreen>

View File

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="Messaging">
<SwitchPreference
android:defaultValue="true"
android:key="gcm_app_wake_for_delivery"
android:persistent="false"
android:summary="Start the app in background to receive the incoming push messages. Disabling this might delay message delivery up to the moment the app is started or cause complete message loss."
android:title="Start app on push message"/>
<Preference
android:selectable="false"
android:key="gcm_app_message_details"
android:summary="Messages: 1000 (37 MB)\nLast message: 22 min ago"/>
</PreferenceCategory>
<PreferenceCategory
android:title="Registration">
<SwitchPreference
android:defaultValue="true"
android:key="gcm_app_allow_register"
android:persistent="false"
android:summary="Allow the app to register for push notifications."
android:title="Allow registration"/>
<Preference
android:title="Unregister"
android:key="gcm_app_register_details"
android:summary="Registered since: 3 month ago"/>
</PreferenceCategory>
</PreferenceScreen>

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2020, microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:title="Push notifications">
<PreferenceCategory
android:key="prefcat_push_apps"
android:title="Apps using push notifications">
<Preference
android:enabled="false"
android:key="pref_push_apps_none"
android:title="No apps"
tools:isPreferenceVisible="true" />
<Preference
android:icon="@drawable/ic_expand_apps"
android:key="pref_push_apps_all"
android:order="5"
android:title="See all" />
</PreferenceCategory>
<PreferenceCategory
android:key="prefcat_push_status"
android:layout="@layout/preference_category_no_label">
<Preference
android:key="pref_push_status"
android:selectable="false"
android:title="Status"
tools:summary="Connected since 15 minutes ago" />
</PreferenceCategory>
<PreferenceCategory android:layout="@layout/preference_category_no_label">
<Preference
android:icon="@drawable/ic_info_outline"
android:selectable="false"
android:summary="@string/pref_gcm_enable_mcs_summary" />
</PreferenceCategory>
</PreferenceScreen>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2020, microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:title="Apps using push notifications">
<Preference
android:key="pref_push_apps_all_progress"
android:layout="@layout/preference_progress_bar"
app:allowDividerBelow="false" />
<PreferenceCategory
android:key="prefcat_push_apps_registered"
android:title="Registered apps"
app:isPreferenceVisible="false"
tools:isPreferenceVisible="true">
<Preference
android:enabled="false"
android:key="pref_push_apps_registered_none"
android:title="No apps"
app:isPreferenceVisible="false"
tools:isPreferenceVisible="true" />
</PreferenceCategory>
<PreferenceCategory
android:key="prefcat_push_apps_unregistered"
android:title="Unregistered apps"
app:isPreferenceVisible="false"
tools:isPreferenceVisible="true">
<Preference
android:enabled="false"
android:key="pref_push_apps_unregistered_none"
android:title="No apps"
app:isPreferenceVisible="false"
tools:isPreferenceVisible="true" />
</PreferenceCategory>
</PreferenceScreen>

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2020, microG Project Team
~ SPDX-License-Identifier: Apache-2.0
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<PreferenceCategory
android:key="prefcat_push_app_settings"
android:layout="@layout/preference_category_no_label">
<SwitchPreference
android:defaultValue="true"
android:key="pref_push_app_allow_register"
android:persistent="false"
android:summary="Allow the app to register for push notifications."
android:title="Allow registration" />
<SwitchPreference
android:defaultValue="true"
android:key="pref_push_app_wake_for_delivery"
android:persistent="false"
android:summary="Start the app while in background to receive the incoming push messages."
android:title="Start app on push message" />
</PreferenceCategory>
<PreferenceCategory
android:key="prefcat_push_app_unregister"
android:layout="@layout/preference_category_no_label">
<Preference
android:key="pref_push_app_unregister"
android:title="Unregister" />
</PreferenceCategory>
<PreferenceCategory android:layout="@layout/preference_category_no_label">
<Preference
android:key="pref_push_app_status"
android:selectable="false"
tools:summary="Messages: 1000 (37 MB)\nLast message: 22 min ago\nRegistered since: 3 month ago" />
</PreferenceCategory>
</PreferenceScreen>

View File

@ -16,16 +16,20 @@
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<org.microg.tools.ui.LongTextPreference
android:selectable="false"
android:icon="@drawable/ic_info_outline"
android:key="pref_snet_summary"
android:summary="@string/snet_intro"/>
<PreferenceCategory android:title="@string/prefcat_test">
android:selectable="false"
android:summary="@string/snet_intro" />
<PreferenceCategory
android:title="@string/prefcat_test"
app:isPreferenceVisible="false">
<Preference
android:enabled="false"
android:key="pref_snet_run_attest"
android:summary="Not yet available"
android:title="@string/pref_snet_testdrive_title"/>
android:title="@string/pref_snet_testdrive_title" />
</PreferenceCategory>
</PreferenceScreen>
</PreferenceScreen>

View File

@ -14,75 +14,59 @@
~ limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/prefcat_setup">
<org.microg.tools.ui.TintIconPreference
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<PreferenceCategory android:layout="@layout/preference_category_no_label">
<Preference
android:icon="@drawable/self_check"
android:summary="@string/self_check_desc"
android:title="@string/self_check_title">
<intent
android:targetClass="org.microg.gms.ui.SelfCheckFragment$AsActivity"
android:targetPackage="com.google.android.gms"/>
</org.microg.tools.ui.TintIconPreference>
android:targetPackage="com.google.android.gms" />
</Preference>
</PreferenceCategory>
<PreferenceCategory android:title="@string/prefcat_google_services">
<org.microg.tools.ui.TintIconPreference
android:icon="@drawable/add_account"
<Preference
android:icon="@drawable/ic_add_account"
android:summary="@string/pref_add_account_summary"
android:title="@string/pref_add_account_title">
<intent
android:targetClass="org.microg.gms.auth.login.LoginActivity"
android:targetPackage="com.google.android.gms"/>
</org.microg.tools.ui.TintIconPreference>
<org.microg.tools.ui.TintIconPreference
android:icon="@drawable/device_login"
android:targetPackage="com.google.android.gms" />
</Preference>
<Preference
android:icon="@drawable/ic_device_login"
android:key="pref_checkin"
android:title="@string/service_name_checkin">
<intent
android:targetClass="org.microg.gms.ui.CheckinFragment$AsActivity"
android:targetPackage="com.google.android.gms"/>
</org.microg.tools.ui.TintIconPreference>
<org.microg.tools.ui.TintIconPreference
android:icon="@drawable/gcm_bell"
android:title="@string/service_name_checkin" />
<Preference
android:icon="@drawable/ic_cloud_bell"
android:key="pref_gcm"
android:title="@string/service_name_mcs">
<intent
android:targetClass="org.microg.gms.ui.GcmFragment$AsActivity"
android:targetPackage="com.google.android.gms"/>
</org.microg.tools.ui.TintIconPreference>
<org.microg.tools.ui.TintIconPreference
android:icon="@drawable/certificate"
android:title="@string/service_name_mcs" />
<Preference
android:icon="@drawable/ic_certificate"
android:key="pref_snet"
android:title="@string/service_name_snet">
<intent
android:targetClass="org.microg.gms.ui.SafetyNetFragment$AsActivity"
android:targetPackage="com.google.android.gms"/>
</org.microg.tools.ui.TintIconPreference>
<org.microg.tools.ui.TintIconPreference
android:title="@string/service_name_snet" />
<Preference
android:icon="@drawable/dots_horizontal"
android:key="pref_google_more"
android:title="@string/pref_more_settings">
android:title="@string/pref_more_settings"
app:isPreferenceVisible="false">
<intent
android:targetClass="org.microg.gms.ui.GoogleMoreFragment$AsActivity"
android:targetPackage="com.google.android.gms"/>
</org.microg.tools.ui.TintIconPreference>
android:targetPackage="com.google.android.gms" />
</Preference>
</PreferenceCategory>
<PreferenceCategory android:title="@string/prefcat_configuration">
<org.microg.tools.ui.TintIconPreference
<PreferenceCategory android:layout="@layout/preference_category_no_label">
<Preference
android:icon="@drawable/ic_map_marker"
android:key="pref_unifiednlp"
android:title="UnifiedNlp">
<intent
android:targetClass="org.microg.nlp.ui.BackendSettingsActivity"
android:targetPackage="com.google.android.gms"/>
</org.microg.tools.ui.TintIconPreference>
android:title="@string/nlp_backends_title" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/prefcat_about">
<org.microg.tools.ui.TintIconPreference
<PreferenceCategory android:layout="@layout/preference_category_no_label">
<Preference
android:icon="@drawable/ic_info_outline"
android:key="pref_about"
android:title="@string/pref_about_title">
<intent
android:targetClass="org.microg.gms.ui.AboutFragment$AsActivity"
android:targetPackage="com.google.android.gms"/>
</org.microg.tools.ui.TintIconPreference>
android:title="@string/pref_about_title" />
</PreferenceCategory>
</PreferenceScreen>