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:name=".AppUpdateStatusService"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
|
<!-- Warning: Please add all new services to HidingManager -->
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".views.main.MainActivity"
|
android:name=".views.main.MainActivity"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
@ -552,6 +554,18 @@
|
|||||||
android:name=".views.panic.ExitActivity"
|
android:name=".views.panic.ExitActivity"
|
||||||
android:theme="@android:style/Theme.NoDisplay"/>
|
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>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -62,6 +62,7 @@ import org.fdroid.fdroid.installer.ApkFileProvider;
|
|||||||
import org.fdroid.fdroid.installer.InstallHistoryService;
|
import org.fdroid.fdroid.installer.InstallHistoryService;
|
||||||
import org.fdroid.fdroid.net.ImageLoaderForUIL;
|
import org.fdroid.fdroid.net.ImageLoaderForUIL;
|
||||||
import org.fdroid.fdroid.net.WifiStateChangeService;
|
import org.fdroid.fdroid.net.WifiStateChangeService;
|
||||||
|
import org.fdroid.fdroid.views.hiding.HidingManager;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@ -286,7 +287,7 @@ public class FDroidApp extends Application {
|
|||||||
Languages.setLanguage(this);
|
Languages.setLanguage(this);
|
||||||
|
|
||||||
ACRA.init(this);
|
ACRA.init(this);
|
||||||
if (isAcraProcess()) {
|
if (isAcraProcess() || HidingManager.isHidden(this)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
|
|||||||
Resources res = context.getResources();
|
Resources res = context.getResources();
|
||||||
defaultPreventScreenshots = res.getBoolean(R.bool.defaultPreventScreenshots);
|
defaultPreventScreenshots = res.getBoolean(R.bool.defaultPreventScreenshots);
|
||||||
defaultPanicExit = res.getBoolean(R.bool.defaultPanicExit);
|
defaultPanicExit = res.getBoolean(R.bool.defaultPanicExit);
|
||||||
|
defaultHideOnLongPressSearch = res.getBoolean(R.bool.defaultHideOnLongPressSearch);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String PREF_UPD_INTERVAL = "updateInterval";
|
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_PREVENT_SCREENSHOTS = "preventScreenshots";
|
||||||
public static final String PREF_PANIC_EXIT = "pref_panic_exit";
|
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_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_ROOTED = true;
|
||||||
private static final boolean DEFAULT_HIDE_ANTI_FEATURE_APPS = false;
|
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 static final boolean DEFAULT_POST_PRIVILEGED_INSTALL = false;
|
||||||
private final boolean defaultPreventScreenshots;
|
private final boolean defaultPreventScreenshots;
|
||||||
private final boolean defaultPanicExit;
|
private final boolean defaultPanicExit;
|
||||||
|
private final boolean defaultHideOnLongPressSearch;
|
||||||
|
|
||||||
public enum Theme {
|
public enum Theme {
|
||||||
light,
|
light,
|
||||||
@ -335,6 +338,10 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
|
|||||||
return preferences.getBoolean(PREF_PANIC_HIDE, false);
|
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.
|
* 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
|
* 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 LocalBroadcastManager localBroadcastManager;
|
||||||
private AppUpdateStatusManager appUpdateStatusManager;
|
private AppUpdateStatusManager appUpdateStatusManager;
|
||||||
|
private BroadcastReceiver broadcastReceiver;
|
||||||
|
private boolean running = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This service does not use binding, so no need to implement this method
|
* 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);
|
localBroadcastManager = LocalBroadcastManager.getInstance(this);
|
||||||
appUpdateStatusManager = AppUpdateStatusManager.getInstance(this);
|
appUpdateStatusManager = AppUpdateStatusManager.getInstance(this);
|
||||||
|
|
||||||
BroadcastReceiver br = new BroadcastReceiver() {
|
broadcastReceiver = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (intent.getData() == null) return;
|
||||||
String packageName = intent.getData().getSchemeSpecificPart();
|
String packageName = intent.getData().getSchemeSpecificPart();
|
||||||
for (AppUpdateStatusManager.AppUpdateStatus status : appUpdateStatusManager.getByPackageName(packageName)) {
|
for (AppUpdateStatusManager.AppUpdateStatus status : appUpdateStatusManager.getByPackageName(packageName)) {
|
||||||
appUpdateStatusManager.updateApk(status.getUniqueKey(), AppUpdateStatusManager.Status.Installed, null);
|
appUpdateStatusManager.updateApk(status.getUniqueKey(), AppUpdateStatusManager.Status.Installed, null);
|
||||||
@ -113,7 +116,15 @@ public class InstallManagerService extends Service {
|
|||||||
IntentFilter intentFilter = new IntentFilter();
|
IntentFilter intentFilter = new IntentFilter();
|
||||||
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
|
||||||
intentFilter.addDataScheme("package");
|
intentFilter.addDataScheme("package");
|
||||||
registerReceiver(br, intentFilter);
|
registerReceiver(broadcastReceiver, intentFilter);
|
||||||
|
running = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
running = false;
|
||||||
|
unregisterReceiver(broadcastReceiver);
|
||||||
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -218,6 +229,10 @@ public class InstallManagerService extends Service {
|
|||||||
final BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
|
final BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (!running) {
|
||||||
|
localBroadcastManager.unregisterReceiver(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
String action = intent.getAction();
|
String action = intent.getAction();
|
||||||
if (Downloader.ACTION_STARTED.equals(action)) {
|
if (Downloader.ACTION_STARTED.equals(action)) {
|
||||||
Utils.debugLog(TAG, action + " " + intent);
|
Utils.debugLog(TAG, action + " " + intent);
|
||||||
@ -273,6 +288,10 @@ public class InstallManagerService extends Service {
|
|||||||
BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
|
BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (!running) {
|
||||||
|
localBroadcastManager.unregisterReceiver(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
Uri downloadUri = intent.getData();
|
Uri downloadUri = intent.getData();
|
||||||
String urlString = downloadUri.toString();
|
String urlString = downloadUri.toString();
|
||||||
long repoId = intent.getLongExtra(Downloader.EXTRA_REPO_ID, 0);
|
long repoId = intent.getLongExtra(Downloader.EXTRA_REPO_ID, 0);
|
||||||
@ -351,6 +370,10 @@ public class InstallManagerService extends Service {
|
|||||||
BroadcastReceiver installReceiver = new BroadcastReceiver() {
|
BroadcastReceiver installReceiver = new BroadcastReceiver() {
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (!running) {
|
||||||
|
localBroadcastManager.unregisterReceiver(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
String downloadUrl = intent.getDataString();
|
String downloadUrl = intent.getDataString();
|
||||||
Apk apk;
|
Apk apk;
|
||||||
switch (intent.getAction()) {
|
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.FrameLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.fdroid.fdroid.Preferences;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.UpdateService;
|
import org.fdroid.fdroid.UpdateService;
|
||||||
import org.fdroid.fdroid.data.CategoryProvider;
|
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.apps.AppListActivity;
|
||||||
import org.fdroid.fdroid.views.categories.CategoryAdapter;
|
import org.fdroid.fdroid.views.categories.CategoryAdapter;
|
||||||
import org.fdroid.fdroid.views.categories.CategoryController;
|
import org.fdroid.fdroid.views.categories.CategoryController;
|
||||||
|
import org.fdroid.fdroid.views.hiding.HidingManager;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -73,6 +75,17 @@ class CategoriesViewBinder implements LoaderManager.LoaderCallbacks<Cursor> {
|
|||||||
activity.startActivity(new Intent(activity, AppListActivity.class));
|
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);
|
activity.getSupportLoaderManager().restartLoader(LOADER_ID, null, this);
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,8 @@ import android.support.v7.widget.RecyclerView;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import org.fdroid.fdroid.Preferences;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.UpdateService;
|
import org.fdroid.fdroid.UpdateService;
|
||||||
import org.fdroid.fdroid.Utils;
|
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.RepoProvider;
|
||||||
import org.fdroid.fdroid.data.Schema;
|
import org.fdroid.fdroid.data.Schema;
|
||||||
import org.fdroid.fdroid.views.apps.AppListActivity;
|
import org.fdroid.fdroid.views.apps.AppListActivity;
|
||||||
|
import org.fdroid.fdroid.views.hiding.HidingManager;
|
||||||
import org.fdroid.fdroid.views.whatsnew.WhatsNewAdapter;
|
import org.fdroid.fdroid.views.whatsnew.WhatsNewAdapter;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -71,6 +74,17 @@ class WhatsNewViewBinder implements LoaderManager.LoaderCallbacks<Cursor> {
|
|||||||
activity.startActivity(new Intent(activity, AppListActivity.class));
|
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);
|
activity.getSupportLoaderManager().initLoader(LOADER_ID, null, this);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ import android.os.Bundle;
|
|||||||
import android.preference.CheckBoxPreference;
|
import android.preference.CheckBoxPreference;
|
||||||
import android.preference.ListPreference;
|
import android.preference.ListPreference;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceCategory;
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.preference.PreferenceFragment;
|
import android.support.v4.preference.PreferenceFragment;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
@ -21,6 +20,7 @@ import android.text.TextUtils;
|
|||||||
|
|
||||||
import org.fdroid.fdroid.Preferences;
|
import org.fdroid.fdroid.Preferences;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
|
import org.fdroid.fdroid.views.hiding.HidingManager;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
@ -79,10 +79,6 @@ public class PanicPreferencesFragment extends PreferenceFragment implements Shar
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO implement app hiding
|
|
||||||
PreferenceCategory category = (PreferenceCategory) findPreference("pref_panic_destructive_actions");
|
|
||||||
category.removePreference(prefHide);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -100,9 +96,8 @@ public class PanicPreferencesFragment extends PreferenceFragment implements Shar
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||||
// enable "exit" if "hiding" gets enabled
|
|
||||||
if (key.equals(PREF_HIDE) && sharedPreferences.getBoolean(PREF_HIDE, false)) {
|
if (key.equals(PREF_HIDE) && sharedPreferences.getBoolean(PREF_HIDE, false)) {
|
||||||
prefExit.setChecked(true);
|
showHideConfirmationDialog();
|
||||||
}
|
}
|
||||||
// disable "hiding" if "exit" gets disabled
|
// disable "hiding" if "exit" gets disabled
|
||||||
if (key.equals(PREF_EXIT) && !sharedPreferences.getBoolean(PREF_EXIT, true)) {
|
if (key.equals(PREF_EXIT) && !sharedPreferences.getBoolean(PREF_EXIT, true)) {
|
||||||
@ -217,4 +212,35 @@ public class PanicPreferencesFragment extends PreferenceFragment implements Shar
|
|||||||
return packageName;
|
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 android.util.Log;
|
||||||
|
|
||||||
import org.fdroid.fdroid.Preferences;
|
import org.fdroid.fdroid.Preferences;
|
||||||
|
import org.fdroid.fdroid.views.hiding.HidingManager;
|
||||||
|
|
||||||
import info.guardianproject.panic.Panic;
|
import info.guardianproject.panic.Panic;
|
||||||
import info.guardianproject.panic.PanicResponder;
|
import info.guardianproject.panic.PanicResponder;
|
||||||
@ -36,7 +37,7 @@ public class PanicResponderActivity extends AppCompatActivity {
|
|||||||
// Performing destructive panic responses
|
// Performing destructive panic responses
|
||||||
if (preferences.panicHide()) {
|
if (preferences.panicHide()) {
|
||||||
Log.i(TAG, "Hiding app...");
|
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 -->
|
<!-- Default Preferences -->
|
||||||
<bool name="defaultPreventScreenshots">false</bool>
|
<bool name="defaultPreventScreenshots">false</bool>
|
||||||
<bool name="defaultPanicExit">true</bool>
|
<bool name="defaultPanicExit">true</bool>
|
||||||
|
<bool name="defaultHideOnLongPressSearch">false</bool>
|
||||||
|
|
||||||
|
<integer name="unhidePin">1337</integer>
|
||||||
|
|
||||||
</resources>
|
</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_destructive_actions">Destructive Actions</string>
|
||||||
<string name="panic_hide_title">Hide %s</string>
|
<string name="panic_hide_title">Hide %s</string>
|
||||||
<string name="panic_hide_summary">App will hide itself</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:
|
status_download takes four parameters:
|
||||||
|
@ -100,6 +100,12 @@
|
|||||||
android:summary="@string/preventScreenshots_summary"
|
android:summary="@string/preventScreenshots_summary"
|
||||||
android:title="@string/preventScreenshots_title"/>
|
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
|
<PreferenceScreen
|
||||||
android:summary="@string/panic_settings_summary"
|
android:summary="@string/panic_settings_summary"
|
||||||
android:title="@string/panic_settings">
|
android:title="@string/panic_settings">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user