diff --git a/.gitignore b/.gitignore
index 9a94f0a..c1bb2bf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,4 +7,4 @@
/build
/captures
/app/build
-output.json
+output-metadata.json
diff --git a/Privacy-Policy.md b/Privacy-Policy.md
new file mode 100644
index 0000000..b7dc0c4
--- /dev/null
+++ b/Privacy-Policy.md
@@ -0,0 +1,8 @@
+## SecondScreen Privacy Policy
+
+This is an open source Android app and its entire [source code](https://github.com/farmerbb/SecondScreen) is available on GitHub under the [Apache 2.0](https://github.com/farmerbb/SecondScreen/blob/master/LICENSE) license.
+
+**This app does not connect to the internet in any way** - in fact, the Android operating system explicitly disallows internet access for this app in particular as it does not request the `android.permission.INTERNET` permission.
+
+This app does allow the Android operating system to backup and restore its data automatically via the Auto Backup service, which involves app data being periodically backed up to your personal Google Drive account.
+* For more information, see the [Auto Backup service documentation](https://developer.android.com/guide/topics/data/autobackup) and the [Google Drive Terms of Service](https://www.google.com/drive/terms-of-service/).
diff --git a/README.md b/README.md
index faf0643..1a13fa7 100644
--- a/README.md
+++ b/README.md
@@ -46,4 +46,6 @@ SecondScreen is an application designed for power users that frequently connect
* César Parga, Adrian Brown (Spanish)
* Christophe Romana (French)
* ja-som (Slovak)
-* Heimen Stoffels (German)
+* Heimen Stoffels (Dutch)
+* Asbesbopispa (Italian)
+* czheji (Chinese)
diff --git a/app/build.gradle b/app/build.gradle
index ec08410..2971e60 100755
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -9,43 +9,35 @@ repositories {
}
android {
- compileSdkVersion 29
- buildToolsVersion "28.0.3"
+ compileSdk 34
+ namespace "com.farmerbb.secondscreen"
defaultConfig {
applicationId "com.farmerbb.secondscreen"
- minSdkVersion 17
-
- /* targetSdkVersion is explicitly set to API 27.
- * This is the earliest API level that Google still allows apps to be published on the
- * Play Store with, and also happens to be the latest API level that Android allows using
- * reflection to set resolution / DPI on non-rooted devices with (on Android 9 and later)
- *
- * After November 1, 2019, the following changes will need to be made to SecondScreen:
- *
- * - Add verbiage somewhere in the app (a snackbar, maybe?) encouraging users to download
- * the SecondScreen Support Library as that will be the only way for users on non-rooted
- * devices running Android 9 or later to set resolution / DPI without a reboot
- *
- * - Re-implement the changes made in commit 434328b (and reverted in 3d36992) setting
- * the default UI refresh method to "soft reboot" on Android 9 and later
- */
+ minSdkVersion 21
+
//noinspection OldTargetApi
- targetSdkVersion 27
+ targetSdkVersion 34
- versionCode 183
- versionName "2.9.1"
+ versionCode 186
+ versionName "2.9.4"
- resConfigs "en", "es", "fr", "sk", "nl", "it"
+ resConfigs "en", "es", "fr", "sk", "nl", "it", "zh"
vectorDrawables.useSupportLibrary = true
- buildConfigField "float", "TESTED_API_VERSION", "29.0f"
+ buildConfigField "float", "TESTED_API_VERSION", "35.0f"
buildConfigField "String", "SUPPORT_APPLICATION_ID", "\"com.farmerbb.secondscreen.support\""
+ buildConfigField "long", "TIMESTAMP", "${System.currentTimeMillis()}L"
+ }
+
+ buildFeatures {
+ buildConfig true
}
compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
+ coreLibraryDesugaringEnabled true
+ sourceCompatibility JavaVersion.VERSION_21
+ targetCompatibility JavaVersion.VERSION_21
}
signingConfigs {
@@ -68,7 +60,7 @@ android {
release {
minifyEnabled true
shrinkResources true
- proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
manifestPlaceholders = [appName: "@string/app_name"]
@@ -106,11 +98,18 @@ android {
}
dependencies {
+ def shizuku_version = '12.1.0'
+
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
- implementation 'androidx.appcompat:appcompat:1.1.0'
- implementation 'com.google.android.material:material:1.0.0'
- implementation 'org.apache.commons:commons-lang3:3.9'
- implementation 'eu.chainfire:libsuperuser:1.1.0.201907261845'
+ implementation 'androidx.appcompat:appcompat:1.7.0'
+ implementation 'com.google.android.material:material:1.12.0'
+ implementation "dev.rikka.shizuku:api:$shizuku_version"
+ implementation "dev.rikka.shizuku:provider:$shizuku_version"
+ implementation 'org.apache.commons:commons-lang3:3.17.0'
+ implementation 'eu.chainfire:libsuperuser:1.1.1'
implementation 'moe.banana:toast-compat:1.0.5'
+ implementation 'org.lsposed.hiddenapibypass:hiddenapibypass:3.0'
implementation group:'com.twofortyfouram', name:'android-plugin-api-for-locale', version:'[1.0.2,2.0['
+
+ coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:2.1.2"
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 61ad2fe..2b3ef65 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -16,7 +16,6 @@
+
+
+
+
+
+
+
+
+
+
+ android:enabled="false"
+ android:exported="true">
@@ -109,7 +121,8 @@
android:name="com.farmerbb.secondscreen.activity.MainActivity"
android:label="${appName}"
android:launchMode="singleTask"
- android:windowSoftInputMode="adjustPan" >
+ android:windowSoftInputMode="adjustPan"
+ android:exported="true">
@@ -123,7 +136,9 @@
android:excludeFromRecents="true"
android:label="${appName}"
android:theme="@style/Theme.Secondscreen.Dialog.List"
- android:documentLaunchMode="always" >
+ android:documentLaunchMode="always"
+ android:exported="true"
+ tools:ignore="ExportedPreferenceActivity">
@@ -163,7 +178,8 @@
android:icon="@mipmap/ic_launcher"
android:label="@string/label_quick_actions"
android:documentLaunchMode="always"
- android:theme="@style/Theme.Secondscreen.QuickActionsDialog" >
+ android:theme="@style/Theme.Secondscreen.QuickActionsDialog"
+ tools:ignore="ExportedPreferenceActivity">
@@ -262,11 +278,16 @@
+ android:exported="true"
+ android:foregroundServiceType="specialUse">
+
+ android:permission="android.permission.BIND_INPUT_METHOD"
+ android:exported="true">
@@ -276,44 +297,92 @@
+ android:exported="true"
+ android:foregroundServiceType="specialUse">
+
+ android:exported="true"
+ android:foregroundServiceType="specialUse">
+
+ android:exported="true"
+ android:foregroundServiceType="specialUse">
+
+ android:exported="true"
+ android:foregroundServiceType="specialUse">
+
+ android:exported="true"
+ android:foregroundServiceType="specialUse">
+
+ android:exported="true"
+ android:foregroundServiceType="specialUse">
+
+ android:exported="true"
+ android:foregroundServiceType="specialUse">
+
+ android:exported="true"
+ android:foregroundServiceType="specialUse">
+
+ android:exported="true"
+ android:foregroundServiceType="specialUse">
+
+ android:exported="true"
+ android:foregroundServiceType="specialUse">
+
+
+
diff --git a/app/src/main/java/com/farmerbb/secondscreen/SecondScreenApplication.java b/app/src/main/java/com/farmerbb/secondscreen/SecondScreenApplication.java
new file mode 100644
index 0000000..b7bcbfc
--- /dev/null
+++ b/app/src/main/java/com/farmerbb/secondscreen/SecondScreenApplication.java
@@ -0,0 +1,32 @@
+/* Copyright 2020 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.secondscreen;
+
+import android.app.Application;
+import android.os.Build;
+
+import org.lsposed.hiddenapibypass.HiddenApiBypass;
+
+public class SecondScreenApplication extends Application {
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ HiddenApiBypass.addHiddenApiExemptions("");
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/farmerbb/secondscreen/activity/HdmiActivity.java b/app/src/main/java/com/farmerbb/secondscreen/activity/HdmiActivity.java
index a1af178..7801cff 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/activity/HdmiActivity.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/activity/HdmiActivity.java
@@ -129,8 +129,7 @@ private void showMenu() {
header.setTypeface(Typeface.DEFAULT);
// Close notification drawer
- Intent closeDrawer = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
- sendBroadcast(closeDrawer);
+ U.closeNotificationDrawer(this);
DisplayManager dm = (DisplayManager) getApplicationContext().getSystemService(DISPLAY_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
diff --git a/app/src/main/java/com/farmerbb/secondscreen/activity/MainActivity.java b/app/src/main/java/com/farmerbb/secondscreen/activity/MainActivity.java
index 32f6091..ef72477 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/activity/MainActivity.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/activity/MainActivity.java
@@ -15,6 +15,7 @@
package com.farmerbb.secondscreen.activity;
+import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.ActivityManager;
@@ -30,6 +31,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
@@ -41,6 +43,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
+import androidx.annotation.NonNull;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.appcompat.app.AppCompatActivity;
import android.view.Window;
@@ -142,12 +145,21 @@ protected Void doInBackground(Void... params) {
su[chromeCommand] = U.chromeCommandRemove;
su[sizeCommand] = U.sizeCommand(MainActivity.this, "reset");
- if(!(getPackageManager().hasSystemFeature("com.cyanogenmod.android")
+ PackageManager pm = getPackageManager();
+ if(!(pm.hasSystemFeature("com.cyanogenmod.android")
&& Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1)) {
- su[densityCommand] = U.densityCommand(MainActivity.this, "reset");
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_HOME);
+ ActivityInfo info = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY).activityInfo;
+
+ if(!info.packageName.startsWith("com.farmerbb.taskbar")
+ || !info.name.endsWith("HSLActivity")
+ || !U.isDesktopModeActive(MainActivity.this)) {
+ su[densityCommand] = U.densityCommand(MainActivity.this, "reset");
- // We run the density command twice, for reliability
- su[densityCommand2] = su[densityCommand];
+ // We run the density command twice, for reliability
+ su[densityCommand2] = su[densityCommand];
+ }
}
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)
@@ -191,7 +203,7 @@ protected void onPostExecute(Void result) {
boolean returningFromGrantingSystemAlertPermission = false;
String savedFilename;
- private BroadcastReceiver showDialogsReceiver = new BroadcastReceiver() {
+ private final BroadcastReceiver showDialogsReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
showMoreDialogs();
@@ -296,7 +308,7 @@ protected void onCreate(Bundle savedInstanceState) {
// Determine if we need to show any dialogs before we create the fragments
if(savedInstanceState == null)
- showDialogs();
+ showDialogs(false);
// Read debug mode preference
if(isDebugModeEnabled(false))
@@ -502,7 +514,7 @@ public void onFirstRunDialogPositiveClick() {
U.startService(this, serviceIntent);
// Determine if we need to show any dialogs before we create the fragments
- showDialogs();
+ showDialogs(false);
// Set launcher shortcuts on API 25+
setLauncherShortcuts();
@@ -904,8 +916,12 @@ public void uninstallPackage(String packageName) {
finish();
}
- private void showDialogs() {
- if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || U.hasElevatedPermissions(this))
+ private void showDialogs(boolean hasPreviouslyRequestedPermission) {
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
+ && checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED
+ && !hasPreviouslyRequestedPermission) {
+ requestPermissions(new String[]{Manifest.permission.POST_NOTIFICATIONS}, 42);
+ } else if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || U.hasElevatedPermissions(this))
showMoreDialogs();
else
startActivity(new Intent(this, UnableToStartActivity.class));
@@ -1061,4 +1077,10 @@ public void onSystemAlertPermissionDialogNegativeClick() {
onFirstLoadPositiveClick(null, filename, false);
}
}
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ showDialogs(true);
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/farmerbb/secondscreen/activity/NotificationSettingsActivity.java b/app/src/main/java/com/farmerbb/secondscreen/activity/NotificationSettingsActivity.java
index b9808bd..d577229 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/activity/NotificationSettingsActivity.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/activity/NotificationSettingsActivity.java
@@ -157,7 +157,7 @@ protected void onStop() {
* A preference value change listener that updates the preference's summary
* to reflect its new value.
*/
- private static Preference.OnPreferenceChangeListener opcl = (preference, value) -> {
+ private static final Preference.OnPreferenceChangeListener opcl = (preference, value) -> {
String stringValue = value.toString();
if(preference instanceof ListPreference) {
@@ -181,6 +181,8 @@ protected void onStop() {
@SuppressWarnings("deprecation")
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ if (key == null) return;
+
if(key.contains("notification_action")) {
String value = sharedPreferences.getString(key, "null");
diff --git a/app/src/main/java/com/farmerbb/secondscreen/activity/TaskerQuickActionsActivity.java b/app/src/main/java/com/farmerbb/secondscreen/activity/TaskerQuickActionsActivity.java
index eb94cf3..c082d17 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/activity/TaskerQuickActionsActivity.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/activity/TaskerQuickActionsActivity.java
@@ -27,6 +27,7 @@
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
+import android.preference.PreferenceCategory;
import android.preference.PreferenceManager;
import android.util.DisplayMetrics;
import android.view.Display;
@@ -63,8 +64,7 @@ protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Close notification drawer
- Intent closeDrawer = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
- sendBroadcast(closeDrawer);
+ U.closeNotificationDrawer(this);
String key = "Null";
String value = "Null";
@@ -132,22 +132,22 @@ else if(!key.equals("Null") && !value.equals("Null"))
findPreference("turn_off").setOnPreferenceClickListener(this);
// Disable unsupported preferences
- if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2)
- getPreferenceScreen().findPreference("temp_overscan").setEnabled(false);
+ if(!U.canEnableOverscan())
+ disablePreference("temp_overscan");
- if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
- getPreferenceScreen().findPreference("temp_immersive_new").setEnabled(false);
+ if(!U.canEnableImmersiveMode())
+ disablePreference("temp_immersive_new");
if(!U.canEnableFreeform(this))
- getPreferenceScreen().findPreference("temp_freeform").setEnabled(false);
+ disablePreference("temp_freeform");
if(U.getChromePackageName(this) == null)
- getPreferenceScreen().findPreference("temp_chrome").setEnabled(false);
+ disablePreference("temp_chrome");
if(U.isInNonRootMode(this)) {
- getPreferenceScreen().findPreference("temp_hdmi_rotation").setEnabled(false);
- getPreferenceScreen().findPreference("temp_chrome").setEnabled(false);
- getPreferenceScreen().findPreference("temp_freeform").setEnabled(false);
+ disablePreference("temp_hdmi_rotation");
+ disablePreference("temp_chrome");
+ disablePreference("temp_freeform");
}
// Set active state of "Reset settings" button
@@ -192,16 +192,14 @@ protected void onPause() {
@SuppressWarnings("deprecation")
private void resetSettingsButton() {
-
SharedPreferences prefSaved = U.getPrefQuickActions(this);
- if(prefSaved.getBoolean("quick_actions_active", false))
- getPreferenceScreen().findPreference("turn_off").setEnabled(true);
- else
- getPreferenceScreen().findPreference("turn_off").setEnabled(false);
+ getPreferenceScreen().findPreference("turn_off").setEnabled(prefSaved.getBoolean("quick_actions_active", false));
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ if (key == null) return;
+
if(launchedFromApp)
runQuickAction(key, sharedPreferences.getString(key, "Null"));
else
@@ -589,4 +587,13 @@ private void loadCurrentProfile(SharedPreferences prefSaved, SharedPreferences p
}
}
}
+
+ @SuppressWarnings("deprecation")
+ private void disablePreference(String preferenceName) {
+ PreferenceCategory category = (PreferenceCategory) getPreferenceScreen().findPreference("available_actions");
+ Preference preference = getPreferenceScreen().findPreference(preferenceName);
+ if (category != null && preference != null) {
+ category.removePreference(preference);
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/farmerbb/secondscreen/activity/TurnOffActivity.java b/app/src/main/java/com/farmerbb/secondscreen/activity/TurnOffActivity.java
index 0f48135..910ab30 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/activity/TurnOffActivity.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/activity/TurnOffActivity.java
@@ -63,8 +63,7 @@ protected void onCreate(Bundle savedInstanceState) {
String filename = prefCurrent.getString("filename", "0");
// Close notification drawer
- Intent closeDrawer = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
- sendBroadcast(closeDrawer);
+ U.closeNotificationDrawer(this);
// Handle intents
Intent quickLaunchIntent = getIntent();
diff --git a/app/src/main/java/com/farmerbb/secondscreen/activity/UnableToStartActivity.java b/app/src/main/java/com/farmerbb/secondscreen/activity/UnableToStartActivity.java
index f661e67..8230db8 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/activity/UnableToStartActivity.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/activity/UnableToStartActivity.java
@@ -16,10 +16,17 @@
package com.farmerbb.secondscreen.activity;
import android.Manifest;
+import android.annotation.SuppressLint;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Build;
import android.os.Bundle;
+
+import androidx.annotation.NonNull;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.appcompat.app.AppCompatActivity;
+
+import android.os.IBinder;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
@@ -28,13 +35,84 @@
import com.farmerbb.secondscreen.R;
import com.farmerbb.secondscreen.util.U;
+import java.lang.reflect.Method;
+
+import rikka.shizuku.Shizuku;
+import rikka.shizuku.ShizukuBinderWrapper;
+import rikka.shizuku.ShizukuProvider;
+import rikka.shizuku.SystemServiceHelper;
+
// This activity is responsible for informing the user that SecondScreen is unable to start.
-public final class UnableToStartActivity extends AppCompatActivity {
+public final class UnableToStartActivity extends AppCompatActivity implements Shizuku.OnRequestPermissionResultListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Shizuku.pingBinder()) {
+ proceedWithOnCreateShizuku();
+
+ boolean isGranted;
+ if(Shizuku.isPreV11() || Shizuku.getVersion() < 11) {
+ isGranted = checkSelfPermission(ShizukuProvider.PERMISSION) == PackageManager.PERMISSION_GRANTED;
+ } else {
+ isGranted = Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED;
+ }
+
+ if(isGranted) {
+ grantWriteSecureSettingsPermission();
+ } else {
+ int SHIZUKU_CODE = 123;
+ if(Shizuku.isPreV11() || Shizuku.getVersion() < 11) {
+ requestPermissions(new String[] { ShizukuProvider.PERMISSION }, SHIZUKU_CODE);
+ } else {
+ Shizuku.requestPermission(SHIZUKU_CODE);
+ }
+ }
+ } else {
+ proceedWithOnCreate();
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ for(int i = 0; i < permissions.length; i++) {
+ String permission = permissions[i];
+ int result = grantResults[i];
+
+ if(permission.equals(ShizukuProvider.PERMISSION)) {
+ onRequestPermissionResult(requestCode, result);
+ }
+ }
+ }
+
+ @Override
+ public void onRequestPermissionResult(int requestCode, int grantResult) {
+ boolean isGranted = grantResult == PackageManager.PERMISSION_GRANTED;
+ if(isGranted) {
+ grantWriteSecureSettingsPermission();
+ } else {
+ proceedWithOnCreate();
+ }
+ }
+
+ @SuppressLint("PrivateApi")
+ private void grantWriteSecureSettingsPermission() {
+ try {
+ Class> iPmClass = Class.forName("android.content.pm.IPackageManager");
+ Class> iPmStub = Class.forName("android.content.pm.IPackageManager$Stub");
+ Method asInterfaceMethod = iPmStub.getMethod("asInterface", IBinder.class);
+ Method grantRuntimePermissionMethod = iPmClass.getMethod("grantRuntimePermission", String.class, String.class, int.class);
+
+ Object iPmInstance = asInterfaceMethod.invoke(null, new ShizukuBinderWrapper(SystemServiceHelper.getSystemService("package")));
+ grantRuntimePermissionMethod.invoke(iPmInstance, BuildConfig.APPLICATION_ID, android.Manifest.permission.WRITE_SECURE_SETTINGS, 0);
+ } catch (Exception ignored) {}
+
+ proceedWithProfileLoad();
+ }
+
+ private void proceedWithOnCreate() {
setContentView(R.layout.activity_turn_off);
setTitle(R.string.permission_needed);
setFinishOnTouchOutside(false);
@@ -50,28 +128,46 @@ protected void onCreate(Bundle savedInstanceState) {
Button button2 = findViewById(R.id.turnOffButtonSecondary);
button1.setText(R.string.action_continue);
- button1.setOnClickListener(v -> {
- if(getIntent().hasExtra("action")) {
- if(U.hasElevatedPermissions(this, true)) {
- switch(getIntent().getStringExtra("action")) {
- case "load-profile":
- U.loadProfile(this, getIntent().getStringExtra("filename"));
- break;
- case "turn-off-profile":
- U.turnOffProfile(this);
- break;
- }
- }
- } else
- LocalBroadcastManager.getInstance(this)
- .sendBroadcast(new Intent("com.farmerbb.secondscreen.SHOW_DIALOGS"));
+ button1.setOnClickListener(v -> proceedWithProfileLoad());
+
+ button2.setVisibility(View.GONE);
+ }
+
+ private void proceedWithOnCreateShizuku() {
+ setContentView(R.layout.activity_turn_off);
+ setTitle(R.string.permission_needed);
- finish();
- });
+ TextView textView = findViewById(R.id.turnOffTextView);
+ textView.setText(R.string.shizuku_dialog);
+
+ Button button1 = findViewById(R.id.turnOffButtonPrimary);
+ Button button2 = findViewById(R.id.turnOffButtonSecondary);
+
+ button1.setText(R.string.action_close);
+ button1.setOnClickListener(v -> finish());
button2.setVisibility(View.GONE);
}
+ private void proceedWithProfileLoad() {
+ if(getIntent().hasExtra("action")) {
+ if(U.hasElevatedPermissions(this, true)) {
+ switch(getIntent().getStringExtra("action")) {
+ case "load-profile":
+ U.loadProfile(this, getIntent().getStringExtra("filename"));
+ break;
+ case "turn-off-profile":
+ U.turnOffProfile(this);
+ break;
+ }
+ }
+ } else
+ LocalBroadcastManager.getInstance(this)
+ .sendBroadcast(new Intent("com.farmerbb.secondscreen.SHOW_DIALOGS"));
+
+ finish();
+ }
+
// Disable the back button
@Override
public void onBackPressed() {}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/OverscanFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/OverscanFragment.java
index b99b94e..8bd1908 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/OverscanFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/OverscanFragment.java
@@ -67,7 +67,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
@@ -166,14 +166,11 @@ public void onStop() {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- // Override default Android "up" behavior to instead mimic the back button
+ if (item.getItemId() == android.R.id.home) {// Override default Android "up" behavior to instead mimic the back button
this.onBackPressed();
return true;
- default:
- return super.onOptionsItemSelected(item);
}
+ return super.onOptionsItemSelected(item);
}
public void onBackPressed() {
@@ -229,6 +226,8 @@ public boolean onPreferenceClick(Preference p) {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ if (key == null) return;
+
if(key.equals("overscan_left_expert")
|| key.equals("overscan_right_expert")
|| key.equals("overscan_top_expert")
@@ -253,7 +252,7 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin
* A preference value change listener that updates the preference's summary
* to reflect its new value.
*/
- private static Preference.OnPreferenceChangeListener opcl = (preference, value) -> {
+ private static final Preference.OnPreferenceChangeListener opcl = (preference, value) -> {
String stringValue = value.toString();
// Damage control if user inputs an empty value
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/ProfileEditFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/ProfileEditFragment.java
index 0c58691..75b9d84 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/ProfileEditFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/ProfileEditFragment.java
@@ -28,10 +28,10 @@
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
-import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.provider.Settings;
@@ -97,7 +97,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
@@ -178,9 +178,9 @@ public void onCreate(Bundle savedInstanceState) {
if(prefMain.getBoolean("expert_mode", false)) {
if("reset".equals(prefSaved.getString("size", "reset"))) {
- editor.putString("size", Integer.toString(prefMain.getInt("width", 0))
+ editor.putString("size", prefMain.getInt("width", 0)
+ "x"
- + Integer.toString(prefMain.getInt("height", 0)));
+ + prefMain.getInt("height", 0));
editor.putBoolean("size-reset", true);
} else
@@ -195,9 +195,9 @@ public void onCreate(Bundle savedInstanceState) {
if(prefSaved.getBoolean("size-reset", false)) {
editor.remove("size-reset");
- String nativeRes = Integer.toString(prefMain.getInt("width", 0))
+ String nativeRes = prefMain.getInt("width", 0)
+ "x"
- + Integer.toString(prefMain.getInt("height", 0));
+ + prefMain.getInt("height", 0);
if(nativeRes.equals(prefSaved.getString("size", "reset")))
editor.putString("size", "reset");
@@ -304,34 +304,37 @@ public void onCreate(Bundle savedInstanceState) {
// Disable unsupported preferences
if(!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH))
- disablePreference(prefNew, "bluetooth_on", true);
+ disablePreference("bluetooth_on", "additional_settings", true);
- if(!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI))
- disablePreference(prefNew, "wifi_on", true);
+ if(!U.canEnableWifi(getActivity()))
+ disablePreference("wifi_on", "additional_settings", true);
if(!getActivity().getPackageManager().hasSystemFeature("com.cyanogenmod.android"))
- disablePreference(prefNew, "navbar", true);
+ disablePreference("navbar", "additional_settings", true);
- if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2)
- disablePreference(prefNew, "overscan_settings", false);
+ if(!U.canEnableOverscan())
+ disablePreference("overscan_settings", "display_settings", false);
- if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
- disablePreference(prefNew, "immersive_new", false);
+ if(!U.canEnableImmersiveMode())
+ disablePreference("immersive_new", "display_settings", false);
if(!U.canEnableFreeform(getActivity()))
- disablePreference(prefNew, "freeform", true);
+ disablePreference("freeform", "desktop_optimization", true);
if(U.getChromePackageName(getActivity()) == null)
- disablePreference(prefNew, "chrome", true);
+ disablePreference("chrome", "desktop_optimization", true);
if(U.isInNonRootMode(getActivity())) {
- disablePreference(prefNew, "hdmi_rotation", false);
- disablePreference(prefNew, "chrome", false);
+ disablePreference("hdmi_rotation", "display_settings", false);
+ disablePreference("chrome", "desktop_optimization", false);
if(!U.hasSupportLibrary(getActivity()))
- disablePreference(prefNew, "show_touches", false);
+ disablePreference("show_touches", "additional_settings", false);
}
+ if(U.getTaskbarPackageName(getActivity()) == null || !U.isPlayStoreRelease(getActivity()))
+ disablePreference("taskbar", "desktop_optimization", true);
+
uiRefreshWarning = true;
}
@@ -347,27 +350,16 @@ public void onResume() {
else
getActivity().setTitle(" " + prefNew.getString("profile_name", getResources().getString(R.string.action_new)));
- if(prefNew.getBoolean("overscan", false))
- findPreference("overscan_settings").setSummary(getResources().getString(R.string.enabled));
- else
- findPreference("overscan_settings").setSummary(getResources().getString(R.string.disabled));
-
- String taskbarPackageName = U.getTaskbarPackageName(getActivity());
- if(taskbarPackageName == null || !U.isPlayStoreRelease(getActivity())) {
- disablePreference(prefNew, "taskbar", true);
-
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
- disablePreference(prefNew, "freeform", true);
- } else {
- findPreference("taskbar").setEnabled(true);
-
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
- findPreference("freeform").setEnabled(true);
+ if(U.canEnableOverscan()) {
+ if(prefNew.getBoolean("overscan", false))
+ findPreference("overscan_settings").setSummary(getResources().getString(R.string.enabled));
+ else
+ findPreference("overscan_settings").setSummary(getResources().getString(R.string.disabled));
}
if(taskbarSettingsPrefEnabled) {
findPreference("taskbar_settings").setTitle(
- taskbarPackageName == null
+ U.getTaskbarPackageName(getActivity()) == null
? R.string.pref_taskbar_settings_title_install
: R.string.pref_taskbar_settings_title_open);
}
@@ -396,39 +388,42 @@ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- switch(item.getItemId()) {
- case android.R.id.home:
- // Override default Android "up" behavior to instead mimic the back button
- onBackPressed(filename, false, true);
- return true;
-
- // Save button
- case R.id.action_save:
- onBackPressed(filename, false, false);
- return true;
-
- // Delete button
- case R.id.action_delete:
- // Show toast if this is the currently active profile
- SharedPreferences prefCurrent = U.getPrefCurrent(getActivity());
- if("quick_actions".equals(prefCurrent.getString("filename", "0"))) {
- SharedPreferences prefSaved = U.getPrefQuickActions(getActivity());
- if(filename.equals(prefSaved.getString("original_filename", "0")))
- U.showToast(getActivity(), R.string.deleting_current_profile);
- else
- listener.showDeleteDialog();
- } else if(filename.equals(prefCurrent.getString("filename", "0")))
+ int itemId = item.getItemId();
+
+ // Override default Android "up" behavior to instead mimic the back button
+ if (itemId == android.R.id.home) {
+ onBackPressed(filename, false, true);
+ return true;
+ }
+ // Save button
+ else if (itemId == R.id.action_save) {
+ onBackPressed(filename, false, false);
+ return true;
+ }
+ // Delete button
+ else if (itemId == R.id.action_delete) {
+ // Show toast if this is the currently active profile
+ SharedPreferences prefCurrent = U.getPrefCurrent(getActivity());
+ if ("quick_actions".equals(prefCurrent.getString("filename", "0"))) {
+ SharedPreferences prefSaved = U.getPrefQuickActions(getActivity());
+ if (filename.equals(prefSaved.getString("original_filename", "0")))
U.showToast(getActivity(), R.string.deleting_current_profile);
else
listener.showDeleteDialog();
- return true;
- default:
- return super.onOptionsItemSelected(item);
+ } else if (filename.equals(prefCurrent.getString("filename", "0")))
+ U.showToast(getActivity(), R.string.deleting_current_profile);
+ else
+ listener.showDeleteDialog();
+ return true;
+ } else {
+ return super.onOptionsItemSelected(item);
}
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ if (key == null) return;
+
prefChange = true;
switch(key) {
@@ -862,17 +857,18 @@ public void preSave(String filename, boolean isEdit, boolean returnToList) {
}
}
- private void disablePreference(SharedPreferences prefNew, String preferenceName, boolean shouldClear) {
+ private void disablePreference(String preferenceName, String categoryName, boolean shouldClear) {
+ Preference pref = getPreferenceScreen().findPreference(preferenceName);
+ if(pref == null) return;
+
+ SharedPreferences prefNew = U.getPrefNew(getActivity());
if(shouldClear && prefNew.getBoolean(preferenceName, false)) {
SharedPreferences.Editor editor = prefNew.edit();
editor.putBoolean(preferenceName, false);
editor.apply();
}
- Preference preference = getPreferenceScreen().findPreference(preferenceName);
- preference.setEnabled(false);
-
- if(preference instanceof CheckBoxPreference)
- ((CheckBoxPreference) preference).setChecked(false);
+ PreferenceCategory category = (PreferenceCategory) getPreferenceScreen().findPreference(categoryName);
+ category.removePreference(pref);
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/ProfileListFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/ProfileListFragment.java
index 3f0a66e..5ba40c4 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/ProfileListFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/ProfileListFragment.java
@@ -117,7 +117,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
@@ -194,28 +194,29 @@ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
- switch(item.getItemId()) {
- // Quick Actions button
- case R.id.action_quick:
- Intent intentQuick = new Intent(getActivity(), TaskerQuickActionsActivity.class);
- intentQuick.putExtra("launched-from-app", true);
- startActivity(intentQuick);
- return true;
-
- // Settings button
- case R.id.action_settings:
- Intent intentSettings = new Intent(getActivity(), FragmentContainerActivity.class);
- intentSettings.putExtra("tag", "SettingsFragment");
- startActivity(intentSettings);
- return true;
-
- // About button
- case R.id.action_about:
- DialogFragment aboutFragment = new AboutDialogFragment();
- aboutFragment.show(getFragmentManager(), "about");
- return true;
- default:
- return super.onOptionsItemSelected(item);
+ int itemId = item.getItemId();
+
+ // Quick Actions button
+ if (itemId == R.id.action_quick) {
+ Intent intentQuick = new Intent(getActivity(), TaskerQuickActionsActivity.class);
+ intentQuick.putExtra("launched-from-app", true);
+ startActivity(intentQuick);
+ return true;
+ }
+ // Settings button
+ else if (itemId == R.id.action_settings) {
+ Intent intentSettings = new Intent(getActivity(), FragmentContainerActivity.class);
+ intentSettings.putExtra("tag", "SettingsFragment");
+ startActivity(intentSettings);
+ return true;
+ }
+ // About button
+ else if (itemId == R.id.action_about) {
+ DialogFragment aboutFragment = new AboutDialogFragment();
+ aboutFragment.show(getFragmentManager(), "about");
+ return true;
+ } else {
+ return super.onOptionsItemSelected(item);
}
}
@@ -264,17 +265,11 @@ private void listProfiles() {
if("quick_actions".equals(prefCurrent.getString("filename", "0"))) {
SharedPreferences prefSaved = listener.getPrefQuickActions();
for(int i = 0; i < numOfFiles; i++) {
- if(profileList[0][i].equals(prefSaved.getString("original_filename", "0")))
- listView.setItemChecked(i, true);
- else
- listView.setItemChecked(i, false);
+ listView.setItemChecked(i, profileList[0][i].equals(prefSaved.getString("original_filename", "0")));
}
} else {
for(int i = 0; i < numOfFiles; i++) {
- if(profileList[0][i].equals(prefCurrent.getString("filename", "0")))
- listView.setItemChecked(i, true);
- else
- listView.setItemChecked(i, false);
+ listView.setItemChecked(i, profileList[0][i].equals(prefCurrent.getString("filename", "0")));
}
}
@@ -292,17 +287,11 @@ private void listProfiles() {
if("quick_actions".equals(prefCurrent.getString("filename", "0"))) {
SharedPreferences prefSaved = listener.getPrefQuickActions();
for(int i = 0; i < numOfFiles; i++) {
- if(profileList[0][i].equals(prefSaved.getString("original_filename", "0")))
- listView.setItemChecked(i, true);
- else
- listView.setItemChecked(i, false);
+ listView.setItemChecked(i, profileList[0][i].equals(prefSaved.getString("original_filename", "0")));
}
} else {
for(int i = 0; i < numOfFiles; i++) {
- if(profileList[0][i].equals(prefCurrent.getString("filename", "0")))
- listView.setItemChecked(i, true);
- else
- listView.setItemChecked(i, false);
+ listView.setItemChecked(i, profileList[0][i].equals(prefCurrent.getString("filename", "0")));
}
}
@@ -319,17 +308,11 @@ private void listProfiles() {
if("quick_actions".equals(prefCurrent.getString("filename", "0"))) {
SharedPreferences prefSaved = listener.getPrefQuickActions();
for(int i = 0; i < numOfFiles; i++) {
- if(profileList[0][i].equals(prefSaved.getString("original_filename", "0")))
- listView.setItemChecked(i, true);
- else
- listView.setItemChecked(i, false);
+ listView.setItemChecked(i, profileList[0][i].equals(prefSaved.getString("original_filename", "0")));
}
} else {
for(int i = 0; i < numOfFiles; i++) {
- if(profileList[0][i].equals(prefCurrent.getString("filename", "0")))
- listView.setItemChecked(i, true);
- else
- listView.setItemChecked(i, false);
+ listView.setItemChecked(i, profileList[0][i].equals(prefCurrent.getString("filename", "0")));
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/ProfileViewFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/ProfileViewFragment.java
index 44d53bb..240b40e 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/ProfileViewFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/ProfileViewFragment.java
@@ -75,7 +75,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
@@ -171,13 +171,12 @@ private void showUI() {
generateProfileSettings(prefSaved.getBoolean("navbar", false), R.string.profile_view_navbar);
generateProfileSettings(prefSaved.getBoolean("freeform", false), R.string.profile_view_freeform);
- switch(prefSaved.getString("hdmi_rotation", "landscape")) {
- case "portrait":
- generateProfileSettings(true, R.string.profile_view_hdmi_output);
- break;
+ if ("portrait".equals(prefSaved.getString("hdmi_rotation", "landscape"))) {
+ generateProfileSettings(true, R.string.profile_view_hdmi_output);
}
- generateProfileSettings(prefSaved.getBoolean("overscan", false), R.string.quick_overscan);
+ if(U.canEnableOverscan())
+ generateProfileSettings(prefSaved.getBoolean("overscan", false), R.string.quick_overscan);
switch(prefSaved.getString("rotation_lock_new", "fallback")) {
case "fallback":
@@ -203,17 +202,17 @@ private void showUI() {
generateProfileSettings(prefSaved.getBoolean("show_touches", false), R.string.pref_title_show_touches);
- switch(prefSaved.getString("immersive_new", "fallback")) {
- case "fallback":
- if(prefSaved.getBoolean("immersive", false))
+ if(U.canEnableImmersiveMode()) {
+ switch(prefSaved.getString("immersive_new", "fallback")) {
+ case "fallback":
+ if(prefSaved.getBoolean("immersive", false))
+ generateProfileSettings(true, R.string.pref_title_immersive);
+ break;
+ case "status-only":
+ case "immersive-mode":
generateProfileSettings(true, R.string.pref_title_immersive);
- break;
- case "status-only":
- generateProfileSettings(true, R.string.pref_title_immersive);
- break;
- case "immersive-mode":
- generateProfileSettings(true, R.string.pref_title_immersive);
- break;
+ break;
+ }
}
generateProfileSettings(prefSaved.getBoolean("taskbar", false), R.string.quick_taskbar);
@@ -267,45 +266,46 @@ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- // Override default Android "up" behavior to instead mimic the back button
- onBackPressed();
- return true;
-
- // Edit button
- case R.id.action_edit:
- Bundle bundle = new Bundle();
- bundle.putString("filename", filename);
-
- Fragment fragment = new ProfileEditFragment();
- fragment.setArguments(bundle);
-
- getFragmentManager()
- .beginTransaction()
- .replace(R.id.profileViewEdit, fragment, "ProfileEditFragment")
- .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
- .commit();
-
- return true;
-
- // Delete button
- case R.id.action_delete_2:
- // Show toast if this is the currently active profile
- SharedPreferences prefCurrent = U.getPrefCurrent(getActivity());
- if("quick_actions".equals(prefCurrent.getString("filename", "0"))) {
- SharedPreferences prefSaved = U.getPrefQuickActions(getActivity());
- if(filename.equals(prefSaved.getString("original_filename", "0")))
- U.showToast(getActivity(), R.string.deleting_current_profile);
- else
- listener.showDeleteDialog();
- } else if(filename.equals(prefCurrent.getString("filename", "0")))
+ int itemId = item.getItemId();
+
+ // Override default Android "up" behavior to instead mimic the back button
+ if (itemId == android.R.id.home) {
+ onBackPressed();
+ return true;
+ }
+ // Edit button
+ else if (itemId == R.id.action_edit) {
+ Bundle bundle = new Bundle();
+ bundle.putString("filename", filename);
+
+ Fragment fragment = new ProfileEditFragment();
+ fragment.setArguments(bundle);
+
+ getFragmentManager()
+ .beginTransaction()
+ .replace(R.id.profileViewEdit, fragment, "ProfileEditFragment")
+ .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
+ .commit();
+
+ return true;
+ }
+ // Delete button
+ else if (itemId == R.id.action_delete_2) {
+ // Show toast if this is the currently active profile
+ SharedPreferences prefCurrent = U.getPrefCurrent(getActivity());
+ if ("quick_actions".equals(prefCurrent.getString("filename", "0"))) {
+ SharedPreferences prefSaved = U.getPrefQuickActions(getActivity());
+ if (filename.equals(prefSaved.getString("original_filename", "0")))
U.showToast(getActivity(), R.string.deleting_current_profile);
else
listener.showDeleteDialog();
- return true;
- default:
- return super.onOptionsItemSelected(item);
+ } else if (filename.equals(prefCurrent.getString("filename", "0")))
+ U.showToast(getActivity(), R.string.deleting_current_profile);
+ else
+ listener.showDeleteDialog();
+ return true;
+ } else {
+ return super.onOptionsItemSelected(item);
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/SettingsFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/SettingsFragment.java
index 789f802..848647f 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/SettingsFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/SettingsFragment.java
@@ -70,7 +70,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
@@ -114,7 +114,6 @@ public void onStart() {
editor.putBoolean("expert_mode", prefMain.getBoolean("expert_mode", false));
editor.putBoolean("force_backlight_off", prefMain.getBoolean("force_backlight_off", false));
editor.putBoolean("tasker_enabled", prefMain.getBoolean("tasker_enabled", true));
- editor.putBoolean("notch_compat_mode", prefMain.getBoolean("notch_compat_mode", false));
editor.apply();
if(addPrefs) {
@@ -126,7 +125,6 @@ public void onStart() {
findPreference("expert_mode").setOnPreferenceClickListener(this);
findPreference("hdmi_select_profile").setOnPreferenceClickListener(this);
findPreference("notification_settings").setOnPreferenceClickListener(this);
- findPreference("notch_compat_mode").setOnPreferenceClickListener(this);
addPrefs = false;
}
@@ -158,22 +156,15 @@ public void onResume() {
} else
findPreference("hdmi_select_profile").setSummary(getResources().getString(R.string.show_list));
}
-
- findPreference("notch_compat_mode").setEnabled(
- Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !prefMain.getBoolean("landscape", false)
- );
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- // Override default Android "up" behavior to instead mimic the back button
- this.onBackPressed();
- return true;
- default:
- return super.onOptionsItemSelected(item);
+ if (item.getItemId() == android.R.id.home) {// Override default Android "up" behavior to instead mimic the back button
+ this.onBackPressed();
+ return true;
}
+ return super.onOptionsItemSelected(item);
}
public void onBackPressed() {
@@ -215,7 +206,6 @@ private void saveSettings() {
editor.putBoolean("expert_mode", prefNew.getBoolean("expert_mode", false));
editor.putBoolean("force_backlight_off", prefNew.getBoolean("force_backlight_off", false));
editor.putBoolean("tasker_enabled", prefNew.getBoolean("tasker_enabled", true));
- editor.putBoolean("notch_compat_mode", prefNew.getBoolean("notch_compat_mode", false));
editor.apply();
// Cleanup
@@ -225,7 +215,6 @@ private void saveSettings() {
prefNewEditor.remove("expert_mode");
prefNewEditor.remove("force_backlight_off");
prefNewEditor.remove("tasker_enabled");
- prefNewEditor.remove("notch_compat_mode");
prefNewEditor.apply();
}
@@ -275,10 +264,6 @@ public boolean onPreferenceClick(Preference p) {
Intent intent = new Intent(getActivity(), NotificationSettingsActivity.class);
startActivity(intent);
break;
- case "notch_compat_mode":
- if(!prefCurrent.getBoolean("not_active", true))
- U.showToast(getActivity(), R.string.notch_compat_mode_toast);
- break;
}
return true;
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/WelcomeFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/WelcomeFragment.java
index 0541b6e..0be6378 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/WelcomeFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/WelcomeFragment.java
@@ -108,28 +108,29 @@ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle presses on the action bar items
- switch(item.getItemId()) {
- // Quick Actions button
- case R.id.action_quick:
- Intent intentQuick = new Intent(getActivity(), TaskerQuickActionsActivity.class);
- intentQuick.putExtra("launched-from-app", true);
- startActivity(intentQuick);
- return true;
-
- // Settings button
- case R.id.action_settings:
- Intent intentSettings = new Intent(getActivity(), FragmentContainerActivity.class);
- intentSettings.putExtra("tag", "SettingsFragment");
- startActivity(intentSettings);
- return true;
-
- // About button
- case R.id.action_about:
- DialogFragment aboutFragment = new AboutDialogFragment();
- aboutFragment.show(getFragmentManager(), "about");
- return true;
- default:
- return super.onOptionsItemSelected(item);
+ int itemId = item.getItemId();
+
+ // Quick Actions button
+ if (itemId == R.id.action_quick) {
+ Intent intentQuick = new Intent(getActivity(), TaskerQuickActionsActivity.class);
+ intentQuick.putExtra("launched-from-app", true);
+ startActivity(intentQuick);
+ return true;
+ }
+ // Settings button
+ else if (itemId == R.id.action_settings) {
+ Intent intentSettings = new Intent(getActivity(), FragmentContainerActivity.class);
+ intentSettings.putExtra("tag", "SettingsFragment");
+ startActivity(intentSettings);
+ return true;
+ }
+ // About button
+ else if (itemId == R.id.action_about) {
+ DialogFragment aboutFragment = new AboutDialogFragment();
+ aboutFragment.show(getFragmentManager(), "about");
+ return true;
+ } else {
+ return super.onOptionsItemSelected(item);
}
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/AboutDialogFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/AboutDialogFragment.java
index 2e79a70..1b2a840 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/AboutDialogFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/AboutDialogFragment.java
@@ -29,6 +29,9 @@
import com.farmerbb.secondscreen.BuildConfig;
import com.farmerbb.secondscreen.R;
+import java.util.Calendar;
+import java.util.TimeZone;
+
// DialogFragment shown when "About SecondScreen" is clicked from the SettingsFragment
public final class AboutDialogFragment extends DialogFragment {
@@ -55,7 +58,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
@@ -81,8 +84,13 @@ public Dialog onCreateDialog(Bundle savedInstanceState) {
builder.setNegativeButton(R.string.check_for_update, (dialog, id) -> listener.onAboutDialogNegativeClick(this));
}
+ Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("America/Denver"));
+ calendar.setTimeInMillis(BuildConfig.TIMESTAMP);
+
+ int year = calendar.get(Calendar.YEAR);
+
textView = view.findViewById(R.id.dialogMessage);
- textView.setText(R.string.dialog_about_message);
+ textView.setText(getString(R.string.dialog_about_message, year));
textView.setMovementMethod(LinkMovementMethod.getInstance());
checkbox = view.findViewById(R.id.checkBoxLayout);
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/AndroidUpgradeDialogFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/AndroidUpgradeDialogFragment.java
index 72d4f20..e2ec403 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/AndroidUpgradeDialogFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/AndroidUpgradeDialogFragment.java
@@ -50,7 +50,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/BusyboxDialogFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/BusyboxDialogFragment.java
index c76e7b1..7c4bf90 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/BusyboxDialogFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/BusyboxDialogFragment.java
@@ -49,7 +49,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/DeleteDialogFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/DeleteDialogFragment.java
index 0cb5d5e..8f66439 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/DeleteDialogFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/DeleteDialogFragment.java
@@ -47,7 +47,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/ExpertModeDialogFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/ExpertModeDialogFragment.java
index 3b67a3b..4ef27f7 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/ExpertModeDialogFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/ExpertModeDialogFragment.java
@@ -52,7 +52,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/ExpertModeSizeDialogFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/ExpertModeSizeDialogFragment.java
index d1b2944..89f2ce6 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/ExpertModeSizeDialogFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/ExpertModeSizeDialogFragment.java
@@ -59,7 +59,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/FirstLoadDialogFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/FirstLoadDialogFragment.java
index 8524ab9..497b68c 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/FirstLoadDialogFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/FirstLoadDialogFragment.java
@@ -55,7 +55,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/FirstRunDialogFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/FirstRunDialogFragment.java
index bb3aab3..23af897 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/FirstRunDialogFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/FirstRunDialogFragment.java
@@ -55,7 +55,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/KeepOverscanDialogFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/KeepOverscanDialogFragment.java
index 65edf7f..3d962d4 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/KeepOverscanDialogFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/KeepOverscanDialogFragment.java
@@ -50,7 +50,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/MultipleVersionsDialogFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/MultipleVersionsDialogFragment.java
index 183f6bf..01a8f4c 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/MultipleVersionsDialogFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/MultipleVersionsDialogFragment.java
@@ -52,7 +52,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/NewDeviceDialogFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/NewDeviceDialogFragment.java
index 9fabd31..c429057 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/NewDeviceDialogFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/NewDeviceDialogFragment.java
@@ -51,7 +51,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/NewProfileDialogFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/NewProfileDialogFragment.java
index a27c924..cfeaf7b 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/NewProfileDialogFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/NewProfileDialogFragment.java
@@ -62,7 +62,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/ReloadProfileDialogFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/ReloadProfileDialogFragment.java
index aece65d..739bd18 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/ReloadProfileDialogFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/ReloadProfileDialogFragment.java
@@ -50,7 +50,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/SafeModeDialogFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/SafeModeDialogFragment.java
index 2dc1c89..ea69fb1 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/SafeModeDialogFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/SafeModeDialogFragment.java
@@ -52,7 +52,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/SystemAlertPermissionDialogFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/SystemAlertPermissionDialogFragment.java
index 2a74e49..884a63d 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/SystemAlertPermissionDialogFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/SystemAlertPermissionDialogFragment.java
@@ -47,7 +47,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/UiRefreshDialogFragment.java b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/UiRefreshDialogFragment.java
index ea3f100..4e937b8 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/UiRefreshDialogFragment.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/fragment/dialog/UiRefreshDialogFragment.java
@@ -49,7 +49,7 @@ public void onAttach(Activity activity) {
listener = (Listener) activity;
} catch (ClassCastException e) {
// The activity doesn't implement the interface, throw exception
- throw new ClassCastException(activity.toString()
+ throw new ClassCastException(activity
+ " must implement Listener");
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/receiver/TaskerConditionReceiver.java b/app/src/main/java/com/farmerbb/secondscreen/receiver/TaskerConditionReceiver.java
index 759ce1a..46db4f5 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/receiver/TaskerConditionReceiver.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/receiver/TaskerConditionReceiver.java
@@ -28,18 +28,25 @@
// Receiver run by Tasker periodically to check the state of currently active profiles, whenever
// a SecondScreen state is included as a condition in a Tasker profile.
public final class TaskerConditionReceiver extends BroadcastReceiver {
+ private Bundle lastbundle = null;
+
@SuppressWarnings("deprecation")
@Override
public void onReceive(Context context, Intent intent) {
if(U.isExternalAccessDisabled(context)) return;
+ if(lastbundle != null && lastbundle.equals(intent.getBundleExtra(com.twofortyfouram.locale.api.Intent.EXTRA_BUNDLE))) {
+ // bundle hasn't changed: we can safely return
+ return;
+ }
+ updateValues(intent);
+
BundleScrubber.scrub(intent);
- final Bundle bundle = intent.getBundleExtra(com.twofortyfouram.locale.api.Intent.EXTRA_BUNDLE);
- BundleScrubber.scrub(bundle);
+ BundleScrubber.scrub(lastbundle);
- if(PluginBundleManager.isBundleValid(bundle)) {
- String filename = bundle.getString(PluginBundleManager.BUNDLE_EXTRA_STRING_MESSAGE);
+ if(PluginBundleManager.isBundleValid(lastbundle)) {
+ String filename = lastbundle.getString(PluginBundleManager.BUNDLE_EXTRA_STRING_MESSAGE);
SharedPreferences prefCurrent = context.getSharedPreferences("current", Context.MODE_MULTI_PROCESS);
if("quick_actions".equals(prefCurrent.getString("filename", "0"))) {
@@ -72,4 +79,8 @@ public void onReceive(Context context, Intent intent) {
}
}
}
+
+ private void updateValues(Intent intent) {
+ lastbundle = intent.getBundleExtra(com.twofortyfouram.locale.api.Intent.EXTRA_BUNDLE);
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/farmerbb/secondscreen/service/BootService.java b/app/src/main/java/com/farmerbb/secondscreen/service/BootService.java
index d9f1916..7bf1267 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/service/BootService.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/service/BootService.java
@@ -60,7 +60,7 @@ protected void onHandleIntent(Intent intent) {
Arrays.fill(su, "");
if("auto-rotate".equals(prefCurrent.getString("rotation_lock_new", "do-nothing"))) {
- su[rotationCommand] = U.rotationCommand + Integer.toString(Intent.EXTRA_DOCK_STATE_DESK);
+ su[rotationCommand] = U.rotationCommand + Intent.EXTRA_DOCK_STATE_DESK;
if(Settings.Secure.getInt(getContentResolver(), "screensaver_enabled", 0) == 1
&& Settings.Secure.getInt(getContentResolver(), "screensaver_activate_on_dock", 0) == 1) {
su[rotationPreCommand] = U.rotationPrePostCommands + "0";
diff --git a/app/src/main/java/com/farmerbb/secondscreen/service/DisableKeyboardService.java b/app/src/main/java/com/farmerbb/secondscreen/service/DisableKeyboardService.java
index ae580d7..89db9e9 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/service/DisableKeyboardService.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/service/DisableKeyboardService.java
@@ -53,7 +53,7 @@ public void onStartInput(EditorInfo attribute, boolean restarting) {
if(notificationId == null && isEditingText && !hasHardwareKeyboard) {
Intent keyboardChangeIntent = new Intent(this, KeyboardChangeReceiver.class);
- PendingIntent keyboardChangePendingIntent = PendingIntent.getBroadcast(this, 0, keyboardChangeIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent keyboardChangePendingIntent = PendingIntent.getBroadcast(this, 0, keyboardChangeIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
NotificationCompat.Builder notification = new NotificationCompat.Builder(this)
.setContentIntent(keyboardChangePendingIntent)
diff --git a/app/src/main/java/com/farmerbb/secondscreen/service/DisplayConnectionService.java b/app/src/main/java/com/farmerbb/secondscreen/service/DisplayConnectionService.java
index 5450974..0724179 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/service/DisplayConnectionService.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/service/DisplayConnectionService.java
@@ -124,7 +124,7 @@ public void onCreate() {
public void startForeground() {
// Intent to launch MainActivity when notification is clicked
Intent mainActivityIntent = new Intent(this, MainActivity.class);
- PendingIntent mainActivityPendingIntent = PendingIntent.getActivity(this, 0, mainActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent mainActivityPendingIntent = PendingIntent.getActivity(this, 0, mainActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
String id = "DisplayConnectionService";
diff --git a/app/src/main/java/com/farmerbb/secondscreen/service/LockDeviceService.java b/app/src/main/java/com/farmerbb/secondscreen/service/LockDeviceService.java
index 71656dc..f65f25c 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/service/LockDeviceService.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/service/LockDeviceService.java
@@ -51,8 +51,7 @@ protected void onHandleIntent(Intent intent) {
super.onHandleIntent(intent);
// Close the notification drawer
- Intent closeDrawer = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
- sendBroadcast(closeDrawer);
+ U.closeNotificationDrawer(this);
// Determine current charging status
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
@@ -94,7 +93,7 @@ protected void onHandleIntent(Intent intent) {
// Schedule TimeoutService to reset lock screen timeout to original value
Intent timeoutService = new Intent(this, TimeoutService.class);
- PendingIntent pendingIntent = PendingIntent.getService(this, 123456, timeoutService, PendingIntent.FLAG_CANCEL_CURRENT);
+ PendingIntent pendingIntent = PendingIntent.getService(this, 123456, timeoutService, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
manager.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, pendingIntent);
diff --git a/app/src/main/java/com/farmerbb/secondscreen/service/NotificationService.java b/app/src/main/java/com/farmerbb/secondscreen/service/NotificationService.java
index c65cf85..a045598 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/service/NotificationService.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/service/NotificationService.java
@@ -177,7 +177,7 @@ protected void startService() {
// Intent to launch MainActivity when notification is clicked
Intent mainActivityIntent = new Intent(this, MainActivity.class);
- PendingIntent mainActivityPendingIntent = PendingIntent.getActivity(this, 0, mainActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ PendingIntent mainActivityPendingIntent = PendingIntent.getActivity(this, 0, mainActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
String id = "NotificationService";
@@ -232,25 +232,25 @@ private void setActionButton(String key, SharedPreferences prefCurrent, int code
// Turn Off
customIntent = new Intent(this, TurnOffActivity.class);
customIntent.putExtra("notification", true);
- customPendingIntent = PendingIntent.getActivity(this, code, customIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ customPendingIntent = PendingIntent.getActivity(this, code, customIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
customString = getResources().getStringArray(R.array.pref_notification_action_list)[0];
} else if(key.equals("lock-device")) {
// Lock Device
customIntent = new Intent(this, LockDeviceService.class);
- customPendingIntent = PendingIntent.getService(this, code, customIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ customPendingIntent = PendingIntent.getService(this, code, customIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
customString = getResources().getStringArray(R.array.pref_notification_action_list)[2];
} else if(key.equals("quick-actions")) {
// Quick Actions
customIntent = new Intent(this, TaskerQuickActionsActivity.class);
customIntent.putExtra("launched-from-app", true);
- customPendingIntent = PendingIntent.getActivity(this, code, customIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ customPendingIntent = PendingIntent.getActivity(this, code, customIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
customString = getResources().getStringArray(R.array.pref_notification_action_list)[1];
} else if(key.startsWith("temp_")) {
// Toggle
customIntent = new Intent(this, TaskerQuickActionsActivity.class);
customIntent.putExtra(U.KEY, key.equals("temp_immersive") ? "temp_immersive_new" : key);
customIntent.putExtra(U.VALUE, "Toggle");
- customPendingIntent = PendingIntent.getActivity(this, code, customIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ customPendingIntent = PendingIntent.getActivity(this, code, customIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
String onOffString;
switch(key) {
@@ -272,13 +272,10 @@ private void setActionButton(String key, SharedPreferences prefCurrent, int code
break;
case "temp_immersive":
case "temp_immersive_new":
- switch(prefCurrent.getString("immersive_new", "fallback")) {
- case "immersive-mode":
- onOffString = " " + getResources().getStringArray(R.array.pref_quick_actions)[1];
- break;
- default:
- onOffString = " " + getResources().getStringArray(R.array.pref_quick_actions)[0];
- break;
+ if ("immersive-mode".equals(prefCurrent.getString("immersive_new", "fallback"))) {
+ onOffString = " " + getResources().getStringArray(R.array.pref_quick_actions)[1];
+ } else {
+ onOffString = " " + getResources().getStringArray(R.array.pref_quick_actions)[0];
}
customString = getResources().getString(R.string.immersive) + onOffString;
diff --git a/app/src/main/java/com/farmerbb/secondscreen/service/ProfileLoadService.java b/app/src/main/java/com/farmerbb/secondscreen/service/ProfileLoadService.java
index ecfa81d..d9dfd00 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/service/ProfileLoadService.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/service/ProfileLoadService.java
@@ -22,6 +22,7 @@
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.hardware.display.DisplayManager;
import android.net.wifi.WifiManager;
@@ -133,32 +134,35 @@ private void loadProfile(SharedPreferences prefCurrent) {
// Build commands to pass to su
// Commands will be run in this order (except if "Restart ActivityManager" is selected)
- final int densityCommand = 0;
- final int densityCommand2 = 1;
- final int sizeCommand = 2;
- final int overscanCommand = 3;
- final int rotationPreCommand = 4;
- final int rotationCommand = 5;
- final int rotationPostCommand = 6;
- final int chromeCommand = 7;
- final int chromeCommand2 = 8;
- final int immersiveCommand = 9;
- final int freeformCommand = 10;
- final int hdmiRotationCommand = 11;
- final int navbarCommand = 12;
- final int daydreamsCommand = 13;
- final int daydreamsChargingCommand = 14;
- final int safeModeDensityCommand = 15;
- final int safeModeSizeCommand = 16;
- final int uiRefreshCommand = 17;
- final int uiRefreshCommand2 = 18;
- final int stayOnCommand = 19;
- final int showTouchesCommand = 20;
- final int vibrationCommand = 21;
- final int backlightCommand = 22;
+ final int wifiCommand = 0;
+ final int densityCommand = 1;
+ final int densityCommand2 = 2;
+ final int sizeCommand = 3;
+ final int overscanCommand = 4;
+ final int rotationPreCommand = 5;
+ final int rotationCommand = 6;
+ final int rotationPostCommand = 7;
+ final int chromeCommand = 8;
+ final int chromeCommand2 = 9;
+ final int immersiveCommand = 10;
+ final int freeformCommand = 11;
+ final int hdmiRotationCommand = 12;
+ final int navbarCommand = 13;
+ final int daydreamsCommand = 14;
+ final int daydreamsChargingCommand = 15;
+ final int safeModeDensityCommand = 16;
+ final int safeModeSizeCommand = 17;
+ final int uiRefreshCommand = 18;
+ final int uiRefreshCommand2 = 19;
+ final int stayOnCommand = 20;
+ final int showTouchesCommand = 21;
+ final int vibrationCommand = 22;
+ final int backlightCommand = 23;
+ final int setHomeActivityCommand = 24;
+ final int total = 25;
// Initialize su array
- String[] su = new String[backlightCommand + 1];
+ String[] su = new String[total];
Arrays.fill(su, "");
// Bluetooth
@@ -188,22 +192,36 @@ private void loadProfile(SharedPreferences prefCurrent) {
}
// Wi-Fi
- if(getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) {
+ if(U.canEnableWifi(this)) {
+ Boolean enableWifi = null;
+
WifiManager wifi = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if(prefCurrent.getBoolean("not_active", true))
editor.putBoolean("wifi_on_system", wifi.isWifiEnabled());
if(prefSaved.getBoolean("wifi_on", false)) {
if(prefCurrent.getBoolean("not_active", true))
- wifi.setWifiEnabled(true);
+ enableWifi = true;
else {
if(!prefCurrent.getBoolean("wifi_on", false))
- wifi.setWifiEnabled(true);
+ enableWifi = true;
}
} else {
if(!prefCurrent.getBoolean("not_active", true))
if(prefCurrent.getBoolean("wifi_on", false))
- wifi.setWifiEnabled(prefCurrent.getBoolean("wifi_on_system", false));
+ enableWifi = prefCurrent.getBoolean("wifi_on_system", false);
+ }
+
+ if (enableWifi != null) {
+ boolean wifiHandled = U.setWifiEnabled(this, enableWifi);
+
+ if (!wifiHandled) {
+ su[wifiCommand] = U.wifiCommand(enableWifi);
+
+ if(CommandDispatcher.getInstance().addCommand(this, su[wifiCommand])
+ || U.isInNonRootMode(this))
+ su[wifiCommand] = "";
+ }
}
}
@@ -223,10 +241,30 @@ private void loadProfile(SharedPreferences prefCurrent) {
String taskbarPackageName = U.getTaskbarPackageName(this);
if(taskbarPackageName != null) {
- if(shouldEnableTaskbarHome)
+ if(shouldEnableTaskbarHome) {
taskbarIntent = new Intent("com.farmerbb.taskbar.ENABLE_HOME");
- else if(shouldDisableTaskbarHome)
+
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+ homeIntent.addCategory(Intent.CATEGORY_HOME);
+ ResolveInfo defaultLauncher = getPackageManager().resolveActivity(homeIntent, PackageManager.MATCH_DEFAULT_ONLY);
+
+ if(defaultLauncher != null) {
+ editor.putString("home_activity", defaultLauncher.activityInfo.packageName + "/" + defaultLauncher.activityInfo.name);
+ su[setHomeActivityCommand] = U.setHomeActivityCommand + taskbarPackageName + "/com.farmerbb.taskbar.activity.HomeActivity";
+ }
+ }
+ } else if(shouldDisableTaskbarHome) {
taskbarIntent = new Intent("com.farmerbb.taskbar.DISABLE_HOME");
+
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ String defaultLauncher = prefCurrent.getString("home_activity", null);
+ if(defaultLauncher != null) {
+ editor.remove("home_activity");
+ su[setHomeActivityCommand] = U.setHomeActivityCommand + defaultLauncher;
+ }
+ }
+ }
}
if(taskbarIntent != null) {
@@ -274,10 +312,8 @@ else if(shouldDisableTaskbarHome)
// Determine if CyanogenMod workaround is needed
// Recent builds of CyanogenMod require the "Restart ActivityManager" UI refresh method
// to be set, to work around the automatic reboot when the DPI is changed.
- boolean cmWorkaround = false;
- if(getPackageManager().hasSystemFeature("com.cyanogenmod.android")
- && Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1)
- cmWorkaround = true;
+ boolean cmWorkaround = getPackageManager().hasSystemFeature("com.cyanogenmod.android")
+ && Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1;
String uiRefresh = (cmWorkaround || rebootRequired)
? "activity-manager"
@@ -293,8 +329,7 @@ else if(shouldDisableTaskbarHome)
String size = prefSaved.getString("size", "reset");
// Swap height and width under certain conditions
- if(!"reset".equals(size) && (prefMain.getBoolean("notch_compat_mode", false)
- || (U.isDesktopModeActive(this) && !prefMain.getBoolean("landscape", false)))) {
+ if(!"reset".equals(size) && (U.isDesktopModeActive(this) && !prefMain.getBoolean("landscape", false))) {
String[] splitSize = size.split("x");
size = splitSize[1] + "x" + splitSize[0];
}
@@ -331,15 +366,15 @@ else if(shouldDisableTaskbarHome)
}
// Overscan
- if(Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ if(U.canEnableOverscan()) {
if(prefSaved.getBoolean("overscan", false)) {
String overscanValues = "";
if(prefCurrent.getBoolean("not_active", true)) {
- overscanValues = Integer.toString(prefSaved.getInt("overscan_bottom", 20)) + ","
- + Integer.toString(prefSaved.getInt("overscan_left", 20)) + ","
- + Integer.toString(prefSaved.getInt("overscan_top", 20)) + ","
- + Integer.toString(prefSaved.getInt("overscan_right", 20));
+ overscanValues = prefSaved.getInt("overscan_bottom", 20) + ","
+ + prefSaved.getInt("overscan_left", 20) + ","
+ + prefSaved.getInt("overscan_top", 20) + ","
+ + prefSaved.getInt("overscan_right", 20);
} else {
if(prefCurrent.getBoolean("overscan", false)) {
// Check saved overscan integers against current overscan integers
@@ -348,34 +383,33 @@ else if(shouldDisableTaskbarHome)
|| (prefSaved.getInt("overscan_top", 0) != prefCurrent.getInt("overscan_top", 20))
|| (prefSaved.getInt("overscan_right", 0) != prefCurrent.getInt("overscan_right", 20))) {
if(prefMain.getBoolean("landscape", false)) {
- overscanValues = Integer.toString(prefSaved.getInt("overscan_left", 20)) + ","
- + Integer.toString(prefSaved.getInt("overscan_top", 20)) + ","
- + Integer.toString(prefSaved.getInt("overscan_right", 20)) + ","
- + Integer.toString(prefSaved.getInt("overscan_bottom", 20));
+ overscanValues = prefSaved.getInt("overscan_left", 20) + ","
+ + prefSaved.getInt("overscan_top", 20) + ","
+ + prefSaved.getInt("overscan_right", 20) + ","
+ + prefSaved.getInt("overscan_bottom", 20);
} else {
- overscanValues = Integer.toString(prefSaved.getInt("overscan_bottom", 20)) + ","
- + Integer.toString(prefSaved.getInt("overscan_left", 20)) + ","
- + Integer.toString(prefSaved.getInt("overscan_top", 20)) + ","
- + Integer.toString(prefSaved.getInt("overscan_right", 20));
+ overscanValues = prefSaved.getInt("overscan_bottom", 20) + ","
+ + prefSaved.getInt("overscan_left", 20) + ","
+ + prefSaved.getInt("overscan_top", 20) + ","
+ + prefSaved.getInt("overscan_right", 20);
}
}
} else if(prefMain.getBoolean("landscape", false)) {
- overscanValues = Integer.toString(prefSaved.getInt("overscan_left", 20)) + ","
- + Integer.toString(prefSaved.getInt("overscan_top", 20)) + ","
- + Integer.toString(prefSaved.getInt("overscan_right", 20)) + ","
- + Integer.toString(prefSaved.getInt("overscan_bottom", 20));
+ overscanValues = prefSaved.getInt("overscan_left", 20) + ","
+ + prefSaved.getInt("overscan_top", 20) + ","
+ + prefSaved.getInt("overscan_right", 20) + ","
+ + prefSaved.getInt("overscan_bottom", 20);
} else {
- overscanValues = Integer.toString(prefSaved.getInt("overscan_bottom", 20)) + ","
- + Integer.toString(prefSaved.getInt("overscan_left", 20)) + ","
- + Integer.toString(prefSaved.getInt("overscan_top", 20)) + ","
- + Integer.toString(prefSaved.getInt("overscan_right", 20));
+ overscanValues = prefSaved.getInt("overscan_bottom", 20) + ","
+ + prefSaved.getInt("overscan_left", 20) + ","
+ + prefSaved.getInt("overscan_top", 20) + ","
+ + prefSaved.getInt("overscan_right", 20);
}
}
if(!overscanValues.isEmpty()) {
// Fix overscan values under certain conditions
- if(prefMain.getBoolean("notch_compat_mode", false)
- || (U.isDesktopModeActive(this) && !prefMain.getBoolean("landscape", false))) {
+ if(U.isDesktopModeActive(this) && !prefMain.getBoolean("landscape", false)) {
String[] splitValues = overscanValues.split(",");
overscanValues = splitValues[1] + ","
+ splitValues[2] + ","
@@ -486,7 +520,7 @@ else if(shouldDisableTaskbarHome)
runRotationCommand = false;
if(runRotationCommand) {
- su[rotationCommand] = U.rotationCommand + Integer.toString(dockMode);
+ su[rotationCommand] = U.rotationCommand + dockMode;
// Workaround for if Daydreams is enabled and we are enabling dock mode
if(dockMode == Intent.EXTRA_DOCK_STATE_DESK
@@ -509,12 +543,12 @@ else if(shouldDisableTaskbarHome)
if(!"always-on".equals(prefCurrent.getString("screen_timeout", "null"))) {
Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, 2147482000);
if(!prefCurrent.getBoolean("not_active", true))
- su[stayOnCommand] = U.stayOnCommand + Integer.toString(prefCurrent.getInt("stay_on_while_plugged_in_system", 0));
+ su[stayOnCommand] = U.stayOnCommand + prefCurrent.getInt("stay_on_while_plugged_in_system", 0);
}
break;
case "always-on-charging":
if(!"always-on-charging".equals(prefCurrent.getString("screen_timeout", "null"))) {
- su[stayOnCommand] = U.stayOnCommand + Integer.toString(BatteryManager.BATTERY_PLUGGED_AC
+ su[stayOnCommand] = U.stayOnCommand + (BatteryManager.BATTERY_PLUGGED_AC
| BatteryManager.BATTERY_PLUGGED_USB | BatteryManager.BATTERY_PLUGGED_WIRELESS);
if(!prefCurrent.getBoolean("not_active", true))
Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, prefCurrent.getInt("screen_timeout_system", 60000));
@@ -523,7 +557,7 @@ else if(shouldDisableTaskbarHome)
case "do-nothing":
if(!"do-nothing".equals(prefCurrent.getString("screen_timeout", "null")) && !prefCurrent.getBoolean("not_active", true)) {
Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, prefCurrent.getInt("screen_timeout_system", 60000));
- su[stayOnCommand] = U.stayOnCommand + Integer.toString(prefCurrent.getInt("stay_on_while_plugged_in_system", 0));
+ su[stayOnCommand] = U.stayOnCommand + prefCurrent.getInt("stay_on_while_plugged_in_system", 0);
}
break;
}
@@ -642,7 +676,7 @@ else if(Settings.Secure.getInt(getContentResolver(), "screensaver_activate_on_sl
if(prefCurrent.getInt("vibration_value", -1) != -1) {
for(File vibrationOff : U.vibrationOff) {
if(vibrationOff.exists())
- su[vibrationCommand] = "echo " + Integer.toString(prefCurrent.getInt("vibration_value", -1)) + " > " + vibrationOff.getAbsolutePath();
+ su[vibrationCommand] = "echo " + prefCurrent.getInt("vibration_value", -1) + " > " + vibrationOff.getAbsolutePath();
}
editor.putInt("vibration_value", -1);
@@ -696,7 +730,7 @@ else if(Settings.Secure.getInt(getContentResolver(), "screensaver_activate_on_sl
// Manually update the sysfs value to guarantee that the backlight will restore
for(File backlightOff : U.backlightOff) {
if(backlightOff.exists()) {
- su[backlightCommand] = "echo " + Integer.toString(prefCurrent.getInt("backlight_value", -1)) + " > " + backlightOff.getAbsolutePath();
+ su[backlightCommand] = "echo " + prefCurrent.getInt("backlight_value", -1) + " > " + backlightOff.getAbsolutePath();
break;
}
}
@@ -742,7 +776,7 @@ else if(Settings.Secure.getInt(getContentResolver(), "screensaver_activate_on_sl
// Manually update the sysfs value to guarantee that the backlight will restore
for(File backlightOff : U.backlightOff) {
if(backlightOff.exists()) {
- su[backlightCommand] = "echo " + Integer.toString(prefCurrent.getInt("backlight_value", -1)) + " > " + backlightOff.getAbsolutePath();
+ su[backlightCommand] = "echo " + prefCurrent.getInt("backlight_value", -1) + " > " + backlightOff.getAbsolutePath();
break;
}
}
@@ -825,36 +859,38 @@ else if(Settings.System.getInt(getContentResolver(), "dev_force_show_navbar", 0)
}
// Immersive mode
- if("fallback".equals(prefSaved.getString("immersive_new", "fallback")) && prefSaved.getBoolean("immersive", false))
- editor.putString("immersive_new", "immersive-mode");
- else
- editor.putString("immersive_new", prefSaved.getString("immersive_new", "do-nothing"));
+ if(U.canEnableImmersiveMode()) {
+ if("fallback".equals(prefSaved.getString("immersive_new", "fallback")) && prefSaved.getBoolean("immersive", false))
+ editor.putString("immersive_new", "immersive-mode");
+ else
+ editor.putString("immersive_new", prefSaved.getString("immersive_new", "do-nothing"));
- switch(prefSaved.getString("immersive_new", "fallback")) {
- case "fallback":
- if(prefSaved.getBoolean("immersive", false)) {
+ switch(prefSaved.getString("immersive_new", "fallback")) {
+ case "fallback":
+ if(prefSaved.getBoolean("immersive", false)) {
+ if(!"immersive-mode".equals(prefCurrent.getString("immersive_new", "do-nothing"))) {
+ su[immersiveCommand] = U.immersiveCommand("immersive-mode");
+ }
+ } else {
+ if(!"do-nothing".equals(prefCurrent.getString("immersive_new", "do-nothing")) && !prefCurrent.getBoolean("not_active", true))
+ su[immersiveCommand] = U.immersiveCommand("do-nothing");
+ }
+ break;
+ case "status-only":
+ if(!"status-only".equals(prefCurrent.getString("immersive_new", "do-nothing"))) {
+ su[immersiveCommand] = U.immersiveCommand("status-only");
+ }
+ break;
+ case "immersive-mode":
if(!"immersive-mode".equals(prefCurrent.getString("immersive_new", "do-nothing"))) {
su[immersiveCommand] = U.immersiveCommand("immersive-mode");
}
- } else {
+ break;
+ case "do-nothing":
if(!"do-nothing".equals(prefCurrent.getString("immersive_new", "do-nothing")) && !prefCurrent.getBoolean("not_active", true))
su[immersiveCommand] = U.immersiveCommand("do-nothing");
- }
- break;
- case "status-only":
- if(!"status-only".equals(prefCurrent.getString("immersive_new", "do-nothing"))) {
- su[immersiveCommand] = U.immersiveCommand("status-only");
- }
- break;
- case "immersive-mode":
- if(!"immersive-mode".equals(prefCurrent.getString("immersive_new", "do-nothing"))) {
- su[immersiveCommand] = U.immersiveCommand("immersive-mode");
- }
- break;
- case "do-nothing":
- if(!"do-nothing".equals(prefCurrent.getString("immersive_new", "do-nothing")) && !prefCurrent.getBoolean("not_active", true))
- su[immersiveCommand] = U.immersiveCommand("do-nothing");
- break;
+ break;
+ }
}
// HDMI rotation
@@ -942,6 +978,7 @@ else if(Settings.System.getInt(getContentResolver(), "dev_force_show_navbar", 0)
su[stayOnCommand],
su[showTouchesCommand],
su[densityCommand],
+ su[setHomeActivityCommand],
su[uiRefreshCommand]};
} else
su = new String[]{
@@ -958,6 +995,7 @@ else if(Settings.System.getInt(getContentResolver(), "dev_force_show_navbar", 0)
su[daydreamsChargingCommand],
su[stayOnCommand],
su[showTouchesCommand],
+ su[setHomeActivityCommand],
su[uiRefreshCommand]};
break;
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/service/TempBacklightOnService.java b/app/src/main/java/com/farmerbb/secondscreen/service/TempBacklightOnService.java
index a08416c..4b3d921 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/service/TempBacklightOnService.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/service/TempBacklightOnService.java
@@ -54,7 +54,7 @@ protected void onHandleIntent(Intent intent) {
// Manually update the sysfs value to guarantee that the backlight will restore
for(File backlightOff : U.backlightOff) {
if(backlightOff.exists()) {
- U.runCommand(this, "echo " + Integer.toString(prefCurrent.getInt("backlight_value", -1)) + " > " + backlightOff.getAbsolutePath());
+ U.runCommand(this, "echo " + prefCurrent.getInt("backlight_value", -1) + " > " + backlightOff.getAbsolutePath());
break;
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/service/TestOverscanService.java b/app/src/main/java/com/farmerbb/secondscreen/service/TestOverscanService.java
index 9e1c4a4..7683315 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/service/TestOverscanService.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/service/TestOverscanService.java
@@ -42,15 +42,15 @@ protected void onHandleIntent(Intent intent) {
if(intent.getBooleanExtra("test_overscan", true)) {
if(prefMain.getBoolean("landscape", false)) {
- overscanValues = Integer.toString(prefNew.getInt("overscan_left", 0)) + ","
- + Integer.toString(prefNew.getInt("overscan_top", 0)) + ","
- + Integer.toString(prefNew.getInt("overscan_right", 0)) + ","
- + Integer.toString(prefNew.getInt("overscan_bottom", 0));
+ overscanValues = prefNew.getInt("overscan_left", 0) + ","
+ + prefNew.getInt("overscan_top", 0) + ","
+ + prefNew.getInt("overscan_right", 0) + ","
+ + prefNew.getInt("overscan_bottom", 0);
} else {
- overscanValues = Integer.toString(prefNew.getInt("overscan_bottom", 0)) + ","
- + Integer.toString(prefNew.getInt("overscan_left", 0)) + ","
- + Integer.toString(prefNew.getInt("overscan_top", 0)) + ","
- + Integer.toString(prefNew.getInt("overscan_right", 0));
+ overscanValues = prefNew.getInt("overscan_bottom", 0) + ","
+ + prefNew.getInt("overscan_left", 0) + ","
+ + prefNew.getInt("overscan_top", 0) + ","
+ + prefNew.getInt("overscan_right", 0);
}
} else {
SharedPreferences prefCurrent = U.getPrefCurrent(this);
@@ -60,15 +60,15 @@ protected void onHandleIntent(Intent intent) {
SharedPreferences prefSaved = U.getPrefSaved(this, prefCurrent.getString("filename", "0"));
if(prefSaved.getBoolean("overscan", false)) {
if(prefMain.getBoolean("landscape", false)) {
- overscanValues = Integer.toString(prefSaved.getInt("overscan_left", 0)) + ","
- + Integer.toString(prefSaved.getInt("overscan_top", 0)) + ","
- + Integer.toString(prefSaved.getInt("overscan_right", 0)) + ","
- + Integer.toString(prefSaved.getInt("overscan_bottom", 0));
+ overscanValues = prefSaved.getInt("overscan_left", 0) + ","
+ + prefSaved.getInt("overscan_top", 0) + ","
+ + prefSaved.getInt("overscan_right", 0) + ","
+ + prefSaved.getInt("overscan_bottom", 0);
} else {
- overscanValues = Integer.toString(prefSaved.getInt("overscan_bottom", 0)) + ","
- + Integer.toString(prefSaved.getInt("overscan_left", 0)) + ","
- + Integer.toString(prefSaved.getInt("overscan_top", 0)) + ","
- + Integer.toString(prefSaved.getInt("overscan_right", 0));
+ overscanValues = prefSaved.getInt("overscan_bottom", 0) + ","
+ + prefSaved.getInt("overscan_left", 0) + ","
+ + prefSaved.getInt("overscan_top", 0) + ","
+ + prefSaved.getInt("overscan_right", 0);
}
} else
overscanValues = "reset";
@@ -76,8 +76,7 @@ protected void onHandleIntent(Intent intent) {
}
// Fix overscan values under certain conditions
- if((prefMain.getBoolean("notch_compat_mode", false)
- || (U.isDesktopModeActive(this) && !prefMain.getBoolean("landscape", false)))
+ if((U.isDesktopModeActive(this) && !prefMain.getBoolean("landscape", false))
&& !overscanValues.equals("reset")) {
String[] splitValues = overscanValues.split(",");
overscanValues = splitValues[1] + ","
diff --git a/app/src/main/java/com/farmerbb/secondscreen/service/TimeoutService.java b/app/src/main/java/com/farmerbb/secondscreen/service/TimeoutService.java
index 0b387b4..bd249c2 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/service/TimeoutService.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/service/TimeoutService.java
@@ -44,7 +44,7 @@ protected void onHandleIntent(Intent intent) {
editor.remove("timeout");
editor.apply();
- U.runCommand(this, U.timeoutCommand + Integer.toString(timeout));
+ U.runCommand(this, U.timeoutCommand + timeout);
}
}
}
diff --git a/app/src/main/java/com/farmerbb/secondscreen/service/TurnOffService.java b/app/src/main/java/com/farmerbb/secondscreen/service/TurnOffService.java
index b94a85d..4d39700 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/service/TurnOffService.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/service/TurnOffService.java
@@ -95,30 +95,33 @@ private void turnOffProfile(SharedPreferences prefCurrent) {
// Build commands to pass to su
// Commands will be run in this order (except if "Restart ActivityManager" is selected)
- final int densityCommand = 0;
- final int densityCommand2 = 1;
- final int sizeCommand = 2;
- final int overscanCommand = 3;
- final int rotationPreCommand = 4;
- final int rotationCommand = 5;
- final int rotationPostCommand = 6;
- final int chromeCommand = 7;
- final int chromeCommand2 = 8;
- final int immersiveCommand = 9;
- final int freeformCommand = 10;
- final int hdmiRotationCommand = 11;
- final int navbarCommand = 12;
- final int daydreamsCommand = 13;
- final int daydreamsChargingCommand = 14;
- final int stayOnCommand = 15;
- final int showTouchesCommand = 16;
- final int uiRefreshCommand = 17;
- final int uiRefreshCommand2 = 18;
- final int vibrationCommand = 19;
- final int backlightCommand = 20;
+ final int wifiCommand = 0;
+ final int densityCommand = 1;
+ final int densityCommand2 = 2;
+ final int sizeCommand = 3;
+ final int overscanCommand = 4;
+ final int rotationPreCommand = 5;
+ final int rotationCommand = 6;
+ final int rotationPostCommand = 7;
+ final int chromeCommand = 8;
+ final int chromeCommand2 = 9;
+ final int immersiveCommand = 10;
+ final int freeformCommand = 11;
+ final int hdmiRotationCommand = 12;
+ final int navbarCommand = 13;
+ final int daydreamsCommand = 14;
+ final int daydreamsChargingCommand = 15;
+ final int stayOnCommand = 16;
+ final int showTouchesCommand = 17;
+ final int uiRefreshCommand = 18;
+ final int uiRefreshCommand2 = 19;
+ final int vibrationCommand = 20;
+ final int backlightCommand = 21;
+ final int setHomeActivityCommand = 22;
+ final int total = 23;
// Initialize su array
- String[] su = new String[backlightCommand + 1];
+ String[] su = new String[total];
Arrays.fill(su, "");
// Bluetooth
@@ -131,25 +134,44 @@ private void turnOffProfile(SharedPreferences prefCurrent) {
}
// Wi-Fi
+ Boolean enableWifi = null;
+
if(prefCurrent.getBoolean("wifi_on", true)) {
- WifiManager wifi = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
- wifi.setWifiEnabled(prefCurrent.getBoolean("wifi_on_system", false));
+ enableWifi = prefCurrent.getBoolean("wifi_on_system", false);
}
- // Clear default home
- boolean shouldDisableTaskbarHome = false;
+ if (enableWifi != null) {
+ boolean wifiHandled = U.setWifiEnabled(this, enableWifi);
+
+ if (!wifiHandled) {
+ su[wifiCommand] = U.wifiCommand(enableWifi);
+
+ if(CommandDispatcher.getInstance().addCommand(this, su[wifiCommand])
+ || U.isInNonRootMode(this))
+ su[wifiCommand] = "";
+ }
+ }
- if(prefCurrent.getBoolean("clear_home", false))
- shouldDisableTaskbarHome = true;
+ // Clear default home
+ boolean shouldDisableTaskbarHome = prefCurrent.getBoolean("clear_home", false);
boolean shouldClearHome = shouldDisableTaskbarHome;
if(shouldClearHome) {
Intent taskbarIntent = null;
String taskbarPackageName = U.getTaskbarPackageName(this);
- if(taskbarPackageName != null)
+ if(taskbarPackageName != null) {
taskbarIntent = new Intent("com.farmerbb.taskbar.DISABLE_HOME");
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ String defaultLauncher = prefCurrent.getString("home_activity", null);
+ if(defaultLauncher != null) {
+ editor.remove("home_activity");
+ su[setHomeActivityCommand] = U.setHomeActivityCommand + defaultLauncher;
+ }
+ }
+ }
+
if(taskbarIntent != null) {
taskbarIntent.setPackage(taskbarPackageName);
taskbarIntent.putExtra("secondscreen", true);
@@ -176,10 +198,8 @@ private void turnOffProfile(SharedPreferences prefCurrent) {
// Determine if CyanogenMod workaround is needed
// Recent builds of CyanogenMod require the "Restart ActivityManager" UI refresh method
// to be set, to work around the automatic reboot when the DPI is changed.
- boolean cmWorkaround = false;
- if(getPackageManager().hasSystemFeature("com.cyanogenmod.android")
- && Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1)
- cmWorkaround = true;
+ boolean cmWorkaround = getPackageManager().hasSystemFeature("com.cyanogenmod.android")
+ && Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP_MR1;
String uiRefresh = (cmWorkaround || rebootRequired)
? "activity-manager"
@@ -221,7 +241,7 @@ private void turnOffProfile(SharedPreferences prefCurrent) {
}
// Overscan
- if((Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1) && prefCurrent.getBoolean("overscan", true))
+ if(U.canEnableOverscan() && prefCurrent.getBoolean("overscan", true))
su[overscanCommand] = U.overscanCommand(this, "reset");
// Screen rotation
@@ -230,13 +250,10 @@ private void turnOffProfile(SharedPreferences prefCurrent) {
// Run checks to determine if rotation command needs to be run.
// Don't run this command if we don't need to.
- boolean runRotationCommand = true;
-
- if(prefCurrent.getInt("dock_mode", Intent.EXTRA_DOCK_STATE_UNDOCKED) == prefCurrent.getInt("dock_mode_current", Intent.EXTRA_DOCK_STATE_UNDOCKED))
- runRotationCommand = false;
+ boolean runRotationCommand = prefCurrent.getInt("dock_mode", Intent.EXTRA_DOCK_STATE_UNDOCKED) != prefCurrent.getInt("dock_mode_current", Intent.EXTRA_DOCK_STATE_UNDOCKED);
if(runRotationCommand) {
- su[rotationCommand] = U.rotationCommand + Integer.toString(prefCurrent.getInt("dock_mode", Intent.EXTRA_DOCK_STATE_UNDOCKED));
+ su[rotationCommand] = U.rotationCommand + prefCurrent.getInt("dock_mode", Intent.EXTRA_DOCK_STATE_UNDOCKED);
// Workaround for if Daydreams is enabled and we are enabling dock mode
if(prefCurrent.getInt("dock_mode", Intent.EXTRA_DOCK_STATE_UNDOCKED) == Intent.EXTRA_DOCK_STATE_DESK
@@ -254,7 +271,7 @@ private void turnOffProfile(SharedPreferences prefCurrent) {
Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, prefCurrent.getInt("screen_timeout_system", 60000));
break;
case "always-on-charging":
- su[stayOnCommand] = U.stayOnCommand + Integer.toString(prefCurrent.getInt("stay_on_while_plugged_in_system", 0));
+ su[stayOnCommand] = U.stayOnCommand + prefCurrent.getInt("stay_on_while_plugged_in_system", 0);
break;
}
@@ -275,7 +292,7 @@ private void turnOffProfile(SharedPreferences prefCurrent) {
if(prefCurrent.getInt("vibration_value", -1) != -1) {
for(File vibrationOff : U.vibrationOff) {
if(vibrationOff.exists())
- su[vibrationCommand] = "echo " + Integer.toString(prefCurrent.getInt("vibration_value", -1)) + " > " + vibrationOff.getAbsolutePath();
+ su[vibrationCommand] = "echo " + prefCurrent.getInt("vibration_value", -1) + " > " + vibrationOff.getAbsolutePath();
}
}
@@ -293,7 +310,7 @@ private void turnOffProfile(SharedPreferences prefCurrent) {
// Manually update the sysfs value to guarantee that the backlight will restore
for(File backlightOff : U.backlightOff) {
if(backlightOff.exists()) {
- su[backlightCommand] = "echo " + Integer.toString(prefCurrent.getInt("backlight_value", -1)) + " > " + backlightOff.getAbsolutePath();
+ su[backlightCommand] = "echo " + prefCurrent.getInt("backlight_value", -1) + " > " + backlightOff.getAbsolutePath();
break;
}
}
@@ -330,7 +347,7 @@ private void turnOffProfile(SharedPreferences prefCurrent) {
}
// Immersive mode
- if(!"do-nothing".equals(prefCurrent.getString("immersive_new", "do-nothing")))
+ if(U.canEnableImmersiveMode() && !"do-nothing".equals(prefCurrent.getString("immersive_new", "do-nothing")))
su[immersiveCommand] = U.immersiveCommand("do-nothing");
// HDMI rotation
@@ -366,6 +383,7 @@ private void turnOffProfile(SharedPreferences prefCurrent) {
su[stayOnCommand],
su[showTouchesCommand],
su[densityCommand],
+ su[setHomeActivityCommand],
su[uiRefreshCommand]};
} else
su = new String[]{
@@ -382,20 +400,15 @@ private void turnOffProfile(SharedPreferences prefCurrent) {
su[daydreamsChargingCommand],
su[stayOnCommand],
su[showTouchesCommand],
+ su[setHomeActivityCommand],
su[uiRefreshCommand]};
break;
}
// Determine if we need to stop Taskbar
- boolean shouldDisableFreeform = false;
-
- if(prefCurrent.getBoolean("freeform", false))
- shouldDisableFreeform = true;
-
- boolean shouldStopTaskbar = false;
+ boolean shouldDisableFreeform = prefCurrent.getBoolean("freeform", false);
- if(prefCurrent.getBoolean("taskbar", false))
- shouldStopTaskbar = true;
+ boolean shouldStopTaskbar = prefCurrent.getBoolean("taskbar", false);
// Clear preferences and commit (for reliability)
editor.clear();
diff --git a/app/src/main/java/com/farmerbb/secondscreen/util/CommandDispatcher.java b/app/src/main/java/com/farmerbb/secondscreen/util/CommandDispatcher.java
index 962af12..a474fa1 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/util/CommandDispatcher.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/util/CommandDispatcher.java
@@ -25,7 +25,7 @@
public class CommandDispatcher {
- private List commands = new ArrayList<>();
+ private final List commands = new ArrayList<>();
private static CommandDispatcher theInstance;
diff --git a/app/src/main/java/com/farmerbb/secondscreen/util/PluginBundleManager.java b/app/src/main/java/com/farmerbb/secondscreen/util/PluginBundleManager.java
index 50d47e5..05e43d8 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/util/PluginBundleManager.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/util/PluginBundleManager.java
@@ -59,10 +59,7 @@ public static boolean isBundleValid(final Bundle bundle)
return false;
- if (TextUtils.isEmpty(bundle.getString(BUNDLE_EXTRA_STRING_MESSAGE)))
- return false;
-
- return true;
+ return !TextUtils.isEmpty(bundle.getString(BUNDLE_EXTRA_STRING_MESSAGE));
}
/**
diff --git a/app/src/main/java/com/farmerbb/secondscreen/util/PluginBundleManagerQuickActions.java b/app/src/main/java/com/farmerbb/secondscreen/util/PluginBundleManagerQuickActions.java
index 78aa921..f47b54b 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/util/PluginBundleManagerQuickActions.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/util/PluginBundleManagerQuickActions.java
@@ -66,10 +66,7 @@ public static boolean isBundleValid(final Bundle bundle)
if (TextUtils.isEmpty(bundle.getString(BUNDLE_EXTRA_STRING_KEY)))
return false;
- if (TextUtils.isEmpty(bundle.getString(BUNDLE_EXTRA_STRING_VALUE)))
- return false;
-
- return true;
+ return !TextUtils.isEmpty(bundle.getString(BUNDLE_EXTRA_STRING_VALUE));
}
public static Bundle generateBundle(final Context context, final String key, final String value)
diff --git a/app/src/main/java/com/farmerbb/secondscreen/util/ShowToast.java b/app/src/main/java/com/farmerbb/secondscreen/util/ShowToast.java
index b0138d4..b6b84c0 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/util/ShowToast.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/util/ShowToast.java
@@ -21,9 +21,9 @@
// Shows a toast message inside ProfileLoadService and TurnOffService, where the standard toast
// methods won't work.
public final class ShowToast implements Runnable {
- private Context context;
- private int text;
- private int length;
+ private final Context context;
+ private final int text;
+ private final int length;
public ShowToast(Context context, int text, int length) {
this.context = context;
@@ -32,13 +32,10 @@ public ShowToast(Context context, int text, int length) {
}
public void run() {
- switch(length) {
- case Toast.LENGTH_LONG:
- U.showToastLong(context, text);
- break;
- default:
- U.showToast(context, text);
- break;
+ if (length == Toast.LENGTH_LONG) {
+ U.showToastLong(context, text);
+ } else {
+ U.showToast(context, text);
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/farmerbb/secondscreen/util/ToastCompatImpl.java b/app/src/main/java/com/farmerbb/secondscreen/util/ToastCompatImpl.java
index 210b380..2afacca 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/util/ToastCompatImpl.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/util/ToastCompatImpl.java
@@ -23,7 +23,7 @@
import moe.banana.support.ToastCompat;
class ToastCompatImpl implements ToastInterface {
- private ToastCompat toast;
+ private final ToastCompat toast;
ToastCompatImpl(Context context, String message, int length) {
toast = ToastCompat.makeText(context, message, length);
diff --git a/app/src/main/java/com/farmerbb/secondscreen/util/ToastFrameworkImpl.java b/app/src/main/java/com/farmerbb/secondscreen/util/ToastFrameworkImpl.java
index a4170c1..fce06b4 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/util/ToastFrameworkImpl.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/util/ToastFrameworkImpl.java
@@ -23,7 +23,7 @@
import com.farmerbb.secondscreen.R;
class ToastFrameworkImpl implements ToastInterface {
- private Toast toast;
+ private final Toast toast;
@SuppressLint("ShowToast")
ToastFrameworkImpl(Context context, String message, int length) {
diff --git a/app/src/main/java/com/farmerbb/secondscreen/util/U.java b/app/src/main/java/com/farmerbb/secondscreen/util/U.java
index 3e66244..f8a4737 100644
--- a/app/src/main/java/com/farmerbb/secondscreen/util/U.java
+++ b/app/src/main/java/com/farmerbb/secondscreen/util/U.java
@@ -37,6 +37,7 @@
import android.content.res.Configuration;
import android.hardware.display.DisplayManager;
import android.net.Uri;
+import android.net.wifi.WifiManager;
import android.os.Build;
import android.preference.Preference;
import android.preference.PreferenceManager;
@@ -115,6 +116,7 @@ private U() {}
public static final File[] backlightOff = {
new File("/sys/class/leds/lcd-backlight", "brightness"),
+ new File("/sys/class/backlight/panel0-backlight", "brightness"),
new File("/sys/class/backlight/pwm-backlight", "brightness"),
new File("/sys/class/backlight/intel_backlight", "brightness"),
new File("/sys/class/backlight/tegra-dsi-backlight.0", "brightness"),
@@ -188,6 +190,11 @@ public static String freeformCommand(boolean checked) {
public static final String stayOnCommand = "settings put global stay_on_while_plugged_in ";
public static final String timeoutCommand = "settings put secure lock_screen_lock_after_timeout ";
public static final String hdmiRotationCommand = "setprop persist.demo.hdmirotation ";
+ public static final String setHomeActivityCommand = "cmd package set-home-activity ";
+
+ public static String wifiCommand(boolean enabled) {
+ return "svc wifi " + (enabled ? "enable" : "disable");
+ }
public static String safeModeSizeCommand(String args) {
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
@@ -267,7 +274,7 @@ public static String uiRefreshCommand(Context context, boolean restartActivityMa
processid = process.pid;
}
- return "sleep 1 && kill " + Integer.toString(processid);
+ return "sleep 1 && kill " + processid;
} else
return "sleep 1 && am restart";
} else {
@@ -287,7 +294,7 @@ public static String uiRefreshCommand(Context context, boolean restartActivityMa
else if(processid == 0)
return "sleep 2 && pkill com.android.systemui";
else
- return "sleep 2 && kill " + Integer.toString(processid);
+ return "sleep 2 && kill " + processid;
}
}
@@ -337,9 +344,9 @@ public static boolean runSizeCommand(Context context, String requestedRes) {
SharedPreferences prefMain = getPrefMain(context);
String currentRes = " ";
- String nativeRes = Integer.toString(prefMain.getInt("width", 0))
+ String nativeRes = prefMain.getInt("width", 0)
+ "x"
- + Integer.toString(prefMain.getInt("height", 0));
+ + prefMain.getInt("height", 0);
if(prefMain.getBoolean("debug_mode", false)) {
SharedPreferences prefCurrent = getPrefCurrent(context);
@@ -350,14 +357,14 @@ public static boolean runSizeCommand(Context context, String requestedRes) {
} else {
if((context.getApplicationContext().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT && !prefMain.getBoolean("landscape", false))
|| (context.getApplicationContext().getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE && prefMain.getBoolean("landscape", false))) {
- currentRes = Integer.toString(metrics.widthPixels)
+ currentRes = metrics.widthPixels
+ "x"
- + Integer.toString(metrics.heightPixels);
+ + metrics.heightPixels;
} else if((context.getApplicationContext().getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE && !prefMain.getBoolean("landscape", false))
|| (context.getApplicationContext().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT && prefMain.getBoolean("landscape", false))) {
- currentRes = Integer.toString(metrics.heightPixels)
+ currentRes = metrics.heightPixels
+ "x"
- + Integer.toString(metrics.widthPixels);
+ + metrics.widthPixels;
}
}
@@ -796,13 +803,10 @@ public static String generateBlurb(Activity a, String key, String value, boolean
if(key.equals("temp_immersive_new"))
key = "temp_immersive";
- switch(prefCurrent.getString("immersive_new", "fallback")) {
- case "immersive-mode":
- value = a.getResources().getStringArray(R.array.pref_quick_actions)[1];
- break;
- default:
- value = a.getResources().getStringArray(R.array.pref_quick_actions)[0];
- break;
+ if ("immersive-mode".equals(prefCurrent.getString("immersive_new", "fallback"))) {
+ value = a.getResources().getStringArray(R.array.pref_quick_actions)[1];
+ } else {
+ value = a.getResources().getStringArray(R.array.pref_quick_actions)[0];
}
break;
case "temp_overscan":
@@ -959,7 +963,7 @@ else if(prefMain.getBoolean("landscape", false)) {
int width = scanner.nextInt();
scanner.close();
- blurb = Integer.toString(width) + "x" + Integer.toString(height);
+ blurb = width + "x" + height;
break;
}
}
@@ -1381,9 +1385,9 @@ && isPlayStoreRelease(context)) {
editor.putBoolean("vibration_off", true);
if(prefMain.getBoolean("expert_mode", false)) {
- editor.putString("size", Integer.toString(prefMain.getInt("width", 0))
+ editor.putString("size", prefMain.getInt("width", 0)
+ "x"
- + Integer.toString(prefMain.getInt("height", 0)));
+ + prefMain.getInt("height", 0));
editor.putString("density", Integer.toString(getSystemProperty("ro.sf.lcd_density", prefMain.getInt("density", 0))));
@@ -1396,9 +1400,9 @@ && isPlayStoreRelease(context)) {
// Other / None
case 5:
if(prefMain.getBoolean("expert_mode", false)) {
- editor.putString("size", Integer.toString(prefMain.getInt("width", 0))
+ editor.putString("size", prefMain.getInt("width", 0)
+ "x"
- + Integer.toString(prefMain.getInt("height", 0)));
+ + prefMain.getInt("height", 0));
editor.putString("density", Integer.toString(getSystemProperty("ro.sf.lcd_density", prefMain.getInt("density", 0))));
@@ -1415,7 +1419,7 @@ && isPlayStoreRelease(context)) {
public static boolean canEnableFreeform(Context context) {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
&& (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT)
- || Build.VERSION.SDK_INT < Build.VERSION_CODES.P
+ || Build.VERSION.SDK_INT != Build.VERSION_CODES.P
|| (getTaskbarPackageName(context) != null && isPlayStoreRelease(context)));
}
@@ -1482,11 +1486,16 @@ public static int getScreenOrientation(Context context) {
}
public static boolean hasSupportLibrary(Context context) {
+ return hasSupportLibrary(context, 0);
+ }
+
+ private static boolean hasSupportLibrary(Context context, int minVersion) {
PackageManager pm = context.getPackageManager();
try {
- pm.getPackageInfo(BuildConfig.SUPPORT_APPLICATION_ID, 0);
+ PackageInfo pInfo = pm.getPackageInfo(BuildConfig.SUPPORT_APPLICATION_ID, 0);
return pm.checkSignatures(BuildConfig.SUPPORT_APPLICATION_ID, BuildConfig.APPLICATION_ID)
- == PackageManager.SIGNATURE_MATCH;
+ == PackageManager.SIGNATURE_MATCH
+ && pInfo.versionCode >= minVersion;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
@@ -1549,4 +1558,47 @@ public static int getExternalDisplayID(Context context) {
return displays[displays.length - 1].getDisplayId();
}
+
+ public static boolean canEnableOverscan() {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 && U.getCurrentApiVersion() <= 29.0f;
+ }
+
+ public static boolean canEnableImmersiveMode() {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && U.getCurrentApiVersion() <= 29.0f;
+ }
+
+ public static boolean canEnableWifi(Context context) {
+ if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI)) {
+ return false;
+ }
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
+ return true;
+ }
+
+ if (hasElevatedPermissions(context) && !isInNonRootMode(context)) {
+ return true;
+ }
+
+ return hasSupportLibrary(context, 3);
+ }
+
+ public static boolean setWifiEnabled(Context context, boolean enabled) {
+ WifiManager wifi = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
+ wifi.setWifiEnabled(enabled);
+ return true;
+ }
+
+ return false;
+ }
+
+ @SuppressLint("MissingPermission")
+ public static void closeNotificationDrawer(Context context) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
+ Intent closeDrawer = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ context.sendBroadcast(closeDrawer);
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/robobunny/SeekBarPreference.java b/app/src/main/java/com/robobunny/SeekBarPreference.java
index 4c044d2..99d0f05 100644
--- a/app/src/main/java/com/robobunny/SeekBarPreference.java
+++ b/app/src/main/java/com/robobunny/SeekBarPreference.java
@@ -115,7 +115,7 @@ public void onBindView(View view) {
}
}
catch(Exception ex) {
- Log.e(TAG, "Error binding view: " + ex.toString());
+ Log.e(TAG, "Error binding view: " + ex);
}
//if dependency is false from the beginning, disable the seek bar
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index 9dd08ab..5cd5094 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -45,7 +45,7 @@
Checking for superuser access… please wait.
No acepto
No se puede eliminar el perfil activo
- SecondScreen: Optimiza tu Android para las grandes pantallas\n\n© 2019 Braden Farmer\nApp logo by mayowadavid
+ SecondScreen: Optimiza tu Android para las grandes pantallas\n\n© %d Braden Farmer\nApp logo by mayowadavid
Acerca SecondScreen
¿Estás seguro?
Eliminar perfil
@@ -223,9 +223,6 @@
Continue
Allow third-party app integration
Disable for improved security
- Notch compatibility mode
- Apply a workaround on devices with screen notches to improve display output
- This setting will take effect the next time a profile is loaded
Profile active
Auto-start
Auto-start enabled, waiting for display connections…
@@ -233,5 +230,6 @@
Performing background operations…
Debug mode
Leaving safe mode on is strongly recommended.\n\nDisabling this option allows SecondScreen to stay active across reboots. Only disable this option if you know how to restore your device\'s resolution and density settings via adb if something goes wrong.
+ SecondScreen uses Shizuku to change device settings, such as resolution and density.\n\nPlease close this dialog once Shizuku permission has been granted.
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 8cdc47f..0d72092 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -45,7 +45,7 @@
Checking for superuser access… please wait.
Je refuse
Impossible de supprimer le profile en cours
- SecondScreen: optimisez votre Android pour les grands écrans\n\n© 2019 Braden Farmer\nApp logo by mayowadavid
+ SecondScreen: optimisez votre Android pour les grands écrans\n\n© %d Braden Farmer\nApp logo by mayowadavid
A propos de SecondScreen
Etes vous sur?
Supprimer le profile
@@ -223,9 +223,6 @@
Continue
Allow third-party app integration
Disable for improved security
- Notch compatibility mode
- Apply a workaround on devices with screen notches to improve display output
- This setting will take effect the next time a profile is loaded
Profile active
Auto-start
Auto-start enabled, waiting for display connections…
@@ -233,5 +230,6 @@
Performing background operations…
Debug mode
Leaving safe mode on is strongly recommended.\n\nDisabling this option allows SecondScreen to stay active across reboots. Only disable this option if you know how to restore your device\'s resolution and density settings via adb if something goes wrong.
+ SecondScreen uses Shizuku to change device settings, such as resolution and density.\n\nPlease close this dialog once Shizuku permission has been granted.
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
index 059ed5d..f03bb91 100644
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -45,7 +45,7 @@
Verifica dell\'accesso superuser... attendere prego.
Declina
Impossibile cancellare il profilo attualmente attivo
- SecondScreen: trasmissione dello schermo migliorata per dispositivi Android\n\n© 2019 Braden Farmer\nLogo dell\'app di mayowadavid
+ SecondScreen: trasmissione dello schermo migliorata per dispositivi Android\n\n© %d Braden Farmer\nLogo dell\'app di mayowadavid
A proposito di SecondScreen
Sei sicuro?
Cancella profilo
@@ -223,9 +223,6 @@
Continua
Permetti l\'integrazione con app di terze parti
Disattiva per migliorare la sicurezza
- Modalità compatibilità notch (tacca)
- Applica un espediente sui dispositivi con notch (tacca) sullo schermo per migliorare lo schermo trasmesso
- Quest\'impostazione avrà effetto la prossima volta che un profilo verrà caricato
Profile active
Auto-start
Auto-start enabled, waiting for display connections…
@@ -233,5 +230,6 @@
Performing background operations…
Debug mode
Leaving safe mode on is strongly recommended.\n\nDisabling this option allows SecondScreen to stay active across reboots. Only disable this option if you know how to restore your device\'s resolution and density settings via adb if something goes wrong.
+ SecondScreen uses Shizuku to change device settings, such as resolution and density.\n\nPlease close this dialog once Shizuku permission has been granted.
diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml
index 865fbbb..ac74e2a 100644
--- a/app/src/main/res/values-nl/strings.xml
+++ b/app/src/main/res/values-nl/strings.xml
@@ -45,7 +45,7 @@
Bezig met controleren op su-toegang… even geduld.
Afwijzen
Het actieve profiel kan niet worden verwijderd
- SecondScreen: betere schermspiegeling voor Android-apparaten\n\n© 2019 Braden Farmer\nApp-logo door mayowadavid
+ SecondScreen: betere schermspiegeling voor Android-apparaten\n\n© %d Braden Farmer\nApp-logo door mayowadavid
Over SecondScreen
Weet je het zeker?
Profiel verwijderen
@@ -223,9 +223,6 @@
Doorgaan
Externe app-integratie toestaan
Schakel dit uit voor meer veiligheid
- Notch compatibility mode
- Apply a workaround on devices with screen notches to improve display output
- This setting will take effect the next time a profile is loaded
Profile active
Auto-start
Auto-start enabled, waiting for display connections…
@@ -233,5 +230,6 @@
Performing background operations…
Debug mode
Leaving safe mode on is strongly recommended.\n\nDisabling this option allows SecondScreen to stay active across reboots. Only disable this option if you know how to restore your device\'s resolution and density settings via adb if something goes wrong.
+ SecondScreen uses Shizuku to change device settings, such as resolution and density.\n\nPlease close this dialog once Shizuku permission has been granted.
diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml
index 17e67f2..c81eed1 100644
--- a/app/src/main/res/values-sk/strings.xml
+++ b/app/src/main/res/values-sk/strings.xml
@@ -45,7 +45,7 @@
Kontroluje sa root prístup…, prosím, počkajte.
Nesúhlasím
Aktívny profil nie je možné vymazať
- SecondScreen: lepšie zrkadlenie obrazovky pre zariadenia s root\n\n© 2019 Braden Farmer\nApp logo by mayowadavid
+ SecondScreen: lepšie zrkadlenie obrazovky pre zariadenia s root\n\n© %d Braden Farmer\nApp logo by mayowadavid
O aplikácii SecondScreen
Ste si istý?
Vymazať profil
@@ -223,9 +223,6 @@
Continue
Allow third-party app integration
Disable for improved security
- Notch compatibility mode
- Apply a workaround on devices with screen notches to improve display output
- This setting will take effect the next time a profile is loaded
Profile active
Auto-start
Auto-start enabled, waiting for display connections…
@@ -233,5 +230,6 @@
Performing background operations…
Debug mode
Leaving safe mode on is strongly recommended.\n\nDisabling this option allows SecondScreen to stay active across reboots. Only disable this option if you know how to restore your device\'s resolution and density settings via adb if something goes wrong.
+ SecondScreen uses Shizuku to change device settings, such as resolution and density.\n\nPlease close this dialog once Shizuku permission has been granted.
diff --git a/app/src/main/res/values-zh-v24/strings.xml b/app/src/main/res/values-zh-v24/strings.xml
new file mode 100644
index 0000000..79feb20
--- /dev/null
+++ b/app/src/main/res/values-zh-v24/strings.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+ 屏保开启
+ 开启屏保
+ 在加载此配置文件之前,请确保已完全配置屏幕保护程序(在系统显示设置中)
+
+
diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml
new file mode 100644
index 0000000..e1c96dd
--- /dev/null
+++ b/app/src/main/res/values-zh/strings.xml
@@ -0,0 +1,235 @@
+
+
+
+
+
+ 接受
+ 接受 (%d)
+ 取消
+ 关闭
+ 删除
+ 编辑
+ 导入
+ 加载 %1$s
+ 新建配置文件
+ 操作
+ 保存
+ 保存 & 重新加载
+ 仅保存
+ 确定
+ 设置
+ 关闭
+ 关闭 %1$s
+ 卸载
+ 当投影到无线设备是,不推荐此模式
+ 任意配置文件
+ SecondScreen
+ SecondScreen (Debug)
+ 可用操作
+ 为了保护您的设备,SecondScreen将不允许您使用此分辨率或DPI.
+ 您的设备上安装了多个版本的SecondScreen. 同时仅支持一个版本的SecondScreen.\n\n请卸载其他版本的SecondScreen,并重新启动.
+ 检查更新
+ 检查超级用户访问… 请等待.
+ 拒绝
+ 无法删除当前使用的配置文件
+ SecondScreen:更好的Android设备屏幕镜像\n\n© %d Braden Farmer\nApp logo by mayowadavid
+ 关于 SecondScreen
+ 是否确定?
+ 删除配置文件
+ • 首先请连接显示设备.\n\n• 请确保您已经通过 root/adb 授权 SecondScreen - 否则本应用无任何作用.\n\n• 等待几秒钟,以便应用调整分辨率和DPI!\n\n• 当SecondScreen的图标在状态栏出现时, 您的设备就可以使用了.\n\n• 为了能更好的使用, 建议在加载配置文件完成后, 连接蓝牙设备来操作.\n\n• 使用完显示器后,在通知中选择“关闭”选项.
+ 操作指南
+ 重新加载配置文件?
+ %1$s 已启用. 您是否要关闭它?
+ 关闭配置文件
+ 您已将UI刷新方法保留为 \"无操作\". 强烈建议当改变分辨率或DPI时,选择UI刷新方法.\n\n是否强制保存?
+ SecondScreen没有在这个Android版本上测试过. 其可能无法工作或发生未知异常.\n\n如果您发现任何问题,请检查应用更新.
+ 显示设备已断开
+ 不要再提示
+ 这是当前生效的配置文件. 是否重新加载以便更改生效?
+ 输入配置文件名称
+ 加载配置文件清单错误!
+ 加载配置文件错误!
+ 专家模式
+ 专家模式改写SecondScreen不安全的分辨率和DPI的内部黑名单. 仅在您确切了解时使用该选项. 强烈建议使用安全模式.\n\n是否准备好启用专家模式?
+ 允许任何用户自定义的分辨率和DPI
+ 错误: 保存配置文件失败!
+ 本应用需要提升权限! 与所有此类应用程序一样,使用不当可能会导致设备无法使用.\n\n此应用仅适用于具有AOSP或原生ROM的设备! 不能保证在具有制造商皮肤的ROM的设备上正常运行.\n\n按下\"接受\",即表示您确认自己对使用此应用程序的方式,使用该设备的设备类型以及获取设备上提升的权限的方法负责.
+ 当连接显示设备时启动SecondScreen
+ 显示设备已连接
+ 加载配置文件
+ 配置文件启用
+ 快速操作
+ 加载SecondScreen…
+ SecondScreen已启用
+ 通知设置
+ SecondScreen似乎已从备份中还原.\n\n如果这是另一台设备,请清除应用程序数据并重新运行SecondScreen以确保其正常运行 (否则可能会发生问题).
+ 找不到配置文件
+ 无法获得超级用户权限!
+ 重新启动后,配置文件将不会保持活动状态
+ 自动启动
+ 自动启动动作
+ 隐藏通知图标
+ 次要动作按钮
+ 安全模式 (推荐)
+ 配置文件已删除
+ 配置文件已保存
+ 配置文件设置
+ 点按个人资料名称以查看或加载其设置.\n使用加号按钮创建其他配置文件.
+ 下面突出显示的配置文件当前处于活动状态.\n点按其名称以查看其设置或将其关闭.
+ 蓝牙已启用
+ Daydreams已启用
+ 强制导航栏
+ 超时 (always on)
+ 超时 (charging)
+ 方向(自动旋转)
+ 方向(横向)
+ 方向(纵向)
+ AI刷新(AI系统)
+ UI刷新(杀死应用程序)
+ UI刷新(软重启)
+ UI刷新(手动重启)
+ Wi-Fi已开启
+ 自由形式模式
+ HDMI (纵向))
+ 使用快速操作无需创建新配置文件即可访问SecondScreen功能,或临时修改现有正在运行的配置文件而无需对其进行编辑.
+ 配置文件未找到!\n\n请重新创建或删除此快捷方式.
+ 注意
+ 选择配置文件
+ 选择一个配置文件
+ 选择屏幕类型:
+ 显示配置文件列表
+ 此配置文件
+ 关闭SecondScreen…
+ 欢迎使用SecondScreen
+ 点击加号按钮创建您的第一个配置文件
+ 编辑配置文件
+ 显示设置
+ 其他设置
+ 配置文件名称
+ 分辨率
+ DPI
+ 过扫描设置
+ 启用过扫描
+ 对于裁剪部分图像的老式电视很有用
+ 启用蓝牙
+ 自动启用蓝牙(以连接键盘,鼠标和/或游戏控制器)
+ 启用Wi-Fi
+ 自动启用Wi-Fi
+ 启用Daydreams
+ 设备锁定时显示屏幕保护程序(仅有线连接)
+ 显示修饰
+ 显示触摸屏事件的视觉反馈
+ 屏幕方向
+ 降低背光
+ 连接显示器时,尽可能调暗设备的背光
+ 降低震动
+ 尽可能禁用设备振动
+ Chrome中的桌面模式
+ 律在Chrome浏览器中显示桌面网站
+ UI刷新方法
+ 强制显示导航栏
+ 显示带有物理按钮的设备的导航栏(仅适用于CyanogenMod ROM)
+ 屏幕超时
+ 启用自由格式模式
+ 在可调整大小的浮动窗口中打开应用
+ HDMI输出方向
+ 过扫描值
+ 上
+ 下
+ 左
+ 右
+ 测试过扫描
+ 注意: 过扫描值假定显示为横向,并且仅在配置文件处于活动状态时才是准确的.
+ 加载此配置文件之前,请确保已完全配置Daydreams(在系统显示设置中).
+ 禁用
+ 启用
+ 背光
+ 震动
+ Chrome桌面模式
+ 过扫描
+ 重置设置
+ 点击以恢复更改的设置
+ 继续使用有效的过扫描值?
+ 与该设备不兼容
+ 桌面
+ 主要动作按钮
+ 状态/导航栏
+ 状态/导航栏
+ 沉浸式
+ 沉浸模式
+ 屏幕方向
+ 自由形式模式
+ HDMI输出方向
+ 还有 %1$d 次启用调试模式.
+ 调试模式已启用
+ 调试模式已禁用
+ 调试模式已启用\n点击以禁用调试模式
+ 显示模拟尺寸/DPI
+ 模拟重启
+ 模拟应用程序升级
+ 转储当前应用程序状态
+ 需要Busybox
+ 忽略
+ 由于此版本的Android中的限制,需要安装Busybox以便SecondScreen正确刷新UI.\n\n强烈建议您安装Busybox或升级到更高版本的Android.
+ SecondScreen需要权限才能修改系统设置,然后才能继续.\n\n请按 \"授予权限\" 并确保将SecondScreen设置为 \"允许修改系统设置\"
+ 需要权限
+ 授予权限
+ 自由格式模式需要选择UI刷新方法
+ 自由格式模式需要重新启动才能生效
+ 启用任务栏
+ 在屏幕上显示最近使用的应用程序和开始菜单,以获得PC般的体验
+ 任务栏
+ SecondScreen需要可选的权限才能 \"覆盖其他应用\" 为了强制其他已安装的应用以横向模式运行.\n\n如果您不授予权限,SecondScreen仍可以将设备的方向锁定为横向,但是某些应用仍将以纵向模式运行.
+ 需要重启
+ 请重新启动设备以使SecondScreen应用设置
+ 以后
+ 请再次按 \"以后\" 确认
+ SecondScreen使用提升的权限来更改设备设置,例如分辨率和DPI. 这些权限是通过root访问或运行adb shell命令来授予的.\n\n请执行以下任一操作:\n\n• ROOT您的设备. 如果您的设备已经ROOT,请确保已允许SecondScreen超级用户权限.\n\n• 将您的设备连接到安装了Android SDK的计算机,然后运行以下命令 (单行):
+ 错误
+ 很遗憾,由于OEM限制,无法在您的设备上启用此功能.\n\n您仍然可以使用此adb shell命令启用它:\n\nappops set %1$s %2$s allow
+ 更改默认启动器
+ 如果已安装任务栏,则将其用作默认启动器; 否则,请清除默认启动器
+ 更改启动器
+ 请拔下并重新插入HDMI电缆,此设置才能生效
+ 禁用软键盘
+ 通过选择此输入方法,SecondScreen可以禁用您的软键盘(如果在连接了硬件键盘的情况下仍然显示该软键盘).\n\n当此输入法处于活动状态时,状态栏中将显示一条通知. 点按即可更改回上一个键盘.
+ 强制关闭背光
+ 在不连接显示器的情况下让背光关闭
+ 系统通知设置
+ 禁用软键盘
+ 点按即可更改键盘
+ 允许SecondScreen关闭设备的屏幕
+ 允许SecondScreen关闭设备的屏幕.\n\n这将要求您在卸载之前以设备管理员的身份停用SecondScreen.
+ 为了锁定设备的屏幕,需要以设备管理员身份激活SecondScreen. 此权限仅用于锁定屏幕,而无其他目的.\n\n如果选择激活此功能,则需要在卸载之前以设备管理员的身份停用SecondScreen.
+ 激活
+ 屏幕超时
+ 桌面模式优化
+ 打开任务栏设置
+ 安装任务栏应用
+ Bliss OS默认配置文件
+ 继续
+ 允许第三方应用程序集成
+ 禁用以提高安全性
+ 配置文件激活
+ 自动启动
+ 启用自动启动,等待显示设备连接…
+ 后台操作
+ 执行后台操作…
+ 调试模式
+ 强烈建议开启安全模式.\n\n禁用此选项可使SecondScreen在重新启动后保持活动状态. \n仅当您知道在出现问题时如何通过adb恢复设备的分辨率和密度设置时,才禁用此选项.
+ SecondScreen uses Shizuku to change device settings, such as resolution and density.\n\nPlease close this dialog once Shizuku permission has been granted.
+
+
diff --git a/app/src/main/res/values-zh/strings_activity_profile_edit.xml b/app/src/main/res/values-zh/strings_activity_profile_edit.xml
new file mode 100644
index 0000000..1e037dc
--- /dev/null
+++ b/app/src/main/res/values-zh/strings_activity_profile_edit.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+ - TV (1080p)
+ - TV (4K)
+ - TV (720p)
+ - 监视器 (1080p)
+ - AppRadio
+ - 其他 / 无
+
+
+ - 设备本机
+ - 3840x2160 (4K)
+ - 1920x1080 (1080p)
+ - 1280x720 (720p)
+ - 854x480 (480p)
+ - 2560x1600
+ - 2560x1440
+ - 2048x1536
+ - 1920x1200
+ - 1600x900
+ - 1440x900
+ - 1366x768
+ - 1280x800
+ - 1280x768
+ - 1024x768
+ - 960x600
+ - 800x600
+ - 800x480
+
+
+ - 设备本机
+ - 120dpi (ldpi)
+ - 160dpi (mdpi)
+ - 213dpi (tvdpi)
+ - 240dpi (hdpi)
+ - 320dpi (xhdpi)
+ - 480dpi (xxhdpi)
+ - 640dpi (xxxhdpi)
+ - 260dpi
+ - 280dpi
+ - 300dpi
+ - 340dpi
+ - 360dpi
+ - 400dpi
+ - 420dpi
+ - 560dpi
+
+
+ - 无动作
+ - 重新启动系统用户界面并杀死后台应用
+ - 重新启动ActivityManager(软重启)
+
+
+ - 无动作
+ - 重新启动ActivityManager(软重启)
+
+
+ - 无动作
+ - 杀死后台应用
+ - 手动重启
+
+
+ - 使用系统设置
+ - 强制自动旋转(停靠模式)
+ - 将方向锁定为横向
+ - 将方向锁定为纵向
+
+
+ - 启用
+ - 停用
+ - 切换
+
+
+ - 关闭
+ - 20%
+ - 40%
+ - 60%
+ - 80%
+ - 100%
+ - 切换
+
+
+ - 关闭
+ - 快速操作
+ - 锁定
+ - 切换背光
+ - 切换Chrome桌面模式
+ - 切换沉浸模式
+ - 切换过扫描
+ - 切换振动
+
+
+ - 使用系统设置
+ - 始终开启
+ - 充电时始终开启
+
+
+ - 设备默认
+ - 仅显示状态栏
+ - 隐藏状态和导航栏(沉浸模式)
+
+
+ - 设备默认
+ - 仅显示状态栏
+ - 隐藏状态和导航栏(沉浸模式)
+ - 切换沉浸式模式
+
+
+ - 横向
+ - 纵向
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 4e71d33..98977e0 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -45,7 +45,7 @@
Checking for superuser access… please wait.
Decline
Cannot delete the currently active profile
- SecondScreen: better screen mirroring for Android devices\n\n© 2019 Braden Farmer\nApp logo by mayowadavid
+ SecondScreen: better screen mirroring for Android devices\n\n© %d Braden Farmer\nApp logo by mayowadavid
About SecondScreen
Are you sure?
Delete profile
@@ -223,9 +223,6 @@
Continue
Allow third-party app integration
Disable for improved security
- Notch compatibility mode
- Apply a workaround on devices with screen notches to improve display output
- This setting will take effect the next time a profile is loaded
Profile active
Auto-start
Auto-start enabled, waiting for display connections…
@@ -233,5 +230,6 @@
Performing background operations…
Debug mode
Leaving safe mode on is strongly recommended.\n\nDisabling this option allows SecondScreen to stay active across reboots. Only disable this option if you know how to restore your device\'s resolution and density settings via adb if something goes wrong.
+ SecondScreen uses Shizuku to change device settings, such as resolution and density.\n\nPlease close this dialog once Shizuku permission has been granted.
diff --git a/app/src/main/res/xml/additional_settings.xml b/app/src/main/res/xml/additional_settings.xml
index 822179f..32876c6 100644
--- a/app/src/main/res/xml/additional_settings.xml
+++ b/app/src/main/res/xml/additional_settings.xml
@@ -15,7 +15,9 @@
-
+
-
+
-
+
-
+
-
+
diff --git a/app/src/main/res/xml/quick_actions_preferences.xml b/app/src/main/res/xml/quick_actions_preferences.xml
index 081f5a9..9808df1 100644
--- a/app/src/main/res/xml/quick_actions_preferences.xml
+++ b/app/src/main/res/xml/quick_actions_preferences.xml
@@ -21,7 +21,10 @@
android:title="@string/quick_turn_off" >
-
+
+
-
-
\(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
+' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
+MAX_FD=maximum
warn () {
echo "$*"
-}
+} >&2
die () {
echo
echo "$*"
echo
exit 1
-}
+} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MINGW* )
- msys=true
- ;;
- NONSTOP* )
- nonstop=true
- ;;
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
+ JAVACMD=$JAVA_HOME/jre/sh/java
else
- JAVACMD="$JAVA_HOME/bin/java"
+ JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -97,92 +133,120 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
- JAVACMD="java"
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
+ fi
fi
# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
fi
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
-if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
- JAVACMD=`cygpath --unix "$JAVACMD"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
# Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
fi
- i=$((i+1))
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
done
- case $i in
- (0) set -- ;;
- (1) set -- "$args0" ;;
- (2) set -- "$args0" "$args1" ;;
- (3) set -- "$args0" "$args1" "$args2" ;;
- (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
- esac
fi
-# Escape application args
-save () {
- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
- echo " "
-}
-APP_ARGS=$(save "$@")
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
-if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
- cd "$(dirname "$0")"
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
fi
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
index 24467a1..9b42019 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -13,8 +13,10 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
+@rem SPDX-License-Identifier: Apache-2.0
+@rem
-@if "%DEBUG%" == "" @echo off
+@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -25,10 +27,14 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@@ -37,13 +43,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
+if %ERRORLEVEL% equ 0 goto execute
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
+echo. 1>&2
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
goto fail
@@ -51,48 +57,36 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-if exist "%JAVA_EXE%" goto init
+if exist "%JAVA_EXE%" goto execute
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
+echo. 1>&2
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
goto fail
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
+if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal