Merge branch 'app-hiding' into 'master'
Implement App Hiding See merge request fdroid/fdroidclient!629
This commit is contained in:
		
						commit
						f83094d9fe
					
				| @ -279,6 +279,8 @@ | ||||
|             android:name=".AppUpdateStatusService" | ||||
|             android:exported="false" /> | ||||
| 
 | ||||
|         <!-- Warning: Please add all new services to HidingManager --> | ||||
| 
 | ||||
|         <activity | ||||
|             android:name=".views.main.MainActivity" | ||||
|             android:launchMode="singleTop" | ||||
| @ -552,6 +554,18 @@ | ||||
|             android:name=".views.panic.ExitActivity" | ||||
|             android:theme="@android:style/Theme.NoDisplay"/> | ||||
| 
 | ||||
|         <activity | ||||
|             android:name=".views.hiding.CalculatorActivity" | ||||
|             android:enabled="false" | ||||
|             android:icon="@mipmap/ic_calculator_launcher" | ||||
|             android:label="@string/hiding_calculator" | ||||
|             android:theme="@style/AppThemeLight"> | ||||
|             <intent-filter> | ||||
|                 <action android:name="android.intent.action.MAIN" /> | ||||
|                 <category android:name="android.intent.category.LAUNCHER" /> | ||||
|             </intent-filter> | ||||
|         </activity> | ||||
| 
 | ||||
|     </application> | ||||
| 
 | ||||
| </manifest> | ||||
|  | ||||
| @ -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; | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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()) { | ||||
|  | ||||
| @ -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; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -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)); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -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<Cursor> { | ||||
|                 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); | ||||
|     } | ||||
|  | ||||
| @ -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<Cursor> { | ||||
|                 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); | ||||
|     } | ||||
|  | ||||
| @ -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(); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -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); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										292
									
								
								app/src/main/res/layout/activity_calculator.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										292
									
								
								app/src/main/res/layout/activity_calculator.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,292 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <android.support.constraint.ConstraintLayout | ||||
|     xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent" | ||||
|     tools:context=".views.hiding.CalculatorActivity"> | ||||
| 
 | ||||
