summaryrefslogtreecommitdiff
path: root/app/src/main/java/com/javispedro/vndroid/SettingsActivity.java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/com/javispedro/vndroid/SettingsActivity.java')
-rw-r--r--app/src/main/java/com/javispedro/vndroid/SettingsActivity.java213
1 files changed, 213 insertions, 0 deletions
diff --git a/app/src/main/java/com/javispedro/vndroid/SettingsActivity.java b/app/src/main/java/com/javispedro/vndroid/SettingsActivity.java
new file mode 100644
index 0000000..676af3d
--- /dev/null
+++ b/app/src/main/java/com/javispedro/vndroid/SettingsActivity.java
@@ -0,0 +1,213 @@
+package com.javispedro.vndroid;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.media.projection.MediaProjectionManager;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.util.Log;
+import android.widget.Toast;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.TwoStatePreference;
+
+import java.util.List;
+
+public class SettingsActivity extends AppCompatActivity {
+ private static final String TAG = SettingsActivity.class.getSimpleName();
+
+ private static final int REQUEST_MEDIA_PROJECTION = 1;
+
+ private static final boolean mirrorScreenMode = true;
+
+
+ public static class SettingsFragment extends PreferenceFragmentCompat implements ServerService.ServerStatusCallback {
+ private ServerConnection serverConnection = null;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+ setPreferencesFromResource(R.xml.root_preferences, rootKey);
+ findPreference(getString(R.string.settings_enable_key)).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ TwoStatePreference pref = (TwoStatePreference) preference;
+ setServerEnabled(pref.isChecked());
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ serverConnection = new ServerConnection();
+ serverConnection.bind(requireActivity(), this);
+ }
+
+ @Override
+ public void onStop() {
+ serverConnection.close(requireActivity());
+ serverConnection = null;
+ super.onStop();
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ switch (requestCode) {
+ case REQUEST_MEDIA_PROJECTION:
+ notifyMediaProjectionResult(resultCode, data);
+ return;
+ }
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+
+ @Override
+ public void onServerStatusChanged() {
+ postUpdateServerStatus();
+ }
+
+ @Override
+ public void onNumClientChanged() {
+ postUpdateServerStatus();
+ }
+
+ private void setServerEnabled(boolean state) {
+ Log.d(TAG, "setServerEnabled: " + state);
+ ServerService server = serverConnection.getServer();
+ if (state) {
+ if (server == null) {
+ throw new IllegalStateException("ServerService not bound");
+ }
+ if (server.isServerActive()) return;
+
+ if (mirrorScreenMode) {
+ MediaProjectionManager manager = requireContext().getSystemService(MediaProjectionManager.class);
+ startActivityForResult(manager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
+ } else {
+ server.startServer();
+ }
+ } else {
+ if (server == null) return;
+ server.stopServer();
+ }
+ }
+
+ private void notifyMediaProjectionResult(int resultCode, Intent resultData) {
+ if (resultCode != Activity.RESULT_OK) {
+ Log.w(TAG, "User cancelled media projection");
+ Toast.makeText(requireContext(), getString(R.string.toast_no_mirror_permission), Toast.LENGTH_SHORT).show();
+ updateServerStatus();
+ return;
+ }
+
+ ServerService server = serverConnection.getServer();
+ if (server == null) {
+ Log.e(TAG, "server died before projection could be sent");
+ updateServerStatus();
+ return;
+ }
+ if (server.isServerActive()) {
+ Log.w(TAG, "server already active");
+ updateServerStatus();
+ return;
+ }
+
+ server.setMediaProjectionResult(resultCode, resultData);
+ server.startServer();
+ }
+
+ private void updateServerStatus() {
+ TwoStatePreference enablePref = findPreference(getString(R.string.settings_enable_key));
+ Preference statusPref = findPreference(getString(R.string.settings_status_key));
+ ServerService server = serverConnection.getServer();
+ if (server != null && server.isServerActive()) {
+ enablePref.setChecked(true);
+ StringBuilder sb = new StringBuilder();
+ int display = server.getListeningDisplay();
+ List<String> ips = server.getListeningIPAddresses();
+ if (!ips.isEmpty()) {
+ sb.append('\n');
+ sb.append(getString(R.string.status_server_addresses));
+ for (String ip : ips) {
+ sb.append(' ');
+ sb.append(ip);
+ sb.append(':');
+ sb.append(display);
+ }
+ }
+ int numClients = server.getNumClients();
+ if (numClients > 0) {
+ sb.append('\n');
+ sb.append(getResources().getQuantityString(R.plurals.status_num_clients, numClients, numClients));
+ }
+ statusPref.setSummary(sb.toString());
+ } else {
+ enablePref.setChecked(false);
+ statusPref.setSummary("");
+ }
+ }
+
+ private void postUpdateServerStatus() {
+ requireActivity().runOnUiThread(new Runnable() {
+ public void run() {
+ updateServerStatus();
+ }
+ });
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.settings_activity);
+ getSupportFragmentManager()
+ .beginTransaction()
+ .replace(R.id.settings, new SettingsFragment())
+ .commit();
+ }
+
+ private static class ServerConnection implements ServiceConnection {
+ private ServerService server = null;
+ private ServerService.ServerStatusCallback callback = null;
+
+ public void bind(Activity activity, ServerService.ServerStatusCallback callback) {
+ this.callback = callback;
+ activity.bindService(new Intent(activity, ServerService.class), this, Context.BIND_AUTO_CREATE);
+ }
+
+ public void close(Activity activity) {
+ server.setServerStatusCallback(null);
+ activity.unbindService(this);
+ }
+
+ public boolean connected() {
+ return server != null;
+ }
+
+ public @Nullable ServerService getServer() {
+ return server;
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ server = ((ServerService.ServerBinder) service).getService();
+ server.setServerStatusCallback(this.callback);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ server = null;
+ }
+ }
+} \ No newline at end of file