diff --git a/play-services-base-core/src/main/java/org/microg/gms/common/ForegroundServiceContext.java b/play-services-base-core/src/main/java/org/microg/gms/common/ForegroundServiceContext.java index 50c3445f..3c2a7dbe 100644 --- a/play-services-base-core/src/main/java/org/microg/gms/common/ForegroundServiceContext.java +++ b/play-services-base-core/src/main/java/org/microg/gms/common/ForegroundServiceContext.java @@ -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(); } } diff --git a/play-services-core/build.gradle b/play-services-core/build.gradle index b55d79ef..8ee555cb 100644 --- a/play-services-core/build.gradle +++ b/play-services-core/build.gradle @@ -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' } } diff --git a/play-services-core/microg-ui-tools/src/main/java/org/microg/tools/ui/SwitchBarResourceSettingsFragment.java b/play-services-core/microg-ui-tools/src/main/java/org/microg/tools/ui/SwitchBarResourceSettingsFragment.java index 950ac8b2..b2b33e3b 100644 --- a/play-services-core/microg-ui-tools/src/main/java/org/microg/tools/ui/SwitchBarResourceSettingsFragment.java +++ b/play-services-core/microg-ui-tools/src/main/java/org/microg/tools/ui/SwitchBarResourceSettingsFragment.java @@ -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(); diff --git a/play-services-core/microg-ui-tools/src/main/res/drawable/self_check.xml b/play-services-core/microg-ui-tools/src/main/res/drawable/self_check.xml index 92b47890..714b5e11 100644 --- a/play-services-core/microg-ui-tools/src/main/res/drawable/self_check.xml +++ b/play-services-core/microg-ui-tools/src/main/res/drawable/self_check.xml @@ -16,12 +16,13 @@ --> + android:width="24dp" + android:height="24dp" + android:tint="?attr/colorAccent" + android:viewportWidth="24" + android:viewportHeight="24"> - \ No newline at end of file + diff --git a/play-services-core/src/main/AndroidManifest.xml b/play-services-core/src/main/AndroidManifest.xml index e6dee201..6b58afd7 100644 --- a/play-services-core/src/main/AndroidManifest.xml +++ b/play-services-core/src/main/AndroidManifest.xml @@ -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"> - + + @@ -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"> @@ -423,13 +423,18 @@ + + + android:targetActivity="org.microg.gms.ui.SettingsActivity"> @@ -452,52 +457,25 @@ - - - - - - - - + android:label="@string/pref_about_title" /> + android:label="@string/gms_settings_name" /> + android:label="@string/service_name_snet" /> + android:label="@string/service_name_snet" /> + android:label="@string/self_check_title" /> - + @@ -507,9 +485,7 @@ - + diff --git a/play-services-core/src/main/java/org/microg/gms/checkin/CheckinManager.java b/play-services-core/src/main/java/org/microg/gms/checkin/CheckinManager.java index 4b67bdd5..631db813 100644 --- a/play-services-core/src/main/java/org/microg/gms/checkin/CheckinManager.java +++ b/play-services-core/src/main/java/org/microg/gms/checkin/CheckinManager.java @@ -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 accounts = new ArrayList(); AccountManager accountManager = AccountManager.get(context); diff --git a/play-services-core/src/main/java/org/microg/gms/checkin/CheckinPrefs.java b/play-services-core/src/main/java/org/microg/gms/checkin/CheckinPrefs.java new file mode 100644 index 00000000..d18914b6 --- /dev/null +++ b/play-services-core/src/main/java/org/microg/gms/checkin/CheckinPrefs.java @@ -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; + } +} diff --git a/play-services-core/src/main/java/org/microg/gms/checkin/CheckinService.java b/play-services-core/src/main/java/org/microg/gms/checkin/CheckinService.java index fd31234a..1f775a93 100644 --- a/play-services-core/src/main/java/org/microg/gms/checkin/CheckinService.java +++ b/play-services-core/src/main/java/org/microg/gms/checkin/CheckinService.java @@ -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)); diff --git a/play-services-core/src/main/java/org/microg/gms/checkin/TriggerReceiver.java b/play-services-core/src/main/java/org/microg/gms/checkin/TriggerReceiver.java index b52a7133..123d76d3 100644 --- a/play-services-core/src/main/java/org/microg/gms/checkin/TriggerReceiver.java +++ b/play-services-core/src/main/java/org/microg/gms/checkin/TriggerReceiver.java @@ -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; diff --git a/play-services-core/src/main/java/org/microg/gms/snet/SafetyNetClientServiceImpl.java b/play-services-core/src/main/java/org/microg/gms/snet/SafetyNetClientServiceImpl.java index 848d1343..8cae71e7 100644 --- a/play-services-core/src/main/java/org/microg/gms/snet/SafetyNetClientServiceImpl.java +++ b/play-services-core/src/main/java/org/microg/gms/snet/SafetyNetClientServiceImpl.java @@ -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)); } diff --git a/play-services-core/src/main/java/org/microg/gms/ui/CheckinFragment.java b/play-services-core/src/main/java/org/microg/gms/ui/CheckinFragment.java deleted file mode 100644 index aee8642f..00000000 --- a/play-services-core/src/main/java/org/microg/gms/ui/CheckinFragment.java +++ /dev/null @@ -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(); - } - } -} diff --git a/play-services-core/src/main/java/org/microg/gms/ui/GcmAdvancedFragment.java b/play-services-core/src/main/java/org/microg/gms/ui/GcmAdvancedFragment.java index e7c846f2..0b66c013 100644 --- a/play-services-core/src/main/java/org/microg/gms/ui/GcmAdvancedFragment.java +++ b/play-services-core/src/main/java/org/microg/gms/ui/GcmAdvancedFragment.java @@ -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(); - } - } } diff --git a/play-services-core/src/main/java/org/microg/gms/ui/GcmAppFragment.java b/play-services-core/src/main/java/org/microg/gms/ui/GcmAppFragment.java deleted file mode 100644 index 232a2d65..00000000 --- a/play-services-core/src/main/java/org/microg/gms/ui/GcmAppFragment.java +++ /dev/null @@ -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 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 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 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; - } - } -} diff --git a/play-services-core/src/main/java/org/microg/gms/ui/GcmFragment.java b/play-services-core/src/main/java/org/microg/gms/ui/GcmFragment.java deleted file mode 100644 index 6c4ee0db..00000000 --- a/play-services-core/src/main/java/org/microg/gms/ui/GcmFragment.java +++ /dev/null @@ -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 prefs, PreferenceGroup container) { - // If there's some items to display, sort the items and add them to the container. - Collections.sort(prefs, new Comparator() { - @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 list = database.getAppList(); - if (!list.isEmpty()) { - List 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 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(); - } - } -} \ No newline at end of file diff --git a/play-services-core/src/main/java/org/microg/gms/ui/SafetyNetFragment.java b/play-services-core/src/main/java/org/microg/gms/ui/SafetyNetFragment.java deleted file mode 100644 index 3756aff8..00000000 --- a/play-services-core/src/main/java/org/microg/gms/ui/SafetyNetFragment.java +++ /dev/null @@ -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(); - } - } -} \ No newline at end of file diff --git a/play-services-core/src/main/java/org/microg/gms/ui/SettingsActivity.java b/play-services-core/src/main/java/org/microg/gms/ui/SettingsActivity.java index 965872ff..05befb86 100644 --- a/play-services-core/src/main/java/org/microg/gms/ui/SettingsActivity.java +++ b/play-services-core/src/main/java/org/microg/gms/ui/SettingsActivity.java @@ -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(); } } diff --git a/play-services-core/src/main/java/org/microg/gms/ui/SettingsDashboardActivity.java b/play-services-core/src/main/java/org/microg/gms/ui/SettingsDashboardActivity.java new file mode 100644 index 00000000..f3b62c1d --- /dev/null +++ b/play-services-core/src/main/java/org/microg/gms/ui/SettingsDashboardActivity.java @@ -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(); + } + +} diff --git a/play-services-core/src/main/java/org/microg/gms/ui/SettingsFragment.java b/play-services-core/src/main/java/org/microg/gms/ui/SettingsFragment.java new file mode 100644 index 00000000..482152e6 --- /dev/null +++ b/play-services-core/src/main/java/org/microg/gms/ui/SettingsFragment.java @@ -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; + }); + } +} diff --git a/play-services-core/src/main/java/org/microg/gms/ui/UnifiedBackendDetailsActivity.java b/play-services-core/src/main/java/org/microg/gms/ui/UnifiedBackendDetailsActivity.java deleted file mode 100644 index 6f786653..00000000 --- a/play-services-core/src/main/java/org/microg/gms/ui/UnifiedBackendDetailsActivity.java +++ /dev/null @@ -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(); - } -} diff --git a/play-services-core/src/main/java/org/microg/gms/ui/UnifiedBackendListActivity.java b/play-services-core/src/main/java/org/microg/gms/ui/UnifiedBackendListActivity.java deleted file mode 100644 index 7bfd0aff..00000000 --- a/play-services-core/src/main/java/org/microg/gms/ui/UnifiedBackendListActivity.java +++ /dev/null @@ -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(); - } -} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/AppIconPreference.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/AppIconPreference.kt new file mode 100644 index 00000000..97bcca1d --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/AppIconPreference.kt @@ -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() + } + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/DeviceRegistrationFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/DeviceRegistrationFragment.kt new file mode 100644 index 00000000..68f30f72 --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/DeviceRegistrationFragment.kt @@ -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 + } + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/DeviceRegistrationPreferencesFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/DeviceRegistrationPreferencesFragment.kt new file mode 100644 index 00000000..9bc63cfe --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/DeviceRegistrationPreferencesFragment.kt @@ -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 + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/PreferenceSwitchBar.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/PreferenceSwitchBar.kt new file mode 100644 index 00000000..b66f1119 --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/PreferenceSwitchBar.kt @@ -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) +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationAllAppsFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationAllAppsFragment.kt new file mode 100644 index 00000000..a55b007d --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationAllAppsFragment.kt @@ -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 + } + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationAppFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationAppFragment.kt new file mode 100644 index 00000000..5699ec07 --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationAppFragment.kt @@ -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() +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationAppPreferencesFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationAppPreferencesFragment.kt new file mode 100644 index 00000000..b327349e --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationAppPreferencesFragment.kt @@ -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() + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationFragment.kt new file mode 100644 index 00000000..fcdc6965 --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationFragment.kt @@ -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 + } +} + diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationPreferencesFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationPreferencesFragment.kt new file mode 100644 index 00000000..f855ea54 --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/PushNotificationPreferencesFragment.kt @@ -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 + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetFragment.kt new file mode 100644 index 00000000..b611a1ac --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetFragment.kt @@ -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 + } +} diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetPreferencesFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetPreferencesFragment.kt new file mode 100644 index 00000000..2a4b4ab2 --- /dev/null +++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/SafetyNetPreferencesFragment.kt @@ -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) + } +} diff --git a/play-services-core/src/main/res/drawable-hdpi/ic_map_marker.png b/play-services-core/src/main/res/drawable-hdpi/ic_map_marker.png deleted file mode 100644 index 58c9a14b..00000000 Binary files a/play-services-core/src/main/res/drawable-hdpi/ic_map_marker.png and /dev/null differ diff --git a/play-services-core/src/main/res/drawable-ldpi/add_account.png b/play-services-core/src/main/res/drawable-ldpi/add_account.png deleted file mode 100644 index c84ada96..00000000 Binary files a/play-services-core/src/main/res/drawable-ldpi/add_account.png and /dev/null differ diff --git a/play-services-core/src/main/res/drawable-mdpi/add_account.png b/play-services-core/src/main/res/drawable-mdpi/add_account.png deleted file mode 100644 index 7cbdff98..00000000 Binary files a/play-services-core/src/main/res/drawable-mdpi/add_account.png and /dev/null differ diff --git a/play-services-core/src/main/res/drawable-mdpi/ic_map_marker.png b/play-services-core/src/main/res/drawable-mdpi/ic_map_marker.png deleted file mode 100644 index f66ef501..00000000 Binary files a/play-services-core/src/main/res/drawable-mdpi/ic_map_marker.png and /dev/null differ diff --git a/play-services-core/src/main/res/drawable-xhdpi/add_account.png b/play-services-core/src/main/res/drawable-xhdpi/add_account.png deleted file mode 100644 index bf14e0a7..00000000 Binary files a/play-services-core/src/main/res/drawable-xhdpi/add_account.png and /dev/null differ diff --git a/play-services-core/src/main/res/drawable-xhdpi/ic_map_marker.png b/play-services-core/src/main/res/drawable-xhdpi/ic_map_marker.png deleted file mode 100644 index 00d32aa4..00000000 Binary files a/play-services-core/src/main/res/drawable-xhdpi/ic_map_marker.png and /dev/null differ diff --git a/play-services-core/src/main/res/drawable-xxhdpi/add_account.png b/play-services-core/src/main/res/drawable-xxhdpi/add_account.png deleted file mode 100644 index 53264c28..00000000 Binary files a/play-services-core/src/main/res/drawable-xxhdpi/add_account.png and /dev/null differ diff --git a/play-services-core/src/main/res/drawable-xxhdpi/ic_map_marker.png b/play-services-core/src/main/res/drawable-xxhdpi/ic_map_marker.png deleted file mode 100644 index 78a7dbe2..00000000 Binary files a/play-services-core/src/main/res/drawable-xxhdpi/ic_map_marker.png and /dev/null differ diff --git a/play-services-core/src/main/res/drawable-xxxhdpi/add_account.png b/play-services-core/src/main/res/drawable-xxxhdpi/add_account.png deleted file mode 100644 index a03e2eaa..00000000 Binary files a/play-services-core/src/main/res/drawable-xxxhdpi/add_account.png and /dev/null differ diff --git a/play-services-core/src/main/res/drawable-xxxhdpi/ic_map_marker.png b/play-services-core/src/main/res/drawable-xxxhdpi/ic_map_marker.png deleted file mode 100644 index 66945c5a..00000000 Binary files a/play-services-core/src/main/res/drawable-xxxhdpi/ic_map_marker.png and /dev/null differ diff --git a/play-services-core/src/main/res/drawable/dots_horizontal.xml b/play-services-core/src/main/res/drawable/dots_horizontal.xml index 5c71aeb7..4110aed7 100644 --- a/play-services-core/src/main/res/drawable/dots_horizontal.xml +++ b/play-services-core/src/main/res/drawable/dots_horizontal.xml @@ -1,13 +1,14 @@ + android:width="24dp" + android:height="24dp" + android:tint="?attr/colorControlNormal" + android:viewportWidth="24" + android:viewportHeight="24"> - \ No newline at end of file + diff --git a/play-services-core/src/main/res/drawable-anydpi-v21/add_account.xml b/play-services-core/src/main/res/drawable/ic_add_account.xml similarity index 92% rename from play-services-core/src/main/res/drawable-anydpi-v21/add_account.xml rename to play-services-core/src/main/res/drawable/ic_add_account.xml index aa8b898a..1ff91a0e 100644 --- a/play-services-core/src/main/res/drawable-anydpi-v21/add_account.xml +++ b/play-services-core/src/main/res/drawable/ic_add_account.xml @@ -2,6 +2,7 @@ @@ -10,4 +11,4 @@ - \ No newline at end of file + diff --git a/play-services-core/src/main/res/drawable/certificate.xml b/play-services-core/src/main/res/drawable/ic_certificate.xml similarity index 71% rename from play-services-core/src/main/res/drawable/certificate.xml rename to play-services-core/src/main/res/drawable/ic_certificate.xml index 6091e969..780e4db4 100644 --- a/play-services-core/src/main/res/drawable/certificate.xml +++ b/play-services-core/src/main/res/drawable/ic_certificate.xml @@ -1,13 +1,14 @@ + android:width="24dp" + android:height="24dp" + android:tint="?attr/colorAccent" + android:viewportWidth="24" + android:viewportHeight="24"> - \ No newline at end of file + diff --git a/play-services-core/src/main/res/drawable/gcm_bell.xml b/play-services-core/src/main/res/drawable/ic_cloud_bell.xml similarity index 79% rename from play-services-core/src/main/res/drawable/gcm_bell.xml rename to play-services-core/src/main/res/drawable/ic_cloud_bell.xml index 89a1cae4..0f41c719 100644 --- a/play-services-core/src/main/res/drawable/gcm_bell.xml +++ b/play-services-core/src/main/res/drawable/ic_cloud_bell.xml @@ -1,11 +1,12 @@ + android:width="24dp" + android:height="24dp" + android:tint="?attr/colorAccent" + android:viewportWidth="24" + android:viewportHeight="24"> - \ No newline at end of file + 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" /> + diff --git a/play-services-core/src/main/res/drawable/device_login.xml b/play-services-core/src/main/res/drawable/ic_device_login.xml similarity index 58% rename from play-services-core/src/main/res/drawable/device_login.xml rename to play-services-core/src/main/res/drawable/ic_device_login.xml index f1a4e1e4..c0bce50c 100644 --- a/play-services-core/src/main/res/drawable/device_login.xml +++ b/play-services-core/src/main/res/drawable/ic_device_login.xml @@ -1,11 +1,12 @@ + android:width="24dp" + android:height="24dp" + android:tint="?attr/colorAccent" + android:viewportWidth="24" + android:viewportHeight="24"> - \ No newline at end of file + 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" /> + diff --git a/play-services-core/src/main/res/drawable/ic_expand_apps.xml b/play-services-core/src/main/res/drawable/ic_expand_apps.xml new file mode 100644 index 00000000..20634f05 --- /dev/null +++ b/play-services-core/src/main/res/drawable/ic_expand_apps.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/play-services-core/src/main/res/drawable/ic_info_outline.xml b/play-services-core/src/main/res/drawable/ic_info_outline.xml new file mode 100644 index 00000000..8e049cce --- /dev/null +++ b/play-services-core/src/main/res/drawable/ic_info_outline.xml @@ -0,0 +1,17 @@ + + + + + + diff --git a/play-services-core/src/main/res/drawable/ic_map_marker.xml b/play-services-core/src/main/res/drawable/ic_map_marker.xml new file mode 100644 index 00000000..b97f8b8d --- /dev/null +++ b/play-services-core/src/main/res/drawable/ic_map_marker.xml @@ -0,0 +1,17 @@ + + + + + + diff --git a/play-services-core/src/main/res/layout/ask_gcm.xml b/play-services-core/src/main/res/layout/ask_gcm.xml index 9d3e8be8..a5c20212 100644 --- a/play-services-core/src/main/res/layout/ask_gcm.xml +++ b/play-services-core/src/main/res/layout/ask_gcm.xml @@ -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"> diff --git a/play-services-core/src/main/res/layout/device_registration_fragment.xml b/play-services-core/src/main/res/layout/device_registration_fragment.xml new file mode 100644 index 00000000..0f0648dc --- /dev/null +++ b/play-services-core/src/main/res/layout/device_registration_fragment.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + diff --git a/play-services-core/src/main/res/layout/preference_category_no_label.xml b/play-services-core/src/main/res/layout/preference_category_no_label.xml new file mode 100644 index 00000000..31b8b654 --- /dev/null +++ b/play-services-core/src/main/res/layout/preference_category_no_label.xml @@ -0,0 +1,9 @@ + + + + diff --git a/play-services-core/src/main/res/layout/preference_progress_bar.xml b/play-services-core/src/main/res/layout/preference_progress_bar.xml new file mode 100644 index 00000000..bd0eb7e0 --- /dev/null +++ b/play-services-core/src/main/res/layout/preference_progress_bar.xml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/play-services-core/src/main/res/layout/preference_switch_bar.xml b/play-services-core/src/main/res/layout/preference_switch_bar.xml new file mode 100644 index 00000000..08ad6530 --- /dev/null +++ b/play-services-core/src/main/res/layout/preference_switch_bar.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/play-services-core/src/main/res/layout/push_notification_app_fragment.xml b/play-services-core/src/main/res/layout/push_notification_app_fragment.xml new file mode 100644 index 00000000..4f63f961 --- /dev/null +++ b/play-services-core/src/main/res/layout/push_notification_app_fragment.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/play-services-core/src/main/res/layout/push_notification_fragment.xml b/play-services-core/src/main/res/layout/push_notification_fragment.xml new file mode 100644 index 00000000..e9611b83 --- /dev/null +++ b/play-services-core/src/main/res/layout/push_notification_fragment.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/play-services-core/src/main/res/layout/safety_net_fragment.xml b/play-services-core/src/main/res/layout/safety_net_fragment.xml new file mode 100644 index 00000000..e97378ae --- /dev/null +++ b/play-services-core/src/main/res/layout/safety_net_fragment.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/play-services-core/src/main/res/layout/settings_root_activity.xml b/play-services-core/src/main/res/layout/settings_root_activity.xml new file mode 100644 index 00000000..a592e38d --- /dev/null +++ b/play-services-core/src/main/res/layout/settings_root_activity.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/play-services-core/src/main/res/navigation/nav_settings.xml b/play-services-core/src/main/res/navigation/nav_settings.xml new file mode 100644 index 00000000..4a7a5246 --- /dev/null +++ b/play-services-core/src/main/res/navigation/nav_settings.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/play-services-core/src/main/res/values/strings.xml b/play-services-core/src/main/res/values/strings.xml index 66b626ce..cfc7fd85 100644 --- a/play-services-core/src/main/res/values/strings.xml +++ b/play-services-core/src/main/res/values/strings.xml @@ -61,6 +61,8 @@ This can take a couple of minutes." Enabled Automatic Manual + On + Off Advanced None diff --git a/play-services-core/src/main/res/xml/preferences_checkin.xml b/play-services-core/src/main/res/xml/preferences_checkin.xml deleted file mode 100644 index 45c982a7..00000000 --- a/play-services-core/src/main/res/xml/preferences_checkin.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/play-services-core/src/main/res/xml/preferences_device_registration.xml b/play-services-core/src/main/res/xml/preferences_device_registration.xml new file mode 100644 index 00000000..886ec0b7 --- /dev/null +++ b/play-services-core/src/main/res/xml/preferences_device_registration.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + diff --git a/play-services-core/src/main/res/xml/preferences_gcm_app_detail.xml b/play-services-core/src/main/res/xml/preferences_gcm_app_detail.xml deleted file mode 100644 index 3dc8186a..00000000 --- a/play-services-core/src/main/res/xml/preferences_gcm_app_detail.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/play-services-core/src/main/res/xml/preferences_push_notifications.xml b/play-services-core/src/main/res/xml/preferences_push_notifications.xml new file mode 100644 index 00000000..06c8fb8a --- /dev/null +++ b/play-services-core/src/main/res/xml/preferences_push_notifications.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + diff --git a/play-services-core/src/main/res/xml/preferences_push_notifications_all_apps.xml b/play-services-core/src/main/res/xml/preferences_push_notifications_all_apps.xml new file mode 100644 index 00000000..6c0f2d36 --- /dev/null +++ b/play-services-core/src/main/res/xml/preferences_push_notifications_all_apps.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + diff --git a/play-services-core/src/main/res/xml/preferences_push_notifications_app.xml b/play-services-core/src/main/res/xml/preferences_push_notifications_app.xml new file mode 100644 index 00000000..fad13b22 --- /dev/null +++ b/play-services-core/src/main/res/xml/preferences_push_notifications_app.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/play-services-core/src/main/res/xml/preferences_snet.xml b/play-services-core/src/main/res/xml/preferences_safetynet.xml similarity index 70% rename from play-services-core/src/main/res/xml/preferences_snet.xml rename to play-services-core/src/main/res/xml/preferences_safetynet.xml index 8a60cf3e..e0a2ed84 100644 --- a/play-services-core/src/main/res/xml/preferences_snet.xml +++ b/play-services-core/src/main/res/xml/preferences_safetynet.xml @@ -16,16 +16,20 @@ --> + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> - + android:selectable="false" + android:summary="@string/snet_intro" /> + + android:title="@string/pref_snet_testdrive_title" /> - \ No newline at end of file + diff --git a/play-services-core/src/main/res/xml/preferences_start.xml b/play-services-core/src/main/res/xml/preferences_start.xml index c51f7dc5..b48d5b7a 100644 --- a/play-services-core/src/main/res/xml/preferences_start.xml +++ b/play-services-core/src/main/res/xml/preferences_start.xml @@ -14,75 +14,59 @@ ~ limitations under the License. --> - - - + + - + android:targetPackage="com.google.android.gms" /> + - - - + + - - - + - - - + - - - + + android:title="@string/pref_more_settings" + app:isPreferenceVisible="false"> - + android:targetPackage="com.google.android.gms" /> + - - + - - + android:title="@string/nlp_backends_title" /> - - + - - + android:title="@string/pref_about_title" />