|     <android.support.v7.widget.Toolbar | ||||
|         android:id="@+id/toolbar" | ||||
|         android:layout_width="match_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         app:layout_constraintTop_toTopOf="parent" | ||||
|         app:popupTheme="?attr/actionBarPopupTheme" | ||||
|         app:theme="?attr/actionBarTheme" /> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/textView" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="0dp" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginEnd="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:layout_marginTop="8dp" | ||||
|         android:gravity="bottom|end" | ||||
|         android:padding="5dp" | ||||
|         android:textAlignment="textEnd" | ||||
|         android:textSize="22sp" | ||||
|         android:typeface="monospace" | ||||
|         app:layout_constraintBottom_toTopOf="@+id/ce" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         app:layout_constraintTop_toBottomOf="@+id/toolbar" | ||||
|         tools:text="1337+42" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/times" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginLeft="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:onClick="op" | ||||
|         android:text="×" | ||||
|         app:layout_constraintBottom_toTopOf="@+id/seven" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         tools:ignore="HardcodedText" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/divided" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginLeft="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:onClick="op" | ||||
|         android:text="÷" | ||||
|         app:layout_constraintBottom_toTopOf="@+id/eight" | ||||
|         app:layout_constraintStart_toEndOf="@+id/times" | ||||
|         tools:ignore="HardcodedText" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/c" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginLeft="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:onClick="c" | ||||
|         android:text="C" | ||||
|         app:layout_constraintBottom_toTopOf="@+id/nine" | ||||
|         app:layout_constraintStart_toEndOf="@+id/divided" | ||||
|         tools:ignore="HardcodedText" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/seven" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginLeft="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:onClick="number" | ||||
|         android:text="7" | ||||
|         app:layout_constraintBottom_toTopOf="@+id/four" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         tools:ignore="HardcodedText" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/eight" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginLeft="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:onClick="number" | ||||
|         android:text="8" | ||||
|         app:layout_constraintBottom_toTopOf="@+id/five" | ||||
|         app:layout_constraintStart_toEndOf="@+id/seven" | ||||
|         tools:ignore="HardcodedText" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/nine" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginLeft="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:onClick="number" | ||||
|         android:text="9" | ||||
|         app:layout_constraintBottom_toTopOf="@+id/six" | ||||
|         app:layout_constraintStart_toEndOf="@+id/eight" | ||||
|         tools:ignore="HardcodedText" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/ce" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginEnd="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:onClick="ce" | ||||
|         android:text="CE" | ||||
|         app:layout_constraintBottom_toTopOf="@+id/plus" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintStart_toEndOf="@+id/nine" | ||||
|         tools:ignore="HardcodedText" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/four" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginLeft="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:onClick="number" | ||||
|         android:text="4" | ||||
|         app:layout_constraintBottom_toTopOf="@+id/one" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         tools:ignore="HardcodedText" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/five" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginLeft="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:onClick="number" | ||||
|         android:text="5" | ||||
|         app:layout_constraintBottom_toTopOf="@+id/two" | ||||
|         app:layout_constraintStart_toEndOf="@+id/four" | ||||
|         tools:ignore="HardcodedText" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/six" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginLeft="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:onClick="number" | ||||
|         android:text="6" | ||||
|         app:layout_constraintBottom_toTopOf="@+id/three" | ||||
|         app:layout_constraintStart_toEndOf="@+id/five" | ||||
|         tools:ignore="HardcodedText" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/plus" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginEnd="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:onClick="op" | ||||
|         android:text="+" | ||||
|         app:layout_constraintBottom_toTopOf="@+id/minus" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintStart_toEndOf="@+id/six" | ||||
|         tools:ignore="HardcodedText" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/minus" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginEnd="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:onClick="op" | ||||
|         android:text="-" | ||||
|         app:layout_constraintBottom_toTopOf="@+id/equals" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintStart_toEndOf="@+id/three" | ||||
|         tools:ignore="HardcodedText" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/one" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginLeft="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:onClick="number" | ||||
|         android:text="1" | ||||
|         app:layout_constraintBottom_toTopOf="@+id/zero" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         tools:ignore="HardcodedText" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/two" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginLeft="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:onClick="number" | ||||
|         android:text="2" | ||||
|         app:layout_constraintBottom_toTopOf="@+id/comma" | ||||
|         app:layout_constraintStart_toEndOf="@+id/one" | ||||
|         tools:ignore="HardcodedText" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/three" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginLeft="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:onClick="number" | ||||
|         android:text="3" | ||||
|         app:layout_constraintBottom_toTopOf="@+id/percent" | ||||
|         app:layout_constraintStart_toEndOf="@+id/two" | ||||
|         tools:ignore="HardcodedText" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/zero" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginLeft="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:onClick="number" | ||||
|         android:text="0" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         tools:ignore="HardcodedText" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/comma" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginLeft="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:onClick="number" | ||||
|         android:text="." | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintStart_toEndOf="@+id/zero" | ||||
|         tools:ignore="HardcodedText" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/percent" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginLeft="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:onClick="op" | ||||
|         android:text="%" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintStart_toEndOf="@+id/comma" | ||||
|         tools:ignore="HardcodedText" /> | ||||
| 
 | ||||
|     <Button | ||||
|         android:id="@+id/equals" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="0dp" | ||||
|         android:layout_marginBottom="8dp" | ||||
|         android:layout_marginEnd="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:onClick="op" | ||||
|         android:text="=" | ||||
|         app:layout_constraintBottom_toBottomOf="parent" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintHorizontal_bias="0.0" | ||||
|         app:layout_constraintStart_toEndOf="@+id/three" | ||||
|         app:layout_constraintTop_toTopOf="@+id/three" | ||||
|         tools:ignore="HardcodedText" /> | ||||
| 
 | ||||
| </android.support.constraint.ConstraintLayout> | ||||
							
								
								
									
										60
									
								
								app/src/main/res/layout/dialog_app_hiding.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								app/src/main/res/layout/dialog_app_hiding.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,60 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:layout_width="match_parent" | ||||
|     android:layout_height="match_parent"> | ||||
| 
 | ||||
