1 /* Copyright 2016 Braden Farmer
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 package com.farmerbb.taskbar.activity;
18 import android.annotation.TargetApi;
19 import android.app.AlertDialog;
20 import android.app.Fragment;
21 import android.app.FragmentTransaction;
22 import android.content.ActivityNotFoundException;
23 import android.content.BroadcastReceiver;
24 import android.content.ComponentName;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.SharedPreferences;
28 import android.content.pm.PackageInfo;
29 import android.content.pm.PackageManager;
30 import android.content.pm.ShortcutInfo;
31 import android.content.pm.ShortcutManager;
32 import android.graphics.drawable.Icon;
33 import android.net.Uri;
34 import android.os.Build;
35 import android.os.Bundle;
36 import android.os.Handler;
37 import android.view.View;
38 import android.widget.ImageView;
40 import androidx.appcompat.app.ActionBar;
41 import androidx.appcompat.app.AppCompatActivity;
42 import androidx.appcompat.widget.SwitchCompat;
44 import com.farmerbb.taskbar.BuildConfig;
45 import com.farmerbb.taskbar.R;
46 import com.farmerbb.taskbar.content.TaskbarIntent;
47 import com.farmerbb.taskbar.fragment.AboutFragment;
48 import com.farmerbb.taskbar.fragment.AdvancedFragment;
49 import com.farmerbb.taskbar.fragment.AppearanceFragment;
50 import com.farmerbb.taskbar.fragment.DesktopModeFragment;
51 import com.farmerbb.taskbar.fragment.FreeformModeFragment;
52 import com.farmerbb.taskbar.fragment.ManageAppDataFragment;
53 import com.farmerbb.taskbar.fragment.SettingsFragment;
54 import com.farmerbb.taskbar.service.DashboardService;
55 import com.farmerbb.taskbar.service.NotificationService;
56 import com.farmerbb.taskbar.service.StartMenuService;
57 import com.farmerbb.taskbar.service.TaskbarService;
58 import com.farmerbb.taskbar.util.FreeformHackHelper;
59 import com.farmerbb.taskbar.util.IconCache;
60 import com.farmerbb.taskbar.util.LauncherHelper;
61 import com.farmerbb.taskbar.util.U;
64 import java.util.Arrays;
65 import java.util.Collections;
67 public class MainActivity extends AppCompatActivity {
69 private SwitchCompat theSwitch;
70 private ImageView helpButton;
72 private BroadcastReceiver switchReceiver = new BroadcastReceiver() {
74 public void onReceive(Context context, Intent intent) {
79 private boolean hasCaption = false;
82 protected void onCreate(Bundle savedInstanceState) {
83 super.onCreate(savedInstanceState);
85 U.registerReceiver(this, switchReceiver, TaskbarIntent.ACTION_UPDATE_SWITCH);
87 final SharedPreferences pref = U.getSharedPreferences(this);
88 SharedPreferences.Editor editor = pref.edit();
90 if(!U.isLibrary(this)) {
91 switch(pref.getString("theme", "light")) {
93 setTheme(R.style.Taskbar);
96 setTheme(R.style.Taskbar_Dark);
100 int theme = getIntent().getIntExtra("theme", -1);
105 if(pref.getBoolean("taskbar_active", false) && !U.isServiceRunning(this, NotificationService.class))
106 editor.putBoolean("taskbar_active", false);
108 // Ensure that components that should be enabled are enabled properly
109 boolean launcherEnabled = (pref.getBoolean("launcher", false) && U.canDrawOverlays(this))
110 || U.isLauncherPermanentlyEnabled(this);
112 boolean desktopModeEnabled = U.isDesktopModeSupported(this)
113 && pref.getBoolean("desktop_mode", false);
115 editor.putBoolean("launcher", launcherEnabled);
116 editor.putBoolean("desktop_mode", desktopModeEnabled);
119 if(!U.isLibrary(this)) {
120 ComponentName component = new ComponentName(this, HomeActivity.class);
121 getPackageManager().setComponentEnabledSetting(component,
122 launcherEnabled && !U.isDelegatingHomeActivity(this)
123 ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
124 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
125 PackageManager.DONT_KILL_APP);
127 ComponentName component2 = new ComponentName(this, KeyboardShortcutActivity.class);
128 getPackageManager().setComponentEnabledSetting(component2,
129 pref.getBoolean("keyboard_shortcut", false)
130 ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
131 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
132 PackageManager.DONT_KILL_APP);
134 ComponentName component3 = new ComponentName(this, ShortcutActivity.class);
135 getPackageManager().setComponentEnabledSetting(component3,
136 U.enableFreeformModeShortcut(this)
137 ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
138 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
139 PackageManager.DONT_KILL_APP);
141 ComponentName component4 = new ComponentName(this, StartTaskbarActivity.class);
142 getPackageManager().setComponentEnabledSetting(component4,
143 PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
144 PackageManager.DONT_KILL_APP);
146 ComponentName component5 = new ComponentName(this, SecondaryHomeActivity.class);
147 getPackageManager().setComponentEnabledSetting(component5,
149 ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
150 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
151 PackageManager.DONT_KILL_APP);
153 ComponentName component6 = new ComponentName(this, HSLActivity.class);
154 getPackageManager().setComponentEnabledSetting(component6,
156 ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
157 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
158 PackageManager.DONT_KILL_APP);
160 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
161 ComponentName component7 = new ComponentName(this, KeyboardShortcutActivityLockDevice.class);
162 getPackageManager().setComponentEnabledSetting(component7,
163 pref.getBoolean("keyboard_shortcut", false)
164 ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
165 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
166 PackageManager.DONT_KILL_APP);
170 if(!launcherEnabled) {
171 U.sendBroadcast(this, TaskbarIntent.ACTION_KILL_HOME_ACTIVITY);
174 // Update caption state
175 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && U.isChromeOs(this)) {
176 getWindow().setRestrictedCaptionAreaListener(rect -> hasCaption = true);
178 new Handler().postDelayed(() -> pref.edit().putBoolean("has_caption", hasCaption).apply(), 500);
181 if(getPackageName().equals(BuildConfig.PAID_APPLICATION_ID)) {
182 File file = new File(getFilesDir() + File.separator + "imported_successfully");
183 if(freeVersionInstalled() && !file.exists()) {
184 startActivity(new Intent(this, ImportSettingsActivity.class));
187 proceedWithAppLaunch(savedInstanceState);
189 proceedWithAppLaunch(savedInstanceState);
192 private boolean freeVersionInstalled() {
193 PackageManager pm = getPackageManager();
195 PackageInfo pInfo = pm.getPackageInfo(BuildConfig.BASE_APPLICATION_ID, 0);
196 return pInfo.versionCode >= 68
197 && pm.checkSignatures(BuildConfig.BASE_APPLICATION_ID, getPackageName())
198 == PackageManager.SIGNATURE_MATCH;
199 } catch (PackageManager.NameNotFoundException e) {
204 private void proceedWithAppLaunch(Bundle savedInstanceState) {
206 setContentView(R.layout.tb_main);
207 } catch (IllegalStateException e) {
208 setTheme(R.style.Theme_AppCompat_Light);
209 setContentView(R.layout.tb_main);
212 ActionBar actionBar = getSupportActionBar();
213 if(actionBar != null && !U.isLibrary(this)) {
214 actionBar.setCustomView(R.layout.tb_switch_layout);
215 actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_CUSTOM);
218 theSwitch = findViewById(R.id.the_switch);
219 helpButton = findViewById(R.id.help_button);
221 if(theSwitch != null) {
222 final SharedPreferences pref = U.getSharedPreferences(this);
223 theSwitch.setChecked(pref.getBoolean("taskbar_active", false));
225 theSwitch.setOnCheckedChangeListener((compoundButton, b) -> {
227 if(U.canDrawOverlays(this)) {
228 boolean firstRun = pref.getBoolean("first_run", true);
229 startTaskbarService();
232 U.showRecentAppsDialog(this);
234 U.showPermissionDialog(this);
235 compoundButton.setChecked(false);
238 stopTaskbarService();
242 if(savedInstanceState == null) {
245 File restoreInProgress = new File(getFilesDir(), "restore_in_progress");
246 File restoreSuccessful = new File(getFilesDir(), "restore_successful");
248 if(restoreInProgress.exists() || restoreSuccessful.exists()) {
249 if(restoreInProgress.exists()) {
250 U.showToastLong(this, R.string.tb_restore_failed);
251 restoreInProgress.delete();
254 if(restoreSuccessful.exists()) {
255 U.showToastLong(this, R.string.tb_restore_successful);
256 restoreSuccessful.delete();
259 getFragmentManager().beginTransaction().replace(R.id.fragmentContainer, new ManageAppDataFragment(), "ManageAppDataFragment").commit();
260 } else if(!getIntent().hasExtra("theme_change"))
261 getFragmentManager().beginTransaction().replace(R.id.fragmentContainer, new AboutFragment(), "AboutFragment").commit();
263 getFragmentManager().beginTransaction().replace(R.id.fragmentContainer, new AppearanceFragment(), "AppearanceFragment").commit();
266 SharedPreferences pref = U.getSharedPreferences(this);
267 if(!getPackageName().equals(BuildConfig.BASE_APPLICATION_ID) && freeVersionInstalled()) {
268 if(!pref.getBoolean("dont_show_uninstall_dialog", false)) {
269 AlertDialog.Builder builder = new AlertDialog.Builder(this);
270 builder.setTitle(R.string.tb_settings_imported_successfully)
271 .setMessage(R.string.tb_import_dialog_message)
272 .setPositiveButton(R.string.tb_action_uninstall, (dialog, which) -> {
273 pref.edit().putBoolean("uninstall_dialog_shown", true).apply();
276 startActivity(new Intent(Intent.ACTION_DELETE, Uri.parse("package:" + BuildConfig.BASE_APPLICATION_ID)));
277 } catch (ActivityNotFoundException e) { /* Gracefully fail */ }
280 if(pref.getBoolean("uninstall_dialog_shown", false))
281 builder.setNegativeButton(R.string.tb_action_dont_show_again, (dialogInterface, i) -> pref.edit().putBoolean("dont_show_uninstall_dialog", true).apply());
283 AlertDialog dialog = builder.create();
285 dialog.setCancelable(false);
288 if(!pref.getBoolean("uninstall_dialog_shown", false)) {
289 if(theSwitch != null) theSwitch.setChecked(false);
291 SharedPreferences.Editor editor = pref.edit();
293 String iconPack = pref.getString("icon_pack", BuildConfig.BASE_APPLICATION_ID);
294 if(iconPack.contains(BuildConfig.BASE_APPLICATION_ID)) {
295 editor.putString("icon_pack", getPackageName());
297 U.refreshPinnedIcons(this);
300 editor.putBoolean("first_run", true);
305 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
306 ShortcutManager shortcutManager = getSystemService(ShortcutManager.class);
308 if(shortcutManager.getDynamicShortcuts().size() == 0) {
309 Intent intent = new Intent(Intent.ACTION_MAIN);
310 intent.setClass(this, StartTaskbarActivity.class);
311 intent.putExtra("is_launching_shortcut", true);
313 ShortcutInfo shortcut = new ShortcutInfo.Builder(this, "start_taskbar")
314 .setShortLabel(getString(R.string.tb_start_taskbar))
315 .setIcon(Icon.createWithResource(this, R.drawable.tb_shortcut_icon_start))
319 if(U.enableFreeformModeShortcut(this)) {
320 Intent intent2 = new Intent(Intent.ACTION_MAIN);
321 intent2.setClass(this, ShortcutActivity.class);
322 intent2.putExtra("is_launching_shortcut", true);
324 ShortcutInfo shortcut2 = new ShortcutInfo.Builder(this, "freeform_mode")
325 .setShortLabel(getString(R.string.tb_pref_header_freeform))
326 .setIcon(Icon.createWithResource(this, R.drawable.tb_shortcut_icon_freeform))
330 shortcutManager.setDynamicShortcuts(Arrays.asList(shortcut, shortcut2));
332 shortcutManager.setDynamicShortcuts(Collections.singletonList(shortcut));
338 protected void onResume() {
345 protected void onDestroy() {
346 U.unregisterReceiver(this, switchReceiver);
348 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && U.isChromeOs(this))
349 getWindow().setRestrictedCaptionAreaListener(null);
354 @TargetApi(Build.VERSION_CODES.N)
355 private void startTaskbarService() {
356 SharedPreferences pref = U.getSharedPreferences(this);
357 SharedPreferences.Editor editor = pref.edit();
359 editor.putBoolean("is_hidden", false);
361 if(pref.getBoolean("first_run", true)) {
362 editor.putBoolean("first_run", false);
363 editor.putBoolean("collapsed", true);
366 editor.putBoolean("taskbar_active", true);
367 editor.putLong("time_of_service_start", System.currentTimeMillis());
370 if(U.hasFreeformSupport(this)
371 && pref.getBoolean("freeform_hack", false)
372 && !FreeformHackHelper.getInstance().isFreeformHackActive()) {
373 U.startFreeformHack(this, true);
376 startService(new Intent(this, TaskbarService.class));
377 startService(new Intent(this, StartMenuService.class));
378 startService(new Intent(this, DashboardService.class));
379 startService(new Intent(this, NotificationService.class));
382 private void stopTaskbarService() {
383 SharedPreferences pref = U.getSharedPreferences(this);
384 pref.edit().putBoolean("taskbar_active", false).apply();
386 if(!LauncherHelper.getInstance().isOnHomeScreen()) {
387 stopService(new Intent(this, TaskbarService.class));
388 stopService(new Intent(this, StartMenuService.class));
389 stopService(new Intent(this, DashboardService.class));
391 IconCache.getInstance(this).clearCache();
393 U.sendBroadcast(this, TaskbarIntent.ACTION_START_MENU_DISAPPEARING);
396 stopService(new Intent(this, NotificationService.class));
399 private void updateSwitch() {
400 if(theSwitch != null) {
401 SharedPreferences pref = U.getSharedPreferences(this);
402 theSwitch.setChecked(pref.getBoolean("taskbar_active", false));
407 public void onBackPressed() {
408 Fragment oldFragment = getFragmentManager().findFragmentById(R.id.fragmentContainer);
410 if(oldFragment instanceof AboutFragment)
411 super.onBackPressed();
413 Fragment newFragment;
416 if(oldFragment instanceof ManageAppDataFragment) {
417 newFragment = new AdvancedFragment();
418 tag = "AdvancedFragment";
420 newFragment = new AboutFragment();
421 tag = "AboutFragment";
426 .replace(R.id.fragmentContainer, newFragment, tag)
427 .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE)
432 public String getAboutFragmentTitle() {
433 if(!U.isLibrary(this))
434 return getString(R.string.tb_app_name);
436 String title = getIntent().getStringExtra("title");
437 return title != null ? title : getString(R.string.tb_settings);
440 public boolean getAboutFragmentBackArrow() {
441 if(!U.isLibrary(this))
444 return getIntent().getBooleanExtra("back_arrow", false);
447 public void updateHelpButton(SettingsFragment fragment) {
448 if(fragment instanceof FreeformModeFragment) {
449 helpButton.setVisibility(View.VISIBLE);
450 helpButton.setOnClickListener(v -> {
451 AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
452 builder.setView(View.inflate(MainActivity.this, R.layout.tb_freeform_help_dialog, null))
453 .setTitle(R.string.tb_freeform_help_dialog_title)
454 .setPositiveButton(R.string.tb_action_close, null);
456 AlertDialog dialog = builder.create();
459 } else if(fragment instanceof DesktopModeFragment) {
460 helpButton.setVisibility(View.VISIBLE);
461 helpButton.setOnClickListener(v -> {
465 helpButton.setVisibility(View.INVISIBLE);
466 helpButton.setOnClickListener(null);