From 6067c150852f420207e9ce0b543a75931cc2ae93 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Mon, 15 Jan 2018 16:54:35 -0200 Subject: [PATCH] Implement App Hiding This commit allows F-Droid to hide itself from the laucher. It can be hidden either as response to a panic trigger or as a manual action by long pressing the floating search button. The latter needs to be explicitly enabled in the settings. Once hidden, a semi-functional fake calculator app appears in the launcher that can be used to bring F-Droid back by entering a pre-defined PIN. --- app/src/main/AndroidManifest.xml | 14 + .../java/org/fdroid/fdroid/FDroidApp.java | 3 +- .../java/org/fdroid/fdroid/Preferences.java | 7 + .../installer/InstallManagerService.java | 27 +- .../views/hiding/CalculatorActivity.java | 152 +++++++++ .../fdroid/views/hiding/HidingManager.java | 123 ++++++++ .../views/main/CategoriesViewBinder.java | 13 + .../fdroid/views/main/WhatsNewViewBinder.java | 14 + .../views/panic/PanicPreferencesFragment.java | 40 ++- .../views/panic/PanicResponderActivity.java | 3 +- .../main/res/layout/activity_calculator.xml | 292 ++++++++++++++++++ app/src/main/res/layout/dialog_app_hiding.xml | 60 ++++ .../mipmap-hdpi/ic_calculator_launcher.png | Bin 0 -> 3439 bytes .../mipmap-mdpi/ic_calculator_launcher.png | Bin 0 -> 2104 bytes .../mipmap-xhdpi/ic_calculator_launcher.png | Bin 0 -> 4940 bytes .../mipmap-xxhdpi/ic_calculator_launcher.png | Bin 0 -> 8599 bytes .../mipmap-xxxhdpi/ic_calculator_launcher.png | Bin 0 -> 12860 bytes app/src/main/res/values/attrs.xml | 3 + app/src/main/res/values/strings.xml | 9 + app/src/main/res/xml/preferences.xml | 6 + 20 files changed, 755 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/org/fdroid/fdroid/views/hiding/CalculatorActivity.java create mode 100644 app/src/main/java/org/fdroid/fdroid/views/hiding/HidingManager.java create mode 100644 app/src/main/res/layout/activity_calculator.xml create mode 100644 app/src/main/res/layout/dialog_app_hiding.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_calculator_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_calculator_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_calculator_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_calculator_launcher.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_calculator_launcher.png diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fa543d83c..f0cee129e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -279,6 +279,8 @@ android:name=".AppUpdateStatusService" android:exported="false" /> + + + + + + + + + diff --git a/app/src/main/java/org/fdroid/fdroid/FDroidApp.java b/app/src/main/java/org/fdroid/fdroid/FDroidApp.java index bbf9d5c4e..a1fade17c 100644 --- a/app/src/main/java/org/fdroid/fdroid/FDroidApp.java +++ b/app/src/main/java/org/fdroid/fdroid/FDroidApp.java @@ -62,6 +62,7 @@ import org.fdroid.fdroid.installer.ApkFileProvider; import org.fdroid.fdroid.installer.InstallHistoryService; import org.fdroid.fdroid.net.ImageLoaderForUIL; import org.fdroid.fdroid.net.WifiStateChangeService; +import org.fdroid.fdroid.views.hiding.HidingManager; import java.io.IOException; import java.net.URL; @@ -286,7 +287,7 @@ public class FDroidApp extends Application { Languages.setLanguage(this); ACRA.init(this); - if (isAcraProcess()) { + if (isAcraProcess() || HidingManager.isHidden(this)) { return; } diff --git a/app/src/main/java/org/fdroid/fdroid/Preferences.java b/app/src/main/java/org/fdroid/fdroid/Preferences.java index 422d2f989..53b604cb6 100644 --- a/app/src/main/java/org/fdroid/fdroid/Preferences.java +++ b/app/src/main/java/org/fdroid/fdroid/Preferences.java @@ -42,6 +42,7 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh Resources res = context.getResources(); defaultPreventScreenshots = res.getBoolean(R.bool.defaultPreventScreenshots); defaultPanicExit = res.getBoolean(R.bool.defaultPanicExit); + defaultHideOnLongPressSearch = res.getBoolean(R.bool.defaultHideOnLongPressSearch); } public static final String PREF_UPD_INTERVAL = "updateInterval"; @@ -73,6 +74,7 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh public static final String PREF_PREVENT_SCREENSHOTS = "preventScreenshots"; public static final String PREF_PANIC_EXIT = "pref_panic_exit"; public static final String PREF_PANIC_HIDE = "pref_panic_hide"; + public static final String PREF_HIDE_ON_LONG_PRESS_SEARCH = "hideOnLongPressSearch"; private static final boolean DEFAULT_ROOTED = true; private static final boolean DEFAULT_HIDE_ANTI_FEATURE_APPS = false; @@ -94,6 +96,7 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh private static final boolean DEFAULT_POST_PRIVILEGED_INSTALL = false; private final boolean defaultPreventScreenshots; private final boolean defaultPanicExit; + private final boolean defaultHideOnLongPressSearch; public enum Theme { light, @@ -335,6 +338,10 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh return preferences.getBoolean(PREF_PANIC_HIDE, false); } + public boolean hideOnLongPressSearch() { + return preferences.getBoolean(PREF_HIDE_ON_LONG_PRESS_SEARCH, defaultHideOnLongPressSearch); + } + /** * This is cached as it is called several times inside app list adapters. * Providing it here means the shared preferences file only needs to be diff --git a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java index 4acf5fcda..654bbfc4f 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/InstallManagerService.java @@ -85,6 +85,8 @@ public class InstallManagerService extends Service { private LocalBroadcastManager localBroadcastManager; private AppUpdateStatusManager appUpdateStatusManager; + private BroadcastReceiver broadcastReceiver; + private boolean running = false; /** * This service does not use binding, so no need to implement this method @@ -101,9 +103,10 @@ public class InstallManagerService extends Service { localBroadcastManager = LocalBroadcastManager.getInstance(this); appUpdateStatusManager = AppUpdateStatusManager.getInstance(this); - BroadcastReceiver br = new BroadcastReceiver() { + broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { + if (intent.getData() == null) return; String packageName = intent.getData().getSchemeSpecificPart(); for (AppUpdateStatusManager.AppUpdateStatus status : appUpdateStatusManager.getByPackageName(packageName)) { appUpdateStatusManager.updateApk(status.getUniqueKey(), AppUpdateStatusManager.Status.Installed, null); @@ -113,7 +116,15 @@ public class InstallManagerService extends Service { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); intentFilter.addDataScheme("package"); - registerReceiver(br, intentFilter); + registerReceiver(broadcastReceiver, intentFilter); + running = true; + } + + @Override + public void onDestroy() { + running = false; + unregisterReceiver(broadcastReceiver); + super.onDestroy(); } @Override @@ -218,6 +229,10 @@ public class InstallManagerService extends Service { final BroadcastReceiver downloadReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { + if (!running) { + localBroadcastManager.unregisterReceiver(this); + return; + } String action = intent.getAction(); if (Downloader.ACTION_STARTED.equals(action)) { Utils.debugLog(TAG, action + " " + intent); @@ -273,6 +288,10 @@ public class InstallManagerService extends Service { BroadcastReceiver downloadReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { + if (!running) { + localBroadcastManager.unregisterReceiver(this); + return; + } Uri downloadUri = intent.getData(); String urlString = downloadUri.toString(); long repoId = intent.getLongExtra(Downloader.EXTRA_REPO_ID, 0); @@ -351,6 +370,10 @@ public class InstallManagerService extends Service { BroadcastReceiver installReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { + if (!running) { + localBroadcastManager.unregisterReceiver(this); + return; + } String downloadUrl = intent.getDataString(); Apk apk; switch (intent.getAction()) { diff --git a/app/src/main/java/org/fdroid/fdroid/views/hiding/CalculatorActivity.java b/app/src/main/java/org/fdroid/fdroid/views/hiding/CalculatorActivity.java new file mode 100644 index 000000000..508f3f348 --- /dev/null +++ b/app/src/main/java/org/fdroid/fdroid/views/hiding/CalculatorActivity.java @@ -0,0 +1,152 @@ +package org.fdroid.fdroid.views.hiding; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; + +import org.fdroid.fdroid.R; + +import java.util.regex.Pattern; + +/** + * A very hacky calculator which is barely functional. + * It is just meant to pass a very casual inspection. + */ +public class CalculatorActivity extends AppCompatActivity { + + // binary operators + private static final String TIMES = "×"; + private static final String DIVIDED = "÷"; + private static final String PLUS = "+"; + private static final String MINUS = "-"; + + // unary operators + private static final String PERCENT = "%"; + + private @Nullable String lastOp; + + // views + private TextView textView; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_calculator); + + Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); + setSupportActionBar(toolbar); + + textView = (TextView) findViewById(R.id.textView); + } + + public void ce(View view) { + // clear display + textView.setText(null); + } + + public void c(View view) { + // clear last character + if (textView.length() > 0) { + String text = textView.getText().toString(); + textView.setText(text.substring(0, text.length() - 1)); + } + } + + public void number(View view) { + String number = ((Button) view).getText().toString(); + String newNumber = String.format("%s%s", textView.getText(), number); + // FIXME don't allow multiple commas + String pin = String.valueOf(HidingManager.getUnhidePin(this)); + if (newNumber.equals(pin)) { + // correct PIN was entered, show app launcher again + HidingManager.show(this); + } + textView.setText(newNumber); + } + + public void op(View view) { + String text = textView.getText().toString(); + + if (text.length() == 0) { + return; + } else if (containsBinaryOperator(String.valueOf(text.charAt(text.length() - 1)))) { + // last character was already binary operator, ignore + return; + } + + String op = ((Button) view).getText().toString(); + if (containsBinaryOperator(op)) { + // remember binary operator + lastOp = op; + // add binary operator to display + textView.setText(String.format("%s%s", text, op)); + } else if (op.equals(PERCENT)) { + double result; + try { + result = Double.valueOf(eval(text)); + } catch (NumberFormatException e) { + result = 0; + } + textView.setText(toString(result / 100)); + } else if ("=".equals(op)) { + textView.setText(eval(text)); + } else { + Toast.makeText(this, "Error: Unknown Operation", Toast.LENGTH_SHORT).show(); + } + } + + private String eval(String s) { + if (lastOp != null && s.contains(lastOp)) { + // remember and reset binary operator + String op = lastOp; + lastOp = null; + + // extract binary operation + String[] parts = s.split(Pattern.quote(op)); + double left; + double right; + try { + left = Double.valueOf(parts[0]); + right = Double.valueOf(parts[1]); + } catch (NumberFormatException e) { + return ""; + } + + // evaluate binary operation + switch (op) { + case PLUS: + return toString(left + right); + case MINUS: + return toString(left - right); + case TIMES: + return toString(left * right); + case DIVIDED: + if (right == 0) return ""; + return toString(left / right); + default: + Toast.makeText(this, "Error: Unknown Operation", Toast.LENGTH_SHORT).show(); + return s; + } + } else { + return s; + } + } + + private boolean containsBinaryOperator(String s) { + return s.contains(TIMES) || s.contains(DIVIDED) || s.contains(PLUS) || s.contains(MINUS); + } + + private String toString(double d) { + String s = String.valueOf(d); + if (s.length() > 2 && s.endsWith(".0")) { + return s.substring(0, s.length() - 2); + } + return s; + } + +} diff --git a/app/src/main/java/org/fdroid/fdroid/views/hiding/HidingManager.java b/app/src/main/java/org/fdroid/fdroid/views/hiding/HidingManager.java new file mode 100644 index 000000000..2d8f90184 --- /dev/null +++ b/app/src/main/java/org/fdroid/fdroid/views/hiding/HidingManager.java @@ -0,0 +1,123 @@ +package org.fdroid.fdroid.views.hiding; + +import android.content.ComponentName; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.support.v4.app.NotificationManagerCompat; +import android.support.v7.app.AlertDialog; + +import org.fdroid.fdroid.AppUpdateStatusService; +import org.fdroid.fdroid.BuildConfig; +import org.fdroid.fdroid.CleanCacheService; +import org.fdroid.fdroid.R; +import org.fdroid.fdroid.UpdateService; +import org.fdroid.fdroid.data.InstalledAppProviderService; +import org.fdroid.fdroid.installer.InstallHistoryService; +import org.fdroid.fdroid.installer.InstallManagerService; +import org.fdroid.fdroid.installer.InstallerService; +import org.fdroid.fdroid.localrepo.CacheSwapAppsService; +import org.fdroid.fdroid.localrepo.SwapService; +import org.fdroid.fdroid.net.DownloaderService; +import org.fdroid.fdroid.net.WifiStateChangeService; +import org.fdroid.fdroid.views.main.MainActivity; + +/** + * This class is encapsulating all methods related to hiding the app from the launcher + * and restoring it. + * + * It can tell you whether the app is hidden, what the PIN to restore is + * and show confirmation dialogs before hiding. + */ +public class HidingManager { + + private static final ComponentName LAUNCHER_NAME = + new ComponentName(BuildConfig.APPLICATION_ID, MainActivity.class.getName()); + + private static final ComponentName CALCULATOR_NAME = + new ComponentName(BuildConfig.APPLICATION_ID, CalculatorActivity.class.getName()); + + public static int getUnhidePin(Context context) { + return context.getResources().getInteger(R.integer.unhidePin); + } + + public static boolean isHidden(Context context) { + PackageManager pm = context.getPackageManager(); + int state = pm.getComponentEnabledSetting(LAUNCHER_NAME); + return state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED; + } + + public static void showHideDialog(final Context context) { + String appName = context.getString(R.string.app_name); + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle(context.getString(R.string.hiding_dialog_title, appName)); + builder.setMessage(context.getString(R.string.hiding_dialog_message, appName, + HidingManager.getUnhidePin(context), context.getString(R.string.hiding_calculator))); + builder.setPositiveButton(context.getString(R.string.panic_hide_title, appName), + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + hide(context); + } + }); + builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + dialogInterface.cancel(); + } + }); + builder.setView(R.layout.dialog_app_hiding); + builder.create().show(); + } + + public static void hide(Context context) { + stopServices(context); + removeNotifications(context); + + PackageManager pm = context.getPackageManager(); + // hide launcher icon + pm.setComponentEnabledSetting(LAUNCHER_NAME, + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP); + // show calculator icon + pm.setComponentEnabledSetting(CALCULATOR_NAME, + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, + 0); // please kill app (faster and safer, because it also stops services) + } + + public static void show(Context context) { + PackageManager pm = context.getPackageManager(); + // show launcher icon + pm.setComponentEnabledSetting(LAUNCHER_NAME, + PackageManager.COMPONENT_ENABLED_STATE_ENABLED, + PackageManager.DONT_KILL_APP); + // hide calculator icon + pm.setComponentEnabledSetting(CALCULATOR_NAME, + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + 0); // please kill app (faster) + } + + private static void removeNotifications(Context context) { + NotificationManagerCompat nm = NotificationManagerCompat.from(context); + nm.cancelAll(); + } + + /** + * Stops all running services, so nothing can pop up and reveal F-Droid's existence on the system + */ + private static void stopServices(Context context) { + context.stopService(new Intent(context, UpdateService.class)); + context.stopService(new Intent(context, DownloaderService.class)); + context.stopService(new Intent(context, InstallerService.class)); + context.stopService(new Intent(context, CleanCacheService.class)); + context.stopService(new Intent(context, WifiStateChangeService.class)); + context.stopService(new Intent(context, SwapService.class)); + context.stopService(new Intent(context, InstallManagerService.class)); + context.stopService(new Intent(context, InstallHistoryService.class)); + context.stopService(new Intent(context, CacheSwapAppsService.class)); + context.stopService(new Intent(context, InstalledAppProviderService.class)); + context.stopService(new Intent(context, AppUpdateStatusService.class)); + } + +} diff --git a/app/src/main/java/org/fdroid/fdroid/views/main/CategoriesViewBinder.java b/app/src/main/java/org/fdroid/fdroid/views/main/CategoriesViewBinder.java index bcc0bbdff..dd476de05 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/main/CategoriesViewBinder.java +++ b/app/src/main/java/org/fdroid/fdroid/views/main/CategoriesViewBinder.java @@ -15,6 +15,7 @@ import android.view.View; import android.widget.FrameLayout; import android.widget.TextView; +import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.R; import org.fdroid.fdroid.UpdateService; import org.fdroid.fdroid.data.CategoryProvider; @@ -22,6 +23,7 @@ import org.fdroid.fdroid.data.Schema; import org.fdroid.fdroid.views.apps.AppListActivity; import org.fdroid.fdroid.views.categories.CategoryAdapter; import org.fdroid.fdroid.views.categories.CategoryController; +import org.fdroid.fdroid.views.hiding.HidingManager; import java.util.ArrayList; import java.util.Collections; @@ -73,6 +75,17 @@ class CategoriesViewBinder implements LoaderManager.LoaderCallbacks { activity.startActivity(new Intent(activity, AppListActivity.class)); } }); + searchFab.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View view) { + if (Preferences.get().hideOnLongPressSearch()) { + HidingManager.showHideDialog(activity); + return true; + } else { + return false; + } + } + }); activity.getSupportLoaderManager().restartLoader(LOADER_ID, null, this); } diff --git a/app/src/main/java/org/fdroid/fdroid/views/main/WhatsNewViewBinder.java b/app/src/main/java/org/fdroid/fdroid/views/main/WhatsNewViewBinder.java index 1ff84b833..051da5b4f 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/main/WhatsNewViewBinder.java +++ b/app/src/main/java/org/fdroid/fdroid/views/main/WhatsNewViewBinder.java @@ -14,6 +14,8 @@ import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.FrameLayout; import android.widget.TextView; + +import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.R; import org.fdroid.fdroid.UpdateService; import org.fdroid.fdroid.Utils; @@ -21,6 +23,7 @@ import org.fdroid.fdroid.data.AppProvider; import org.fdroid.fdroid.data.RepoProvider; import org.fdroid.fdroid.data.Schema; import org.fdroid.fdroid.views.apps.AppListActivity; +import org.fdroid.fdroid.views.hiding.HidingManager; import org.fdroid.fdroid.views.whatsnew.WhatsNewAdapter; import java.util.Date; @@ -71,6 +74,17 @@ class WhatsNewViewBinder implements LoaderManager.LoaderCallbacks { activity.startActivity(new Intent(activity, AppListActivity.class)); } }); + searchFab.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View view) { + if (Preferences.get().hideOnLongPressSearch()) { + HidingManager.showHideDialog(activity); + return true; + } else { + return false; + } + } + }); activity.getSupportLoaderManager().initLoader(LOADER_ID, null, this); } diff --git a/app/src/main/java/org/fdroid/fdroid/views/panic/PanicPreferencesFragment.java b/app/src/main/java/org/fdroid/fdroid/views/panic/PanicPreferencesFragment.java index 9b69258dd..ed35bdc85 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/panic/PanicPreferencesFragment.java +++ b/app/src/main/java/org/fdroid/fdroid/views/panic/PanicPreferencesFragment.java @@ -13,7 +13,6 @@ import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.ListPreference; import android.preference.Preference; -import android.preference.PreferenceCategory; import android.support.annotation.Nullable; import android.support.v4.preference.PreferenceFragment; import android.support.v7.app.AlertDialog; @@ -21,6 +20,7 @@ import android.text.TextUtils; import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.R; +import org.fdroid.fdroid.views.hiding.HidingManager; import java.util.ArrayList; @@ -79,10 +79,6 @@ public class PanicPreferencesFragment extends PreferenceFragment implements Shar return true; } }); - - // TODO implement app hiding - PreferenceCategory category = (PreferenceCategory) findPreference("pref_panic_destructive_actions"); - category.removePreference(prefHide); } @Override @@ -100,9 +96,8 @@ public class PanicPreferencesFragment extends PreferenceFragment implements Shar @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - // enable "exit" if "hiding" gets enabled if (key.equals(PREF_HIDE) && sharedPreferences.getBoolean(PREF_HIDE, false)) { - prefExit.setChecked(true); + showHideConfirmationDialog(); } // disable "hiding" if "exit" gets disabled if (key.equals(PREF_EXIT) && !sharedPreferences.getBoolean(PREF_EXIT, true)) { @@ -217,4 +212,35 @@ public class PanicPreferencesFragment extends PreferenceFragment implements Shar return packageName; } + private void showHideConfirmationDialog() { + String appName = getString(R.string.app_name); + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setTitle(R.string.panic_hide_warning_title); + builder.setMessage(getString(R.string.panic_hide_warning_message, appName, + HidingManager.getUnhidePin(getContext()), getString(R.string.hiding_calculator))); + builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + // enable "exit" if "hiding" gets enabled + prefExit.setChecked(true); + // dismiss, but not cancel dialog + dialogInterface.dismiss(); + } + }); + builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + dialogInterface.cancel(); + } + }); + builder.setOnCancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialogInterface) { + prefHide.setChecked(false); + } + }); + builder.setView(R.layout.dialog_app_hiding); + builder.create().show(); + } + } diff --git a/app/src/main/java/org/fdroid/fdroid/views/panic/PanicResponderActivity.java b/app/src/main/java/org/fdroid/fdroid/views/panic/PanicResponderActivity.java index b2275fdca..d0c18e6ab 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/panic/PanicResponderActivity.java +++ b/app/src/main/java/org/fdroid/fdroid/views/panic/PanicResponderActivity.java @@ -7,6 +7,7 @@ import android.support.v7.app.AppCompatActivity; import android.util.Log; import org.fdroid.fdroid.Preferences; +import org.fdroid.fdroid.views.hiding.HidingManager; import info.guardianproject.panic.Panic; import info.guardianproject.panic.PanicResponder; @@ -36,7 +37,7 @@ public class PanicResponderActivity extends AppCompatActivity { // Performing destructive panic responses if (preferences.panicHide()) { Log.i(TAG, "Hiding app..."); - // TODO + HidingManager.hide(this); } } diff --git a/app/src/main/res/layout/activity_calculator.xml b/app/src/main/res/layout/activity_calculator.xml new file mode 100644 index 000000000..deec73027 --- /dev/null +++ b/app/src/main/res/layout/activity_calculator.xml @@ -0,0 +1,292 @@ + + + + + + + +