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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/dialog_app_hiding.xml b/app/src/main/res/layout/dialog_app_hiding.xml
new file mode 100644
index 000000000..a80dfc4b3
--- /dev/null
+++ b/app/src/main/res/layout/dialog_app_hiding.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_calculator_launcher.png b/app/src/main/res/mipmap-hdpi/ic_calculator_launcher.png
new file mode 100644
index 000000000..15d6c7058
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_calculator_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_calculator_launcher.png b/app/src/main/res/mipmap-mdpi/ic_calculator_launcher.png
new file mode 100644
index 000000000..895a4ea06
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_calculator_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_calculator_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_calculator_launcher.png
new file mode 100644
index 000000000..96d438e6c
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_calculator_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_calculator_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_calculator_launcher.png
new file mode 100644
index 000000000..0d56e0187
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_calculator_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_calculator_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_calculator_launcher.png
new file mode 100644
index 000000000..375e4ad6d
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_calculator_launcher.png differ
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
index e24ed6d35..1c59a906b 100644
--- a/app/src/main/res/values/attrs.xml
+++ b/app/src/main/res/values/attrs.xml
@@ -17,5 +17,8 @@
false
true
+ false
+
+ 1337
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f4377daa8..b528f91d1 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -259,6 +259,15 @@ This often occurs with apps installed via Google Play or other sources, if they
Destructive Actions
Hide %s
App will hide itself
+ Remember how to restore
+ In a panic event, this will remove %1$s from the launcher. Only typing \"%2$d\" in the fake %3$s app can restore it.
+
+ Calculator
+ Hide %s Now
+ Are you sure you want to remove %1$s from the launcher? Only typing \"%2$d\" in the fake %3$s app can restore it.
+ Warning: Any app shortcut on the home screen will also be removed and needs to be re-added manually.
+ Hide with search button
+ Long pressing the search button will hide the app