|     <ImageView | ||||
|         android:id="@+id/launcherIcon" | ||||
|         android:layout_width="48dp" | ||||
|         android:layout_height="48dp" | ||||
|         android:layout_marginLeft="24dp" | ||||
|         android:layout_marginStart="24dp" | ||||
|         android:layout_marginTop="16dp" | ||||
|         android:contentDescription="@string/hiding_calculator" | ||||
|         app:layout_constraintStart_toStartOf="parent" | ||||
|         app:layout_constraintTop_toTopOf="parent" | ||||
|         app:srcCompat="@mipmap/ic_calculator_launcher" /> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/appName" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="0dp" | ||||
|         android:layout_marginLeft="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:gravity="center_vertical" | ||||
|         android:text="@string/hiding_calculator" | ||||
|         android:textSize="18sp" | ||||
|         app:layout_constraintBottom_toBottomOf="@+id/launcherIcon" | ||||
|         app:layout_constraintStart_toEndOf="@+id/launcherIcon" | ||||
|         app:layout_constraintTop_toTopOf="@+id/launcherIcon" /> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/pin" | ||||
|         android:layout_width="wrap_content" | ||||
|         android:layout_height="0dp" | ||||
|         android:layout_marginEnd="8dp" | ||||
|         android:layout_marginStart="8dp" | ||||
|         android:gravity="center_vertical" | ||||
|         android:text="@integer/unhidePin" | ||||
|         android:textColor="@color/red" | ||||
|         android:textSize="18sp" | ||||
|         app:layout_constraintBottom_toBottomOf="@+id/launcherIcon" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintStart_toEndOf="@+id/appName" | ||||
|         app:layout_constraintTop_toTopOf="@+id/launcherIcon" /> | ||||
| 
 | ||||
|     <TextView | ||||
|         android:id="@+id/warningText" | ||||
|         android:layout_width="0dp" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginEnd="8dp" | ||||
|         android:layout_marginRight="8dp" | ||||
|         android:layout_marginTop="8dp" | ||||
|         android:text="@string/hiding_dialog_warning" | ||||
|         android:textColor="?android:textColorPrimary" | ||||
|         app:layout_constraintEnd_toEndOf="parent" | ||||
|         app:layout_constraintStart_toStartOf="@+id/launcherIcon" | ||||
|         app:layout_constraintTop_toBottomOf="@+id/launcherIcon" /> | ||||
| 
 | ||||
| </android.support.constraint.ConstraintLayout> | ||||
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-hdpi/ic_calculator_launcher.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-hdpi/ic_calculator_launcher.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 3.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-mdpi/ic_calculator_launcher.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-mdpi/ic_calculator_launcher.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 2.1 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xhdpi/ic_calculator_launcher.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xhdpi/ic_calculator_launcher.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 4.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xxhdpi/ic_calculator_launcher.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xxhdpi/ic_calculator_launcher.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 8.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xxxhdpi/ic_calculator_launcher.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/mipmap-xxxhdpi/ic_calculator_launcher.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 13 KiB | 
| @ -17,5 +17,8 @@ | ||||
|     <!-- Default Preferences --> | ||||
|     <bool name="defaultPreventScreenshots">false</bool> | ||||
|     <bool name="defaultPanicExit">true</bool> | ||||
|     <bool name="defaultHideOnLongPressSearch">false</bool> | ||||
| 
 | ||||
|     <integer name="unhidePin">1337</integer> | ||||
| 
 | ||||
| </resources> | ||||
|  | ||||
| @ -259,6 +259,15 @@ This often occurs with apps installed via Google Play or other sources, if they | ||||
|     <string name="panic_destructive_actions">Destructive Actions</string> | ||||
|     <string name="panic_hide_title">Hide %s</string> | ||||
|     <string name="panic_hide_summary">App will hide itself</string> | ||||
|     <string name="panic_hide_warning_title">Remember how to restore</string> | ||||
|     <string name="panic_hide_warning_message">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.</string> | ||||
| 
 | ||||
|     <string name="hiding_calculator">Calculator</string> | ||||
|     <string name="hiding_dialog_title">Hide %s Now</string> | ||||
|     <string name="hiding_dialog_message">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.</string> | ||||
|     <string name="hiding_dialog_warning">Warning: Any app shortcut on the home screen will also be removed and needs to be re-added manually.</string> | ||||
|     <string name="hide_on_long_search_press_title">Hide with search button</string> | ||||
|     <string name="hide_on_long_search_press_summary">Long pressing the search button will hide the app</string> | ||||
| 
 | ||||
|     <!-- | ||||
|     status_download takes four parameters: | ||||
|  | ||||
| @ -100,6 +100,12 @@ | ||||
|             android:summary="@string/preventScreenshots_summary" | ||||
|             android:title="@string/preventScreenshots_title"/> | ||||
| 
 | ||||
|         <CheckBoxPreference | ||||
|             android:defaultValue="@bool/defaultHideOnLongPressSearch" | ||||
|             android:key="hideOnLongPressSearch" | ||||
|             android:summary="@string/hide_on_long_search_press_summary" | ||||
|             android:title="@string/hide_on_long_search_press_title"/> | ||||
| 
 | ||||
|         <PreferenceScreen | ||||
|             android:summary="@string/panic_settings_summary" | ||||
|             android:title="@string/panic_settings"> | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Hans-Christoph Steiner
						Hans-Christoph Steiner