minSdkVersion 21
targetSdkVersion SDK_VERSION
- versionCode 181
- versionName "3.8.2"
+ versionCode 182
+ versionName "3.9"
resConfigs "en", "ja", "ru", "de", "zh-rCN"
<!-- Manifest used for Android-x86 builds of Taskbar, with the following changes:
* HomeActivity is enabled by default
- * SendSettingsReceiver and ReceiveSettingsReceiver are not exposed
+ * Certain BroadcastReceivers are not exposed
-->
-<manifest android:versionCode="181"
- android:versionName="3.8.2"
+<manifest android:versionCode="182"
+ android:versionName="3.9"
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.farmerbb.taskbar" >
<permission android:name="com.farmerbb.taskbar.androidx86.START_STOP_TASKBAR"
android:protectionLevel="signature" />
- <permission android:name="com.farmerbb.taskbar.androidx86.ENABLE_DISABLE_HOME"
- android:protectionLevel="signature" />
-
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
</intent-filter>
</receiver>
<receiver
- android:name=".receiver.EnableHomeReceiver"
- android:enabled="true"
- android:exported="true"
- android:permission="com.farmerbb.taskbar.androidx86.ENABLE_DISABLE_HOME" >
- <intent-filter>
- <action android:name="com.farmerbb.taskbar.ENABLE_HOME"/>
- </intent-filter>
- </receiver>
- <receiver
- android:name=".receiver.DisableHomeReceiver"
- android:enabled="true"
- android:exported="true"
- android:permission="com.farmerbb.taskbar.androidx86.ENABLE_DISABLE_HOME" >
- <intent-filter>
- <action android:name="com.farmerbb.taskbar.DISABLE_HOME"/>
- </intent-filter>
- </receiver>
- <receiver
android:name=".receiver.ToggleFreeformModeReceiver"
android:permission="com.farmerbb.taskbar.androidx86.START_STOP_TASKBAR" >
<intent-filter>
}
public static void startForegroundService(Context context, Intent intent) {
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
- context.startForegroundService(intent);
- else
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ if(Settings.canDrawOverlays(context))
+ context.startForegroundService(intent);
+ } else
context.startService(intent);
}
package com.farmerbb.taskbar;
import android.app.AlertDialog;
-import android.app.AppOpsManager;
import android.app.FragmentTransaction;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
-import android.provider.Settings;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
// Ensure that components that should be enabled are enabled properly
boolean launcherEnabled = (pref.getBoolean("launcher", false) && U.canDrawOverlays(this))
- || U.hasSupportLibrary(this)
- || BuildConfig.APPLICATION_ID.equals(BuildConfig.ANDROIDX86_APPLICATION_ID);
+ || U.isLauncherPermanentlyEnabled(this);
editor.putBoolean("launcher", launcherEnabled);
editor.apply();
boolean firstRun = pref.getBoolean("first_run", true);
startTaskbarService();
- if(firstRun && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !U.isSystemApp(this))
- showRecentAppsDialog();
+ if(firstRun)
+ U.showRecentAppsDialog(this);
} else {
- U.showPermissionDialog(MainActivity.this);
+ U.showPermissionDialog(this);
compoundButton.setChecked(false);
}
} else
}
}
- private void showRecentAppsDialog() {
- ApplicationInfo applicationInfo = null;
- try {
- applicationInfo = getPackageManager().getApplicationInfo(BuildConfig.APPLICATION_ID, 0);
- } catch (PackageManager.NameNotFoundException e) { /* Gracefully fail */ }
-
- if(applicationInfo != null) {
- AppOpsManager appOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
- int mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, applicationInfo.uid, applicationInfo.packageName);
-
- if(mode != AppOpsManager.MODE_ALLOWED) {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle(R.string.pref_header_recent_apps)
- .setMessage(R.string.enable_recent_apps)
- .setPositiveButton(R.string.action_ok, (dialog, which) -> {
- try {
- startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));
- U.showToastLong(this, R.string.usage_stats_message);
- } catch (ActivityNotFoundException e) {
- U.showErrorDialog(this, "GET_USAGE_STATS");
- }
- }).setNegativeButton(R.string.action_cancel, null);
-
- AlertDialog dialog = builder.create();
- dialog.show();
- dialog.setCancelable(false);
- }
- }
- }
-
@Override
protected void onResume() {
super.onResume();
intent2.putExtra("uninstall", packageName);
intent2.putExtra("user_id", userId);
- startActivity(intent2);
+ try {
+ startActivity(intent2);
+ } catch (IllegalArgumentException e) { /* Gracefully fail */ }
} else {
Intent intent2 = new Intent(Intent.ACTION_DELETE, Uri.parse("package:" + packageName));
intent2.putExtra(Intent.EXTRA_USER, userManager.getUserForSerialNumber(userId));
new Handler().post(() -> {
try {
startActivity(intent2);
- } catch (ActivityNotFoundException e) { /* Gracefully fail */ }
+ } catch (ActivityNotFoundException | IllegalArgumentException e) { /* Gracefully fail */ }
});
}
U.launchApp(this, () -> {
Intent intent2 = new Intent(this, MainActivity.class);
intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- startActivity(intent2, U.getActivityOptionsBundle(ApplicationType.APPLICATION));
+
+ try {
+ startActivity(intent2, U.getActivityOptionsBundle(ApplicationType.APPLICATION));
+ } catch (IllegalArgumentException e) { /* Gracefully fail */ }
});
showStartMenu = false;
case "show_window_sizes":
generateWindowSizes();
- if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
+ if(U.hasBrokenSetLaunchBoundsApi())
U.showToastLong(this, R.string.window_sizes_not_available);
- }
getListView().setOnItemLongClickListener((parent, view, position, id) -> {
String[] windowSizes = { "standard", "large", "fullscreen", "half_left", "half_right", "phone_size" };
U.launchApp(getApplicationContext(), packageName, componentName, userId, windowSize, false, true);
- if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1)
+ if(U.hasBrokenSetLaunchBoundsApi())
U.cancelToast();
showStartMenu = false;
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
U.launchAppMaximized(getApplicationContext(), intent);
- } else
- startActivity(intent);
+ } else {
+ try {
+ startActivity(intent);
+ } catch (IllegalArgumentException e) { /* Gracefully fail */ }
+ }
showStartMenu = false;
shouldHideTaskbar = true;
startActivity(fileManagerIntent, U.getActivityOptionsBundle(ApplicationType.APPLICATION));
} catch (ActivityNotFoundException e) {
U.showToast(this, R.string.lock_device_not_supported);
- }
+ } catch (IllegalArgumentException e) { /* Gracefully fail */ }
});
showStartMenu = false;
startActivity(settingsIntent, U.getActivityOptionsBundle(ApplicationType.APPLICATION));
} catch (ActivityNotFoundException e) {
U.showToast(this, R.string.lock_device_not_supported);
- }
+ } catch (IllegalArgumentException e) { /* Gracefully fail */ }
});
showStartMenu = false;
getListView().setOnItemLongClickListener(null);
- if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1)
+ if(U.hasBrokenSetLaunchBoundsApi())
U.cancelToast();
} else {
if(contextMenuFix && !showStartMenu)
import android.os.Handler;
import android.os.UserManager;
import android.provider.Settings;
-import android.support.v7.view.ContextThemeWrapper;
import android.view.View;
import com.farmerbb.taskbar.R;
startActivity(intent);
} catch (ActivityNotFoundException e) { /* Gracefully fail */ }
} else if(getIntent().hasExtra("device_admin")) {
- SharedPreferences pref = U.getSharedPreferences(this);
-
- int theme = -1;
- switch(pref.getString("theme", "light")) {
- case "light":
- theme = R.style.AppTheme;
- break;
- case "dark":
- theme = R.style.AppTheme_Dark;
- break;
- }
-
- AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(this, theme));
+ AlertDialog.Builder builder = new AlertDialog.Builder(U.wrapContext(this));
builder.setTitle(R.string.permission_dialog_title)
.setMessage(R.string.device_admin_disclosure)
.setNegativeButton(R.string.action_cancel, (dialog, which) -> new Handler().post(this::finish))
dialog.show();
dialog.setCancelable(false);
} else if(getIntent().hasExtra("accessibility")) {
- SharedPreferences pref = U.getSharedPreferences(this);
-
- int theme = -1;
- switch(pref.getString("theme", "light")) {
- case "light":
- theme = R.style.AppTheme;
- break;
- case "dark":
- theme = R.style.AppTheme_Dark;
- break;
- }
-
- AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(this, theme));
+ AlertDialog.Builder builder = new AlertDialog.Builder(U.wrapContext(this));
builder.setTitle(R.string.permission_dialog_title)
.setMessage(R.string.enable_accessibility)
.setNegativeButton(R.string.action_cancel, (dialog, which) -> new Handler().post(this::finish))
}
finish();
- } else finish();
+ } else if(getIntent().hasExtra("show_permission_dialog"))
+ U.showPermissionDialog(U.wrapContext(this), null, this::finish);
+ else if(getIntent().hasExtra("show_recent_apps_dialog"))
+ U.showRecentAppsDialog(U.wrapContext(this), null, this::finish);
+ else
+ finish();
}
}
}
\ No newline at end of file
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.content.LocalBroadcastManager;
-import android.support.v7.view.ContextThemeWrapper;
import android.util.DisplayMetrics;
import android.view.GestureDetector;
import android.view.MotionEvent;
if(pref.getBoolean("double_tap_to_sleep", false)) {
U.lockDevice(HomeActivity.this);
} else {
- int theme = -1;
- switch(pref.getString("theme", "light")) {
- case "light":
- theme = R.style.AppTheme;
- break;
- case "dark":
- theme = R.style.AppTheme_Dark;
- break;
- }
-
- AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(HomeActivity.this, theme));
+ AlertDialog.Builder builder = new AlertDialog.Builder(U.wrapContext(HomeActivity.this));
builder.setTitle(R.string.double_tap_to_sleep)
.setMessage(R.string.enable_double_tap_to_sleep)
.setNegativeButton(pref.getBoolean("double_tap_dialog_shown", false)
LocalBroadcastManager.getInstance(this).registerReceiver(killReceiver, new IntentFilter("com.farmerbb.taskbar.KILL_HOME_ACTIVITY"));
LocalBroadcastManager.getInstance(this).registerReceiver(forceTaskbarStartReceiver, new IntentFilter("com.farmerbb.taskbar.FORCE_TASKBAR_RESTART"));
+ SharedPreferences pref = U.getSharedPreferences(this);
+ pref.edit().putBoolean("launcher", true).apply();
+
U.initPrefs(this);
}
} else if(U.launcherIsDefault(this))
startFreeformHack();
} else
- dialog = U.showPermissionDialog(this);
+ dialog = U.showPermissionDialog(U.wrapContext(this),
+ () -> dialog = U.showErrorDialog(U.wrapContext(this), "SYSTEM_ALERT_WINDOW"),
+ null);
}
private boolean bootToFreeform() {
}
private void startTaskbar() {
+ SharedPreferences pref = U.getSharedPreferences(this);
+ if(pref.getBoolean("first_run", true)) {
+ SharedPreferences.Editor editor = pref.edit();
+ editor.putBoolean("first_run", false);
+ editor.putBoolean("collapsed", true);
+ editor.apply();
+
+ dialog = U.showRecentAppsDialog(U.wrapContext(this),
+ () -> dialog = U.showErrorDialog(U.wrapContext(this), "GET_USAGE_STATS"),
+ null);
+ }
+
// We always start the Taskbar and Start Menu services, even if the app isn't normally running
startService(new Intent(this, TaskbarService.class));
startService(new Intent(this, StartMenuService.class));
startService(new Intent(this, DashboardService.class));
- SharedPreferences pref = U.getSharedPreferences(this);
if(pref.getBoolean("taskbar_active", false) && !U.isServiceRunning(this, NotificationService.class))
pref.edit().putBoolean("taskbar_active", false).apply();
LauncherHelper.getInstance().setOnHomeScreen(true);
bootToFreeform = true;
+ SharedPreferences pref = U.getSharedPreferences(this);
+ if(pref.getBoolean("first_run", true)) {
+ SharedPreferences.Editor editor = pref.edit();
+ editor.putBoolean("first_run", false);
+ editor.putBoolean("collapsed", true);
+ editor.apply();
+
+ new Handler().postDelayed(() -> {
+ Intent intent = new Intent(this, DummyActivity.class);
+ intent.putExtra("show_recent_apps_dialog", true);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ startActivity(intent);
+ }, 250);
+ }
+
// We always start the Taskbar and Start Menu services, even if the app isn't normally running
startService(new Intent(this, TaskbarService.class));
startService(new Intent(this, StartMenuService.class));
startService(new Intent(this, DashboardService.class));
- SharedPreferences pref = U.getSharedPreferences(this);
if(pref.getBoolean("taskbar_active", false) && !U.isServiceRunning(this, NotificationService.class))
pref.edit().putBoolean("taskbar_active", false).apply();
findPreference("button_home").setOnPreferenceClickListener(this);
findPreference("button_recents").setOnPreferenceClickListener(this);
- if(U.hasSupportLibrary(this))
+ if(U.isBlissOs(this))
findPreference("auto_hide_navbar").setOnPreferenceClickListener(this);
else
getPreferenceScreen().removePreference(findPreference("auto_hide_navbar_category"));
openContextMenu(entry, location);
}
- if(action == MotionEvent.ACTION_SCROLL && visualFeedbackEnabled())
+ if(action == MotionEvent.ACTION_SCROLL && U.visualFeedbackEnabled(getContext()))
view.setBackgroundColor(0);
return false;
});
- if(visualFeedbackEnabled()) {
+ if(U.visualFeedbackEnabled(getContext())) {
layout.setOnHoverListener((v, event) -> {
if(event.getAction() == MotionEvent.ACTION_HOVER_ENTER) {
int backgroundTint = pref.getBoolean("transparent_start_menu", false)
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && FreeformHackHelper.getInstance().isInFreeformWorkspace()) {
DisplayMetrics metrics = U.getRealDisplayMetrics(getContext());
- if(intent != null && Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1)
+ if(intent != null && U.hasBrokenSetLaunchBoundsApi())
intent.putExtra("context_menu_fix", true);
getContext().startActivity(intent, U.getActivityOptions(ApplicationType.CONTEXT_MENU).setLaunchBounds(new Rect(0, 0, metrics.widthPixels, metrics.heightPixels)).toBundle());
&& pref.getBoolean("freeform_hack", false)
&& !FreeformHackHelper.getInstance().isFreeformHackActive();
}
-
- private boolean visualFeedbackEnabled() {
- SharedPreferences pref = U.getSharedPreferences(getContext());
- return Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1 && pref.getBoolean("visual_feedback", true);
- }
}
package com.farmerbb.taskbar.fragment;
import android.annotation.SuppressLint;
+import android.app.Activity;
import android.content.ActivityNotFoundException;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
boolean secondScreenPrefEnabled = false;
+ private BroadcastReceiver homeToggleReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ SharedPreferences pref = U.getSharedPreferences(getActivity());
+ CheckBoxPreference checkBox = (CheckBoxPreference) findPreference("launcher");
+ checkBox.setChecked(pref.getBoolean("launcher", false));
+ }
+ };
+
@Override
public void onCreate(Bundle savedInstanceState) {
finishedLoadingPrefs = false;
SharedPreferences pref = U.getSharedPreferences(getActivity());
boolean lockHomeToggle = pref.getBoolean("launcher", false)
- && (U.hasSupportLibrary(getActivity())
- || BuildConfig.APPLICATION_ID.equals(BuildConfig.ANDROIDX86_APPLICATION_ID));
+ && U.isLauncherPermanentlyEnabled(getActivity());
findPreference("launcher").setEnabled(!lockHomeToggle);
if(secondScreenPrefEnabled) {
findPreference("secondscreen").setTitle(
- getSecondScreenPackageName() == null
+ U.getSecondScreenPackageName(getActivity()) == null
? R.string.pref_secondscreen_title_install
: R.string.pref_secondscreen_title_open);
}
updateDashboardGridSize(false);
}
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+
+ LocalBroadcastManager.getInstance(getActivity()).registerReceiver(homeToggleReceiver,
+ new IntentFilter("com.farmerbb.taskbar.LAUNCHER_PREF_CHANGED"));
+ }
+
+ @Override
+ public void onDetach() {
+ LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(homeToggleReceiver);
+
+ super.onDetach();
+ }
+
@SuppressLint("SetTextI18n")
@Override
public boolean onPreferenceClick(final Preference p) {
break;
case "secondscreen":
PackageManager packageManager = getActivity().getPackageManager();
- String packageName = getSecondScreenPackageName();
+ String packageName = U.getSecondScreenPackageName(getActivity());
Intent intent2;
if(packageName == null) {
if(restartTaskbar) U.restartTaskbar(getActivity());
}
-
- private String getSecondScreenPackageName() {
- PackageManager pm = getActivity().getPackageManager();
- String packageName;
-
- try {
- packageName = "com.farmerbb.secondscreen.free";
- pm.getPackageInfo(packageName, 0);
- } catch (PackageManager.NameNotFoundException e) {
- try {
- packageName = "com.farmerbb.secondscreen";
- pm.getPackageInfo(packageName, 0);
- } catch (PackageManager.NameNotFoundException e1) {
- packageName = null;
- }
- }
-
- return packageName;
- }
}
AlertDialog dialog = builder.create();
dialog.show();
dialog.setCancelable(false);
- } else if(U.isUntestedAndroidVersion(getActivity())
- && pref.getInt("current_api_version", Build.VERSION.SDK_INT - 1) < Build.VERSION.SDK_INT) {
+ } else if(U.isUntestedAndroidVersion(getActivity())) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.samsung_freeform_title)
.setMessage(R.string.dialog_upgrade_message)
- .setPositiveButton(R.string.action_ok, (dialog, which) -> pref.edit().putInt("current_api_version", Build.VERSION.SDK_INT).apply());
+ .setPositiveButton(R.string.action_ok, (dialog, which) -> pref.edit().putFloat("current_api_version_new", U.getCurrentApiVersion()).apply());
AlertDialog dialog = builder.create();
dialog.show();
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
builder.setTitle(R.string.freeform_dialog_title)
.setMessage(R.string.freeform_dialog_message_alt)
- .setPositiveButton(R.string.action_ok, (dialogInterface, i) -> freeformSetupComplete());
+ .setPositiveButton(R.string.action_continue, (dialogInterface, i) -> freeformSetupComplete());
} else {
builder.setTitle(R.string.freeform_dialog_title)
.setMessage(R.string.freeform_dialog_message)
CompatUtils.pinAppShortcut(getActivity());
break;
case "window_size":
- if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
+ if(U.hasBrokenSetLaunchBoundsApi())
U.showToastLong(getActivity(), R.string.window_sizes_not_available);
- }
-
break;
}
import com.farmerbb.taskbar.util.FreeformHackHelper;
import com.farmerbb.taskbar.util.U;
-public class SettingsFragment extends PreferenceFragment {
+public abstract class SettingsFragment extends PreferenceFragment {
boolean finishedLoadingPrefs;
boolean showReminderToast = false;
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
+ if(Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
+ // Initialize preferences on BlissOS
SharedPreferences pref = U.getSharedPreferences(context);
+ if(U.isBlissOs(context) && !pref.getBoolean("bliss_os_prefs", false))
+ U.initPrefs(context);
+
SharedPreferences.Editor editor = pref.edit();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
public class PackageUpgradeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- if(intent.getAction().equals(Intent.ACTION_MY_PACKAGE_REPLACED)) {
+ if(Intent.ACTION_MY_PACKAGE_REPLACED.equals(intent.getAction())) {
SharedPreferences pref = U.getSharedPreferences(context);
boolean startServices = false;
public class QuitReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- Intent taskbarIntent = new Intent(context, TaskbarService.class);
- Intent startMenuIntent = new Intent(context, StartMenuService.class);
- Intent dashboardIntent = new Intent(context, DashboardService.class);
- Intent notificationIntent = new Intent(context, NotificationService.class);
-
SharedPreferences pref = U.getSharedPreferences(context);
- pref.edit().putBoolean("taskbar_active", false).apply();
+ if(!pref.getBoolean("skip_quit_receiver", false)) {
+ Intent taskbarIntent = new Intent(context, TaskbarService.class);
+ Intent startMenuIntent = new Intent(context, StartMenuService.class);
+ Intent dashboardIntent = new Intent(context, DashboardService.class);
+ Intent notificationIntent = new Intent(context, NotificationService.class);
+
+ pref.edit().putBoolean("taskbar_active", false).apply();
- if(!LauncherHelper.getInstance().isOnHomeScreen()) {
- context.stopService(taskbarIntent);
- context.stopService(startMenuIntent);
- context.stopService(dashboardIntent);
+ if(!LauncherHelper.getInstance().isOnHomeScreen()) {
+ context.stopService(taskbarIntent);
+ context.stopService(startMenuIntent);
+ context.stopService(dashboardIntent);
- IconCache.getInstance(context).clearCache();
+ IconCache.getInstance(context).clearCache();
- LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.START_MENU_DISAPPEARING"));
- }
+ LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.START_MENU_DISAPPEARING"));
+ }
- context.stopService(notificationIntent);
+ context.stopService(notificationIntent);
+ } else
+ pref.edit().remove("skip_quit_receiver").apply();
}
}
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
+import android.os.Handler;
import com.farmerbb.taskbar.activity.DummyActivity;
import com.farmerbb.taskbar.service.NotificationService;
public void onReceive(Context context, Intent intent) {
SharedPreferences pref = U.getSharedPreferences(context);
- boolean taskbarNotActive = !pref.getBoolean("taskbar_active", false);
- boolean taskbarActiveButHidden = pref.getBoolean("taskbar_active", false) && pref.getBoolean("is_hidden", false);
+ boolean taskbarNotActive = !U.isServiceRunning(context, NotificationService.class);
+ boolean taskbarActiveButHidden = !taskbarNotActive && pref.getBoolean("is_hidden", false);
+
+ if(!U.canDrawOverlays(context)) {
+ new Handler().postDelayed(() -> {
+ Intent intent2 = new Intent(context, DummyActivity.class);
+ intent2.putExtra("show_permission_dialog", true);
+ intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ context.startActivity(intent2);
+ }, 250);
+ } else if(taskbarNotActive || taskbarActiveButHidden) {
+ U.initPrefs(context);
- if(taskbarNotActive || taskbarActiveButHidden) {
SharedPreferences.Editor editor = pref.edit();
editor.putBoolean("is_hidden", false);
if(pref.getBoolean("first_run", true)) {
editor.putBoolean("first_run", false);
editor.putBoolean("collapsed", true);
+
+ new Handler().postDelayed(() -> {
+ Intent intent2 = new Intent(context, DummyActivity.class);
+ intent2.putExtra("show_recent_apps_dialog", true);
+ intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ context.startActivity(intent2);
+ }, 250);
}
editor.putBoolean("taskbar_active", true);
notificationIntent.putExtra("start_services", true);
CompatUtils.startForegroundService(context, notificationIntent);
- }
+ } else if(intent.hasExtra("secondscreen"))
+ pref.edit().putBoolean("skip_quit_receiver", true).apply();
}
}
import android.os.Handler;
import android.os.IBinder;
import android.os.Process;
-import android.provider.Settings;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.graphics.ColorUtils;
import android.util.SparseArray;
SharedPreferences pref = U.getSharedPreferences(this);
if(pref.getBoolean("dashboard", false)) {
if(pref.getBoolean("taskbar_active", false) || LauncherHelper.getInstance().isOnHomeScreen()) {
- if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(this))
+ if(U.canDrawOverlays(this))
drawDashboard();
else {
pref.edit().putBoolean("taskbar_active", false).apply();
}
if(inFreeformMode) {
- if(intent != null && Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1)
+ if(intent != null && U.hasBrokenSetLaunchBoundsApi())
intent.putExtra("context_menu_fix", true);
U.launchAppMaximized(this, intent);
} catch (IllegalArgumentException e) { /* Gracefully fail */ }
SharedPreferences pref = U.getSharedPreferences(this);
- if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(this))
+ if(U.canDrawOverlays(this))
drawDashboard();
else {
pref.edit().putBoolean("taskbar_active", false).apply();
import android.content.SharedPreferences;
import android.os.Build;
import android.os.IBinder;
-import android.provider.Settings;
import android.service.quicksettings.TileService;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.ContextCompat;
SharedPreferences pref = U.getSharedPreferences(this);
if(pref.getBoolean("taskbar_active", false)) {
- if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(this)) {
+ if(U.canDrawOverlays(this)) {
isHidden = U.getSharedPreferences(this).getBoolean("is_hidden", false);
Intent intent = new Intent(this, MainActivity.class);
import android.support.v7.widget.SearchView;
import android.util.DisplayMetrics;
import android.util.Patterns;
-import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
SharedPreferences pref = U.getSharedPreferences(this);
if(pref.getBoolean("taskbar_active", false) || LauncherHelper.getInstance().isOnHomeScreen()) {
- if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(this))
+ if(U.canDrawOverlays(this))
drawStartMenu();
else {
pref.edit().putBoolean("taskbar_active", false).apply();
}
// Initialize views
- int theme = 0;
-
- switch(pref.getString("theme", "light")) {
- case "light":
- theme = R.style.AppTheme;
- break;
- case "dark":
- theme = R.style.AppTheme_Dark;
- break;
- }
-
- ContextThemeWrapper wrapper = new ContextThemeWrapper(this, theme);
- layout = (StartMenuLayout) LayoutInflater.from(wrapper).inflate(layoutId, null);
+ layout = (StartMenuLayout) LayoutInflater.from(U.wrapContext(this)).inflate(layoutId, null);
startMenu = U.findViewById(layout, R.id.start_menu);
if((shouldShowSearchBox && !hasHardwareKeyboard) || Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1)
if(pref.getBoolean("transparent_start_menu", false))
startMenu.setBackgroundColor(0);
+ if(U.visualFeedbackEnabled(this))
+ startMenu.setRecyclerListener(view -> view.setBackgroundColor(0));
+
searchView = U.findViewById(layout, R.id.search);
int backgroundTint = U.getBackgroundTint(this);
boolean inFreeformMode = FreeformHackHelper.getInstance().isInFreeformWorkspace();
if(!U.isChromeOs(this) && (!onHomeScreen || inFreeformMode)) {
- Class clazz = inFreeformMode && Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1
+ Class clazz = inFreeformMode && !U.hasBrokenSetLaunchBoundsApi()
? InvisibleActivityAlt.class
: InvisibleActivity.class;
windowManager.removeView(layout);
} catch (IllegalArgumentException e) { /* Gracefully fail */ }
- if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(this))
+ if(U.canDrawOverlays(this))
drawStartMenu();
else {
SharedPreferences pref = U.getSharedPreferences(this);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && FreeformHackHelper.getInstance().isInFreeformWorkspace()) {
DisplayMetrics metrics = U.getRealDisplayMetrics(this);
- if(intent != null && Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1)
+ if(intent != null && U.hasBrokenSetLaunchBoundsApi())
intent.putExtra("context_menu_fix", true);
startActivity(intent, U.getActivityOptions(ApplicationType.CONTEXT_MENU).setLaunchBounds(new Rect(0, 0, metrics.widthPixels, metrics.heightPixels)).toBundle());
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
-import android.provider.Settings;
import android.speech.RecognizerIntent;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.ColorUtils;
import android.util.DisplayMetrics;
-import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
SharedPreferences pref = U.getSharedPreferences(this);
if(pref.getBoolean("taskbar_active", false) || LauncherHelper.getInstance().isOnHomeScreen()) {
- if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(this))
+ if(U.canDrawOverlays(this))
drawTaskbar();
else {
pref.edit().putBoolean("taskbar_active", false).apply();
}
// Initialize views
- int theme = 0;
-
SharedPreferences pref = U.getSharedPreferences(this);
- switch(pref.getString("theme", "light")) {
- case "light":
- theme = R.style.AppTheme;
- break;
- case "dark":
- theme = R.style.AppTheme_Dark;
- break;
- }
-
boolean altButtonConfig = pref.getBoolean("alt_button_config", false);
- ContextThemeWrapper wrapper = new ContextThemeWrapper(this, theme);
- layout = (LinearLayout) LayoutInflater.from(wrapper).inflate(layoutId, null);
+ layout = (LinearLayout) LayoutInflater.from(U.wrapContext(this)).inflate(layoutId, null);
taskbar = U.findViewById(layout, R.id.taskbar);
scrollView = U.findViewById(layout, R.id.taskbar_scrollview);
if(pref.getBoolean("app_drawer_icon", false)) {
startButton.setImageDrawable(ContextCompat.getDrawable(this,
- U.hasSupportLibrary(this, 5)
- ? R.drawable.bliss
- : R.mipmap.ic_launcher));
+ U.isBlissOs(this) ? R.drawable.bliss : R.mipmap.ic_launcher));
padding = getResources().getDimensionPixelSize(R.dimen.app_drawer_icon_padding_alt);
} else {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && FreeformHackHelper.getInstance().isInFreeformWorkspace()) {
DisplayMetrics metrics = U.getRealDisplayMetrics(this);
- if(intent != null && Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1)
+ if(intent != null && U.hasBrokenSetLaunchBoundsApi())
intent.putExtra("context_menu_fix", true);
startActivity(intent, U.getActivityOptions(ApplicationType.CONTEXT_MENU).setLaunchBounds(new Rect(0, 0, metrics.widthPixels, metrics.heightPixels)).toBundle());
currentTaskbarPosition = 0;
- if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(this))
+ if(U.canDrawOverlays(this))
drawTaskbar();
else {
SharedPreferences pref = U.getSharedPreferences(this);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && FreeformHackHelper.getInstance().isInFreeformWorkspace()) {
DisplayMetrics metrics = U.getRealDisplayMetrics(this);
- if(intent != null && Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1)
+ if(intent != null && U.hasBrokenSetLaunchBoundsApi())
intent.putExtra("context_menu_fix", true);
startActivity(intent, U.getActivityOptions(ApplicationType.CONTEXT_MENU).setLaunchBounds(new Rect(0, 0, metrics.widthPixels, metrics.heightPixels)).toBundle());
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.AlertDialog;
+import android.app.AppOpsManager;
import android.app.Service;
import android.app.admin.DevicePolicyManager;
import android.content.ActivityNotFoundException;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
-import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ShortcutInfo;
import android.os.UserManager;
import android.provider.Settings;
import android.support.v4.content.LocalBroadcastManager;
+import android.support.v7.view.ContextThemeWrapper;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Surface;
import com.farmerbb.taskbar.service.PowerMenuService;
import com.farmerbb.taskbar.service.StartMenuService;
import com.farmerbb.taskbar.service.TaskbarService;
+import com.jrummyapps.android.os.SystemProperties;
import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
public class U {
return pref;
}
+ public static void showPermissionDialog(Context context) {
+ showPermissionDialog(context, null, null);
+ }
+
@TargetApi(Build.VERSION_CODES.M)
- public static AlertDialog showPermissionDialog(final Context context) {
+ public static AlertDialog showPermissionDialog(Context context, Runnable onError, Runnable onFinish) {
+ Runnable finalOnFinish = onFinish == null
+ ? () -> {}
+ : onFinish;
+
+ Runnable finalOnError = onError == null
+ ? () -> showErrorDialog(context, "SYSTEM_ALERT_WINDOW", finalOnFinish)
+ : onError;
+
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.permission_dialog_title)
.setMessage(R.string.permission_dialog_message)
try {
context.startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + BuildConfig.APPLICATION_ID)));
+
+ finalOnFinish.run();
} catch (ActivityNotFoundException e) {
- showErrorDialog(context, "SYSTEM_ALERT_WINDOW");
+ finalOnError.run();
}
});
return dialog;
}
- public static void showErrorDialog(final Context context, String appopCmd) {
+ public static AlertDialog showErrorDialog(Context context, String appopCmd) {
+ return showErrorDialog(context, appopCmd, null);
+ }
+
+ private static AlertDialog showErrorDialog(Context context, String appopCmd, Runnable onFinish) {
+ Runnable finalOnFinish = onFinish == null
+ ? () -> {}
+ : onFinish;
+
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.error_dialog_title)
.setMessage(context.getString(R.string.error_dialog_message, BuildConfig.APPLICATION_ID, appopCmd))
- .setPositiveButton(R.string.action_ok, null);
+ .setPositiveButton(R.string.action_ok, (dialog, which) -> finalOnFinish.run());
AlertDialog dialog = builder.create();
dialog.show();
+ dialog.setCancelable(false);
+
+ return dialog;
}
public static void lockDevice(Context context) {
SharedPreferences pref = getSharedPreferences(context);
FreeformHackHelper helper = FreeformHackHelper.getInstance();
- boolean specialLaunch = Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1
+ boolean specialLaunch = hasBrokenSetLaunchBoundsApi()
&& FreeformHackHelper.getInstance().isInFreeformWorkspace()
&& MenuHelper.getInstance().isContextMenuOpen();
public static boolean hasFreeformSupport(Context context) {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
&& (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT)
- || Settings.Global.getInt(context.getContentResolver(), "enable_freeform_support", -1) == 1
+ || Settings.Global.getInt(context.getContentResolver(), "enable_freeform_support", 0) != 0
|| (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1
- && Settings.Global.getInt(context.getContentResolver(), "force_resizable_activities", -1) == 1));
+ && Settings.Global.getInt(context.getContentResolver(), "force_resizable_activities", 0) != 0));
}
public static boolean hasPartialFreeformSupport() {
stackId = FREEFORM_WORKSPACE_STACK_ID;
break;
case CONTEXT_MENU:
- if(Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1)
+ if(hasBrokenSetLaunchBoundsApi())
stackId = FULLSCREEN_WORKSPACE_STACK_ID;
break;
}
return context.getPackageManager().hasSystemFeature("org.chromium.arc");
}
- public static boolean hasSupportLibrary(Context context) {
- return hasSupportLibrary(context, 0);
+ public static boolean isBlissOs(Context context) {
+ String blissVersion = SystemProperties.get("ro.bliss.version");
+ return blissVersion != null && !blissVersion.isEmpty()
+ && BuildConfig.APPLICATION_ID.equals(BuildConfig.BASE_APPLICATION_ID)
+ && isSystemApp(context);
}
- public static boolean hasSupportLibrary(Context context, int minVersion) {
+ public static boolean isLauncherPermanentlyEnabled(Context context) {
+ if(BuildConfig.APPLICATION_ID.equals(BuildConfig.ANDROIDX86_APPLICATION_ID))
+ return true;
+
PackageManager pm = context.getPackageManager();
try {
- PackageInfo pInfo = pm.getPackageInfo(BuildConfig.SUPPORT_APPLICATION_ID, 0);
- return pInfo.versionCode >= minVersion
- && pm.checkSignatures(BuildConfig.SUPPORT_APPLICATION_ID, BuildConfig.APPLICATION_ID) == PackageManager.SIGNATURE_MATCH
+ pm.getPackageInfo(BuildConfig.SUPPORT_APPLICATION_ID, 0);
+ return pm.checkSignatures(BuildConfig.SUPPORT_APPLICATION_ID, BuildConfig.APPLICATION_ID) == PackageManager.SIGNATURE_MATCH
&& BuildConfig.APPLICATION_ID.equals(BuildConfig.BASE_APPLICATION_ID)
&& isSystemApp(context);
} catch (PackageManager.NameNotFoundException e) {
}
}
- // Customizations for Bliss-x86
- if(hasSupportLibrary(context, 5)
- && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ // Customizations for BlissOS
+ if(isBlissOs(context) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
+ && !pref.getBoolean("bliss_os_prefs", false)) {
SharedPreferences.Editor editor = pref.edit();
- if(U.hasFreeformSupport(context)) {
+ if(hasFreeformSupport(context)) {
editor.putBoolean("freeform_hack", true);
}
editor.putBoolean("button_home", true);
editor.putBoolean("button_recents", true);
editor.putBoolean("auto_hide_navbar", true);
+ editor.putBoolean("bliss_os_prefs", true);
try {
Settings.Secure.putString(context.getContentResolver(),
}
public static boolean isOverridingFreeformHack(Context context) {
- SharedPreferences pref = U.getSharedPreferences(context);
+ SharedPreferences pref = getSharedPreferences(context);
return isChromeOs(context) && pref.getBoolean("chrome_os_context_menu_fix", true);
}
}
public static boolean isUntestedAndroidVersion(Context context) {
- int androidSdkInt = Build.VERSION.SDK_INT;
- int targetSdkInt = context.getApplicationInfo().targetSdkVersion;
+ SharedPreferences pref = getSharedPreferences(context);
+ float testedApiVersion = 27.0f;
- if(androidSdkInt > targetSdkInt)
- return true;
+ return getCurrentApiVersion() > Math.max(testedApiVersion, pref.getFloat("current_api_version_new", testedApiVersion));
+ }
+
+ public static float getCurrentApiVersion() {
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
+ return Float.valueOf(Build.VERSION.SDK_INT + "." + Build.VERSION.PREVIEW_SDK_INT);
+ else
+ return (float) Build.VERSION.SDK_INT;
+ }
+
+ public static boolean hasBrokenSetLaunchBoundsApi() {
+ return Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1;
+ }
+
+ public static String getSecondScreenPackageName(Context context) {
+ return getInstalledPackage(context, Arrays.asList(
+ "com.farmerbb.secondscreen.free",
+ "com.farmerbb.secondscreen"));
+ }
+
+ // Returns the name of an installed package from a list of package names, in order of preference
+ private static String getInstalledPackage(Context context, List<String> packageNames) {
+ if(packageNames == null || packageNames.isEmpty())
+ return null;
- if(androidSdkInt >= Build.VERSION_CODES.M) {
- int previewSdkInt = Build.VERSION.PREVIEW_SDK_INT;
+ List<String> packages = packageNames instanceof ArrayList ? packageNames : new ArrayList<>(packageNames);
+ String packageName = packages.get(0);
- return androidSdkInt == targetSdkInt && previewSdkInt > 0;
+ try {
+ context.getPackageManager().getPackageInfo(packageName, 0);
+ return packageName;
+ } catch (PackageManager.NameNotFoundException e) {
+ packages.remove(0);
+ return getInstalledPackage(context, packages);
}
+ }
- return false;
+ public static boolean visualFeedbackEnabled(Context context) {
+ SharedPreferences pref = getSharedPreferences(context);
+ return Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1 && pref.getBoolean("visual_feedback", true);
+ }
+
+ public static void showRecentAppsDialog(Context context) {
+ showRecentAppsDialog(context, null, null);
+ }
+
+ public static AlertDialog showRecentAppsDialog(Context context, Runnable onError, Runnable onFinish) {
+ Runnable finalOnFinish = onFinish == null
+ ? () -> {}
+ : onFinish;
+
+ Runnable finalOnError = onError == null
+ ? () -> showErrorDialog(context, "GET_USAGE_STATS", finalOnFinish)
+ : onError;
+
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !isSystemApp(context)) {
+ ApplicationInfo applicationInfo = null;
+ try {
+ applicationInfo = context.getPackageManager().getApplicationInfo(BuildConfig.APPLICATION_ID, 0);
+ } catch (PackageManager.NameNotFoundException e) { /* Gracefully fail */ }
+
+ if(applicationInfo != null) {
+ AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+ int mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, applicationInfo.uid, applicationInfo.packageName);
+
+ if(mode != AppOpsManager.MODE_ALLOWED) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setTitle(R.string.pref_header_recent_apps)
+ .setMessage(R.string.enable_recent_apps)
+ .setPositiveButton(R.string.action_ok, (dialog, which) -> {
+ try {
+ context.startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));
+ showToastLong(context, R.string.usage_stats_message);
+
+ finalOnFinish.run();
+ } catch (ActivityNotFoundException e) {
+ finalOnError.run();
+ }
+ })
+ .setNegativeButton(R.string.action_cancel, (dialog, which) -> finalOnFinish.run());
+
+ AlertDialog dialog = builder.create();
+ dialog.show();
+ dialog.setCancelable(false);
+
+ return dialog;
+ }
+ }
+ }
+
+ finalOnFinish.run();
+ return null;
+ }
+
+ public static Context wrapContext(Context context) {
+ SharedPreferences pref = getSharedPreferences(context);
+
+ int theme = -1;
+ switch(pref.getString("theme", "light")) {
+ case "light":
+ theme = R.style.AppTheme;
+ break;
+ case "dark":
+ theme = R.style.AppTheme_Dark;
+ break;
+ }
+
+ return theme > -1 ? new ContextThemeWrapper(context, theme) : context;
}
}
--- /dev/null
+/*
+ * Copyright (C) 2015 Jared Rummler <jared.rummler@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.jrummyapps.android.os;
+
+/**
+ * Gives access to the system properties store. The system properties tore contains a list of string
+ * key-value pairs.
+ *
+ * @author Jared Rummler <jared.rummler@gmail.com>
+ * @since Feb 8, 2015
+ */
+public class SystemProperties {
+
+ // ===========================================================
+ // STATIC FIELDS
+ // ===========================================================
+
+ private static Class<?> CLASS;
+
+ // ===========================================================
+ // STATIC INITIALIZERS
+ // ===========================================================
+
+ static {
+ try {
+ CLASS = Class.forName("android.os.SystemProperties");
+ } catch (ClassNotFoundException e) {
+ }
+ }
+
+ // ===========================================================
+ // STATIC METHODS
+ // ===========================================================
+
+ /** Get the value for the given key. */
+ public static String get(String key) {
+ try {
+ return (String) CLASS.getMethod("get", String.class).invoke(null, key);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * Get the value for the given key.
+ *
+ * @return if the key isn't found, return def if it isn't null, or an empty string otherwise
+ */
+ public static String get(String key, String def) {
+ try {
+ return (String) CLASS.getMethod("get", String.class, String.class).invoke(null, key,
+ def);
+ } catch (Exception e) {
+ return def;
+ }
+ }
+
+ /**
+ * Get the value for the given key, and return as an integer.
+ *
+ * @param key
+ * the key to lookup
+ * @param def
+ * a default value to return
+ * @return the key parsed as an integer, or def if the key isn't found or cannot be parsed
+ */
+ public static int getInt(String key, int def) {
+ try {
+ return (Integer) CLASS.getMethod("getInt", String.class, int.class).invoke(null, key,
+ def);
+ } catch (Exception e) {
+ return def;
+ }
+ }
+
+ /**
+ * Get the value for the given key, and return as a long.
+ *
+ * @param key
+ * the key to lookup
+ * @param def
+ * a default value to return
+ * @return the key parsed as a long, or def if the key isn't found or cannot be parsed
+ */
+ public static long getLong(String key, long def) {
+ try {
+ return (Long) CLASS.getMethod("getLong", String.class, long.class).invoke(null, key,
+ def);
+ } catch (Exception e) {
+ return def;
+ }
+ }
+
+ /**
+ * Get the value for the given key, returned as a boolean. Values 'n', 'no', '0', 'false' or
+ * 'off' are considered false. Values 'y', 'yes', '1', 'true' or 'on' are considered true. (case
+ * sensitive). If the key does not exist, or has any other value, then the default result is
+ * returned.
+ *
+ * @param key
+ * the key to lookup
+ * @param def
+ * a default value to return
+ * @return the key parsed as a boolean, or def if the key isn't found or is not able to be
+ * parsed as a boolean.
+ */
+ public static boolean getBoolean(String key, boolean def) {
+ try {
+ return (Boolean) CLASS.getMethod("getBoolean", String.class, boolean.class).invoke(
+ null, key, def);
+ } catch (Exception e) {
+ return def;
+ }
+ }
+
+ /** Set the value for the given key. */
+ public static void set(String key, String val) {
+ try {
+ CLASS.getMethod("set", String.class, String.class).invoke(null, key, val);
+ } catch (Exception ignored) {
+ }
+ }
+
+ public static void addChangeCallback(Runnable callback) {
+ try {
+ CLASS.getMethod("addChangeCallback", Runnable.class).invoke(null, callback);
+ } catch (Exception ignored) {
+ }
+ }
+
+ public static void callChangeCallbacks() {
+ try {
+ CLASS.getMethod("callChangeCallbacks").invoke(null, (Object[]) null);
+ } catch (Exception ignored) {
+ }
+ }
+
+ private SystemProperties() {
+
+ }
+}
\ No newline at end of file
<string name="press_enter_alt">@string/press_enter</string>
- <string name="freeform_dialog_message_alt">In order for Taskbar to launch apps in freeform window mode, please follow these steps:\n\n• Go to Developer Options and enable USB debugging\n\n• Connect your device to a computer with the Android SDK installed, and run the following adb shell command:\n\nsettings put global enable_freeform_support 1\n\n• Reboot your device</string>
+ <string name="freeform_dialog_message_alt">In order for Taskbar to launch apps in freeform window mode, please follow these steps:\n\n• Go to Developer Options and enable USB debugging\n\n• Connect your device to a computer with the Android SDK installed, and run the following command (one-line):\n\nadb shell settings put global enable_freeform_support 1\n\n• Reboot your device</string>
<string name="color_picker_alpha">Alpha</string>
<string name="color_picker_red">Red</string>
<string name="pref_secondscreen_title_install">Install SecondScreen</string>
<string name="pref_secondscreen_description">Change your device\'s resolution and density when connected to an external display, for a Continuum or DeX-like experience</string>
- <string name="dialog_upgrade_message">Taskbar\'s freeform mode support has not been tested on this version of Android. It may behave in unexpected ways - check for updates if there are any issues.</string>
+ <string name="dialog_upgrade_message">Taskbar\'s freeform mode support has not been tested on this version of Android. It may stop working completely or behave in other unexpected ways.\n\nCheck for app updates if you see any issues.</string>
<string name="use_default">Use default</string>
+ <string name="action_continue">Continue</string>
+
</resources>
<dimen name="start_menu_grid_padding">4dp</dimen>
<dimen name="start_menu_icon_padding">6dp</dimen>
<dimen name="start_menu_no_apps_found_text">16sp</dimen>
+ <dimen name="phone_size_width">360dp</dimen>
+ <dimen name="phone_size_height">640dp</dimen>
</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2018 Braden Farmer
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <dimen name="phone_size_width">411dp</dimen>
+ <dimen name="phone_size_height">731dp</dimen>
+</resources>
<string name="press_enter_alt">@string/press_enter</string>
- <string name="freeform_dialog_message_alt">In order for Taskbar to launch apps in freeform window mode, please follow these steps:\n\n• Go to Developer Options and enable USB debugging\n\n• Connect your device to a computer with the Android SDK installed, and run the following adb shell command:\n\nsettings put global enable_freeform_support 1\n\n• Reboot your device</string>
+ <string name="freeform_dialog_message_alt">In order for Taskbar to launch apps in freeform window mode, please follow these steps:\n\n• Go to Developer Options and enable USB debugging\n\n• Connect your device to a computer with the Android SDK installed, and run the following command (one-line):\n\nadb shell settings put global enable_freeform_support 1\n\n• Reboot your device</string>
<string name="color_picker_alpha">Alpha</string>
<string name="color_picker_red">Red</string>
<string name="pref_secondscreen_title_install">Install SecondScreen</string>
<string name="pref_secondscreen_description">Change your device\'s resolution and density when connected to an external display, for a Continuum or DeX-like experience</string>
- <string name="dialog_upgrade_message">Taskbar\'s freeform mode support has not been tested on this version of Android. It may behave in unexpected ways - check for updates if there are any issues.</string>
+ <string name="dialog_upgrade_message">Taskbar\'s freeform mode support has not been tested on this version of Android. It may stop working completely or behave in other unexpected ways.\n\nCheck for app updates if you see any issues.</string>
<string name="use_default">Use default</string>
+ <string name="action_continue">Continue</string>
+
</resources>
<string name="pref_secondscreen_title_install">Install SecondScreen</string>
<string name="pref_secondscreen_description">Change your device\'s resolution and density when connected to an external display, for a Continuum or DeX-like experience</string>
- <string name="dialog_upgrade_message">Taskbar\'s freeform mode support has not been tested on this version of Android. It may behave in unexpected ways - check for updates if there are any issues.</string>
+ <string name="dialog_upgrade_message">Taskbar\'s freeform mode support has not been tested on this version of Android. It may stop working completely or behave in other unexpected ways.\n\nCheck for app updates if you see any issues.</string>
<string name="use_default">Use default</string>
+ <string name="action_continue">Continue</string>
+
</resources>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2016 Braden Farmer
+
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
+
http://www.apache.org/licenses/LICENSE-2.0
+
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2016 Braden Farmer
+
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
+
http://www.apache.org/licenses/LICENSE-2.0
+
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<resources>
<dimen name="context_menu_width">320dp</dimen>
- <dimen name="phone_size_width">360dp</dimen>
- <dimen name="phone_size_height">640dp</dimen>
</resources>
\ No newline at end of file
<resources>
<dimen name="max_width">720dp</dimen>
- <dimen name="phone_size_width">411dp</dimen>
- <dimen name="phone_size_height">731dp</dimen>
</resources>
<string name="pref_secondscreen_title_install">Install SecondScreen</string>
<string name="pref_secondscreen_description">Change your device\'s resolution and density when connected to an external display, for a Continuum or DeX-like experience</string>
- <string name="dialog_upgrade_message">Taskbar\'s freeform mode support has not been tested on this version of Android. It may behave in unexpected ways - check for updates if there are any issues.</string>
+ <string name="dialog_upgrade_message">Taskbar\'s freeform mode support has not been tested on this version of Android. It may stop working completely or behave in other unexpected ways.\n\nCheck for app updates if you see any issues.</string>
<string name="use_default">Use default</string>
+ <string name="action_continue">Continue</string>
+
</resources>
\ No newline at end of file
<color name="ic_launcher_adaptive_bg">#4557A6</color>
<color name="ic_freeform_mode_adaptive_bg">#4790CD</color>
+
+ <color name="app_shortcut_bg">#F5F5F5</color>
</resources>
<string name="pref_title_invisible_button">Hide button while Taskbar is collapsed</string>
<string name="pref_title_freeform_mode_help">Help & instructions for freeform mode</string>
<string name="freeform_help_dialog_title">Help & instructions</string>
- <string name="freeform_help_dialog_message"><b>About freeform mode</b>\n\nTaskbar lets you launch apps in freeform floating windows on Android 7.0+ (Nougat). No root access is required. Android 8.0+ (Oreo) is also supported via an adb shell command.\n\nSimply follow these steps to configure your device for launching apps in freeform mode:\n\n<b>1.</b> Check the box for \"Freeform window support\" inside the Taskbar app\n\n<b>2.</b> Follow the directions that appear in the pop-up to enable the proper settings on your device (one-time setup)\n\n<b>3.</b> Go to your device\'s recent apps page and clear all recent apps*\n\n<b>4.</b> Select an app using Taskbar to launch it in a freeform window\n\n* For best results, especially on Android 8.0+, restart your device before using freeform mode\n\n<b>Window size presets</b>\n\nTaskbar can launch app windows in various preset sizes. You can choose a window size by long-pressing or right-clicking an app icon and selecting \"New window.\"\n\nTo save a window size preset for a specific app, simply long-press the preset, and a checkmark will appear indicating that it is set as default. Taskbar will launch the app using this selected size on subsequent launches.\n\nNote that window sizes don\'t work correctly on Android 8.0+. However, you can work around this by launching the app, immediately closing it, then launching it again from Android\'s overview menu.\n\n<b>Troubleshooting</b>\n\n<i>• Apps still launch fullscreen</i>\n\nIf an app is launched that is already loaded into memory, Taskbar will bring it into the foreground. In order to launch the app into freeform mode, it has to be launched from a fresh state.\n\nSwipe the app away from recents, and then re-launch it from the recent apps page using Taskbar. If this doesn\'t work, then long-press the app icon, select \"App info,\" and then force stop the app. Alternatively, you can restart your device.\n\n<i>• Apps that are maximized cannot be restored into a window</i>\n\nIf you press the Maximize button on an app\'s title bar, Android will bring the app out of freeform mode and into fullscreen mode. As mentioned above, Taskbar can only launch apps into freeform windows if they are launched from a fresh state.\n\nTo fix this, you can maximize windows by tapping or clicking just outside the app\'s window frame. This will expand the window to fill all the available space while keeping it in the freeform window workspace.\n\n<b>Enabling full system-level freeform window support</b>\n\nIf you have access to a computer with the Android SDK installed, you can enable support for freeform mode at the system level by running the following adb shell command:\n\nsettings put global enable_freeform_support 1\n\nReboot your device after running the above command, and a new button will appear for app entries in your device\'s recent apps page to enter/exit freeform mode for a given app. (Note that the button does not work on Android 7.1.2)</string>
+ <string name="freeform_help_dialog_message"><b>About freeform mode</b>\n\nTaskbar lets you launch apps in freeform floating windows on Android 7.0+ (Nougat). No root access is required. Android 8.0+ (Oreo) is also supported via an adb shell command.\n\nSimply follow these steps to configure your device for launching apps in freeform mode:\n\n<b>1.</b> Check the box for \"Freeform window support\" inside the Taskbar app\n\n<b>2.</b> Follow the directions that appear in the pop-up to enable the proper settings on your device (one-time setup)\n\n<b>3.</b> Go to your device\'s recent apps page and clear all recent apps*\n\n<b>4.</b> Select an app using Taskbar to launch it in a freeform window\n\n* For best results, especially on Android 8.0+, restart your device before using freeform mode\n\n<b>Window size presets</b>\n\nTaskbar can launch app windows in various preset sizes. You can choose a window size by long-pressing or right-clicking an app icon and selecting \"New window.\"\n\nTo save a window size preset for a specific app, simply long-press the preset, and a checkmark will appear indicating that it is set as default. Taskbar will launch the app using this selected size on subsequent launches.\n\nNote that window sizes don\'t work correctly on Android 8.0+. However, you can work around this by launching the app, immediately closing it, then launching it again from Android\'s overview menu.\n\n<b>Troubleshooting</b>\n\n<i>• Apps still launch fullscreen</i>\n\nIf an app is launched that is already loaded into memory, Taskbar will bring it into the foreground. In order to launch the app into freeform mode, it has to be launched from a fresh state.\n\nSwipe the app away from recents, and then re-launch it from the recent apps page using Taskbar. If this doesn\'t work, then long-press the app icon, select \"App info,\" and then force stop the app. Alternatively, you can restart your device.\n\n<i>• Apps that are maximized cannot be restored into a window</i>\n\nIf you press the Maximize button on an app\'s title bar, Android will bring the app out of freeform mode and into fullscreen mode. As mentioned above, Taskbar can only launch apps into freeform windows if they are launched from a fresh state.\n\nTo fix this, you can maximize windows by tapping or clicking just outside the app\'s window frame. This will expand the window to fill all the available space while keeping it in the freeform window workspace.\n\n<b>Enabling full system-level freeform window support</b>\n\nIf you have access to a computer with the Android SDK installed, you can enable support for freeform mode at the system level by running the following command (one-line):\n\nadb shell settings put global enable_freeform_support 1\n\nReboot your device after running the above command, and a new button will appear for app entries in your device\'s recent apps page to enter/exit freeform mode for a given app. (Note that the button does not work on Android 7.1.2)</string>
<string name="action_developer_options">Open Developer Options</string>
<string name="action_close">Close</string>
<string name="press_enter_alt">No apps found\n\nPress Enter to open in browser</string>
- <string name="freeform_dialog_message_alt">In order for Taskbar to launch apps in freeform window mode, please follow these steps:\n\n• Go to Developer Options and enable USB debugging\n\n• Connect your device to a computer with the Android SDK installed, and run the following adb shell command:\n\nsettings put global enable_freeform_support 1\n\n• Reboot your device</string>
+ <string name="freeform_dialog_message_alt">In order for Taskbar to launch apps in freeform window mode, please follow these steps:\n\n• Go to Developer Options and enable USB debugging\n\n• Connect your device to a computer with the Android SDK installed, and run the following command (one-line):\n\nadb shell settings put global enable_freeform_support 1\n\n• Reboot your device</string>
<string name="color_picker_alpha">Alpha</string>
<string name="color_picker_red">Red</string>
<string name="pref_secondscreen_title_install">Install SecondScreen</string>
<string name="pref_secondscreen_description">Change your device\'s resolution and density when connected to an external display, for a Continuum or DeX-like experience</string>
- <string name="dialog_upgrade_message">Taskbar\'s freeform mode support has not been tested on this version of Android. It may behave in unexpected ways - check for updates if there are any issues.</string>
+ <string name="dialog_upgrade_message">Taskbar\'s freeform mode support has not been tested on this version of Android. It may stop working completely or behave in other unexpected ways.\n\nCheck for app updates if you see any issues.</string>
<string name="use_default">Use default</string>
+ <string name="action_continue">Continue</string>
+
</resources>
<permission android:name="${applicationId}.ENABLE_DISABLE_HOME"
android:protectionLevel="signature" />
+ <permission android:name="${applicationId}.ENABLE_DISABLE_FREEFORM"
+ android:protectionLevel="signature" />
+
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<action android:name="com.farmerbb.taskbar.TOGGLE_FREEFORM_MODE"/>
</intent-filter>
</receiver>
+ <receiver
+ android:name=".receiver.EnableFreeformReceiver"
+ android:enabled="true"
+ android:exported="true"
+ android:permission="${applicationId}.ENABLE_DISABLE_FREEFORM" >
+ <intent-filter>
+ <action android:name="com.farmerbb.taskbar.ENABLE_FREEFORM_MODE"/>
+ </intent-filter>
+ </receiver>
+ <receiver
+ android:name=".receiver.DisableFreeformReceiver"
+ android:enabled="true"
+ android:exported="true"
+ android:permission="${applicationId}.ENABLE_DISABLE_FREEFORM" >
+ <intent-filter>
+ <action android:name="com.farmerbb.taskbar.DISABLE_FREEFORM_MODE"/>
+ </intent-filter>
+ </receiver>
</application>
--- /dev/null
+/* Copyright 2018 Braden Farmer
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.farmerbb.taskbar.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.support.v4.content.LocalBroadcastManager;
+
+import com.farmerbb.taskbar.util.U;
+
+public class DisableFreeformReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ SharedPreferences pref = U.getSharedPreferences(context);
+ boolean freeformEnabled = pref.getBoolean("freeform_hack", false);
+
+ if(pref.getBoolean("skip_disable_freeform_receiver", false))
+ pref.edit().remove("skip_disable_freeform_receiver").apply();
+ else if(!U.isChromeOs(context) && freeformEnabled) {
+ U.restartNotificationService(context);
+
+ pref.edit().putBoolean("freeform_hack", false).apply();
+
+ LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.UPDATE_FREEFORM_CHECKBOX"));
+ }
+ }
+}
\ No newline at end of file
@Override
public void onReceive(Context context, Intent intent) {
SharedPreferences pref = U.getSharedPreferences(context);
- pref.edit().putBoolean("launcher", false).apply();
+ if(pref.getBoolean("skip_disable_home_receiver", false))
+ pref.edit().remove("skip_disable_home_receiver").apply();
+ else if(!U.isLauncherPermanentlyEnabled(context)) {
+ pref.edit().putBoolean("launcher", false).apply();
- ComponentName component = new ComponentName(context, HomeActivity.class);
- context.getPackageManager().setComponentEnabledSetting(component,
- PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP);
+ ComponentName component = new ComponentName(context, HomeActivity.class);
+ context.getPackageManager().setComponentEnabledSetting(component,
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP);
- LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.KILL_HOME_ACTIVITY"));
+ LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(context);
+ lbm.sendBroadcast(new Intent("com.farmerbb.taskbar.KILL_HOME_ACTIVITY"));
+ lbm.sendBroadcast(new Intent("com.farmerbb.taskbar.LAUNCHER_PREF_CHANGED"));
+ }
}
}
--- /dev/null
+/* Copyright 2018 Braden Farmer
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.farmerbb.taskbar.receiver;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.support.v4.content.LocalBroadcastManager;
+
+import com.farmerbb.taskbar.util.U;
+
+public class EnableFreeformReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ SharedPreferences pref = U.getSharedPreferences(context);
+ boolean freeformEnabled = pref.getBoolean("freeform_hack", false);
+
+ if(intent.hasExtra("secondscreen") && freeformEnabled)
+ pref.edit().putBoolean("skip_disable_freeform_receiver", true).apply();
+ else if(U.hasFreeformSupport(context) && !freeformEnabled) {
+ U.restartNotificationService(context);
+
+ pref.edit().putBoolean("freeform_hack", true).apply();
+
+ LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.UPDATE_FREEFORM_CHECKBOX"));
+ }
+ }
+}
\ No newline at end of file
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
+import android.support.v4.content.LocalBroadcastManager;
import com.farmerbb.taskbar.activity.HomeActivity;
import com.farmerbb.taskbar.util.U;
public class EnableHomeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- if(U.canDrawOverlays(context)) {
- SharedPreferences pref = U.getSharedPreferences(context);
+ SharedPreferences pref = U.getSharedPreferences(context);
+ if(intent.hasExtra("secondscreen") && pref.getBoolean("launcher", false))
+ pref.edit().putBoolean("skip_disable_home_receiver", true).apply();
+ else if(U.canDrawOverlays(context)) {
SharedPreferences.Editor editor = pref.edit();
editor.putBoolean("launcher", true);
editor.apply();
context.getPackageManager().setComponentEnabledSetting(component,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
+
+ LocalBroadcastManager.getInstance(context)
+ .sendBroadcast(new Intent("com.farmerbb.taskbar.LAUNCHER_PREF_CHANGED"));
}
}
}
import com.farmerbb.taskbar.util.SavedWindowSizes;
import com.farmerbb.taskbar.util.SavedWindowSizesEntry;
import com.farmerbb.taskbar.util.TopApps;
-import com.farmerbb.taskbar.util.U;
import java.io.BufferedReader;
import java.io.File;
--- /dev/null
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="54.0"
+ android:viewportHeight="54.0">
+ <path
+ android:fillColor="@color/colorPrimary"
+ android:pathData="M23,20.5v14l11,-7z"/>
+</vector>
--- /dev/null
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="62.0"
+ android:viewportHeight="62.0">
+ <path
+ android:pathData="M26,24L24,24c-1.11,0 -2,0.9 -2,2v12c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L40,26c0,-1.1 -0.89,-2 -2,-2zM19,38L24,38L24,28h14v10z"
+ android:fillColor="@color/colorPrimary"/>
+</vector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/app_shortcut_bg"/>
+ <foreground android:drawable="@drawable/ic_web_asset_black_24dp_alt"/>
+</adaptive-icon>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/app_shortcut_bg"/>
+ <foreground android:drawable="@drawable/ic_play_arrow_black_24dp"/>
+</adaptive-icon>
\ No newline at end of file
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.5.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip