From 78bb1d8b46e968361629b4b9e4f0eebc97116ffc Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Tue, 6 Jun 2023 12:31:36 +0200 Subject: [PATCH 01/56] MainService: make client connect callbacks package-private --- .../main/java/net/christianbeier/droidvnc_ng/MainService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index de538a2e..b09ff689 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -279,7 +279,7 @@ public int onStartCommand(Intent intent, int flags, int startId) } @SuppressLint("WakelockTimeout") - public static void onClientConnected(long client) { + static void onClientConnected(long client) { Log.d(TAG, "onClientConnected: client " + client); try { @@ -290,7 +290,7 @@ public static void onClientConnected(long client) { } } - public static void onClientDisconnected(long client) { + static void onClientDisconnected(long client) { Log.d(TAG, "onClientDisconnected: client " + client); try { From 739ccb8f96c070a8efc13d675753ff5d001ad8a2 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Tue, 6 Jun 2023 12:57:40 +0200 Subject: [PATCH 02/56] MainService: make more internal static functions package-private --- .../java/net/christianbeier/droidvnc_ng/MainService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index b09ff689..e09b38b5 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -465,7 +465,7 @@ private void stopScreenCapture() { * Get whether Media Projection was granted by the user. * @return -1 if unknown, 0 if denied, 1 if granted */ - public static int isMediaProjectionEnabled() { + static int isMediaProjectionEnabled() { if(instance == null) return -1; if(instance.mResultCode == 0 || instance.mResultData == null) @@ -474,7 +474,7 @@ public static int isMediaProjectionEnabled() { return 1; } - public static void togglePortraitInLandscapeWorkaround() { + static void togglePortraitInLandscapeWorkaround() { try { // set instance.mHasPortraitInLandscapeWorkaroundSet = true; @@ -492,7 +492,7 @@ public static void togglePortraitInLandscapeWorkaround() { * Get non-loopback IPv4 addresses together with the port the user specified. * @return A list of strings in the form IP:port. */ - public static ArrayList getIPv4sAndPorts() { + static ArrayList getIPv4sAndPorts() { int port = 5900; From 48013962098db96dd5ed3492c06046990a054c89 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 09:34:18 +0200 Subject: [PATCH 03/56] MainService: make getStatusEventStream() package-private An approach with broadcast intents being sent on create/destroy was evaluated, but there is no nice way for 3rd party apps to query whether or not the service is running, see https://stackoverflow.com/questions/600207/how-to-check-if-a-service-is-running-on-android So, there is no use making this a public API, thus mark it as package-private. --- .../main/java/net/christianbeier/droidvnc_ng/MainService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index e09b38b5..b6af4899 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -120,7 +120,7 @@ public enum StatusEvent { public MainService() { } - public static Observable getStatusEventStream() { + static Observable getStatusEventStream() { return mStatusEventStream; } From 5bcb720b2b5a1d69e21c6048f50182562382e3b0 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Thu, 8 Jun 2023 12:14:56 +0200 Subject: [PATCH 04/56] MainService: move vncStartServer() to intent handling --- .../droidvnc_ng/MainService.java | 47 +++++++++++-------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index b6af4899..00809615 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -178,21 +178,9 @@ public void onCreate() { mWakeLock = ((PowerManager) instance.getSystemService(Context.POWER_SERVICE)).newWakeLock((PowerManager.SCREEN_DIM_WAKE_LOCK| PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE), TAG + ":clientsConnected"); /* - Start the server FIXME move this to intent handling? + Load defaults */ - DisplayMetrics displayMetrics = new DisplayMetrics(); - WindowManager wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE); - wm.getDefaultDisplay().getRealMetrics(displayMetrics); - - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); mDefaults = new Defaults(this); - - if (!vncStartServer(displayMetrics.widthPixels, - displayMetrics.heightPixels, - prefs.getInt(Constants.PREFS_KEY_SETTINGS_PORT, mDefaults.getPort()), - Settings.Secure.getString(getContentResolver(), "bluetooth_name"), - prefs.getString(Constants.PREFS_KEY_SETTINGS_PASSWORD, mDefaults.getPassword()))) - stopSelf(); } @@ -200,10 +188,7 @@ public void onCreate() { public void onConfigurationChanged(@NonNull Configuration newConfig) { super.onConfigurationChanged(newConfig); - DisplayMetrics displayMetrics = new DisplayMetrics(); - WindowManager wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE); - wm.getDefaultDisplay().getRealMetrics(displayMetrics); - + DisplayMetrics displayMetrics = getDisplayMetrics(); Log.d(TAG, "onConfigurationChanged: width: " + displayMetrics.widthPixels + " height: " + displayMetrics.heightPixels); startScreenCapture(); @@ -229,6 +214,15 @@ public int onStartCommand(Intent intent, int flags, int startId) // Step 4 (optional): coming back from capturing permission check, now starting capturing machinery mResultCode = intent.getIntExtra(EXTRA_MEDIA_PROJECTION_RESULT_CODE, 0); mResultData = intent.getParcelableExtra(EXTRA_MEDIA_PROJECTION_RESULT_DATA); + + DisplayMetrics displayMetrics = getDisplayMetrics(); + if (!vncStartServer(displayMetrics.widthPixels, + displayMetrics.heightPixels, + PreferenceManager.getDefaultSharedPreferences(this).getInt(Constants.PREFS_KEY_SETTINGS_PORT, mDefaults.getPort()), + Settings.Secure.getString(getContentResolver(), "bluetooth_name"), + PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.PREFS_KEY_SETTINGS_PASSWORD, mDefaults.getPassword()))) + stopSelf(); + startScreenCapture(); // if we got here, we want to restart if we were killed return START_REDELIVER_INTENT; @@ -239,6 +233,14 @@ public int onStartCommand(Intent intent, int flags, int startId) // Step 3: coming back from write storage permission check, start capturing // or ask for ask for capturing permission first (then going in step 4) if (mResultCode != 0 && mResultData != null) { + DisplayMetrics displayMetrics = getDisplayMetrics(); + if (!vncStartServer(displayMetrics.widthPixels, + displayMetrics.heightPixels, + PreferenceManager.getDefaultSharedPreferences(this).getInt(Constants.PREFS_KEY_SETTINGS_PORT, mDefaults.getPort()), + Settings.Secure.getString(getContentResolver(), "bluetooth_name"), + PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.PREFS_KEY_SETTINGS_PASSWORD, mDefaults.getPassword()))) + stopSelf(); + startScreenCapture(); // if we got here, we want to restart if we were killed return START_REDELIVER_INTENT; @@ -326,9 +328,7 @@ private void startScreenCapture() { if (mVirtualDisplay != null) mVirtualDisplay.release(); - final DisplayMetrics metrics = new DisplayMetrics(); - WindowManager wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE); - wm.getDefaultDisplay().getRealMetrics(metrics); + final DisplayMetrics metrics = getDisplayMetrics(); // apply scaling preference float scaling = PreferenceManager.getDefaultSharedPreferences(this).getFloat(Constants.PREFS_KEY_SETTINGS_SCALING, mDefaults.getScaling()); @@ -554,4 +554,11 @@ public static boolean connectRepeater(String host, int port, String repeaterIden return false; } } + + private DisplayMetrics getDisplayMetrics() { + DisplayMetrics displayMetrics = new DisplayMetrics(); + WindowManager wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE); + wm.getDefaultDisplay().getRealMetrics(displayMetrics); + return displayMetrics; + } } From f9dfc24b071315e507b508c5d50b425a95b22a68 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Thu, 8 Jun 2023 12:17:32 +0200 Subject: [PATCH 05/56] native: add vncIsActive() --- app/src/main/cpp/droidvnc-ng.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/cpp/droidvnc-ng.c b/app/src/main/cpp/droidvnc-ng.c index 334ef060..b584315a 100644 --- a/app/src/main/cpp/droidvnc-ng.c +++ b/app/src/main/cpp/droidvnc-ng.c @@ -461,3 +461,7 @@ JNIEXPORT jint JNICALL Java_net_christianbeier_droidvnc_1ng_MainService_vncGetFr return theScreen->height; } + +JNIEXPORT jboolean JNICALL Java_net_christianbeier_droidvnc_1ng_MainService_vncIsActive(JNIEnv *env, jobject thiz) { + return theScreen && rfbIsActive(theScreen); +} \ No newline at end of file From ec57ac83d07674abeb85426346feb078acef7949 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Thu, 8 Jun 2023 12:17:58 +0200 Subject: [PATCH 06/56] MainService: expose vncIsActive() --- .../main/java/net/christianbeier/droidvnc_ng/MainService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index 00809615..e8b1fca9 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -109,6 +109,7 @@ public enum StatusEvent { private native boolean vncStartServer(int width, int height, int port, String desktopname, String password); private native boolean vncStopServer(); + private native boolean vncIsActive(); private native boolean vncConnectReverse(String host, int port); private native boolean vncConnectRepeater(String host, int port, String repeaterIdentifier); private native boolean vncNewFramebuffer(int width, int height); From 9e64a718d21a6dcec3fb49b693f3ac922f62066b Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Thu, 8 Jun 2023 13:26:07 +0200 Subject: [PATCH 07/56] MainService: stop if no known action was given ...and the server is not active. --- .../christianbeier/droidvnc_ng/MainService.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index e8b1fca9..ef9d97e3 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -251,6 +251,9 @@ public int onStartCommand(Intent intent, int flags, int startId) Intent mediaProjectionRequestIntent = new Intent(this, MediaProjectionRequestActivity.class); mediaProjectionRequestIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(mediaProjectionRequestIntent); + // if screen capturing was not started, we don't want a restart if we were killed + // especially, we don't want the permission asking to replay. + return START_NOT_STICKY; } } @@ -261,6 +264,9 @@ public int onStartCommand(Intent intent, int flags, int startId) Intent writeStorageRequestIntent = new Intent(this, WriteStorageRequestActivity.class); writeStorageRequestIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(writeStorageRequestIntent); + // if screen capturing was not started, we don't want a restart if we were killed + // especially, we don't want the permission asking to replay. + return START_NOT_STICKY; } if(ACTION_START.equals(intent.getAction())) { @@ -269,15 +275,22 @@ public int onStartCommand(Intent intent, int flags, int startId) Intent inputRequestIntent = new Intent(this, InputRequestActivity.class); inputRequestIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(inputRequestIntent); + // if screen capturing was not started, we don't want a restart if we were killed + // especially, we don't want the permission asking to replay. + return START_NOT_STICKY; } if(ACTION_STOP.equals(intent.getAction())) { Log.d(TAG, "onStartCommand: stop"); stopSelf(); + return START_NOT_STICKY; + } + + // no known action was given, stop the _service_ again if the _server_ is not active + if(!vncIsActive()) { + stopSelf(); } - // if screen capturing was not started, we don't want a restart if we were killed - // especially, we don't want the permission asking to replay. return START_NOT_STICKY; } From b1ff2a66a0ced93619424a9ecc6d86f3104fa27a Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Fri, 9 Jun 2023 16:18:31 +0200 Subject: [PATCH 08/56] MainActivity: show password on input focus --- .../droidvnc_ng/MainActivity.java | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java index 52daa5ad..c9676186 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java @@ -33,6 +33,8 @@ import android.text.Editable; import android.text.InputType; import android.text.TextWatcher; +import android.text.method.PasswordTransformationMethod; +import android.text.method.SingleLineTransformationMethod; import android.util.Log; import android.util.TypedValue; import android.view.View; @@ -259,9 +261,12 @@ public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { - SharedPreferences.Editor ed = prefs.edit(); - ed.putString(Constants.PREFS_KEY_SETTINGS_PASSWORD, charSequence.toString()); - ed.apply(); + // only save new value if it differs from the default + if(!charSequence.toString().equals(mDefaults.getPassword())) { + SharedPreferences.Editor ed = prefs.edit(); + ed.putString(Constants.PREFS_KEY_SETTINGS_PASSWORD, charSequence.toString()); + ed.apply(); + } } @Override @@ -269,6 +274,17 @@ public void afterTextChanged(Editable editable) { } }); + // show/hide password on focus change. NB that this triggers onTextChanged above, so we have + // to take special precautions there. + password.setOnFocusChangeListener((v, hasFocus) -> { + if (hasFocus) { + password.setTransformationMethod(new SingleLineTransformationMethod()); + } else { + password.setTransformationMethod(new PasswordTransformationMethod()); + } + // move cursor to end of text + password.setSelection(password.getText().length()); + }); final SwitchMaterial startOnBoot = findViewById(R.id.settings_start_on_boot); startOnBoot.setChecked(prefs.getBoolean(Constants.PREFS_KEY_SETTINGS_START_ON_BOOT, true)); From 9a9cc1f2d3abd710fdd9678a8b3b1c8d3356ebd9 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Fri, 9 Jun 2023 16:59:30 +0200 Subject: [PATCH 09/56] Defaults,Constants: provide an access key --- README.md | 3 +- .../christianbeier/droidvnc_ng/Constants.java | 11 ++++++++ .../christianbeier/droidvnc_ng/Defaults.kt | 28 ++++++++++++++++++- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ff3ed739..62f38eb9 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,8 @@ An example `defaults.json` with completely new defaults (not all entries need to "portReverse": 5555, "portRepeater": 5556, "scaling": 0.7, - "password": "supersecure" + "password": "supersecure", + "accessKey": "evenmoresecure" } ``` diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java b/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java index fd1940f3..93c62fe5 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java @@ -22,10 +22,21 @@ package net.christianbeier.droidvnc_ng; public class Constants { + /* + user settings + */ public static final String PREFS_KEY_SETTINGS_PORT = "settings_port"; public static final String PREFS_KEY_SETTINGS_PASSWORD = "settings_password" ; public static final String PREFS_KEY_SETTINGS_START_ON_BOOT = "settings_start_on_boot" ; public static final String PREFS_KEY_SETTINGS_SCALING = "settings_scaling" ; + public static final String PREFS_KEY_SETTINGS_ACCESS_KEY = "settings_access_key"; + /* + persisted generated defaults + */ + public static final String PREFS_KEY_DEFAULTS_ACCESS_KEY = "defaults_access_key"; + /* + persisted ui values + */ public static final String PREFS_KEY_REVERSE_VNC_LAST_HOST = "reverse_vnc_last_host" ; public static final String PREFS_KEY_REPEATER_VNC_LAST_HOST = "repeater_vnc_last_host" ; public static final String PREFS_KEY_REPEATER_VNC_LAST_ID = "repeater_vnc_last_id" ; diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt b/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt index 8af5bd4c..451040cb 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt @@ -22,10 +22,13 @@ package net.christianbeier.droidvnc_ng import android.content.Context +import android.content.SharedPreferences import android.util.Log -import java.io.File +import androidx.preference.PreferenceManager import kotlinx.serialization.* import kotlinx.serialization.json.* +import java.io.File +import java.util.UUID @OptIn(ExperimentalSerializationApi::class) @@ -54,11 +57,33 @@ class Defaults { @EncodeDefault var password = "" private set + + @EncodeDefault + var accessKey = "" + private set /* NB if adding fields here, don't forget to add their copying in the constructor as well! */ constructor(context: Context) { + /* + persist randomly generated defaults + */ + val prefs = PreferenceManager.getDefaultSharedPreferences(context) + val defaultAccessKey = prefs.getString(Constants.PREFS_KEY_DEFAULTS_ACCESS_KEY, null) + if (defaultAccessKey == null) { + val ed: SharedPreferences.Editor = prefs.edit() + ed.putString( + Constants.PREFS_KEY_DEFAULTS_ACCESS_KEY, + UUID.randomUUID().toString().replace("-".toRegex(), "") + ) + ed.apply() + } + this.accessKey = prefs.getString(Constants.PREFS_KEY_DEFAULTS_ACCESS_KEY, null)!! + + /* + read provided defaults + */ val jsonFile = File(context.getExternalFilesDir(null), "defaults.json") try { val jsonString = jsonFile.readText() @@ -68,6 +93,7 @@ class Defaults { this.portRepeater = readDefault.portRepeater this.scaling = readDefault.scaling this.password = readDefault.password + this.accessKey = readDefault.accessKey // add here! } catch (e: Exception) { Log.w(TAG, "${e.message}") From 382b39ab160ac56ce1be4fe53113a807cfdbc412 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Fri, 9 Jun 2023 17:54:22 +0200 Subject: [PATCH 10/56] MainActivity: wire up access key setting UI --- .../droidvnc_ng/MainActivity.java | 35 +++++++++++++++++++ app/src/main/res/layout/activity_main.xml | 29 +++++++++++++++ app/src/main/res/values-zh-rCN/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 4 files changed, 66 insertions(+) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java index c9676186..1a4bb441 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java @@ -286,6 +286,39 @@ public void afterTextChanged(Editable editable) { password.setSelection(password.getText().length()); }); + final EditText accessKey = findViewById(R.id.settings_access_key); + accessKey.setText(prefs.getString(Constants.PREFS_KEY_SETTINGS_ACCESS_KEY, mDefaults.getAccessKey())); + accessKey.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + // only save new value if it differs from the default + if(!charSequence.toString().equals(mDefaults.getAccessKey())) { + SharedPreferences.Editor ed = prefs.edit(); + ed.putString(Constants.PREFS_KEY_SETTINGS_ACCESS_KEY, charSequence.toString()); + ed.apply(); + } + } + + @Override + public void afterTextChanged(Editable editable) { + } + }); + // show/hide access key on focus change. NB that this triggers onTextChanged above, so we have + // to take special precautions there. + accessKey.setOnFocusChangeListener((v, hasFocus) -> { + if (hasFocus) { + accessKey.setTransformationMethod(new SingleLineTransformationMethod()); + } else { + accessKey.setTransformationMethod(new PasswordTransformationMethod()); + } + // move cursor to end of text + accessKey.setSelection(accessKey.getText().length()); + }); + final SwitchMaterial startOnBoot = findViewById(R.id.settings_start_on_boot); startOnBoot.setChecked(prefs.getBoolean(Constants.PREFS_KEY_SETTINGS_START_ON_BOOT, true)); startOnBoot.setOnCheckedChangeListener((compoundButton, b) -> { @@ -334,6 +367,7 @@ public void afterTextChanged(Editable editable) { // indicate that changing these settings does not have an effect when the server is running findViewById(R.id.settings_port).setEnabled(false); findViewById(R.id.settings_password).setEnabled(false); + findViewById(R.id.settings_access_key).setEnabled(false); findViewById(R.id.settings_scaling).setEnabled(false); mIsMainServiceRunning = true; @@ -356,6 +390,7 @@ public void afterTextChanged(Editable editable) { // indicate that changing these settings does have an effect when the server is stopped findViewById(R.id.settings_port).setEnabled(true); findViewById(R.id.settings_password).setEnabled(true); + findViewById(R.id.settings_access_key).setEnabled(true); findViewById(R.id.settings_scaling).setEnabled(true); mIsMainServiceRunning = false; diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index b2b95819..feebb2e7 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -82,6 +82,35 @@ + + + + + + + + + + diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 0a70fae2..775dc3f4 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -4,6 +4,7 @@ 设置 端口 密码 + 访问键 开机启动 缩放 权限仪表盘 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9708578a..1de010d8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -4,6 +4,7 @@ Settings Port Password + Access Key Start on Boot Scaling Permissions Dashboard From a18bf1834a9c23d34731c2a269b16c6eef955229 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Fri, 9 Jun 2023 17:21:03 +0200 Subject: [PATCH 11/56] MainService: export and require access key --- app/src/main/AndroidManifest.xml | 7 +++++++ .../net/christianbeier/droidvnc_ng/MainService.java | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d1ce297d..a487dfc5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -23,9 +23,16 @@ + Date: Fri, 9 Jun 2023 17:06:00 +0200 Subject: [PATCH 12/56] MainActivity: provide access key --- .../main/java/net/christianbeier/droidvnc_ng/MainActivity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java index 1a4bb441..0d8d6834 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java @@ -80,6 +80,7 @@ protected void onCreate(Bundle savedInstanceState) { mButtonToggle.setOnClickListener(view -> { Intent intent = new Intent(MainActivity.this, MainService.class); + intent.putExtra(MainService.EXTRA_ACCESS_KEY, prefs.getString(Constants.PREFS_KEY_SETTINGS_ACCESS_KEY, mDefaults.getAccessKey())); if(mIsMainServiceRunning) { intent.setAction(MainService.ACTION_STOP); } From ce6a9f267a86302424bcbe9e6a725d6d5d75af20 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Fri, 9 Jun 2023 17:06:15 +0200 Subject: [PATCH 13/56] InputRequestActivity: provide access key --- .../net/christianbeier/droidvnc_ng/InputRequestActivity.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/InputRequestActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/InputRequestActivity.java index 52a85f43..867b5091 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/InputRequestActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/InputRequestActivity.java @@ -28,6 +28,7 @@ import android.util.Log; import androidx.appcompat.app.AppCompatActivity; +import androidx.preference.PreferenceManager; public class InputRequestActivity extends AppCompatActivity { @@ -81,6 +82,7 @@ private void postResultAndFinish(boolean isA11yEnabled) { Intent intent = new Intent(this, MainService.class); intent.setAction(MainService.ACTION_HANDLE_INPUT_RESULT); intent.putExtra(MainService.EXTRA_INPUT_RESULT, isA11yEnabled); + intent.putExtra(MainService.EXTRA_ACCESS_KEY, PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.PREFS_KEY_SETTINGS_ACCESS_KEY, new Defaults(this).getAccessKey())); startService(intent); finish(); } From 05a4f385c1b69e3a1eee5c9f548d4b09fdb67cfe Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Fri, 9 Jun 2023 17:06:40 +0200 Subject: [PATCH 14/56] MediaProjectionRequestActivity: provide access key --- .../droidvnc_ng/MediaProjectionRequestActivity.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MediaProjectionRequestActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MediaProjectionRequestActivity.java index cad47143..36b3a640 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MediaProjectionRequestActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MediaProjectionRequestActivity.java @@ -23,6 +23,7 @@ package net.christianbeier.droidvnc_ng; import androidx.appcompat.app.AppCompatActivity; +import androidx.preference.PreferenceManager; import android.app.Activity; import android.content.Context; @@ -61,6 +62,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { Intent intent = new Intent(this, MainService.class); intent.setAction(MainService.ACTION_HANDLE_MEDIA_PROJECTION_RESULT); + intent.putExtra(MainService.EXTRA_ACCESS_KEY, PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.PREFS_KEY_SETTINGS_ACCESS_KEY, new Defaults(this).getAccessKey())); intent.putExtra(MainService.EXTRA_MEDIA_PROJECTION_RESULT_CODE, resultCode); intent.putExtra(MainService.EXTRA_MEDIA_PROJECTION_RESULT_DATA, data); startService(intent); From cb46a8902782e7d4af80624b7012fc44ba6bade4 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Fri, 9 Jun 2023 17:06:59 +0200 Subject: [PATCH 15/56] OnBootReceiver: provide access key --- .../main/java/net/christianbeier/droidvnc_ng/OnBootReceiver.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/OnBootReceiver.java b/app/src/main/java/net/christianbeier/droidvnc_ng/OnBootReceiver.java index a5154df5..03bcfccd 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/OnBootReceiver.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/OnBootReceiver.java @@ -43,6 +43,7 @@ public void onReceive(Context context, Intent arg1) Log.i(TAG, "onReceive: configured to start"); Intent intent = new Intent(context, MainService.class); intent.setAction(MainService.ACTION_START); + intent.putExtra(MainService.EXTRA_ACCESS_KEY, prefs.getString(Constants.PREFS_KEY_SETTINGS_ACCESS_KEY, new Defaults(context).getAccessKey())); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { context.startForegroundService(intent); } else { From 4aa4f22ddcac5a80b5bb7ae326ab693c17067c3f Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Fri, 9 Jun 2023 17:07:15 +0200 Subject: [PATCH 16/56] WriteStorageRequestActivity: provide access key --- .../christianbeier/droidvnc_ng/WriteStorageRequestActivity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/WriteStorageRequestActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/WriteStorageRequestActivity.java index a90fa2a2..ddc27870 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/WriteStorageRequestActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/WriteStorageRequestActivity.java @@ -92,6 +92,7 @@ private void postResultAndFinish(boolean isPermissionGiven) { Intent intent = new Intent(this, MainService.class); intent.setAction(MainService.ACTION_HANDLE_WRITE_STORAGE_RESULT); + intent.putExtra(MainService.EXTRA_ACCESS_KEY, PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.PREFS_KEY_SETTINGS_ACCESS_KEY, new Defaults(this).getAccessKey())); intent.putExtra(MainService.EXTRA_WRITE_STORAGE_RESULT, isPermissionGiven); startService(intent); finish(); From c2a719355c99f16d0996bf73bdf920ac89b04913 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 09:42:18 +0200 Subject: [PATCH 17/56] MainService,MainActivity: replace static connectReverse() w/ Intent --- .../droidvnc_ng/MainActivity.java | 62 ++++++++++++++++--- .../droidvnc_ng/MainService.java | 37 ++++++++--- 2 files changed, 83 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java index 0d8d6834..b19d26c1 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java @@ -23,7 +23,10 @@ import android.Manifest; import android.annotation.SuppressLint; +import android.content.BroadcastReceiver; +import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.res.Resources; @@ -52,6 +55,7 @@ import com.google.android.material.switchmaterial.SwitchMaterial; import java.util.ArrayList; +import java.util.UUID; import io.reactivex.rxjava3.disposables.Disposable; @@ -65,6 +69,8 @@ public class MainActivity extends AppCompatActivity { private TextView mAddress; private boolean mIsMainServiceRunning; private Disposable mMainServiceStatusEventStreamConnection; + private BroadcastReceiver mMainServiceBroadcastReceiver; + private String mLastMainServiceRequestId; private Defaults mDefaults; @@ -138,13 +144,18 @@ protected void onCreate(Bundle savedInstanceState) { } } Log.d(TAG, "reverse vnc " + host + ":" + port); - if(MainService.connectReverse(host,port)) { - Toast.makeText(MainActivity.this, getString(R.string.main_activity_reverse_vnc_success, host, port), Toast.LENGTH_LONG).show(); - SharedPreferences.Editor ed = prefs.edit(); - ed.putString(Constants.PREFS_KEY_REVERSE_VNC_LAST_HOST, inputText.getText().toString()); - ed.apply(); - } else - Toast.makeText(MainActivity.this, getString(R.string.main_activity_reverse_vnc_fail, host, port), Toast.LENGTH_LONG).show(); + mLastMainServiceRequestId = UUID.randomUUID().toString(); + Intent request = new Intent(MainActivity.this, MainService.class); + request.putExtra(MainService.EXTRA_ACCESS_KEY, prefs.getString(Constants.PREFS_KEY_SETTINGS_ACCESS_KEY, mDefaults.getAccessKey())); + request.setAction(MainService.ACTION_CONNECT_REVERSE); + request.putExtra(MainService.EXTRA_HOST, host); + request.putExtra(MainService.EXTRA_PORT, port); + request.putExtra(MainService.EXTRA_REQUEST_ID, mLastMainServiceRequestId); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + startForegroundService(request); + } else { + startService(request); + } }) .setNegativeButton(android.R.string.cancel, (dialogInterface, i) -> dialogInterface.cancel()) .create(); @@ -398,6 +409,42 @@ public void afterTextChanged(Editable editable) { } }); + + mMainServiceBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (MainService.ACTION_CONNECT_REVERSE.equals(intent.getAction()) + && mLastMainServiceRequestId != null + && mLastMainServiceRequestId.equals(intent.getStringExtra(MainService.EXTRA_REQUEST_ID))) { + // was a CONNECT_REVERSE requested by us + if (intent.getBooleanExtra(MainService.EXTRA_REQUEST_SUCCESS, false)) { + Toast.makeText(MainActivity.this, + getString(R.string.main_activity_reverse_vnc_success, + intent.getStringExtra(MainService.EXTRA_HOST), + intent.getIntExtra(MainService.EXTRA_PORT, mDefaults.getPortReverse())), + Toast.LENGTH_LONG) + .show(); + SharedPreferences.Editor ed = prefs.edit(); + ed.putString(Constants.PREFS_KEY_REVERSE_VNC_LAST_HOST, + intent.getStringExtra(MainService.EXTRA_HOST) + ":" + intent.getIntExtra(MainService.EXTRA_PORT, mDefaults.getPortReverse())); + ed.apply(); + } else + Toast.makeText(MainActivity.this, + getString(R.string.main_activity_reverse_vnc_fail, + intent.getStringExtra(MainService.EXTRA_HOST), + intent.getIntExtra(MainService.EXTRA_PORT, mDefaults.getPortReverse())), + Toast.LENGTH_LONG) + .show(); + + // reset this + mLastMainServiceRequestId = null; + } + + } + }; + IntentFilter filter = new IntentFilter(); + filter.addAction(MainService.ACTION_CONNECT_REVERSE); + registerReceiver(mMainServiceBroadcastReceiver, filter); } @SuppressLint("SetTextI18n") @@ -455,6 +502,7 @@ protected void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy"); mMainServiceStatusEventStreamConnection.dispose(); + unregisterReceiver(mMainServiceBroadcastReceiver); } diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index 4012ff10..11f884a2 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -68,6 +68,11 @@ public class MainService extends Service { private static final int NOTIFICATION_ID = 11; final static String ACTION_START = "start"; final static String ACTION_STOP = "stop"; + public static final String ACTION_CONNECT_REVERSE = "net.christianbeier.droidvnc_ng.ACTION_CONNECT_REVERSE"; + public static final String EXTRA_REQUEST_ID = "net.christianbeier.droidvnc_ng.EXTRA_REQUEST_ID"; + public static final String EXTRA_REQUEST_SUCCESS = "net.christianbeier.droidvnc_ng.EXTRA_REQUEST_SUCCESS"; + public static final String EXTRA_HOST = "net.christianbeier.droidvnc_ng.EXTRA_HOST"; + public static final String EXTRA_PORT = "net.christianbeier.droidvnc_ng.EXTRA_PORT"; public static final String EXTRA_ACCESS_KEY = "net.christianbeier.droidvnc_ng.EXTRA_ACCESS_KEY"; final static String ACTION_HANDLE_MEDIA_PROJECTION_RESULT = "action_handle_media_projection_result"; @@ -298,6 +303,29 @@ public int onStartCommand(Intent intent, int flags, int startId) return START_NOT_STICKY; } + if(ACTION_CONNECT_REVERSE.equals(intent.getAction())) { + Log.d(TAG, "onStartCommand: connect reverse"); + boolean status = false; + if(vncIsActive()) { + try { + //TODO run on worker thread + status = instance.vncConnectReverse(intent.getStringExtra(EXTRA_HOST), intent.getIntExtra(EXTRA_PORT, mDefaults.getPortReverse())); + } catch (NullPointerException ignored) { + } + } else { + stopSelf(); + } + + Intent answer = new Intent(ACTION_CONNECT_REVERSE); + // use request's extras + answer.putExtras(intent); + // but don't leak the access key! + answer.removeExtra(EXTRA_ACCESS_KEY); + answer.putExtra(EXTRA_REQUEST_SUCCESS, status); + sendBroadcast(answer); + return START_NOT_STICKY; + } + // no known action was given, stop the _service_ again if the _server_ is not active if(!vncIsActive()) { stopSelf(); @@ -563,15 +591,6 @@ static ArrayList getIPv4sAndPorts() { return hostsAndPorts; } - public static boolean connectReverse(String host, int port) { - try { - return instance.vncConnectReverse(host, port); - } - catch (NullPointerException e) { - return false; - } - } - public static boolean connectRepeater(String host, int port, String repeaterIdentifier) { try { return instance.vncConnectRepeater(host, port, repeaterIdentifier); From ea759ad433ea1650e0a2b2aa2b52a1a5c783a82b Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 10:37:02 +0200 Subject: [PATCH 18/56] MainService: get password and port from Intent extras ...instead of from SharedPrefs. Also, move VNC server start right to ACTION_START handling. This also prevents a caller from stopping a service that's in the process of starting up. --- .../droidvnc_ng/MainService.java | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index 11f884a2..7aa97914 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -66,7 +66,7 @@ public class MainService extends Service { private static final String TAG = "MainService"; private static final int NOTIFICATION_ID = 11; - final static String ACTION_START = "start"; + public final static String ACTION_START = "net.christianbeier.droidvnc_ng.ACTION_START"; final static String ACTION_STOP = "stop"; public static final String ACTION_CONNECT_REVERSE = "net.christianbeier.droidvnc_ng.ACTION_CONNECT_REVERSE"; public static final String EXTRA_REQUEST_ID = "net.christianbeier.droidvnc_ng.EXTRA_REQUEST_ID"; @@ -74,6 +74,7 @@ public class MainService extends Service { public static final String EXTRA_HOST = "net.christianbeier.droidvnc_ng.EXTRA_HOST"; public static final String EXTRA_PORT = "net.christianbeier.droidvnc_ng.EXTRA_PORT"; public static final String EXTRA_ACCESS_KEY = "net.christianbeier.droidvnc_ng.EXTRA_ACCESS_KEY"; + public static final String EXTRA_PASSWORD = "net.christianbeier.droidvnc_ng.EXTRA_PASSWORD"; final static String ACTION_HANDLE_MEDIA_PROJECTION_RESULT = "action_handle_media_projection_result"; final static String EXTRA_MEDIA_PROJECTION_RESULT_DATA = "result_data_media_projection"; @@ -232,15 +233,6 @@ public int onStartCommand(Intent intent, int flags, int startId) // Step 4 (optional): coming back from capturing permission check, now starting capturing machinery mResultCode = intent.getIntExtra(EXTRA_MEDIA_PROJECTION_RESULT_CODE, 0); mResultData = intent.getParcelableExtra(EXTRA_MEDIA_PROJECTION_RESULT_DATA); - - DisplayMetrics displayMetrics = getDisplayMetrics(); - if (!vncStartServer(displayMetrics.widthPixels, - displayMetrics.heightPixels, - PreferenceManager.getDefaultSharedPreferences(this).getInt(Constants.PREFS_KEY_SETTINGS_PORT, mDefaults.getPort()), - Settings.Secure.getString(getContentResolver(), "bluetooth_name"), - PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.PREFS_KEY_SETTINGS_PASSWORD, mDefaults.getPassword()))) - stopSelf(); - startScreenCapture(); // if we got here, we want to restart if we were killed return START_REDELIVER_INTENT; @@ -251,14 +243,6 @@ public int onStartCommand(Intent intent, int flags, int startId) // Step 3: coming back from write storage permission check, start capturing // or ask for ask for capturing permission first (then going in step 4) if (mResultCode != 0 && mResultData != null) { - DisplayMetrics displayMetrics = getDisplayMetrics(); - if (!vncStartServer(displayMetrics.widthPixels, - displayMetrics.heightPixels, - PreferenceManager.getDefaultSharedPreferences(this).getInt(Constants.PREFS_KEY_SETTINGS_PORT, mDefaults.getPort()), - Settings.Secure.getString(getContentResolver(), "bluetooth_name"), - PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.PREFS_KEY_SETTINGS_PASSWORD, mDefaults.getPassword()))) - stopSelf(); - startScreenCapture(); // if we got here, we want to restart if we were killed return START_REDELIVER_INTENT; @@ -288,6 +272,15 @@ public int onStartCommand(Intent intent, int flags, int startId) if(ACTION_START.equals(intent.getAction())) { Log.d(TAG, "onStartCommand: start"); + // Step 0: start server w/ provided arguments + DisplayMetrics displayMetrics = getDisplayMetrics(); + if (!vncStartServer(displayMetrics.widthPixels, + displayMetrics.heightPixels, + intent.getIntExtra(EXTRA_PORT, mDefaults.getPort()), + Settings.Secure.getString(getContentResolver(), "bluetooth_name"), + intent.getStringExtra(EXTRA_PASSWORD) != null ? intent.getStringExtra(EXTRA_PASSWORD) : mDefaults.getPassword())) + stopSelf(); + // Step 1: check input permission Intent inputRequestIntent = new Intent(this, InputRequestActivity.class); inputRequestIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); From fbfa68e06058aa5d0bf4033f527bff75836fef64 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 10:39:28 +0200 Subject: [PATCH 19/56] MainActivity: provide port and password w/ start Intent --- .../main/java/net/christianbeier/droidvnc_ng/MainActivity.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java index b19d26c1..215252cd 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java @@ -86,6 +86,8 @@ protected void onCreate(Bundle savedInstanceState) { mButtonToggle.setOnClickListener(view -> { Intent intent = new Intent(MainActivity.this, MainService.class); + intent.putExtra(MainService.EXTRA_PORT, prefs.getInt(Constants.PREFS_KEY_SETTINGS_PORT, mDefaults.getPort())); + intent.putExtra(MainService.EXTRA_PASSWORD, prefs.getString(Constants.PREFS_KEY_SETTINGS_PASSWORD, mDefaults.getPassword())); intent.putExtra(MainService.EXTRA_ACCESS_KEY, prefs.getString(Constants.PREFS_KEY_SETTINGS_ACCESS_KEY, mDefaults.getAccessKey())); if(mIsMainServiceRunning) { intent.setAction(MainService.ACTION_STOP); From d9251199e5550416d31c817fdc0b6c491236a0e8 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 11:07:03 +0200 Subject: [PATCH 20/56] InputService: rename isEnabled() to isConnected() --- .../net/christianbeier/droidvnc_ng/InputRequestActivity.java | 4 ++-- .../java/net/christianbeier/droidvnc_ng/InputService.java | 2 +- .../java/net/christianbeier/droidvnc_ng/MainActivity.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/InputRequestActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/InputRequestActivity.java index 867b5091..b8e379be 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/InputRequestActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/InputRequestActivity.java @@ -40,7 +40,7 @@ public class InputRequestActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if(!InputService.isEnabled()) { + if(!InputService.isConnected()) { new AlertDialog.Builder(this) .setCancelable(false) .setTitle(R.string.input_a11y_title) @@ -68,7 +68,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_INPUT) { Log.d(TAG, "onActivityResult"); - postResultAndFinish(InputService.isEnabled()); + postResultAndFinish(InputService.isConnected()); } } diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/InputService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/InputService.java index 1fd1ec04..dbbb7ffa 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/InputService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/InputService.java @@ -92,7 +92,7 @@ public void onDestroy() { Log.i(TAG, "onDestroy"); } - public static boolean isEnabled() + public static boolean isConnected() { return instance != null; } diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java index 215252cd..e7510086 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java @@ -458,7 +458,7 @@ protected void onResume() { Update Input permission display. */ TextView inputStatus = findViewById(R.id.permission_status_input); - if(InputService.isEnabled()) { + if(InputService.isConnected()) { inputStatus.setText(R.string.main_activity_granted); inputStatus.setTextColor(getColor(android.R.color.holo_green_dark)); } else { From 89e91a06d59bd60a6056a9e2eb687244cb5e593f Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 12:05:24 +0200 Subject: [PATCH 21/56] MainActivity: fix password and access key entry 9043e44dd9043e1b3157b940a9fde4a91256c5a8 did not quite get it right. --- .../java/net/christianbeier/droidvnc_ng/MainActivity.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java index e7510086..b18c6c9f 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java @@ -275,8 +275,8 @@ public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { - // only save new value if it differs from the default - if(!charSequence.toString().equals(mDefaults.getPassword())) { + // only save new value if it differs from the default and was not saved before + if(!(prefs.getString(Constants.PREFS_KEY_SETTINGS_PASSWORD, null) == null && charSequence.toString().equals(mDefaults.getPassword()))) { SharedPreferences.Editor ed = prefs.edit(); ed.putString(Constants.PREFS_KEY_SETTINGS_PASSWORD, charSequence.toString()); ed.apply(); @@ -309,8 +309,8 @@ public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) @Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { - // only save new value if it differs from the default - if(!charSequence.toString().equals(mDefaults.getAccessKey())) { + // only save new value if it differs from the default and was not saved before + if(!(prefs.getString(Constants.PREFS_KEY_SETTINGS_ACCESS_KEY, null) == null && charSequence.toString().equals(mDefaults.getAccessKey()))) { SharedPreferences.Editor ed = prefs.edit(); ed.putString(Constants.PREFS_KEY_SETTINGS_ACCESS_KEY, charSequence.toString()); ed.apply(); From 4b59bc15f813fa3e783639746f4eaf4b0a1a2088 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 12:12:28 +0200 Subject: [PATCH 22/56] Defaults, README: add new viewOnly default --- README.md | 1 + app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/README.md b/README.md index 62f38eb9..512a2dc2 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,7 @@ An example `defaults.json` with completely new defaults (not all entries need to "portReverse": 5555, "portRepeater": 5556, "scaling": 0.7, + "viewOnly": false, "password": "supersecure", "accessKey": "evenmoresecure" } diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt b/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt index 451040cb..9e9427b7 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt @@ -54,6 +54,10 @@ class Defaults { var scaling = 1.0f private set + @EncodeDefault + var viewOnly = false + private set + @EncodeDefault var password = "" private set @@ -92,6 +96,7 @@ class Defaults { this.portReverse = readDefault.portReverse this.portRepeater = readDefault.portRepeater this.scaling = readDefault.scaling + this.viewOnly = readDefault.viewOnly this.password = readDefault.password this.accessKey = readDefault.accessKey // add here! From 3602398768e42c9b9e01e054c265ef3f3abae764 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 12:13:49 +0200 Subject: [PATCH 23/56] Constants: add view-only setting key --- app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java b/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java index 93c62fe5..b92153e5 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java @@ -29,6 +29,7 @@ public class Constants { public static final String PREFS_KEY_SETTINGS_PASSWORD = "settings_password" ; public static final String PREFS_KEY_SETTINGS_START_ON_BOOT = "settings_start_on_boot" ; public static final String PREFS_KEY_SETTINGS_SCALING = "settings_scaling" ; + public static final String PREFS_KEY_SETTINGS_VIEW_ONLY = "settings_view_only" ; public static final String PREFS_KEY_SETTINGS_ACCESS_KEY = "settings_access_key"; /* persisted generated defaults From e424d43dca36953d605890df9639934d83a4e87e Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 12:14:28 +0200 Subject: [PATCH 24/56] InputService: add means to enable/disable while connected --- .../christianbeier/droidvnc_ng/InputService.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/InputService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/InputService.java index dbbb7ffa..2d76083d 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/InputService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/InputService.java @@ -51,6 +51,7 @@ public synchronized void onCancelled(GestureDescription gestureDescription) { private static final String TAG = "InputService"; private static InputService instance; + static boolean isEnabled; private Handler mMainHandler; @@ -115,6 +116,10 @@ public static boolean setScaling(float scaling) { @SuppressWarnings("unused") public static void onPointerEvent(int buttonMask, int x, int y, long client) { + if(!isEnabled) { + return; + } + try { x /= instance.mScaling; y /= instance.mScaling; @@ -172,6 +177,11 @@ public static void onPointerEvent(int buttonMask, int x, int y, long client) { } public static void onKeyEvent(int down, long keysym, long client) { + + if(!isEnabled) { + return; + } + Log.d(TAG, "onKeyEvent: keysym " + keysym + " down " + down + " by client " + client); /* @@ -235,6 +245,11 @@ public static void onKeyEvent(int down, long keysym, long client) { } public static void onCutText(String text, long client) { + + if(!isEnabled) { + return; + } + Log.d(TAG, "onCutText: text '" + text + "' by client " + client); try { From 655f8634b594e8c9439c0ad5e6a9d3f9afe110b4 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 12:15:48 +0200 Subject: [PATCH 25/56] MainService,InputRequestActivity: don't enable input if EXTRA_VIEW_ONLY is given --- .../christianbeier/droidvnc_ng/InputRequestActivity.java | 6 ++++++ .../java/net/christianbeier/droidvnc_ng/MainService.java | 9 ++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/InputRequestActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/InputRequestActivity.java index b8e379be..57a3b65e 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/InputRequestActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/InputRequestActivity.java @@ -40,6 +40,12 @@ public class InputRequestActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + // if VIEW_ONLY is set, bail out early without bothering the user + if(getIntent().getBooleanExtra(MainService.EXTRA_VIEW_ONLY, new Defaults(this).getViewOnly())) { + postResultAndFinish(false); + return; + } + if(!InputService.isConnected()) { new AlertDialog.Builder(this) .setCancelable(false) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index 7aa97914..0f14df89 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -75,6 +75,7 @@ public class MainService extends Service { public static final String EXTRA_PORT = "net.christianbeier.droidvnc_ng.EXTRA_PORT"; public static final String EXTRA_ACCESS_KEY = "net.christianbeier.droidvnc_ng.EXTRA_ACCESS_KEY"; public static final String EXTRA_PASSWORD = "net.christianbeier.droidvnc_ng.EXTRA_PASSWORD"; + public static final String EXTRA_VIEW_ONLY = "net.christianbeier.droidvnc_ng.EXTRA_VIEW_ONLY"; final static String ACTION_HANDLE_MEDIA_PROJECTION_RESULT = "action_handle_media_projection_result"; final static String EXTRA_MEDIA_PROJECTION_RESULT_DATA = "result_data_media_projection"; @@ -261,7 +262,12 @@ public int onStartCommand(Intent intent, int flags, int startId) if(ACTION_HANDLE_INPUT_RESULT.equals(intent.getAction())) { Log.d(TAG, "onStartCommand: handle input result"); // Step 2: coming back from input permission check, now setup InputService and ask for write storage permission - InputService.setScaling(PreferenceManager.getDefaultSharedPreferences(this).getFloat(Constants.PREFS_KEY_SETTINGS_SCALING, mDefaults.getScaling())); + if(intent.getBooleanExtra(EXTRA_INPUT_RESULT, false)) { + InputService.isEnabled = true; + InputService.setScaling(PreferenceManager.getDefaultSharedPreferences(this).getFloat(Constants.PREFS_KEY_SETTINGS_SCALING, mDefaults.getScaling())); + } else { + InputService.isEnabled = false; + } Intent writeStorageRequestIntent = new Intent(this, WriteStorageRequestActivity.class); writeStorageRequestIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(writeStorageRequestIntent); @@ -283,6 +289,7 @@ public int onStartCommand(Intent intent, int flags, int startId) // Step 1: check input permission Intent inputRequestIntent = new Intent(this, InputRequestActivity.class); + inputRequestIntent.putExtra(EXTRA_VIEW_ONLY, intent.getBooleanExtra(EXTRA_VIEW_ONLY, mDefaults.getViewOnly())); inputRequestIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(inputRequestIntent); // if screen capturing was not started, we don't want a restart if we were killed From fb3c32511c5f1bfc67ec328f3c1068533068f379 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 12:16:03 +0200 Subject: [PATCH 26/56] MainActivity: wire up view-only setting --- .../droidvnc_ng/MainActivity.java | 11 +++++++ app/src/main/res/layout/activity_main.xml | 29 +++++++++++++++++++ app/src/main/res/values-zh-rCN/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 4 files changed, 42 insertions(+) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java index b18c6c9f..8c36d12f 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java @@ -88,6 +88,7 @@ protected void onCreate(Bundle savedInstanceState) { Intent intent = new Intent(MainActivity.this, MainService.class); intent.putExtra(MainService.EXTRA_PORT, prefs.getInt(Constants.PREFS_KEY_SETTINGS_PORT, mDefaults.getPort())); intent.putExtra(MainService.EXTRA_PASSWORD, prefs.getString(Constants.PREFS_KEY_SETTINGS_PASSWORD, mDefaults.getPassword())); + intent.putExtra(MainService.EXTRA_VIEW_ONLY, prefs.getBoolean(Constants.PREFS_KEY_SETTINGS_VIEW_ONLY, mDefaults.getViewOnly())); intent.putExtra(MainService.EXTRA_ACCESS_KEY, prefs.getString(Constants.PREFS_KEY_SETTINGS_ACCESS_KEY, mDefaults.getAccessKey())); if(mIsMainServiceRunning) { intent.setAction(MainService.ACTION_STOP); @@ -350,6 +351,14 @@ public void afterTextChanged(Editable editable) { ed.apply(); }); + final SwitchMaterial viewOnly = findViewById(R.id.settings_view_only); + viewOnly.setChecked(prefs.getBoolean(Constants.PREFS_KEY_SETTINGS_VIEW_ONLY, mDefaults.getViewOnly())); + viewOnly.setOnCheckedChangeListener((compoundButton, b) -> { + SharedPreferences.Editor ed = prefs.edit(); + ed.putBoolean(Constants.PREFS_KEY_SETTINGS_VIEW_ONLY, b); + ed.apply(); + }); + TextView about = findViewById(R.id.about); about.setText(getString(R.string.main_activity_about, BuildConfig.VERSION_NAME)); @@ -383,6 +392,7 @@ public void afterTextChanged(Editable editable) { findViewById(R.id.settings_password).setEnabled(false); findViewById(R.id.settings_access_key).setEnabled(false); findViewById(R.id.settings_scaling).setEnabled(false); + findViewById(R.id.settings_view_only).setEnabled(false); mIsMainServiceRunning = true; } @@ -406,6 +416,7 @@ public void afterTextChanged(Editable editable) { findViewById(R.id.settings_password).setEnabled(true); findViewById(R.id.settings_access_key).setEnabled(true); findViewById(R.id.settings_scaling).setEnabled(true); + findViewById(R.id.settings_view_only).setEnabled(true); mIsMainServiceRunning = false; } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index feebb2e7..5e19703e 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -171,6 +171,35 @@ + + + + + + + + + + + diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 775dc3f4..e5ee00c0 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -7,6 +7,7 @@ 访问键 开机启动 缩放 + 只读 权限仪表盘 截屏 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1de010d8..f45eea86 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -7,6 +7,7 @@ Access Key Start on Boot Scaling + View Only Permissions Dashboard : Screen Capturing From 43a2da73ea98698ecb3a28c7a7536f9e9d474ced Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 13:10:53 +0200 Subject: [PATCH 27/56] Constants: add keys for persisting runtime port and password --- .../main/java/net/christianbeier/droidvnc_ng/Constants.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java b/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java index b92153e5..d268becb 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java @@ -36,9 +36,11 @@ public class Constants { */ public static final String PREFS_KEY_DEFAULTS_ACCESS_KEY = "defaults_access_key"; /* - persisted ui values + persisted runtime values */ public static final String PREFS_KEY_REVERSE_VNC_LAST_HOST = "reverse_vnc_last_host" ; public static final String PREFS_KEY_REPEATER_VNC_LAST_HOST = "repeater_vnc_last_host" ; public static final String PREFS_KEY_REPEATER_VNC_LAST_ID = "repeater_vnc_last_id" ; + public static final String PREFS_KEY_SERVER_LAST_PORT = "server_last_port" ; + public static final String PREFS_KEY_SERVER_LAST_PASSWORD = "server_last_password" ; } From 85066d53c22e7838ebf5ab0e536b858cca705375 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 13:12:23 +0200 Subject: [PATCH 28/56] MainService: go back to call vncStartServer() from redelivered intents eb46e8f6591e17a022dfdb65cd138f886760d963 was quite right, but was not able to recover from crashes. --- .../droidvnc_ng/MainService.java | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index 0f14df89..437b7f74 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -234,6 +234,13 @@ public int onStartCommand(Intent intent, int flags, int startId) // Step 4 (optional): coming back from capturing permission check, now starting capturing machinery mResultCode = intent.getIntExtra(EXTRA_MEDIA_PROJECTION_RESULT_CODE, 0); mResultData = intent.getParcelableExtra(EXTRA_MEDIA_PROJECTION_RESULT_DATA); + DisplayMetrics displayMetrics = getDisplayMetrics(); + if (!vncStartServer(displayMetrics.widthPixels, + displayMetrics.heightPixels, + PreferenceManager.getDefaultSharedPreferences(this).getInt(Constants.PREFS_KEY_SERVER_LAST_PORT, mDefaults.getPort()), + Settings.Secure.getString(getContentResolver(), "bluetooth_name"), + PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.PREFS_KEY_SERVER_LAST_PASSWORD, mDefaults.getPassword()))) + stopSelf(); startScreenCapture(); // if we got here, we want to restart if we were killed return START_REDELIVER_INTENT; @@ -244,6 +251,13 @@ public int onStartCommand(Intent intent, int flags, int startId) // Step 3: coming back from write storage permission check, start capturing // or ask for ask for capturing permission first (then going in step 4) if (mResultCode != 0 && mResultData != null) { + DisplayMetrics displayMetrics = getDisplayMetrics(); + if (!vncStartServer(displayMetrics.widthPixels, + displayMetrics.heightPixels, + PreferenceManager.getDefaultSharedPreferences(this).getInt(Constants.PREFS_KEY_SERVER_LAST_PORT, mDefaults.getPort()), + Settings.Secure.getString(getContentResolver(), "bluetooth_name"), + PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.PREFS_KEY_SERVER_LAST_PASSWORD, mDefaults.getPassword()))) + stopSelf(); startScreenCapture(); // if we got here, we want to restart if we were killed return START_REDELIVER_INTENT; @@ -278,15 +292,11 @@ public int onStartCommand(Intent intent, int flags, int startId) if(ACTION_START.equals(intent.getAction())) { Log.d(TAG, "onStartCommand: start"); - // Step 0: start server w/ provided arguments - DisplayMetrics displayMetrics = getDisplayMetrics(); - if (!vncStartServer(displayMetrics.widthPixels, - displayMetrics.heightPixels, - intent.getIntExtra(EXTRA_PORT, mDefaults.getPort()), - Settings.Secure.getString(getContentResolver(), "bluetooth_name"), - intent.getStringExtra(EXTRA_PASSWORD) != null ? intent.getStringExtra(EXTRA_PASSWORD) : mDefaults.getPassword())) - stopSelf(); - + // Step 0: persist given arguments to be able to recover from possible crash later + SharedPreferences.Editor ed = PreferenceManager.getDefaultSharedPreferences(this).edit(); + ed.putInt(Constants.PREFS_KEY_SERVER_LAST_PORT, intent.getIntExtra(EXTRA_PORT, mDefaults.getPort())); + ed.putString(Constants.PREFS_KEY_SERVER_LAST_PASSWORD, intent.getStringExtra(EXTRA_PASSWORD) != null ? intent.getStringExtra(EXTRA_PASSWORD) : mDefaults.getPassword()); + ed.apply(); // Step 1: check input permission Intent inputRequestIntent = new Intent(this, InputRequestActivity.class); inputRequestIntent.putExtra(EXTRA_VIEW_ONLY, intent.getBooleanExtra(EXTRA_VIEW_ONLY, mDefaults.getViewOnly())); From ce1c9db8ee205ea58dd72c6bfdccbded7785e3d4 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 13:59:25 +0200 Subject: [PATCH 29/56] Constants: add pref keys for persisting last scaling and input --- app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java b/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java index d268becb..e0e75031 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java @@ -43,4 +43,6 @@ public class Constants { public static final String PREFS_KEY_REPEATER_VNC_LAST_ID = "repeater_vnc_last_id" ; public static final String PREFS_KEY_SERVER_LAST_PORT = "server_last_port" ; public static final String PREFS_KEY_SERVER_LAST_PASSWORD = "server_last_password" ; + public static final String PREFS_KEY_SERVER_LAST_SCALING = "server_last_scaling" ; + public static final String PREFS_KEY_INPUT_LAST_ENABLED = "input_last_enabled" ; } From 9783f38d264d670cab062976991361a1b77159b0 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 13:59:56 +0200 Subject: [PATCH 30/56] MainActivity: add scaling user pref to start intent --- .../main/java/net/christianbeier/droidvnc_ng/MainActivity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java index 8c36d12f..206eda67 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java @@ -89,6 +89,7 @@ protected void onCreate(Bundle savedInstanceState) { intent.putExtra(MainService.EXTRA_PORT, prefs.getInt(Constants.PREFS_KEY_SETTINGS_PORT, mDefaults.getPort())); intent.putExtra(MainService.EXTRA_PASSWORD, prefs.getString(Constants.PREFS_KEY_SETTINGS_PASSWORD, mDefaults.getPassword())); intent.putExtra(MainService.EXTRA_VIEW_ONLY, prefs.getBoolean(Constants.PREFS_KEY_SETTINGS_VIEW_ONLY, mDefaults.getViewOnly())); + intent.putExtra(MainService.EXTRA_SCALING, prefs.getFloat(Constants.PREFS_KEY_SETTINGS_SCALING, mDefaults.getScaling())); intent.putExtra(MainService.EXTRA_ACCESS_KEY, prefs.getString(Constants.PREFS_KEY_SETTINGS_ACCESS_KEY, mDefaults.getAccessKey())); if(mIsMainServiceRunning) { intent.setAction(MainService.ACTION_STOP); From d2a1b36ae01e596743f40dca0377d0227aebab7a Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 14:01:44 +0200 Subject: [PATCH 31/56] InputService,MainService: rework input enabling && scaling setting --- .../droidvnc_ng/InputService.java | 27 +++++++------------ .../droidvnc_ng/MainService.java | 17 ++++++------ 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/InputService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/InputService.java index 2d76083d..9ee0342b 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/InputService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/InputService.java @@ -51,6 +51,11 @@ public synchronized void onCancelled(GestureDescription gestureDescription) { private static final String TAG = "InputService"; private static InputService instance; + /** + * Scaling factor that's applied to incoming pointer events by dividing coordinates by + * the given factor. + */ + static float scaling; static boolean isEnabled; private Handler mMainHandler; @@ -65,7 +70,6 @@ public synchronized void onCancelled(GestureDescription gestureDescription) { private boolean mIsKeyDelDown; private boolean mIsKeyEscDown; - private float mScaling; private final GestureCallback mGestureCallback = new GestureCallback(); @@ -81,8 +85,9 @@ public void onServiceConnected() { super.onServiceConnected(); instance = this; + isEnabled = PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.PREFS_KEY_INPUT_LAST_ENABLED, !new Defaults(this).getViewOnly()); + scaling = PreferenceManager.getDefaultSharedPreferences(this).getFloat(Constants.PREFS_KEY_SERVER_LAST_SCALING, new Defaults(this).getScaling()); mMainHandler = new Handler(instance.getMainLooper()); - mScaling = PreferenceManager.getDefaultSharedPreferences(this).getFloat(Constants.PREFS_KEY_SETTINGS_SCALING, new Defaults(this).getScaling()); Log.i(TAG, "onServiceConnected"); } @@ -98,20 +103,6 @@ public static boolean isConnected() return instance != null; } - /** - * Set scaling factor that's applied to incoming pointer events by dividing coordinates by - * the given factor. - * @param scaling The scaling factor as a real number. - * @return Whether scaling was applied or not. - */ - public static boolean setScaling(float scaling) { - try { - instance.mScaling = scaling; - return true; - } catch (Exception e) { - return false; - } - } @SuppressWarnings("unused") public static void onPointerEvent(int buttonMask, int x, int y, long client) { @@ -121,8 +112,8 @@ public static void onPointerEvent(int buttonMask, int x, int y, long client) { } try { - x /= instance.mScaling; - y /= instance.mScaling; + x /= scaling; + y /= scaling; /* left mouse button diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index 437b7f74..446ab8d4 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -76,6 +76,7 @@ public class MainService extends Service { public static final String EXTRA_ACCESS_KEY = "net.christianbeier.droidvnc_ng.EXTRA_ACCESS_KEY"; public static final String EXTRA_PASSWORD = "net.christianbeier.droidvnc_ng.EXTRA_PASSWORD"; public static final String EXTRA_VIEW_ONLY = "net.christianbeier.droidvnc_ng.EXTRA_VIEW_ONLY"; + public static final String EXTRA_SCALING = "net.christianbeier.droidvnc_ng.EXTRA_SCALING"; final static String ACTION_HANDLE_MEDIA_PROJECTION_RESULT = "action_handle_media_projection_result"; final static String EXTRA_MEDIA_PROJECTION_RESULT_DATA = "result_data_media_projection"; @@ -276,12 +277,7 @@ public int onStartCommand(Intent intent, int flags, int startId) if(ACTION_HANDLE_INPUT_RESULT.equals(intent.getAction())) { Log.d(TAG, "onStartCommand: handle input result"); // Step 2: coming back from input permission check, now setup InputService and ask for write storage permission - if(intent.getBooleanExtra(EXTRA_INPUT_RESULT, false)) { - InputService.isEnabled = true; - InputService.setScaling(PreferenceManager.getDefaultSharedPreferences(this).getFloat(Constants.PREFS_KEY_SETTINGS_SCALING, mDefaults.getScaling())); - } else { - InputService.isEnabled = false; - } + InputService.isEnabled = intent.getBooleanExtra(EXTRA_INPUT_RESULT, false); Intent writeStorageRequestIntent = new Intent(this, WriteStorageRequestActivity.class); writeStorageRequestIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(writeStorageRequestIntent); @@ -296,7 +292,12 @@ public int onStartCommand(Intent intent, int flags, int startId) SharedPreferences.Editor ed = PreferenceManager.getDefaultSharedPreferences(this).edit(); ed.putInt(Constants.PREFS_KEY_SERVER_LAST_PORT, intent.getIntExtra(EXTRA_PORT, mDefaults.getPort())); ed.putString(Constants.PREFS_KEY_SERVER_LAST_PASSWORD, intent.getStringExtra(EXTRA_PASSWORD) != null ? intent.getStringExtra(EXTRA_PASSWORD) : mDefaults.getPassword()); + ed.putBoolean(Constants.PREFS_KEY_INPUT_LAST_ENABLED, !intent.getBooleanExtra(EXTRA_VIEW_ONLY, mDefaults.getViewOnly())); + ed.putFloat(Constants.PREFS_KEY_SERVER_LAST_SCALING, intent.getFloatExtra(EXTRA_SCALING, mDefaults.getScaling())); ed.apply(); + // also set new value for InputService + InputService.scaling = intent.getFloatExtra(EXTRA_SCALING, mDefaults.getScaling()); + // Step 1: check input permission Intent inputRequestIntent = new Intent(this, InputRequestActivity.class); inputRequestIntent.putExtra(EXTRA_VIEW_ONLY, intent.getBooleanExtra(EXTRA_VIEW_ONLY, mDefaults.getViewOnly())); @@ -394,8 +395,8 @@ private void startScreenCapture() { final DisplayMetrics metrics = getDisplayMetrics(); - // apply scaling preference - float scaling = PreferenceManager.getDefaultSharedPreferences(this).getFloat(Constants.PREFS_KEY_SETTINGS_SCALING, mDefaults.getScaling()); + // apply selected scaling + float scaling = PreferenceManager.getDefaultSharedPreferences(this).getFloat(Constants.PREFS_KEY_SERVER_LAST_SCALING, new Defaults(this).getScaling()); int scaledWidth = (int) (metrics.widthPixels * scaling); int scaledHeight = (int) (metrics.heightPixels * scaling); From d711ddb4f813281f3a59975b209c537462de8446 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 14:22:37 +0200 Subject: [PATCH 32/56] Constants: add file transfer keys --- .../main/java/net/christianbeier/droidvnc_ng/Constants.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java b/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java index e0e75031..f443c42a 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java @@ -31,6 +31,8 @@ public class Constants { public static final String PREFS_KEY_SETTINGS_SCALING = "settings_scaling" ; public static final String PREFS_KEY_SETTINGS_VIEW_ONLY = "settings_view_only" ; public static final String PREFS_KEY_SETTINGS_ACCESS_KEY = "settings_access_key"; + public static final String PREFS_KEY_SETTINGS_FILE_TRANSFER = "settings_file_transfer"; + /* persisted generated defaults */ @@ -44,5 +46,6 @@ public class Constants { public static final String PREFS_KEY_SERVER_LAST_PORT = "server_last_port" ; public static final String PREFS_KEY_SERVER_LAST_PASSWORD = "server_last_password" ; public static final String PREFS_KEY_SERVER_LAST_SCALING = "server_last_scaling" ; + public static final String PREFS_KEY_SERVER_LAST_FILE_TRANSFER = "server_last_file_transfer" ; public static final String PREFS_KEY_INPUT_LAST_ENABLED = "input_last_enabled" ; } From 49ee711bb62075d86d42366b37340f4549b8027d Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 14:22:56 +0200 Subject: [PATCH 33/56] Defaults: add file transfer defaults --- app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt b/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt index 9e9427b7..7c00d710 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt @@ -58,6 +58,10 @@ class Defaults { var viewOnly = false private set + @EncodeDefault + var fileTranfer = false + private set + @EncodeDefault var password = "" private set @@ -95,6 +99,7 @@ class Defaults { this.port = readDefault.port this.portReverse = readDefault.portReverse this.portRepeater = readDefault.portRepeater + this.fileTranfer = readDefault.fileTranfer this.scaling = readDefault.scaling this.viewOnly = readDefault.viewOnly this.password = readDefault.password From 46af73f87e99b231aef4f46faedf6fd24954867b Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 14:24:15 +0200 Subject: [PATCH 34/56] MainService: wire up EXTRA_FILE_TRANSFER --- .../java/net/christianbeier/droidvnc_ng/MainService.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index 446ab8d4..03a92ee8 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -77,6 +77,7 @@ public class MainService extends Service { public static final String EXTRA_PASSWORD = "net.christianbeier.droidvnc_ng.EXTRA_PASSWORD"; public static final String EXTRA_VIEW_ONLY = "net.christianbeier.droidvnc_ng.EXTRA_VIEW_ONLY"; public static final String EXTRA_SCALING = "net.christianbeier.droidvnc_ng.EXTRA_SCALING"; + public static final String EXTRA_FILE_TRANSFER = "net.christianbeier.droidvnc_ng.EXTRA_FILE_TRANSFER"; final static String ACTION_HANDLE_MEDIA_PROJECTION_RESULT = "action_handle_media_projection_result"; final static String EXTRA_MEDIA_PROJECTION_RESULT_DATA = "result_data_media_projection"; @@ -279,6 +280,9 @@ public int onStartCommand(Intent intent, int flags, int startId) // Step 2: coming back from input permission check, now setup InputService and ask for write storage permission InputService.isEnabled = intent.getBooleanExtra(EXTRA_INPUT_RESULT, false); Intent writeStorageRequestIntent = new Intent(this, WriteStorageRequestActivity.class); + writeStorageRequestIntent.putExtra( + EXTRA_FILE_TRANSFER, + PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.PREFS_KEY_SERVER_LAST_FILE_TRANSFER, mDefaults.getFileTranfer())); writeStorageRequestIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(writeStorageRequestIntent); // if screen capturing was not started, we don't want a restart if we were killed @@ -292,6 +296,7 @@ public int onStartCommand(Intent intent, int flags, int startId) SharedPreferences.Editor ed = PreferenceManager.getDefaultSharedPreferences(this).edit(); ed.putInt(Constants.PREFS_KEY_SERVER_LAST_PORT, intent.getIntExtra(EXTRA_PORT, mDefaults.getPort())); ed.putString(Constants.PREFS_KEY_SERVER_LAST_PASSWORD, intent.getStringExtra(EXTRA_PASSWORD) != null ? intent.getStringExtra(EXTRA_PASSWORD) : mDefaults.getPassword()); + ed.putBoolean(Constants.PREFS_KEY_SERVER_LAST_FILE_TRANSFER, intent.getBooleanExtra(EXTRA_FILE_TRANSFER, mDefaults.getFileTranfer())); ed.putBoolean(Constants.PREFS_KEY_INPUT_LAST_ENABLED, !intent.getBooleanExtra(EXTRA_VIEW_ONLY, mDefaults.getViewOnly())); ed.putFloat(Constants.PREFS_KEY_SERVER_LAST_SCALING, intent.getFloatExtra(EXTRA_SCALING, mDefaults.getScaling())); ed.apply(); From 772eff819a0e8c4e89b0130b260e42dbfed1e56c Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 14:24:58 +0200 Subject: [PATCH 35/56] WriteStorageRequestActivity: read EXTRA_FILE_TRANSFER --- .../droidvnc_ng/WriteStorageRequestActivity.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/WriteStorageRequestActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/WriteStorageRequestActivity.java index ddc27870..6b75229e 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/WriteStorageRequestActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/WriteStorageRequestActivity.java @@ -44,6 +44,12 @@ public class WriteStorageRequestActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + // if file transfer not wanted, bail out early without bothering the user + if(!getIntent().getBooleanExtra(MainService.EXTRA_FILE_TRANSFER, new Defaults(this).getFileTranfer())) { + postResultAndFinish(false); + return; + } + if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { Log.i(TAG, "Has no permission! Ask!"); final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); From 6218f252eede5fbfd9372d692138e47074c4f66c Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 14:25:19 +0200 Subject: [PATCH 36/56] MainActivity: wire up file transfer setting --- .../droidvnc_ng/MainActivity.java | 12 ++++++++ app/src/main/res/layout/activity_main.xml | 29 +++++++++++++++++++ app/src/main/res/values-zh-rCN/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 4 files changed, 43 insertions(+) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java index 206eda67..cb6ce328 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java @@ -88,6 +88,7 @@ protected void onCreate(Bundle savedInstanceState) { Intent intent = new Intent(MainActivity.this, MainService.class); intent.putExtra(MainService.EXTRA_PORT, prefs.getInt(Constants.PREFS_KEY_SETTINGS_PORT, mDefaults.getPort())); intent.putExtra(MainService.EXTRA_PASSWORD, prefs.getString(Constants.PREFS_KEY_SETTINGS_PASSWORD, mDefaults.getPassword())); + intent.putExtra(MainService.EXTRA_FILE_TRANSFER, prefs.getBoolean(Constants.PREFS_KEY_SETTINGS_FILE_TRANSFER, mDefaults.getFileTranfer())); intent.putExtra(MainService.EXTRA_VIEW_ONLY, prefs.getBoolean(Constants.PREFS_KEY_SETTINGS_VIEW_ONLY, mDefaults.getViewOnly())); intent.putExtra(MainService.EXTRA_SCALING, prefs.getFloat(Constants.PREFS_KEY_SETTINGS_SCALING, mDefaults.getScaling())); intent.putExtra(MainService.EXTRA_ACCESS_KEY, prefs.getString(Constants.PREFS_KEY_SETTINGS_ACCESS_KEY, mDefaults.getAccessKey())); @@ -343,6 +344,14 @@ public void afterTextChanged(Editable editable) { ed.apply(); }); + final SwitchMaterial fileTransfer = findViewById(R.id.settings_file_transfer); + fileTransfer.setChecked(prefs.getBoolean(Constants.PREFS_KEY_SETTINGS_FILE_TRANSFER, mDefaults.getFileTranfer())); + fileTransfer.setOnCheckedChangeListener((compoundButton, b) -> { + SharedPreferences.Editor ed = prefs.edit(); + ed.putBoolean(Constants.PREFS_KEY_SETTINGS_FILE_TRANSFER, b); + ed.apply(); + }); + Slider scaling = findViewById(R.id.settings_scaling); scaling.setValue(prefs.getFloat(Constants.PREFS_KEY_SETTINGS_SCALING, mDefaults.getScaling())*100); scaling.setLabelFormatter(value -> Math.round(value) + " %"); @@ -394,6 +403,7 @@ public void afterTextChanged(Editable editable) { findViewById(R.id.settings_access_key).setEnabled(false); findViewById(R.id.settings_scaling).setEnabled(false); findViewById(R.id.settings_view_only).setEnabled(false); + findViewById(R.id.settings_file_transfer).setEnabled(false); mIsMainServiceRunning = true; } @@ -418,6 +428,8 @@ public void afterTextChanged(Editable editable) { findViewById(R.id.settings_access_key).setEnabled(true); findViewById(R.id.settings_scaling).setEnabled(true); findViewById(R.id.settings_view_only).setEnabled(true); + findViewById(R.id.settings_file_transfer).setEnabled(true); + mIsMainServiceRunning = false; } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 5e19703e..ac9d0b50 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -139,6 +139,35 @@ + + + + + + + + + + + diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index e5ee00c0..3f7008e5 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -6,6 +6,7 @@ 密码 访问键 开机启动 + 文件传输 缩放 只读 权限仪表盘 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f45eea86..b489b8e8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -6,6 +6,7 @@ Password Access Key Start on Boot + File Transfer Scaling View Only Permissions Dashboard From 5f5556f05a7c6e9ebdcf599a1cdfa8b7db340d5a Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 14:39:41 +0200 Subject: [PATCH 37/56] MainActivity: adapt UI to disable listening Closes #118 --- .../java/net/christianbeier/droidvnc_ng/MainActivity.java | 6 +++--- app/src/main/res/values-zh-rCN/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java index cb6ce328..2afb79fc 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java @@ -258,11 +258,11 @@ public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { @Override public void afterTextChanged(Editable editable) { if(port.getText().length() == 0) { - // hint that default is set - port.setHint(String.valueOf(mDefaults.getPort())); + // hint that not listening + port.setHint(R.string.main_activity_settings_port_not_listening); // and set default SharedPreferences.Editor ed = prefs.edit(); - ed.putInt(Constants.PREFS_KEY_SETTINGS_PORT, mDefaults.getPort()); + ed.putInt(Constants.PREFS_KEY_SETTINGS_PORT, -1); ed.apply(); } } diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 3f7008e5..a36812e2 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -3,6 +3,7 @@ droidVNC-NG管理面板 设置 端口 + 禁用传入连接 密码 访问键 开机启动 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b489b8e8..fad86ca4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -3,6 +3,7 @@ droidVNC-NG Admin Panel Settings Port + Incoming connections disabled Password Access Key Start on Boot From 77455d70707c50779b0c610a414f05393ca05a75 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 14:44:01 +0200 Subject: [PATCH 38/56] MainService: make ACTION_STOP public --- .../main/java/net/christianbeier/droidvnc_ng/MainService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index 03a92ee8..cbdbaa67 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -67,7 +67,7 @@ public class MainService extends Service { private static final String TAG = "MainService"; private static final int NOTIFICATION_ID = 11; public final static String ACTION_START = "net.christianbeier.droidvnc_ng.ACTION_START"; - final static String ACTION_STOP = "stop"; + public final static String ACTION_STOP = "net.christianbeier.droidvnc_ng.ACTION_STOP"; public static final String ACTION_CONNECT_REVERSE = "net.christianbeier.droidvnc_ng.ACTION_CONNECT_REVERSE"; public static final String EXTRA_REQUEST_ID = "net.christianbeier.droidvnc_ng.EXTRA_REQUEST_ID"; public static final String EXTRA_REQUEST_SUCCESS = "net.christianbeier.droidvnc_ng.EXTRA_REQUEST_SUCCESS"; From bf85388088725dbf79ab87339ae5ae0b6ecf68ec Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 15:00:53 +0200 Subject: [PATCH 39/56] MainService,MainActivity: replace static connectRepeater() w/ Intent --- .../droidvnc_ng/MainActivity.java | 53 ++++++++++++++++--- .../droidvnc_ng/MainService.java | 37 +++++++++---- 2 files changed, 73 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java index 2afb79fc..bc48cf56 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java @@ -220,15 +220,19 @@ protected void onCreate(Bundle savedInstanceState) { } // done Log.d(TAG, "repeater vnc " + host + ":" + port + ":" + repeaterId); - if(MainService.connectRepeater(host, port, /*"ID:" +*/ repeaterId)) { - Toast.makeText(MainActivity.this, getString(R.string.main_activity_repeater_vnc_success, host, port, repeaterId), Toast.LENGTH_LONG).show(); - SharedPreferences.Editor ed = prefs.edit(); - ed.putString(Constants.PREFS_KEY_REPEATER_VNC_LAST_HOST, host + ":" + port); - ed.putString(Constants.PREFS_KEY_REPEATER_VNC_LAST_ID, repeaterId); - ed.apply(); + mLastMainServiceRequestId = UUID.randomUUID().toString(); + Intent request = new Intent(MainActivity.this, MainService.class); + request.putExtra(MainService.EXTRA_ACCESS_KEY, prefs.getString(Constants.PREFS_KEY_SETTINGS_ACCESS_KEY, mDefaults.getAccessKey())); + request.setAction(MainService.ACTION_CONNECT_REPEATER); + request.putExtra(MainService.EXTRA_HOST, host); + request.putExtra(MainService.EXTRA_PORT, port); + request.putExtra(MainService.EXTRA_REPEATER_ID, repeaterId); + request.putExtra(MainService.EXTRA_REQUEST_ID, mLastMainServiceRequestId); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + startForegroundService(request); + } else { + startService(request); } - else - Toast.makeText(MainActivity.this, getString(R.string.main_activity_repeater_vnc_fail, host, port, repeaterId), Toast.LENGTH_LONG).show(); }) .setNegativeButton(android.R.string.cancel, (dialogInterface, i) -> dialogInterface.cancel()) .create(); @@ -466,10 +470,43 @@ public void onReceive(Context context, Intent intent) { mLastMainServiceRequestId = null; } + if (MainService.ACTION_CONNECT_REPEATER.equals(intent.getAction()) + && mLastMainServiceRequestId != null + && mLastMainServiceRequestId.equals(intent.getStringExtra(MainService.EXTRA_REQUEST_ID))) { + // was a CONNECT_REPEATER requested by us + if (intent.getBooleanExtra(MainService.EXTRA_REQUEST_SUCCESS, false)) { + Toast.makeText(MainActivity.this, + getString(R.string.main_activity_repeater_vnc_success, + intent.getStringExtra(MainService.EXTRA_HOST), + intent.getIntExtra(MainService.EXTRA_PORT, mDefaults.getPortRepeater()), + intent.getStringExtra(MainService.EXTRA_REPEATER_ID)), + Toast.LENGTH_LONG) + .show(); + SharedPreferences.Editor ed = prefs.edit(); + ed.putString(Constants.PREFS_KEY_REPEATER_VNC_LAST_HOST, + intent.getStringExtra(MainService.EXTRA_HOST) + ":" + intent.getIntExtra(MainService.EXTRA_PORT, mDefaults.getPortRepeater())); + ed.putString(Constants.PREFS_KEY_REPEATER_VNC_LAST_ID, + intent.getStringExtra(MainService.EXTRA_REPEATER_ID)); + ed.apply(); + } + else + Toast.makeText(MainActivity.this, + getString(R.string.main_activity_repeater_vnc_fail, + intent.getStringExtra(MainService.EXTRA_HOST), + intent.getIntExtra(MainService.EXTRA_PORT, mDefaults.getPortRepeater()), + intent.getStringExtra(MainService.EXTRA_REPEATER_ID)), + Toast.LENGTH_LONG) + .show(); + + // reset this + mLastMainServiceRequestId = null; + } + } }; IntentFilter filter = new IntentFilter(); filter.addAction(MainService.ACTION_CONNECT_REVERSE); + filter.addAction(MainService.ACTION_CONNECT_REPEATER); registerReceiver(mMainServiceBroadcastReceiver, filter); } diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index cbdbaa67..0288daac 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -69,10 +69,12 @@ public class MainService extends Service { public final static String ACTION_START = "net.christianbeier.droidvnc_ng.ACTION_START"; public final static String ACTION_STOP = "net.christianbeier.droidvnc_ng.ACTION_STOP"; public static final String ACTION_CONNECT_REVERSE = "net.christianbeier.droidvnc_ng.ACTION_CONNECT_REVERSE"; + public static final String ACTION_CONNECT_REPEATER = "net.christianbeier.droidvnc_ng.ACTION_CONNECT_REPEATER"; public static final String EXTRA_REQUEST_ID = "net.christianbeier.droidvnc_ng.EXTRA_REQUEST_ID"; public static final String EXTRA_REQUEST_SUCCESS = "net.christianbeier.droidvnc_ng.EXTRA_REQUEST_SUCCESS"; public static final String EXTRA_HOST = "net.christianbeier.droidvnc_ng.EXTRA_HOST"; public static final String EXTRA_PORT = "net.christianbeier.droidvnc_ng.EXTRA_PORT"; + public static final String EXTRA_REPEATER_ID = "net.christianbeier.droidvnc_ng.EXTRA_REPEATER_ID"; public static final String EXTRA_ACCESS_KEY = "net.christianbeier.droidvnc_ng.EXTRA_ACCESS_KEY"; public static final String EXTRA_PASSWORD = "net.christianbeier.droidvnc_ng.EXTRA_PASSWORD"; public static final String EXTRA_VIEW_ONLY = "net.christianbeier.droidvnc_ng.EXTRA_VIEW_ONLY"; @@ -342,6 +344,32 @@ public int onStartCommand(Intent intent, int flags, int startId) return START_NOT_STICKY; } + if(ACTION_CONNECT_REPEATER.equals(intent.getAction())) { + Log.d(TAG, "onStartCommand: connect repeater"); + boolean status = false; + if(vncIsActive()) { + try { + //TODO run on worker thread + status = instance.vncConnectRepeater( + intent.getStringExtra(EXTRA_HOST), + intent.getIntExtra(EXTRA_PORT, mDefaults.getPortRepeater()), + intent.getStringExtra(EXTRA_REPEATER_ID)); + } catch (NullPointerException ignored) { + } + } else { + stopSelf(); + } + + Intent answer = new Intent(ACTION_CONNECT_REPEATER); + // use request's extras + answer.putExtras(intent); + // but don't leak the access key! + answer.removeExtra(EXTRA_ACCESS_KEY); + answer.putExtra(EXTRA_REQUEST_SUCCESS, status); + sendBroadcast(answer); + return START_NOT_STICKY; + } + // no known action was given, stop the _service_ again if the _server_ is not active if(!vncIsActive()) { stopSelf(); @@ -607,15 +635,6 @@ static ArrayList getIPv4sAndPorts() { return hostsAndPorts; } - public static boolean connectRepeater(String host, int port, String repeaterIdentifier) { - try { - return instance.vncConnectRepeater(host, port, repeaterIdentifier); - } - catch (NullPointerException e) { - return false; - } - } - private DisplayMetrics getDisplayMetrics() { DisplayMetrics displayMetrics = new DisplayMetrics(); WindowManager wm = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE); From 6b4518d9bb08cc7efe31ba8330dbc409c10634be Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 15:08:54 +0200 Subject: [PATCH 40/56] MainService: fix lints --- .../java/net/christianbeier/droidvnc_ng/MainService.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index 0288daac..07270590 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -119,7 +119,8 @@ public enum StatusEvent { System.loadLibrary("droidvnc-ng"); } - private native boolean vncStartServer(int width, int height, int port, String desktopname, String password); + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + private native boolean vncStartServer(int width, int height, int port, String desktopName, String password); private native boolean vncStopServer(); private native boolean vncIsActive(); private native boolean vncConnectReverse(String host, int port); @@ -379,6 +380,7 @@ public int onStartCommand(Intent intent, int flags, int startId) } @SuppressLint("WakelockTimeout") + @SuppressWarnings("unused") static void onClientConnected(long client) { Log.d(TAG, "onClientConnected: client " + client); @@ -390,6 +392,7 @@ static void onClientConnected(long client) { } } + @SuppressWarnings("unused") static void onClientDisconnected(long client) { Log.d(TAG, "onClientDisconnected: client " + client); From 1d83a5789a40941977f5c14dd990e290ae480dbe Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 15:11:23 +0200 Subject: [PATCH 41/56] MainService: send result of ACTION_STOP --- .../java/net/christianbeier/droidvnc_ng/MainService.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index 07270590..999d8000 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -319,6 +319,13 @@ public int onStartCommand(Intent intent, int flags, int startId) if(ACTION_STOP.equals(intent.getAction())) { Log.d(TAG, "onStartCommand: stop"); stopSelf(); + Intent answer = new Intent(ACTION_STOP); + // use request's extras + answer.putExtras(intent); + // but don't leak the access key! + answer.removeExtra(EXTRA_ACCESS_KEY); + answer.putExtra(EXTRA_REQUEST_SUCCESS, true); + sendBroadcast(answer); return START_NOT_STICKY; } From bb2099914f0d0791280688abba84a6c21a5eb388 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 15:23:29 +0200 Subject: [PATCH 42/56] MainActivity: show port hint instead of -1 --- .../java/net/christianbeier/droidvnc_ng/MainActivity.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java index bc48cf56..8d191004 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java @@ -242,7 +242,11 @@ protected void onCreate(Bundle savedInstanceState) { final EditText port = findViewById(R.id.settings_port); - port.setText(String.valueOf(prefs.getInt(Constants.PREFS_KEY_SETTINGS_PORT, mDefaults.getPort()))); + if(prefs.getInt(Constants.PREFS_KEY_SETTINGS_PORT, mDefaults.getPort()) < 0) { + port.setHint(R.string.main_activity_settings_port_not_listening); + } else { + port.setText(String.valueOf(prefs.getInt(Constants.PREFS_KEY_SETTINGS_PORT, mDefaults.getPort()))); + } port.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { From 38de484704cd745217b6467be3e8356c462da064 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 15:31:54 +0200 Subject: [PATCH 43/56] MainActivity: add shorter wording --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fad86ca4..7afdc25a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -3,7 +3,7 @@ droidVNC-NG Admin Panel Settings Port - Incoming connections disabled + Inbound connections disabled Password Access Key Start on Boot From 21271721c024c9079e50a3970ab5db1f1642ab2d Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 15:33:34 +0200 Subject: [PATCH 44/56] MainService: don't leak request args in broadcast answers --- .../christianbeier/droidvnc_ng/MainService.java | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index 999d8000..bd235cce 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -320,10 +320,7 @@ public int onStartCommand(Intent intent, int flags, int startId) Log.d(TAG, "onStartCommand: stop"); stopSelf(); Intent answer = new Intent(ACTION_STOP); - // use request's extras - answer.putExtras(intent); - // but don't leak the access key! - answer.removeExtra(EXTRA_ACCESS_KEY); + answer.putExtra(EXTRA_REQUEST_ID, intent.getStringExtra(EXTRA_REQUEST_ID)); answer.putExtra(EXTRA_REQUEST_SUCCESS, true); sendBroadcast(answer); return START_NOT_STICKY; @@ -343,10 +340,7 @@ public int onStartCommand(Intent intent, int flags, int startId) } Intent answer = new Intent(ACTION_CONNECT_REVERSE); - // use request's extras - answer.putExtras(intent); - // but don't leak the access key! - answer.removeExtra(EXTRA_ACCESS_KEY); + answer.putExtra(EXTRA_REQUEST_ID, intent.getStringExtra(EXTRA_REQUEST_ID)); answer.putExtra(EXTRA_REQUEST_SUCCESS, status); sendBroadcast(answer); return START_NOT_STICKY; @@ -369,10 +363,7 @@ public int onStartCommand(Intent intent, int flags, int startId) } Intent answer = new Intent(ACTION_CONNECT_REPEATER); - // use request's extras - answer.putExtras(intent); - // but don't leak the access key! - answer.removeExtra(EXTRA_ACCESS_KEY); + answer.putExtra(EXTRA_REQUEST_ID, intent.getStringExtra(EXTRA_REQUEST_ID)); answer.putExtra(EXTRA_REQUEST_SUCCESS, status); sendBroadcast(answer); return START_NOT_STICKY; From e3b08b188d08556873bf95fbc529cab7725aba12 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 15:33:47 +0200 Subject: [PATCH 45/56] MainActivity: save request extras locally --- .../droidvnc_ng/MainActivity.java | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java index 8d191004..1c3ef3aa 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java @@ -71,6 +71,11 @@ public class MainActivity extends AppCompatActivity { private Disposable mMainServiceStatusEventStreamConnection; private BroadcastReceiver mMainServiceBroadcastReceiver; private String mLastMainServiceRequestId; + private String mLastReverseHost; + private int mLastReversePort; + private String mLastRepeaterHost; + private int mLastRepeaterPort; + private String mLastRepeaterId; private Defaults mDefaults; @@ -150,6 +155,8 @@ protected void onCreate(Bundle savedInstanceState) { } Log.d(TAG, "reverse vnc " + host + ":" + port); mLastMainServiceRequestId = UUID.randomUUID().toString(); + mLastReverseHost = host; + mLastReversePort = port; Intent request = new Intent(MainActivity.this, MainService.class); request.putExtra(MainService.EXTRA_ACCESS_KEY, prefs.getString(Constants.PREFS_KEY_SETTINGS_ACCESS_KEY, mDefaults.getAccessKey())); request.setAction(MainService.ACTION_CONNECT_REVERSE); @@ -221,6 +228,9 @@ protected void onCreate(Bundle savedInstanceState) { // done Log.d(TAG, "repeater vnc " + host + ":" + port + ":" + repeaterId); mLastMainServiceRequestId = UUID.randomUUID().toString(); + mLastRepeaterHost = host; + mLastRepeaterPort = port; + mLastRepeaterId = repeaterId; Intent request = new Intent(MainActivity.this, MainService.class); request.putExtra(MainService.EXTRA_ACCESS_KEY, prefs.getString(Constants.PREFS_KEY_SETTINGS_ACCESS_KEY, mDefaults.getAccessKey())); request.setAction(MainService.ACTION_CONNECT_REPEATER); @@ -454,19 +464,19 @@ public void onReceive(Context context, Intent intent) { if (intent.getBooleanExtra(MainService.EXTRA_REQUEST_SUCCESS, false)) { Toast.makeText(MainActivity.this, getString(R.string.main_activity_reverse_vnc_success, - intent.getStringExtra(MainService.EXTRA_HOST), - intent.getIntExtra(MainService.EXTRA_PORT, mDefaults.getPortReverse())), + mLastReverseHost, + mLastReversePort), Toast.LENGTH_LONG) .show(); SharedPreferences.Editor ed = prefs.edit(); ed.putString(Constants.PREFS_KEY_REVERSE_VNC_LAST_HOST, - intent.getStringExtra(MainService.EXTRA_HOST) + ":" + intent.getIntExtra(MainService.EXTRA_PORT, mDefaults.getPortReverse())); + mLastReverseHost + ":" + mLastReversePort); ed.apply(); } else Toast.makeText(MainActivity.this, getString(R.string.main_activity_reverse_vnc_fail, - intent.getStringExtra(MainService.EXTRA_HOST), - intent.getIntExtra(MainService.EXTRA_PORT, mDefaults.getPortReverse())), + mLastReverseHost, + mLastReversePort), Toast.LENGTH_LONG) .show(); @@ -481,24 +491,24 @@ public void onReceive(Context context, Intent intent) { if (intent.getBooleanExtra(MainService.EXTRA_REQUEST_SUCCESS, false)) { Toast.makeText(MainActivity.this, getString(R.string.main_activity_repeater_vnc_success, - intent.getStringExtra(MainService.EXTRA_HOST), - intent.getIntExtra(MainService.EXTRA_PORT, mDefaults.getPortRepeater()), - intent.getStringExtra(MainService.EXTRA_REPEATER_ID)), + mLastRepeaterHost, + mLastRepeaterPort, + mLastRepeaterId), Toast.LENGTH_LONG) .show(); SharedPreferences.Editor ed = prefs.edit(); ed.putString(Constants.PREFS_KEY_REPEATER_VNC_LAST_HOST, - intent.getStringExtra(MainService.EXTRA_HOST) + ":" + intent.getIntExtra(MainService.EXTRA_PORT, mDefaults.getPortRepeater())); + mLastRepeaterHost + ":" + mLastRepeaterPort); ed.putString(Constants.PREFS_KEY_REPEATER_VNC_LAST_ID, - intent.getStringExtra(MainService.EXTRA_REPEATER_ID)); + mLastRepeaterId); ed.apply(); } else Toast.makeText(MainActivity.this, getString(R.string.main_activity_repeater_vnc_fail, - intent.getStringExtra(MainService.EXTRA_HOST), - intent.getIntExtra(MainService.EXTRA_PORT, mDefaults.getPortRepeater()), - intent.getStringExtra(MainService.EXTRA_REPEATER_ID)), + mLastRepeaterHost, + mLastRepeaterPort, + mLastRepeaterId), Toast.LENGTH_LONG) .show(); From d6fdc809176b2e6cbe44fae425271a08e71d5ac7 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 15:48:17 +0200 Subject: [PATCH 46/56] MainService: broadcast results for ACTION_START --- .../christianbeier/droidvnc_ng/Constants.java | 1 + .../droidvnc_ng/MainService.java | 41 ++++++++++++++----- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java b/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java index f443c42a..507bba33 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java @@ -47,5 +47,6 @@ public class Constants { public static final String PREFS_KEY_SERVER_LAST_PASSWORD = "server_last_password" ; public static final String PREFS_KEY_SERVER_LAST_SCALING = "server_last_scaling" ; public static final String PREFS_KEY_SERVER_LAST_FILE_TRANSFER = "server_last_file_transfer" ; + public static final String PREFS_KEY_SERVER_LAST_START_REQUEST_ID = "server_last_start_request_id" ; public static final String PREFS_KEY_INPUT_LAST_ENABLED = "input_last_enabled" ; } diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index bd235cce..cadb9c44 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -240,15 +240,25 @@ public int onStartCommand(Intent intent, int flags, int startId) mResultCode = intent.getIntExtra(EXTRA_MEDIA_PROJECTION_RESULT_CODE, 0); mResultData = intent.getParcelableExtra(EXTRA_MEDIA_PROJECTION_RESULT_DATA); DisplayMetrics displayMetrics = getDisplayMetrics(); - if (!vncStartServer(displayMetrics.widthPixels, + boolean status = vncStartServer(displayMetrics.widthPixels, displayMetrics.heightPixels, PreferenceManager.getDefaultSharedPreferences(this).getInt(Constants.PREFS_KEY_SERVER_LAST_PORT, mDefaults.getPort()), Settings.Secure.getString(getContentResolver(), "bluetooth_name"), - PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.PREFS_KEY_SERVER_LAST_PASSWORD, mDefaults.getPassword()))) + PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.PREFS_KEY_SERVER_LAST_PASSWORD, mDefaults.getPassword())); + + Intent answer = new Intent(ACTION_START); + answer.putExtra(EXTRA_REQUEST_ID, PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.PREFS_KEY_SERVER_LAST_START_REQUEST_ID, null)); + answer.putExtra(EXTRA_REQUEST_SUCCESS, status); + sendBroadcast(answer); + + if(status) { + startScreenCapture(); + // if we got here, we want to restart if we were killed + return START_REDELIVER_INTENT; + } else { stopSelf(); - startScreenCapture(); - // if we got here, we want to restart if we were killed - return START_REDELIVER_INTENT; + return START_NOT_STICKY; + } } if(ACTION_HANDLE_WRITE_STORAGE_RESULT.equals(intent.getAction())) { @@ -257,15 +267,25 @@ public int onStartCommand(Intent intent, int flags, int startId) // or ask for ask for capturing permission first (then going in step 4) if (mResultCode != 0 && mResultData != null) { DisplayMetrics displayMetrics = getDisplayMetrics(); - if (!vncStartServer(displayMetrics.widthPixels, + boolean status = vncStartServer(displayMetrics.widthPixels, displayMetrics.heightPixels, PreferenceManager.getDefaultSharedPreferences(this).getInt(Constants.PREFS_KEY_SERVER_LAST_PORT, mDefaults.getPort()), Settings.Secure.getString(getContentResolver(), "bluetooth_name"), - PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.PREFS_KEY_SERVER_LAST_PASSWORD, mDefaults.getPassword()))) + PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.PREFS_KEY_SERVER_LAST_PASSWORD, mDefaults.getPassword())); + + Intent answer = new Intent(ACTION_START); + answer.putExtra(EXTRA_REQUEST_ID, PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.PREFS_KEY_SERVER_LAST_START_REQUEST_ID, null)); + answer.putExtra(EXTRA_REQUEST_SUCCESS, status); + sendBroadcast(answer); + + if(status) { + startScreenCapture(); + // if we got here, we want to restart if we were killed + return START_REDELIVER_INTENT; + } else { stopSelf(); - startScreenCapture(); - // if we got here, we want to restart if we were killed - return START_REDELIVER_INTENT; + return START_NOT_STICKY; + } } else { Log.i(TAG, "Requesting confirmation"); // This initiates a prompt dialog for the user to confirm screen projection. @@ -302,6 +322,7 @@ public int onStartCommand(Intent intent, int flags, int startId) ed.putBoolean(Constants.PREFS_KEY_SERVER_LAST_FILE_TRANSFER, intent.getBooleanExtra(EXTRA_FILE_TRANSFER, mDefaults.getFileTranfer())); ed.putBoolean(Constants.PREFS_KEY_INPUT_LAST_ENABLED, !intent.getBooleanExtra(EXTRA_VIEW_ONLY, mDefaults.getViewOnly())); ed.putFloat(Constants.PREFS_KEY_SERVER_LAST_SCALING, intent.getFloatExtra(EXTRA_SCALING, mDefaults.getScaling())); + ed.putString(Constants.PREFS_KEY_SERVER_LAST_START_REQUEST_ID, intent.getStringExtra(EXTRA_REQUEST_ID)); ed.apply(); // also set new value for InputService InputService.scaling = intent.getFloatExtra(EXTRA_SCALING, mDefaults.getScaling()); From 9b12a555035e52ee5361018a02640ec6eefc65f3 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Mon, 12 Jun 2023 16:03:44 +0200 Subject: [PATCH 47/56] Constants,Defaults: make key private This is a Defaults implementation detail and not to be used by other components. --- .../java/net/christianbeier/droidvnc_ng/Constants.java | 4 ---- .../main/java/net/christianbeier/droidvnc_ng/Defaults.kt | 7 ++++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java b/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java index 507bba33..6735ef04 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java @@ -33,10 +33,6 @@ public class Constants { public static final String PREFS_KEY_SETTINGS_ACCESS_KEY = "settings_access_key"; public static final String PREFS_KEY_SETTINGS_FILE_TRANSFER = "settings_file_transfer"; - /* - persisted generated defaults - */ - public static final String PREFS_KEY_DEFAULTS_ACCESS_KEY = "defaults_access_key"; /* persisted runtime values */ diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt b/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt index 7c00d710..f1c0bae9 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt @@ -36,6 +36,7 @@ import java.util.UUID class Defaults { companion object { private const val TAG = "Defaults" + private const val PREFS_KEY_DEFAULTS_ACCESS_KEY = "defaults_access_key" } @EncodeDefault @@ -78,16 +79,16 @@ class Defaults { persist randomly generated defaults */ val prefs = PreferenceManager.getDefaultSharedPreferences(context) - val defaultAccessKey = prefs.getString(Constants.PREFS_KEY_DEFAULTS_ACCESS_KEY, null) + val defaultAccessKey = prefs.getString(PREFS_KEY_DEFAULTS_ACCESS_KEY, null) if (defaultAccessKey == null) { val ed: SharedPreferences.Editor = prefs.edit() ed.putString( - Constants.PREFS_KEY_DEFAULTS_ACCESS_KEY, + PREFS_KEY_DEFAULTS_ACCESS_KEY, UUID.randomUUID().toString().replace("-".toRegex(), "") ) ed.apply() } - this.accessKey = prefs.getString(Constants.PREFS_KEY_DEFAULTS_ACCESS_KEY, null)!! + this.accessKey = prefs.getString(PREFS_KEY_DEFAULTS_ACCESS_KEY, null)!! /* read provided defaults From bfc4d7eacd8138cbea98d6c4a3ee5d71f7f6ad6f Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Tue, 13 Jun 2023 09:51:41 +0200 Subject: [PATCH 48/56] MainService: let ACTION_START, ACTION_STOP return whether they succeeded --- .../net/christianbeier/droidvnc_ng/MainService.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index cadb9c44..99cdf7ba 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -315,6 +315,15 @@ public int onStartCommand(Intent intent, int flags, int startId) if(ACTION_START.equals(intent.getAction())) { Log.d(TAG, "onStartCommand: start"); + + if(vncIsActive()) { + Intent answer = new Intent(ACTION_START); + answer.putExtra(EXTRA_REQUEST_ID, intent.getStringExtra(EXTRA_REQUEST_ID)); + answer.putExtra(EXTRA_REQUEST_SUCCESS, false); + sendBroadcast(answer); + return START_NOT_STICKY; + } + // Step 0: persist given arguments to be able to recover from possible crash later SharedPreferences.Editor ed = PreferenceManager.getDefaultSharedPreferences(this).edit(); ed.putInt(Constants.PREFS_KEY_SERVER_LAST_PORT, intent.getIntExtra(EXTRA_PORT, mDefaults.getPort())); @@ -342,7 +351,7 @@ public int onStartCommand(Intent intent, int flags, int startId) stopSelf(); Intent answer = new Intent(ACTION_STOP); answer.putExtra(EXTRA_REQUEST_ID, intent.getStringExtra(EXTRA_REQUEST_ID)); - answer.putExtra(EXTRA_REQUEST_SUCCESS, true); + answer.putExtra(EXTRA_REQUEST_SUCCESS, vncIsActive()); sendBroadcast(answer); return START_NOT_STICKY; } From 4217c14b766c5c7df3a8a27aa3b63134aa7af5cc Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Tue, 13 Jun 2023 10:05:42 +0200 Subject: [PATCH 49/56] Constants,MainActivity: make keys private They are a MainActivity implementation detail and not to be used by other components. --- .../net/christianbeier/droidvnc_ng/Constants.java | 3 --- .../christianbeier/droidvnc_ng/MainActivity.java | 15 +++++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java b/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java index 6735ef04..f72b639f 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java @@ -36,9 +36,6 @@ public class Constants { /* persisted runtime values */ - public static final String PREFS_KEY_REVERSE_VNC_LAST_HOST = "reverse_vnc_last_host" ; - public static final String PREFS_KEY_REPEATER_VNC_LAST_HOST = "repeater_vnc_last_host" ; - public static final String PREFS_KEY_REPEATER_VNC_LAST_ID = "repeater_vnc_last_id" ; public static final String PREFS_KEY_SERVER_LAST_PORT = "server_last_port" ; public static final String PREFS_KEY_SERVER_LAST_PASSWORD = "server_last_password" ; public static final String PREFS_KEY_SERVER_LAST_SCALING = "server_last_scaling" ; diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java index 1c3ef3aa..70928fa9 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java @@ -62,6 +62,9 @@ public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; + private static final String PREFS_KEY_REVERSE_VNC_LAST_HOST = "reverse_vnc_last_host" ; + private static final String PREFS_KEY_REPEATER_VNC_LAST_HOST = "repeater_vnc_last_host" ; + private static final String PREFS_KEY_REPEATER_VNC_LAST_ID = "repeater_vnc_last_id" ; private Button mButtonToggle; private Button mButtonReverseVNC; @@ -121,7 +124,7 @@ protected void onCreate(Bundle savedInstanceState) { final EditText inputText = new EditText(this); inputText.setInputType(InputType.TYPE_CLASS_TEXT); inputText.setHint(getString(R.string.main_activity_reverse_vnc_hint)); - String lastHost = prefs.getString(Constants.PREFS_KEY_REVERSE_VNC_LAST_HOST, null); + String lastHost = prefs.getString(PREFS_KEY_REVERSE_VNC_LAST_HOST, null); if(lastHost != null) { inputText.setText(lastHost); // select all to make new input quicker @@ -181,7 +184,7 @@ protected void onCreate(Bundle savedInstanceState) { final EditText hostInputText = new EditText(this); hostInputText.setInputType(InputType.TYPE_CLASS_TEXT); hostInputText.setHint(getString(R.string.main_activity_repeater_vnc_hint)); - String lastHost = prefs.getString(Constants.PREFS_KEY_REPEATER_VNC_LAST_HOST, ""); + String lastHost = prefs.getString(PREFS_KEY_REPEATER_VNC_LAST_HOST, ""); hostInputText.setText(lastHost); //host:port hostInputText.requestFocus(); hostInputText.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); @@ -189,7 +192,7 @@ protected void onCreate(Bundle savedInstanceState) { final EditText idInputText = new EditText(this); idInputText.setInputType(InputType.TYPE_CLASS_NUMBER); idInputText.setHint(getString(R.string.main_activity_repeater_vnc_hint_id)); - String lastID = prefs.getString(Constants.PREFS_KEY_REPEATER_VNC_LAST_ID, ""); + String lastID = prefs.getString(PREFS_KEY_REPEATER_VNC_LAST_ID, ""); idInputText.setText(lastID); //host:port idInputText.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); @@ -469,7 +472,7 @@ public void onReceive(Context context, Intent intent) { Toast.LENGTH_LONG) .show(); SharedPreferences.Editor ed = prefs.edit(); - ed.putString(Constants.PREFS_KEY_REVERSE_VNC_LAST_HOST, + ed.putString(PREFS_KEY_REVERSE_VNC_LAST_HOST, mLastReverseHost + ":" + mLastReversePort); ed.apply(); } else @@ -497,9 +500,9 @@ public void onReceive(Context context, Intent intent) { Toast.LENGTH_LONG) .show(); SharedPreferences.Editor ed = prefs.edit(); - ed.putString(Constants.PREFS_KEY_REPEATER_VNC_LAST_HOST, + ed.putString(PREFS_KEY_REPEATER_VNC_LAST_HOST, mLastRepeaterHost + ":" + mLastRepeaterPort); - ed.putString(Constants.PREFS_KEY_REPEATER_VNC_LAST_ID, + ed.putString(PREFS_KEY_REPEATER_VNC_LAST_ID, mLastRepeaterId); ed.apply(); } From eb8741f1a5f04abc52b5209578a13e2655d7b465 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Tue, 13 Jun 2023 10:12:53 +0200 Subject: [PATCH 50/56] Constants,MainService: make pref keys private They are a MainService implementation detail and not to be used by other components. --- .../christianbeier/droidvnc_ng/Constants.java | 6 +---- .../droidvnc_ng/MainService.java | 27 +++++++++++-------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java b/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java index f72b639f..f4854beb 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/Constants.java @@ -34,12 +34,8 @@ public class Constants { public static final String PREFS_KEY_SETTINGS_FILE_TRANSFER = "settings_file_transfer"; /* - persisted runtime values + persisted runtime values shared between components */ - public static final String PREFS_KEY_SERVER_LAST_PORT = "server_last_port" ; - public static final String PREFS_KEY_SERVER_LAST_PASSWORD = "server_last_password" ; public static final String PREFS_KEY_SERVER_LAST_SCALING = "server_last_scaling" ; - public static final String PREFS_KEY_SERVER_LAST_FILE_TRANSFER = "server_last_file_transfer" ; - public static final String PREFS_KEY_SERVER_LAST_START_REQUEST_ID = "server_last_start_request_id" ; public static final String PREFS_KEY_INPUT_LAST_ENABLED = "input_last_enabled" ; } diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index 99cdf7ba..bfe91727 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -91,6 +91,11 @@ public class MainService extends Service { final static String ACTION_HANDLE_WRITE_STORAGE_RESULT = "action_handle_write_storage_result"; final static String EXTRA_WRITE_STORAGE_RESULT = "result_write_storage"; + private static final String PREFS_KEY_SERVER_LAST_PORT = "server_last_port" ; + private static final String PREFS_KEY_SERVER_LAST_PASSWORD = "server_last_password" ; + private static final String PREFS_KEY_SERVER_LAST_FILE_TRANSFER = "server_last_file_transfer" ; + private static final String PREFS_KEY_SERVER_LAST_START_REQUEST_ID = "server_last_start_request_id" ; + private int mResultCode; private Intent mResultData; private ImageReader mImageReader; @@ -242,12 +247,12 @@ public int onStartCommand(Intent intent, int flags, int startId) DisplayMetrics displayMetrics = getDisplayMetrics(); boolean status = vncStartServer(displayMetrics.widthPixels, displayMetrics.heightPixels, - PreferenceManager.getDefaultSharedPreferences(this).getInt(Constants.PREFS_KEY_SERVER_LAST_PORT, mDefaults.getPort()), + PreferenceManager.getDefaultSharedPreferences(this).getInt(PREFS_KEY_SERVER_LAST_PORT, mDefaults.getPort()), Settings.Secure.getString(getContentResolver(), "bluetooth_name"), - PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.PREFS_KEY_SERVER_LAST_PASSWORD, mDefaults.getPassword())); + PreferenceManager.getDefaultSharedPreferences(this).getString(PREFS_KEY_SERVER_LAST_PASSWORD, mDefaults.getPassword())); Intent answer = new Intent(ACTION_START); - answer.putExtra(EXTRA_REQUEST_ID, PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.PREFS_KEY_SERVER_LAST_START_REQUEST_ID, null)); + answer.putExtra(EXTRA_REQUEST_ID, PreferenceManager.getDefaultSharedPreferences(this).getString(PREFS_KEY_SERVER_LAST_START_REQUEST_ID, null)); answer.putExtra(EXTRA_REQUEST_SUCCESS, status); sendBroadcast(answer); @@ -269,12 +274,12 @@ public int onStartCommand(Intent intent, int flags, int startId) DisplayMetrics displayMetrics = getDisplayMetrics(); boolean status = vncStartServer(displayMetrics.widthPixels, displayMetrics.heightPixels, - PreferenceManager.getDefaultSharedPreferences(this).getInt(Constants.PREFS_KEY_SERVER_LAST_PORT, mDefaults.getPort()), + PreferenceManager.getDefaultSharedPreferences(this).getInt(PREFS_KEY_SERVER_LAST_PORT, mDefaults.getPort()), Settings.Secure.getString(getContentResolver(), "bluetooth_name"), - PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.PREFS_KEY_SERVER_LAST_PASSWORD, mDefaults.getPassword())); + PreferenceManager.getDefaultSharedPreferences(this).getString(PREFS_KEY_SERVER_LAST_PASSWORD, mDefaults.getPassword())); Intent answer = new Intent(ACTION_START); - answer.putExtra(EXTRA_REQUEST_ID, PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.PREFS_KEY_SERVER_LAST_START_REQUEST_ID, null)); + answer.putExtra(EXTRA_REQUEST_ID, PreferenceManager.getDefaultSharedPreferences(this).getString(PREFS_KEY_SERVER_LAST_START_REQUEST_ID, null)); answer.putExtra(EXTRA_REQUEST_SUCCESS, status); sendBroadcast(answer); @@ -305,7 +310,7 @@ public int onStartCommand(Intent intent, int flags, int startId) Intent writeStorageRequestIntent = new Intent(this, WriteStorageRequestActivity.class); writeStorageRequestIntent.putExtra( EXTRA_FILE_TRANSFER, - PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.PREFS_KEY_SERVER_LAST_FILE_TRANSFER, mDefaults.getFileTranfer())); + PreferenceManager.getDefaultSharedPreferences(this).getBoolean(PREFS_KEY_SERVER_LAST_FILE_TRANSFER, mDefaults.getFileTranfer())); writeStorageRequestIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(writeStorageRequestIntent); // if screen capturing was not started, we don't want a restart if we were killed @@ -326,12 +331,12 @@ public int onStartCommand(Intent intent, int flags, int startId) // Step 0: persist given arguments to be able to recover from possible crash later SharedPreferences.Editor ed = PreferenceManager.getDefaultSharedPreferences(this).edit(); - ed.putInt(Constants.PREFS_KEY_SERVER_LAST_PORT, intent.getIntExtra(EXTRA_PORT, mDefaults.getPort())); - ed.putString(Constants.PREFS_KEY_SERVER_LAST_PASSWORD, intent.getStringExtra(EXTRA_PASSWORD) != null ? intent.getStringExtra(EXTRA_PASSWORD) : mDefaults.getPassword()); - ed.putBoolean(Constants.PREFS_KEY_SERVER_LAST_FILE_TRANSFER, intent.getBooleanExtra(EXTRA_FILE_TRANSFER, mDefaults.getFileTranfer())); + ed.putInt(PREFS_KEY_SERVER_LAST_PORT, intent.getIntExtra(EXTRA_PORT, mDefaults.getPort())); + ed.putString(PREFS_KEY_SERVER_LAST_PASSWORD, intent.getStringExtra(EXTRA_PASSWORD) != null ? intent.getStringExtra(EXTRA_PASSWORD) : mDefaults.getPassword()); + ed.putBoolean(PREFS_KEY_SERVER_LAST_FILE_TRANSFER, intent.getBooleanExtra(EXTRA_FILE_TRANSFER, mDefaults.getFileTranfer())); ed.putBoolean(Constants.PREFS_KEY_INPUT_LAST_ENABLED, !intent.getBooleanExtra(EXTRA_VIEW_ONLY, mDefaults.getViewOnly())); ed.putFloat(Constants.PREFS_KEY_SERVER_LAST_SCALING, intent.getFloatExtra(EXTRA_SCALING, mDefaults.getScaling())); - ed.putString(Constants.PREFS_KEY_SERVER_LAST_START_REQUEST_ID, intent.getStringExtra(EXTRA_REQUEST_ID)); + ed.putString(PREFS_KEY_SERVER_LAST_START_REQUEST_ID, intent.getStringExtra(EXTRA_REQUEST_ID)); ed.apply(); // also set new value for InputService InputService.scaling = intent.getFloatExtra(EXTRA_SCALING, mDefaults.getScaling()); From d5f71a8a3017ac94041f34cfc38ae4827054035f Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Tue, 13 Jun 2023 10:19:31 +0200 Subject: [PATCH 51/56] MainService: let getIPv4sAndPorts() return last used port --- .../main/java/net/christianbeier/droidvnc_ng/MainService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index bfe91727..7a0d5b59 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -632,7 +632,7 @@ static ArrayList getIPv4sAndPorts() { try { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(instance); - port = prefs.getInt(Constants.PREFS_KEY_SETTINGS_PORT, 5900); + port = prefs.getInt(PREFS_KEY_SERVER_LAST_PORT, new Defaults(instance).getPort()); } catch (NullPointerException e) { //unused } From 5eb73f4d0ddf5e104f3c7f584c05d21d52512251 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Tue, 13 Jun 2023 10:26:23 +0200 Subject: [PATCH 52/56] OnBootReceiver: provide user prefs to MainService --- .../christianbeier/droidvnc_ng/OnBootReceiver.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/OnBootReceiver.java b/app/src/main/java/net/christianbeier/droidvnc_ng/OnBootReceiver.java index 03bcfccd..a8774189 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/OnBootReceiver.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/OnBootReceiver.java @@ -41,9 +41,18 @@ public void onReceive(Context context, Intent arg1) final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); if(prefs.getBoolean(Constants.PREFS_KEY_SETTINGS_START_ON_BOOT, true)) { Log.i(TAG, "onReceive: configured to start"); + + Defaults defaults = new Defaults(context); + Intent intent = new Intent(context, MainService.class); intent.setAction(MainService.ACTION_START); - intent.putExtra(MainService.EXTRA_ACCESS_KEY, prefs.getString(Constants.PREFS_KEY_SETTINGS_ACCESS_KEY, new Defaults(context).getAccessKey())); + intent.putExtra(MainService.EXTRA_PORT, prefs.getInt(Constants.PREFS_KEY_SETTINGS_PORT, defaults.getPort())); + intent.putExtra(MainService.EXTRA_PASSWORD, prefs.getString(Constants.PREFS_KEY_SETTINGS_PASSWORD, defaults.getPassword())); + intent.putExtra(MainService.EXTRA_FILE_TRANSFER, prefs.getBoolean(Constants.PREFS_KEY_SETTINGS_FILE_TRANSFER, defaults.getFileTranfer())); + intent.putExtra(MainService.EXTRA_VIEW_ONLY, prefs.getBoolean(Constants.PREFS_KEY_SETTINGS_VIEW_ONLY, defaults.getViewOnly())); + intent.putExtra(MainService.EXTRA_SCALING, prefs.getFloat(Constants.PREFS_KEY_SETTINGS_SCALING, defaults.getScaling())); + intent.putExtra(MainService.EXTRA_ACCESS_KEY, prefs.getString(Constants.PREFS_KEY_SETTINGS_ACCESS_KEY, defaults.getAccessKey())); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { context.startForegroundService(intent); } else { From 41f0dca19b5ae3de23b33a418b66b969e8df7c29 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Tue, 13 Jun 2023 10:28:54 +0200 Subject: [PATCH 53/56] README: update example defaults.json --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 512a2dc2..e27e77f2 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ An example `defaults.json` with completely new defaults (not all entries need to "portRepeater": 5556, "scaling": 0.7, "viewOnly": false, + "fileTranfer": true, "password": "supersecure", "accessKey": "evenmoresecure" } From 5cc8133d9d222b75c2ff67ff614e48fee772fe1c Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Tue, 13 Jun 2023 12:03:46 +0200 Subject: [PATCH 54/56] README: document intent remote control --- README.md | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/README.md b/README.md index e27e77f2..bc17fc38 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,84 @@ An example `defaults.json` with completely new defaults (not all entries need to } ``` +### Remote Control via the Intent Interface + +droidVNC-NG features a remote control interface by means of Intents. This allows starting the VNC +server from other apps or on certain events. It is designed to be working with automation apps +like [MacroDroid](https://www.macrodroid.com/), [Automate](https://llamalab.com/automate/) or +[Tasker](https://tasker.joaoapps.com/) as well as to be called from code. + +You basically send an explicit Intent to `net.christianbeier.droidvnc_ng.MainService` with one of +the following Actions and associated Extras set: + +* `net.christianbeier.droidvnc_ng.ACTION_START`: Starts the server. + * `net.christianbeier.droidvnc_ng.EXTRA_ACCESS_KEY`: Required String Extra containing the remote control interface's access key. You can get/set this from the Admin Panel. + * `net.christianbeier.droidvnc_ng.EXTRA_REQUEST_ID`: Optional String Extra containing a unique id for this request. Used to identify the answer from the service. + * `net.christianbeier.droidvnc_ng.EXTRA_PORT`: Optional Integer Extra setting the listening port. Set to `-1` to disable listening. + * `net.christianbeier.droidvnc_ng.EXTRA_PASSWORD`: Optional String Extra containing VNC password. + * `net.christianbeier.droidvnc_ng.EXTRA_SCALING`: Optional Float Extra between 0.0 and 1.0 describing the server-side framebuffer scaling. + * `net.christianbeier.droidvnc_ng.EXTRA_VIEW_ONLY`: Optional Boolean Extra toggling view-only mode. + * `net.christianbeier.droidvnc_ng.EXTRA_FILE_TRANSFER`: Optional Boolean Extra toggling the file transfer feature. + +* `net.christianbeier.droidvnc_ng.ACTION_CONNECT_REVERSE`: Make an outbound connection to a listening viewer. + * `net.christianbeier.droidvnc_ng.EXTRA_ACCESS_KEY`: Required String Extra containing the remote control interface's access key. You can get/set this from the Admin Panel. + * `net.christianbeier.droidvnc_ng.EXTRA_REQUEST_ID`: Optional String Extra containing a unique id for this request. Used to identify the answer from the service. + * `net.christianbeier.droidvnc_ng.EXTRA_HOST`: Required String Extra setting the host to connect to. + * `net.christianbeier.droidvnc_ng.EXTRA_PORT`: Optional Integer Extra setting the remote port. + +* `net.christianbeier.droidvnc_ng.ACTION_CONNECT_REPEATER` Make an outbound connection to a repeater. + * `net.christianbeier.droidvnc_ng.EXTRA_ACCESS_KEY`: Required String Extra containing the remote control interface's access key. You can get/set this from the Admin Panel. + * `net.christianbeier.droidvnc_ng.EXTRA_REQUEST_ID`: Optional String Extra containing a unique id for this request. Used to identify the answer from the service. + * `net.christianbeier.droidvnc_ng.EXTRA_HOST`: Required String Extra setting the host to connect to. + * `net.christianbeier.droidvnc_ng.EXTRA_PORT`: Optional Integer Extra setting the remote port. + * `net.christianbeier.droidvnc_ng.EXTRA_REPEATER_ID`: Required String Extra setting the ID on the repeater. + +* `net.christianbeier.droidvnc_ng.ACTION_STOP`: Stops the server. + * `net.christianbeier.droidvnc_ng.EXTRA_ACCESS_KEY`: Required String Extra containing the remote control interface's access key. You can get/set this from the Admin Panel. + * `net.christianbeier.droidvnc_ng.EXTRA_REQUEST_ID`: Optional String Extra containing a unique id for this request. Used to identify the answer from the service. + +The service answers with a Broadcast Intent with its Action mirroring your request: + +* Action: one of the above Actions you requested + * `net.christianbeier.droidvnc_ng.EXTRA_REQUEST_ID`: The request id this answer is for. + * `net.christianbeier.droidvnc_ng.EXTRA_REQUEST_SUCCESS`: Boolean Extra describing the outcome of the request. + +#### Examples + +##### Start a password-protected view-only server on port 5901 + +Using `adb shell am` syntax: + +```shell +adb shell am start-foreground-service \ + -n net.christianbeier.droidvnc_ng/.MainService \ + -a net.christianbeier.droidvnc_ng.ACTION_START \ + --es net.christianbeier.droidvnc_ng.EXTRA_ACCESS_KEY de32550a6efb43f8a5d145e6c07b2cde \ + --es net.christianbeier.droidvnc_ng.EXTRA_REQUEST_ID abc123 \ + --ei net.christianbeier.droidvnc_ng.EXTRA_PORT 5901 \ + --es net.christianbeier.droidvnc_ng.EXTRA_PASSWORD supersecure \ + --ez net.christianbeier.droidvnc_ng.EXTRA_VIEW_ONLY true +``` + +##### Make an outbound connection to a listening viewer from the running server + +For example from Java code: + +See [MainActivity.java](app/src/main/java/net/christianbeier/droidvnc_ng/MainActivity.java). + +##### Stop the server again + +Using `adb shell am` syntax again: + +```shell +adb shell am start-foreground-service \ + -n net.christianbeier.droidvnc_ng/.MainService \ + -a net.christianbeier.droidvnc_ng.ACTION_STOP \ + --es net.christianbeier.droidvnc_ng.EXTRA_ACCESS_KEY de32550a6efb43f8a5d145e6c07b2cde \ + --es net.christianbeier.droidvnc_ng.EXTRA_REQUEST_ID def456 +``` + + ## Notes * Requires at least Android 7. From 0a9c93a1e6ac1846b2c33a8a716e33e75b3e0253 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Tue, 13 Jun 2023 12:23:26 +0200 Subject: [PATCH 55/56] Defaults: set fileTransfer to what it is for older versions --- app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt b/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt index f1c0bae9..041bd2ea 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/Defaults.kt @@ -60,7 +60,7 @@ class Defaults { private set @EncodeDefault - var fileTranfer = false + var fileTranfer = true private set @EncodeDefault From e76521ac281c2fd681977644588305369d4f85c1 Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Tue, 13 Jun 2023 12:26:29 +0200 Subject: [PATCH 56/56] MainService: use user settings for values not provided in EXTRA_START ...not only Defaults. --- .../net/christianbeier/droidvnc_ng/MainService.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java index 7a0d5b59..f23f9b81 100644 --- a/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java +++ b/app/src/main/java/net/christianbeier/droidvnc_ng/MainService.java @@ -330,12 +330,13 @@ public int onStartCommand(Intent intent, int flags, int startId) } // Step 0: persist given arguments to be able to recover from possible crash later - SharedPreferences.Editor ed = PreferenceManager.getDefaultSharedPreferences(this).edit(); - ed.putInt(PREFS_KEY_SERVER_LAST_PORT, intent.getIntExtra(EXTRA_PORT, mDefaults.getPort())); - ed.putString(PREFS_KEY_SERVER_LAST_PASSWORD, intent.getStringExtra(EXTRA_PASSWORD) != null ? intent.getStringExtra(EXTRA_PASSWORD) : mDefaults.getPassword()); - ed.putBoolean(PREFS_KEY_SERVER_LAST_FILE_TRANSFER, intent.getBooleanExtra(EXTRA_FILE_TRANSFER, mDefaults.getFileTranfer())); - ed.putBoolean(Constants.PREFS_KEY_INPUT_LAST_ENABLED, !intent.getBooleanExtra(EXTRA_VIEW_ONLY, mDefaults.getViewOnly())); - ed.putFloat(Constants.PREFS_KEY_SERVER_LAST_SCALING, intent.getFloatExtra(EXTRA_SCALING, mDefaults.getScaling())); + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + SharedPreferences.Editor ed = prefs.edit(); + ed.putInt(PREFS_KEY_SERVER_LAST_PORT, intent.getIntExtra(EXTRA_PORT, prefs.getInt(Constants.PREFS_KEY_SETTINGS_PORT, mDefaults.getPort()))); + ed.putString(PREFS_KEY_SERVER_LAST_PASSWORD, intent.getStringExtra(EXTRA_PASSWORD) != null ? intent.getStringExtra(EXTRA_PASSWORD) : prefs.getString(Constants.PREFS_KEY_SETTINGS_PASSWORD, mDefaults.getPassword())); + ed.putBoolean(PREFS_KEY_SERVER_LAST_FILE_TRANSFER, intent.getBooleanExtra(EXTRA_FILE_TRANSFER, prefs.getBoolean(Constants.PREFS_KEY_SETTINGS_FILE_TRANSFER, mDefaults.getFileTranfer()))); + ed.putBoolean(Constants.PREFS_KEY_INPUT_LAST_ENABLED, !intent.getBooleanExtra(EXTRA_VIEW_ONLY, prefs.getBoolean(Constants.PREFS_KEY_SETTINGS_VIEW_ONLY, mDefaults.getViewOnly()))); + ed.putFloat(Constants.PREFS_KEY_SERVER_LAST_SCALING, intent.getFloatExtra(EXTRA_SCALING, prefs.getFloat(Constants.PREFS_KEY_SETTINGS_SCALING, mDefaults.getScaling()))); ed.putString(PREFS_KEY_SERVER_LAST_START_REQUEST_ID, intent.getStringExtra(EXTRA_REQUEST_ID)); ed.apply(); // also set new value for InputService