summaryrefslogtreecommitdiff
path: root/app/src/main/java/com
diff options
context:
space:
mode:
authorJavier <dev.git@javispedro.com>2020-02-16 22:18:38 +0100
committerJavier <dev.git@javispedro.com>2020-02-16 22:18:38 +0100
commit0a72437088b3e8387aa6ab77e20293bc2385788a (patch)
treed9add727dee224eda5d4d4823a08ce14e37f107f /app/src/main/java/com
parente88fb30dd01e64a0b2bfd1baec949b1836772fc0 (diff)
downloadvndroid-0a72437088b3e8387aa6ab77e20293bc2385788a.tar.gz
vndroid-0a72437088b3e8387aa6ab77e20293bc2385788a.zip
update to sdk 29, migrate to androidx, new GUI
Diffstat (limited to 'app/src/main/java/com')
-rw-r--r--app/src/main/java/com/javispedro/vndroid/ControlService.java3
-rw-r--r--app/src/main/java/com/javispedro/vndroid/KeyEventOutput.java3
-rw-r--r--app/src/main/java/com/javispedro/vndroid/RFBServer.java15
-rw-r--r--app/src/main/java/com/javispedro/vndroid/ScreenGrabber.java3
-rw-r--r--app/src/main/java/com/javispedro/vndroid/ScreenMirrorGrabber.java36
-rw-r--r--app/src/main/java/com/javispedro/vndroid/ServerRunningNotification.java12
-rw-r--r--app/src/main/java/com/javispedro/vndroid/ServerService.java230
-rw-r--r--app/src/main/java/com/javispedro/vndroid/SettingsActivity.java213
-rw-r--r--app/src/main/java/com/javispedro/vndroid/SetupActivity.java78
9 files changed, 422 insertions, 171 deletions
diff --git a/app/src/main/java/com/javispedro/vndroid/ControlService.java b/app/src/main/java/com/javispedro/vndroid/ControlService.java
index db5362d..166e379 100644
--- a/app/src/main/java/com/javispedro/vndroid/ControlService.java
+++ b/app/src/main/java/com/javispedro/vndroid/ControlService.java
@@ -2,10 +2,11 @@ package com.javispedro.vndroid;
import android.accessibilityservice.AccessibilityService;
import android.content.Intent;
-import android.support.annotation.Nullable;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
+import androidx.annotation.Nullable;
+
public class ControlService extends AccessibilityService {
private final String TAG = ControlService.class.getSimpleName();
diff --git a/app/src/main/java/com/javispedro/vndroid/KeyEventOutput.java b/app/src/main/java/com/javispedro/vndroid/KeyEventOutput.java
index 597942a..3ec4319 100644
--- a/app/src/main/java/com/javispedro/vndroid/KeyEventOutput.java
+++ b/app/src/main/java/com/javispedro/vndroid/KeyEventOutput.java
@@ -1,10 +1,11 @@
package com.javispedro.vndroid;
import android.os.Bundle;
-import android.support.annotation.Nullable;
import android.util.Log;
import android.view.accessibility.AccessibilityNodeInfo;
+import androidx.annotation.Nullable;
+
import com.javispedro.vndroid.keymaps.KeyActionHandler;
import com.javispedro.vndroid.keymaps.KeyHandler;
diff --git a/app/src/main/java/com/javispedro/vndroid/RFBServer.java b/app/src/main/java/com/javispedro/vndroid/RFBServer.java
index f5af05c..8838818 100644
--- a/app/src/main/java/com/javispedro/vndroid/RFBServer.java
+++ b/app/src/main/java/com/javispedro/vndroid/RFBServer.java
@@ -2,8 +2,8 @@ package com.javispedro.vndroid;
import android.graphics.PixelFormat;
import android.media.Image;
-import android.support.annotation.Nullable;
-import android.util.EventLog;
+
+import androidx.annotation.Nullable;
import java.nio.ByteBuffer;
@@ -25,6 +25,7 @@ public class RFBServer {
public interface EventCallback {
void onPointerEvent(int buttonMask, int x, int y);
void onKeyEvent(int key, boolean state);
+ void onClientEvent();
}
public RFBServer() {
@@ -40,13 +41,13 @@ public class RFBServer {
}
public void stop() {
- forgetLastImage();
shutdown();
+ forgetLastImage();
}
public void finalize() {
- forgetLastImage();
shutdown();
+ forgetLastImage();
deallocate();
}
@@ -77,6 +78,10 @@ public class RFBServer {
lastImage = image;
}
+ public int getNumClients() {
+ return get_num_clients();
+ }
+
private void forgetLastImage() {
if (lastImage != null) {
lastImage.close();
@@ -95,4 +100,6 @@ public class RFBServer {
private native void set_event_callback(EventCallback c);
private native boolean put_image(int width, int height, ByteBuffer buffer, int pixel_stride, int row_stride);
+
+ private native int get_num_clients();
}
diff --git a/app/src/main/java/com/javispedro/vndroid/ScreenGrabber.java b/app/src/main/java/com/javispedro/vndroid/ScreenGrabber.java
index 54d11bc..a5701b3 100644
--- a/app/src/main/java/com/javispedro/vndroid/ScreenGrabber.java
+++ b/app/src/main/java/com/javispedro/vndroid/ScreenGrabber.java
@@ -5,9 +5,10 @@ import android.content.ContextWrapper;
import android.hardware.display.VirtualDisplay;
import android.media.Image;
import android.media.ImageReader;
-import android.support.annotation.Nullable;
import android.util.Log;
+import androidx.annotation.Nullable;
+
public abstract class ScreenGrabber extends ContextWrapper {
private static final String TAG = ScreenGrabber.class.getSimpleName();
diff --git a/app/src/main/java/com/javispedro/vndroid/ScreenMirrorGrabber.java b/app/src/main/java/com/javispedro/vndroid/ScreenMirrorGrabber.java
index 9f78b3c..c223c65 100644
--- a/app/src/main/java/com/javispedro/vndroid/ScreenMirrorGrabber.java
+++ b/app/src/main/java/com/javispedro/vndroid/ScreenMirrorGrabber.java
@@ -1,34 +1,50 @@
package com.javispedro.vndroid;
+import android.app.Activity;
import android.content.Context;
+import android.content.Intent;
import android.graphics.PixelFormat;
import android.hardware.display.DisplayManager;
import android.media.ImageReader;
import android.media.projection.MediaProjection;
+import android.media.projection.MediaProjectionManager;
import android.os.Handler;
-import android.support.annotation.NonNull;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
+import android.view.WindowManager;
public class ScreenMirrorGrabber extends ScreenGrabber {
private static final String TAG = ScreenMirrorGrabber.class.getSimpleName();
- protected final MediaProjection projection;
- protected final Display realDisplay;
+ protected MediaProjection projection;
- protected final DisplayMetrics realDisplayMetrics;
+ protected int projAskCode;
+ protected Intent projAskData;
+
+ protected Display realDisplay;
+ protected DisplayMetrics realDisplayMetrics;
private float scale = 0.5f;
- public ScreenMirrorGrabber(Context context, @NonNull MediaProjection proj, @NonNull Display display) {
+ public ScreenMirrorGrabber(Context context, MediaProjection proj) {
super(context);
projection = proj;
- realDisplay = display;
- realDisplayMetrics = new DisplayMetrics();
+ projAskCode = 0;
+ projAskData = null; // Already obtained
+ }
+
+ public ScreenMirrorGrabber(Context context, int projectionResultCode, Intent projectionResultData) {
+ super(context);
+ projection = null;
+ projAskCode = projectionResultCode;
+ projAskData = projectionResultData;
}
private void initDisplay() {
+ WindowManager wm = getSystemService(WindowManager.class);
+ realDisplay = wm.getDefaultDisplay();
+ realDisplayMetrics = new DisplayMetrics();
realDisplay.getRealMetrics(realDisplayMetrics);
Log.d(TAG, "real display size: " + realDisplayMetrics.widthPixels + "x" + realDisplayMetrics.heightPixels);
@@ -55,6 +71,12 @@ public class ScreenMirrorGrabber extends ScreenGrabber {
Log.w(TAG, "already started");
return;
}
+ if (projection == null && projAskCode == Activity.RESULT_OK) {
+ MediaProjectionManager manager = getSystemService(MediaProjectionManager.class);
+ projection = manager.getMediaProjection(projAskCode, projAskData);
+ projAskCode = 0;
+ projAskData = null;
+ }
initDisplay();
}
diff --git a/app/src/main/java/com/javispedro/vndroid/ServerRunningNotification.java b/app/src/main/java/com/javispedro/vndroid/ServerRunningNotification.java
index 6fcf8ab..224df0e 100644
--- a/app/src/main/java/com/javispedro/vndroid/ServerRunningNotification.java
+++ b/app/src/main/java/com/javispedro/vndroid/ServerRunningNotification.java
@@ -1,6 +1,5 @@
package com.javispedro.vndroid;
-import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -8,11 +7,8 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.net.Uri;
-import android.os.Build;
-import android.support.v4.app.NotificationCompat;
+
+import androidx.core.app.NotificationCompat;
/**
* Helper class for showing and canceling server running
@@ -86,7 +82,7 @@ public class ServerRunningNotification {
PendingIntent.getActivity(
context,
0,
- new Intent(context, SetupActivity.class),
+ new Intent(context, SettingsActivity.class),
PendingIntent.FLAG_UPDATE_CURRENT))
// Example additional actions for this notification. These will
@@ -100,7 +96,7 @@ public class ServerRunningNotification {
PendingIntent.getForegroundService(
context,
0,
- new Intent(context, ServerService.class).setAction(ServerService.ACTION_STOP),
+ new Intent(context, ServerService.class).setAction(ServerService.ACTION_STOP_SERVER),
PendingIntent.FLAG_UPDATE_CURRENT));
return builder.build();
diff --git a/app/src/main/java/com/javispedro/vndroid/ServerService.java b/app/src/main/java/com/javispedro/vndroid/ServerService.java
index bf72d21..96420df 100644
--- a/app/src/main/java/com/javispedro/vndroid/ServerService.java
+++ b/app/src/main/java/com/javispedro/vndroid/ServerService.java
@@ -1,61 +1,80 @@
package com.javispedro.vndroid;
-import android.app.Activity;
import android.app.Notification;
import android.app.Service;
import android.content.Intent;
import android.content.res.Configuration;
import android.media.Image;
-import android.media.projection.MediaProjection;
-import android.media.projection.MediaProjectionManager;
+import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
-import android.view.WindowManager;
import android.widget.Toast;
import com.javispedro.vndroid.keymaps.AndroidKeyHandler;
import com.javispedro.vndroid.keymaps.SpanishKeyHandler;
+import java.lang.ref.WeakReference;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.List;
+
public class ServerService extends Service {
private static final String TAG = ServerService.class.getSimpleName();
- public static final String ACTION_START = "ACTION_START";
- public static final String ACTION_STOP = "ACTION_STOP";
- public static final String ACTION_NOTIFY_MEDIA_PROJECTION_RESULT = "ACTION_NOTIFY_MEDIA_PROJECTION_RESULT";
+
+ public static final String ACTION_START_SERVER = "ACTION_START_SERVER";
+ public static final String ACTION_STOP_SERVER = "ACTION_STOP_SERVER";
+
+ public class ServerBinder extends Binder {
+ ServerService getService() {
+ return ServerService.this;
+ }
+ }
+ public interface ServerStatusCallback {
+ void onServerStatusChanged();
+ void onNumClientChanged();
+ }
+
+ private ServerBinder binder;
+ private WeakReference<ServerStatusCallback> callback;
private ScreenGrabber screenGrabber;
private RFBServer rfbServer;
private PointerEventOutput pointerOut;
private KeyEventOutput keyOut;
- public ServerService() {
- }
-
@Override
public void onCreate() {
+ Log.d(TAG, "onCreate");
+ binder = new ServerBinder();
ServerRunningNotification.initNotificationChannel(this);
System.loadLibrary("native-lib");
}
@Override
+ public void onDestroy() {
+ Log.d(TAG, "onDestroy");
+ cleanupServer();
+ binder = null;
+ callback = null;
+ }
+
+ @Override
public IBinder onBind(Intent intent) {
- throw new UnsupportedOperationException("Not implemented");
+ return binder;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
- if (intent != null) {
- switch (intent.getAction()) {
- case ACTION_START:
- start();
- break;
- case ACTION_STOP:
- stop();
- break;
- case ACTION_NOTIFY_MEDIA_PROJECTION_RESULT:
- notifyMediaProjectionResult(intent.getIntExtra("resultCode", Activity.RESULT_CANCELED),
- (Intent) intent.getParcelableExtra("resultData"));
- break;
- }
+ Log.d(TAG, "onStartCommand intent=" + intent);
+ switch (intent.getAction()) {
+ case ACTION_START_SERVER:
+ startServer();
+ return START_REDELIVER_INTENT;
+ case ACTION_STOP_SERVER:
+ stopServer();
+ return START_NOT_STICKY;
}
return super.onStartCommand(intent, flags, startId);
}
@@ -69,43 +88,15 @@ public class ServerService extends Service {
}
}
- protected class ScreenGrabberCallback implements ScreenGrabber.Callback {
- @Override
- public void onImage(Image image) {
- if (rfbServer != null) {
- rfbServer.putImage(image);
- } else {
- image.close();
- }
+ public void setServerStatusCallback(ServerStatusCallback callback) {
+ if (callback != null) {
+ this.callback = new WeakReference<>(callback);
+ } else {
+ this.callback = null;
}
}
- protected class EventCallback implements RFBServer.EventCallback {
- @Override
- public void onPointerEvent(int buttonMask, int x, int y) {
- try {
- x = screenGrabber.scaleInputX(x);
- y = screenGrabber.scaleInputY(y);
- pointerOut.postPointerEvent((byte) buttonMask, x, y);
- } catch (Exception e) {
- Log.e(TAG, "Exception on pointer EventCallback: " + e.toString());
- e.printStackTrace();
- // Need to supress the exception, otherwise we'll crash JNI
- }
- }
-
- @Override
- public void onKeyEvent(int key, boolean state) {
- try {
- keyOut.postKeyEvent(key, state);
- } catch (Exception e) {
- Log.e(TAG, "Exception on key EventCallback: " + e.toString());
- e.printStackTrace();
- }
- }
- }
-
- protected void start() {
+ public void startServer() {
if (rfbServer != null) {
Log.w(TAG, "cannot start, already started");
return;
@@ -113,6 +104,9 @@ public class ServerService extends Service {
Log.d(TAG, "starting");
+ Notification notification = ServerRunningNotification.build(this);
+ startForeground(1, notification);
+
if (!ControlService.isServiceStarted()) {
Toast toast = Toast.makeText(this, R.string.toast_no_input_service, Toast.LENGTH_SHORT);
toast.show();
@@ -123,7 +117,6 @@ public class ServerService extends Service {
keyOut.addHandler(new AndroidKeyHandler());
keyOut.addHandler(new SpanishKeyHandler());
-
if (screenGrabber == null) {
screenGrabber = new ScreenVirtualGrabber(this);
}
@@ -135,13 +128,61 @@ public class ServerService extends Service {
screenGrabber.setCallback(new ScreenGrabberCallback());
screenGrabber.start();
- Notification notification = ServerRunningNotification.build(this);
- startForeground(1, notification);
+ notifyServerStatusChanged();
}
- protected void stop() {
+ public void stopServer() {
Log.d(TAG, "stopping");
+ cleanupServer();
+
+ stopForeground(true);
+ stopSelf();
+
+ notifyServerStatusChanged();
+ }
+
+ public boolean isServerActive() {
+ return rfbServer != null;
+ }
+
+ public void setMediaProjectionResult(int resultCode, Intent data) {
+ if (screenGrabber != null) {
+ Log.w(TAG, "already have an screen grabber");
+ }
+
+ screenGrabber = new ScreenMirrorGrabber(this, resultCode, data);
+ }
+
+ public int getListeningDisplay() {
+ return 0;
+ }
+
+ public List<String> getListeningIPAddresses() {
+ LinkedList<String> result = new LinkedList<String>();
+ try {
+ for (Enumeration<NetworkInterface> netif_it = NetworkInterface.getNetworkInterfaces(); netif_it.hasMoreElements(); ) {
+ NetworkInterface netif = netif_it.nextElement();
+
+ for (Enumeration<InetAddress> addr_it = netif.getInetAddresses(); addr_it.hasMoreElements(); ) {
+ InetAddress addr = addr_it.nextElement();
+
+ if (addr.isLoopbackAddress()) continue;
+
+ result.add(addr.getHostAddress());
+ }
+ }
+ } catch (Exception ex) {
+ Log.w(TAG, "While enumerating IP addresses: " + ex.toString());
+ }
+ return result;
+ }
+
+ public int getNumClients() {
+ return rfbServer.getNumClients();
+ }
+
+ private void cleanupServer() {
if (rfbServer != null) {
rfbServer.stop();
rfbServer = null;
@@ -156,20 +197,67 @@ public class ServerService extends Service {
if (keyOut != null) {
keyOut = null;
}
+ }
- stopForeground(true);
- stopSelf();
+ private ServerStatusCallback getStatusCallback() {
+ return callback == null ? null : callback.get();
}
- protected void notifyMediaProjectionResult(int resultCode, Intent data) {
- if (screenGrabber != null) {
- Log.w(TAG, "already have an screen grabber");
+ private void notifyServerStatusChanged() {
+ ServerStatusCallback cb = getStatusCallback();
+ if (cb == null) return;
+ cb.onServerStatusChanged();
+ }
+
+ private void notifyNumClientChanged() {
+ ServerStatusCallback cb = getStatusCallback();
+ if (cb == null) return;
+ cb.onNumClientChanged();
+ }
+
+ private class ScreenGrabberCallback implements ScreenGrabber.Callback {
+ @Override
+ public void onImage(Image image) {
+ if (rfbServer != null) {
+ rfbServer.putImage(image);
+ } else {
+ image.close();
+ }
}
- MediaProjectionManager manager = getSystemService(MediaProjectionManager.class);
- MediaProjection projection = manager.getMediaProjection(resultCode, data);
+ }
- WindowManager wm = getSystemService(WindowManager.class);
+ private class EventCallback implements RFBServer.EventCallback {
+ @Override
+ public void onPointerEvent(int buttonMask, int x, int y) {
+ try {
+ x = screenGrabber.scaleInputX(x);
+ y = screenGrabber.scaleInputY(y);
+ pointerOut.postPointerEvent((byte) buttonMask, x, y);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception on pointer EventCallback: " + e.toString());
+ e.printStackTrace();
+ // Need to suppress the exception, otherwise we'll crash JNI
+ }
+ }
- screenGrabber = new ScreenMirrorGrabber(this, projection, wm.getDefaultDisplay());
+ @Override
+ public void onKeyEvent(int key, boolean state) {
+ try {
+ keyOut.postKeyEvent(key, state);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception on key EventCallback: " + e.toString());
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onClientEvent() {
+ try {
+ notifyNumClientChanged();
+ } catch (Exception e) {
+ Log.e(TAG, "Exception on client EventCallback: " + e.toString());
+ e.printStackTrace();
+ }
+ }
}
}
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
diff --git a/app/src/main/java/com/javispedro/vndroid/SetupActivity.java b/app/src/main/java/com/javispedro/vndroid/SetupActivity.java
deleted file mode 100644
index 123bbe7..0000000
--- a/app/src/main/java/com/javispedro/vndroid/SetupActivity.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package com.javispedro.vndroid;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.media.projection.MediaProjectionManager;
-import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.util.Log;
-import android.view.View;
-
-public class SetupActivity extends AppCompatActivity {
- private static String TAG = SetupActivity.class.getSimpleName();
-
- private static final int REQUEST_MEDIA_PROJECTION = 1;
-
- private boolean mirror = true;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_setup);
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data)
- {
- switch (requestCode) {
- case REQUEST_MEDIA_PROJECTION:
- if (resultCode != Activity.RESULT_OK) {
- Log.w(TAG, "User cancelled media projection");
- return;
- }
-
- notifyMediaProjectionResult(resultCode, data);
- startServer();
-
- break;
- }
- }
-
- private void startServer()
- {
- Intent intent = new Intent(this, ServerService.class);
- intent.setAction(ServerService.ACTION_START);
- startService(intent);
- }
-
- private void stopServer()
- {
- Intent intent = new Intent(this, ServerService.class);
- intent.setAction(ServerService.ACTION_STOP);
- startService(intent);
- }
-
- private void notifyMediaProjectionResult(int resultCode, Intent resultData)
- {
- Intent intent = new Intent(this, ServerService.class);
- intent.setAction(ServerService.ACTION_NOTIFY_MEDIA_PROJECTION_RESULT);
- intent.putExtra("resultCode", resultCode);
- intent.putExtra("resultData", resultData);
- startService(intent);
- }
-
- public void onStartClick(View view) {
- Log.d(TAG, "onStartClick");
- if (mirror) {
- MediaProjectionManager manager = getSystemService(MediaProjectionManager.class);
- startActivityForResult(manager.createScreenCaptureIntent(), REQUEST_MEDIA_PROJECTION);
- } else {
- startServer();
- }
- }
-
- public void onStopClick(View view) {
- Log.d(TAG, "onStopClick");
- stopServer();
- }
-}