From 19d75ac8d842e06c80b5b286c4d259b3e2431d61 Mon Sep 17 00:00:00 2001 From: Dmitriy Krivoruchko Date: Mon, 29 Aug 2016 09:54:42 +0300 Subject: [PATCH] Workflow optimization --- .../info/dvkr/screenstream/AppContext.java | 38 ++--- .../java/info/dvkr/screenstream/AppState.java | 19 +-- .../info/dvkr/screenstream/AppViewState.java | 16 +++ .../java/info/dvkr/screenstream/Client.java | 4 +- .../dvkr/screenstream/ForegroundService.java | 134 +++++++++--------- .../screenstream/ForegroundTaskHandler.java | 32 +++-- .../dvkr/screenstream/ImageGenerator.java | 10 +- .../info/dvkr/screenstream/JpegStreamer.java | 14 +- .../info/dvkr/screenstream/MainActivity.java | 133 +++++++++-------- app/src/main/res/layout/activity_main.xml | 2 +- 10 files changed, 205 insertions(+), 197 deletions(-) create mode 100644 app/src/main/java/info/dvkr/screenstream/AppViewState.java diff --git a/app/src/main/java/info/dvkr/screenstream/AppContext.java b/app/src/main/java/info/dvkr/screenstream/AppContext.java index fd32d603..ae247b99 100644 --- a/app/src/main/java/info/dvkr/screenstream/AppContext.java +++ b/app/src/main/java/info/dvkr/screenstream/AppContext.java @@ -15,8 +15,6 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.util.Locale; -import java.util.concurrent.ConcurrentLinkedDeque; -import java.util.concurrent.ConcurrentLinkedQueue; import static info.dvkr.screenstream.ForegroundService.SERVICE_MESSAGE; import static info.dvkr.screenstream.ForegroundService.SERVICE_MESSAGE_PREPARE_STREAMING; @@ -25,6 +23,7 @@ public class AppContext extends Application { private static AppContext instance; + private final AppViewState appViewState = new AppViewState(); private final AppState appState = new AppState(); private AppSettings appSettings; private WindowManager windowManager; @@ -33,11 +32,6 @@ public class AppContext extends Application { private String pinRequestHTMLPage; private byte[] iconBytes; - private final ConcurrentLinkedDeque JPEGQueue = new ConcurrentLinkedDeque<>(); - private final ConcurrentLinkedQueue clientQueue = new ConcurrentLinkedQueue<>(); - - private volatile boolean isStreamRunning; - @Override public void onCreate() { super.onCreate(); @@ -48,11 +42,11 @@ public void onCreate() { appSettings.generateAndSaveNewPin(); } - appState.serverAddress.set(getServerAddress()); - appState.pinEnabled.set(appSettings.isEnablePin()); - appState.pinAutoHide.set(appSettings.isPinAutoHide()); - appState.streamPin.set(appSettings.getUserPin()); - appState.wifiConnected.set(isWiFiConnected()); + appViewState.serverAddress.set(getServerAddress()); + appViewState.pinEnabled.set(appSettings.isEnablePin()); + appViewState.pinAutoHide.set(appSettings.isPinAutoHide()); + appViewState.streamPin.set(appSettings.getUserPin()); + appViewState.wifiConnected.set(isWiFiConnected()); windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); densityDPI = getDensityDPI(); @@ -70,6 +64,10 @@ public void onCreate() { .putExtra(SERVICE_MESSAGE, SERVICE_MESSAGE_PREPARE_STREAMING)); } + static AppViewState getAppViewState() { + return instance.appViewState; + } + static AppState getAppState() { return instance.appState; } @@ -96,13 +94,9 @@ static Point getScreenSize() { return screenSize; } - static boolean isStreamRunning() { - return instance.isStreamRunning; - } - static void setIsStreamRunning(final boolean isRunning) { - instance.isStreamRunning = isRunning; - getAppState().streaming.set(isRunning); + instance.appState.isStreamRunning = isRunning; + getAppViewState().streaming.set(isRunning); } static String getIndexHTMLPage(final String streamAddress) { @@ -122,14 +116,6 @@ static String getServerAddress() { return "http://" + instance.getIPAddress() + ":" + instance.appSettings.getSeverPort(); } - static ConcurrentLinkedDeque getJPEGQueue() { - return instance.JPEGQueue; - } - - static ConcurrentLinkedQueue getClientQueue() { - return instance.clientQueue; - } - static boolean isWiFiConnected() { final WifiManager wifi = (WifiManager) instance.getSystemService(Context.WIFI_SERVICE); return wifi.getConnectionInfo().getIpAddress() > 0; diff --git a/app/src/main/java/info/dvkr/screenstream/AppState.java b/app/src/main/java/info/dvkr/screenstream/AppState.java index 02e92da8..9c3675d0 100644 --- a/app/src/main/java/info/dvkr/screenstream/AppState.java +++ b/app/src/main/java/info/dvkr/screenstream/AppState.java @@ -1,16 +1,11 @@ package info.dvkr.screenstream; -import android.databinding.ObservableBoolean; -import android.databinding.ObservableField; -import android.databinding.ObservableInt; +import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.concurrent.ConcurrentLinkedQueue; -public final class AppState { - public final ObservableField serverAddress = new ObservableField<>(); - public final ObservableBoolean pinEnabled = new ObservableBoolean(); - public final ObservableBoolean pinAutoHide = new ObservableBoolean(); - public final ObservableField streamPin = new ObservableField<>(); - public final ObservableBoolean streaming = new ObservableBoolean(); - public final ObservableBoolean wifiConnected = new ObservableBoolean(); - public final ObservableBoolean httpServerError = new ObservableBoolean(); - public final ObservableInt clients = new ObservableInt(); +class AppState { + final ConcurrentLinkedDeque JPEGQueue = new ConcurrentLinkedDeque<>(); + final ConcurrentLinkedQueue clientQueue = new ConcurrentLinkedQueue<>(); + volatile boolean isStreamRunning; + volatile int httpServerStatus = HTTPServer.SERVER_STATUS_UNKNOWN; } diff --git a/app/src/main/java/info/dvkr/screenstream/AppViewState.java b/app/src/main/java/info/dvkr/screenstream/AppViewState.java new file mode 100644 index 00000000..4af21122 --- /dev/null +++ b/app/src/main/java/info/dvkr/screenstream/AppViewState.java @@ -0,0 +1,16 @@ +package info.dvkr.screenstream; + +import android.databinding.ObservableBoolean; +import android.databinding.ObservableField; +import android.databinding.ObservableInt; + +public final class AppViewState { + public final ObservableField serverAddress = new ObservableField<>(); + public final ObservableBoolean pinEnabled = new ObservableBoolean(); + public final ObservableBoolean pinAutoHide = new ObservableBoolean(); + public final ObservableField streamPin = new ObservableField<>(); + public final ObservableBoolean streaming = new ObservableBoolean(); + public final ObservableBoolean wifiConnected = new ObservableBoolean(); + public final ObservableBoolean httpServerError = new ObservableBoolean(); + public final ObservableInt clients = new ObservableInt(); +} diff --git a/app/src/main/java/info/dvkr/screenstream/Client.java b/app/src/main/java/info/dvkr/screenstream/Client.java index 9ab8421a..3255d26b 100644 --- a/app/src/main/java/info/dvkr/screenstream/Client.java +++ b/app/src/main/java/info/dvkr/screenstream/Client.java @@ -33,8 +33,8 @@ private void closeSocket() { } catch (IOException e) { FirebaseCrash.report(e); } - AppContext.getClientQueue().remove(Client.this); - AppContext.getAppState().clients.set(AppContext.getClientQueue().size()); + AppContext.getAppState().clientQueue.remove(Client.this); + AppContext.getAppViewState().clients.set(AppContext.getAppState().clientQueue.size()); } diff --git a/app/src/main/java/info/dvkr/screenstream/ForegroundService.java b/app/src/main/java/info/dvkr/screenstream/ForegroundService.java index 9125af86..10a20e3a 100644 --- a/app/src/main/java/info/dvkr/screenstream/ForegroundService.java +++ b/app/src/main/java/info/dvkr/screenstream/ForegroundService.java @@ -17,6 +17,14 @@ import android.support.v4.app.NotificationCompat; import android.support.v4.content.ContextCompat; +import java.util.concurrent.ConcurrentLinkedQueue; + +import static info.dvkr.screenstream.AppContext.getAppSettings; +import static info.dvkr.screenstream.AppContext.getAppState; +import static info.dvkr.screenstream.AppContext.getAppViewState; +import static info.dvkr.screenstream.AppContext.getServerAddress; +import static info.dvkr.screenstream.AppContext.isWiFiConnected; + public final class ForegroundService extends Service { private static ForegroundService foregroundService; @@ -27,15 +35,12 @@ public final class ForegroundService extends Service { private ImageGenerator imageGenerator; private ForegroundTaskHandler foregroundServiceTaskHandler; - private int httpServerStatus = HTTPServer.SERVER_STATUS_UNKNOWN; - // Fields for broadcast static final String SERVICE_ACTION = "info.dvkr.screenstream.ForegroundService.SERVICE_ACTION"; static final String SERVICE_PERMISSION = "info.dvkr.screenstream.RECEIVE_BROADCAST"; static final String SERVICE_MESSAGE = "SERVICE_MESSAGE"; static final int SERVICE_MESSAGE_EMPTY = 0; static final int SERVICE_MESSAGE_HAS_NEW = 1; - static final int SERVICE_MESSAGE_GET_CURRENT = 11; static final int SERVICE_MESSAGE_PREPARE_STREAMING = 110; static final int SERVICE_MESSAGE_START_STREAMING = 111; static final int SERVICE_MESSAGE_STOP_STREAMING = 112; @@ -46,7 +51,7 @@ public final class ForegroundService extends Service { static final int SERVICE_MESSAGE_IMAGE_GENERATOR_ERROR = 4000; static final int SERVICE_MESSAGE_EXIT = 9000; - private int currentServiceMessage; + private ConcurrentLinkedQueue serviceMessages = new ConcurrentLinkedQueue<>(); // Fields for notifications private BroadcastReceiver localNotificationReceiver; @@ -59,31 +64,33 @@ public final class ForegroundService extends Service { private BroadcastReceiver broadcastReceiver; - static MediaProjectionManager getProjectionManager() { - return foregroundService.projectionManager; - } - static void setMediaProjection(final MediaProjection mediaProjection) { foregroundService.mediaProjection = mediaProjection; } + @Nullable + static MediaProjectionManager getProjectionManager() { + return foregroundService == null ? null : foregroundService.projectionManager; + } + @Nullable static MediaProjection getMediaProjection() { - return foregroundService.mediaProjection; + return foregroundService == null ? null : foregroundService.mediaProjection; } + @Nullable static ImageGenerator getImageGenerator() { - return foregroundService.imageGenerator; + return foregroundService == null ? null : foregroundService.imageGenerator; } - static int getHttpServerStatus() { - if (foregroundService == null) return HTTPServer.SERVER_STATUS_UNKNOWN; - return foregroundService.httpServerStatus; + @Nullable + static ConcurrentLinkedQueue getServiceMessages() { + return foregroundService == null ? null : foregroundService.serviceMessages; } static void errorInImageGenerator() { - foregroundService.currentServiceMessage = SERVICE_MESSAGE_IMAGE_GENERATOR_ERROR; - foregroundService.relayMessageViaActivity(); + if (foregroundService != null) + foregroundService.relayMessageViaActivity(SERVICE_MESSAGE_IMAGE_GENERATOR_ERROR); } @Override @@ -99,6 +106,7 @@ public void onStop() { }; httpServer = new HTTPServer(); imageGenerator = new ImageGenerator(); + imageGenerator.addDefaultScreen(getApplicationContext()); // Starting thread Handler final HandlerThread looperThread = new HandlerThread(ForegroundService.class.getSimpleName(), Process.THREAD_PRIORITY_MORE_FAVORABLE); @@ -114,70 +122,61 @@ public void onStop() { localNotificationReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - if (intent.getAction().equals(KEY_START)) { - currentServiceMessage = SERVICE_MESSAGE_START_STREAMING; - relayMessageViaActivity(); - } - - if (intent.getAction().equals(KEY_STOP)) { - currentServiceMessage = SERVICE_MESSAGE_STOP_STREAMING; - relayMessageViaActivity(); - } - - if (intent.getAction().equals(KEY_CLOSE)) { - currentServiceMessage = SERVICE_MESSAGE_EXIT; - relayMessageViaActivity(); + final String action = intent.getAction(); + switch (action) { + case KEY_START: + relayMessageViaActivity(SERVICE_MESSAGE_START_STREAMING); + break; + case KEY_STOP: + relayMessageViaActivity(SERVICE_MESSAGE_STOP_STREAMING); + break; + case KEY_CLOSE: + relayMessageViaActivity(SERVICE_MESSAGE_EXIT); + break; } } }; registerReceiver(localNotificationReceiver, localNotificationIntentFilter); - // Registering receiver for screen off messages - final IntentFilter screenOnOffFilter = new IntentFilter(); - screenOnOffFilter.addAction(Intent.ACTION_SCREEN_OFF); - screenOnOffFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); + // Registering receiver for screen off messages and WiFi changes + final IntentFilter screenOnOffAndWiFiFilter = new IntentFilter(); + screenOnOffAndWiFiFilter.addAction(Intent.ACTION_SCREEN_OFF); + screenOnOffAndWiFiFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - if (AppContext.getAppSettings().isPauseOnSleep()) - if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) - if (AppContext.isStreamRunning()) { - currentServiceMessage = SERVICE_MESSAGE_STOP_STREAMING; - relayMessageViaActivity(); - } - - if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { - if (AppContext.getAppState().wifiConnected.get() != AppContext.isWiFiConnected()) { - AppContext.getAppState().serverAddress.set(AppContext.getServerAddress()); - AppContext.getAppState().wifiConnected.set(AppContext.isWiFiConnected()); - - if ((!AppContext.getAppState().wifiConnected.get()) && AppContext.isStreamRunning()) { - currentServiceMessage = SERVICE_MESSAGE_STOP_STREAMING; - relayMessageViaActivity(); - } + final String action = intent.getAction(); + if (action.equals(Intent.ACTION_SCREEN_OFF)) { + if (getAppSettings().isPauseOnSleep() && getAppState().isStreamRunning) + relayMessageViaActivity(SERVICE_MESSAGE_STOP_STREAMING); + } + + if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { + if (getAppViewState().wifiConnected.get() != isWiFiConnected()) { + getAppViewState().serverAddress.set(getServerAddress()); + getAppViewState().wifiConnected.set(isWiFiConnected()); + + if ((!getAppViewState().wifiConnected.get()) && getAppState().isStreamRunning) + relayMessageViaActivity(SERVICE_MESSAGE_STOP_STREAMING); } } } }; - registerReceiver(broadcastReceiver, screenOnOffFilter); - imageGenerator.addDefaultScreen(getApplicationContext()); + registerReceiver(broadcastReceiver, screenOnOffAndWiFiFilter); httpServerStartAndCheck(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { - final int messageFromActivity = intent.getIntExtra(SERVICE_MESSAGE, 0); - + final int messageFromActivity = intent.getIntExtra(SERVICE_MESSAGE, SERVICE_MESSAGE_EMPTY); +// Log.wtf(">>>>>>>>>>> messageFromActivity", "" + messageFromActivity); switch (messageFromActivity) { case SERVICE_MESSAGE_PREPARE_STREAMING: startForeground(110, getNotificationStart()); break; - case SERVICE_MESSAGE_GET_CURRENT: - serviceGetCurrentMessage(); - break; case SERVICE_MESSAGE_START_STREAMING: serviceStartStreaming(); break; @@ -201,12 +200,6 @@ private void serviceStartStreaming() { if (mediaProjection != null) mediaProjection.registerCallback(projectionCallback, null); } - private void serviceGetCurrentMessage() { - if (currentServiceMessage == SERVICE_MESSAGE_EMPTY) return; - sendBroadcast(new Intent(SERVICE_ACTION).putExtra(SERVICE_MESSAGE, currentServiceMessage), SERVICE_PERMISSION); - currentServiceMessage = SERVICE_MESSAGE_EMPTY; - } - private void serviceStopStreaming() { stopForeground(true); foregroundServiceTaskHandler.obtainMessage(ForegroundTaskHandler.HANDLER_STOP_STREAMING).sendToTarget(); @@ -227,21 +220,22 @@ private void serviceUpdatePinStatus() { httpServerStartAndCheck(); } - private void relayMessageViaActivity() { + private void relayMessageViaActivity(final int message) { + if (message == SERVICE_MESSAGE_EMPTY) return; + serviceMessages.add(message); startActivity(new Intent(this, MainActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); sendBroadcast(new Intent(SERVICE_ACTION).putExtra(SERVICE_MESSAGE, SERVICE_MESSAGE_HAS_NEW), SERVICE_PERMISSION); } private void httpServerStartAndCheck() { - httpServerStatus = httpServer.start(); - if (httpServerStatus == HTTPServer.SERVER_ERROR_PORT_IN_USE) { - currentServiceMessage = SERVICE_MESSAGE_HTTP_PORT_IN_USE; - AppContext.getAppState().httpServerError.set(true); + AppContext.getAppState().httpServerStatus = httpServer.start(); + if (AppContext.getAppState().httpServerStatus == HTTPServer.SERVER_ERROR_PORT_IN_USE) { + getAppViewState().httpServerError.set(true); + relayMessageViaActivity(SERVICE_MESSAGE_HTTP_PORT_IN_USE); } else { - currentServiceMessage = SERVICE_MESSAGE_HTTP_OK; - AppContext.getAppState().httpServerError.set(false); + getAppViewState().httpServerError.set(false); + relayMessageViaActivity(SERVICE_MESSAGE_HTTP_OK); } - relayMessageViaActivity(); } @Override @@ -280,7 +274,7 @@ private Notification getNotificationStop() { stopNotificationBuilder.setSmallIcon(R.drawable.ic_cast_http_24dp); stopNotificationBuilder.setColor(ContextCompat.getColor(this, R.color.colorPrimaryDark)); stopNotificationBuilder.setContentTitle(getString(R.string.stream)); - stopNotificationBuilder.setContentText(getString(R.string.go_to) + AppContext.getServerAddress()); + stopNotificationBuilder.setContentText(getString(R.string.go_to) + getServerAddress()); stopNotificationBuilder.setContentIntent(pendingMainActivityIntent); stopNotificationBuilder.addAction(R.drawable.ic_stop_24dp, getString(R.string.stop).toUpperCase(), PendingIntent.getBroadcast(this, 0, stopStreamIntent, 0)); stopNotificationBuilder.setPriority(NotificationCompat.PRIORITY_MAX); diff --git a/app/src/main/java/info/dvkr/screenstream/ForegroundTaskHandler.java b/app/src/main/java/info/dvkr/screenstream/ForegroundTaskHandler.java index a7654685..2adefffd 100644 --- a/app/src/main/java/info/dvkr/screenstream/ForegroundTaskHandler.java +++ b/app/src/main/java/info/dvkr/screenstream/ForegroundTaskHandler.java @@ -9,6 +9,9 @@ import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_180; +import static info.dvkr.screenstream.AppContext.getAppState; +import static info.dvkr.screenstream.AppContext.getWindowsManager; +import static info.dvkr.screenstream.AppContext.setIsStreamRunning; final class ForegroundTaskHandler extends Handler { static final int HANDLER_START_STREAMING = 0; @@ -18,6 +21,7 @@ final class ForegroundTaskHandler extends Handler { private static final int HANDLER_RESUME_STREAMING = 5; private static final int HANDLER_DETECT_ROTATION = 10; + private ImageGenerator imageGenerator; private boolean currentOrientation; private boolean newOrientation; private int rotation; @@ -30,34 +34,38 @@ final class ForegroundTaskHandler extends Handler { public void handleMessage(Message message) { switch (message.what) { case HANDLER_START_STREAMING: - if (AppContext.isStreamRunning()) break; + if (getAppState().isStreamRunning) break; removeMessages(HANDLER_DETECT_ROTATION); currentOrientation = getOrientation(); - ForegroundService.getImageGenerator().start(); + imageGenerator = ForegroundService.getImageGenerator(); + if (imageGenerator != null) imageGenerator.start(); sendMessageDelayed(obtainMessage(HANDLER_DETECT_ROTATION), 250); - AppContext.setIsStreamRunning(true); + setIsStreamRunning(true); break; case HANDLER_PAUSE_STREAMING: - if (!AppContext.isStreamRunning()) break; - ForegroundService.getImageGenerator().stop(); + if (!getAppState().isStreamRunning) break; + imageGenerator = ForegroundService.getImageGenerator(); + if (imageGenerator != null) imageGenerator.stop(); sendMessageDelayed(obtainMessage(HANDLER_RESUME_STREAMING), 250); break; case HANDLER_RESUME_STREAMING: - if (!AppContext.isStreamRunning()) break; - ForegroundService.getImageGenerator().start(); + if (!getAppState().isStreamRunning) break; + imageGenerator = ForegroundService.getImageGenerator(); + if (imageGenerator != null) imageGenerator.start(); sendMessageDelayed(obtainMessage(HANDLER_DETECT_ROTATION), 250); break; case HANDLER_STOP_STREAMING: - if (!AppContext.isStreamRunning()) break; + if (!getAppState().isStreamRunning) break; removeMessages(HANDLER_DETECT_ROTATION); removeMessages(HANDLER_STOP_STREAMING); - ForegroundService.getImageGenerator().stop(); + imageGenerator = ForegroundService.getImageGenerator(); + if (imageGenerator != null) imageGenerator.stop(); final MediaProjection mediaProjection = ForegroundService.getMediaProjection(); if (mediaProjection != null) mediaProjection.stop(); - AppContext.setIsStreamRunning(false); + setIsStreamRunning(false); break; case HANDLER_DETECT_ROTATION: - if (!AppContext.isStreamRunning()) break; + if (!getAppState().isStreamRunning) break; newOrientation = getOrientation(); if (currentOrientation == newOrientation) { sendMessageDelayed(obtainMessage(HANDLER_DETECT_ROTATION), 250); @@ -72,7 +80,7 @@ public void handleMessage(Message message) { } private boolean getOrientation() { - rotation = AppContext.getWindowsManager().getDefaultDisplay().getRotation(); + rotation = getWindowsManager().getDefaultDisplay().getRotation(); return rotation == ROTATION_0 || rotation == ROTATION_180; } } \ No newline at end of file diff --git a/app/src/main/java/info/dvkr/screenstream/ImageGenerator.java b/app/src/main/java/info/dvkr/screenstream/ImageGenerator.java index 5833ad40..e22a6729 100644 --- a/app/src/main/java/info/dvkr/screenstream/ImageGenerator.java +++ b/app/src/main/java/info/dvkr/screenstream/ImageGenerator.java @@ -72,10 +72,10 @@ public void onImageAvailable(ImageReader reader) { jpegByteArray = jpegOutputStream.toByteArray(); if (jpegByteArray != null) { - if (AppContext.getJPEGQueue().size() > 6) { - AppContext.getJPEGQueue().pollLast(); + if (AppContext.getAppState().JPEGQueue.size() > 6) { + AppContext.getAppState().JPEGQueue.pollLast(); } - AppContext.getJPEGQueue().add(jpegByteArray); + AppContext.getAppState().JPEGQueue.add(jpegByteArray); jpegByteArray = null; } } @@ -138,13 +138,13 @@ void stop() { } void addDefaultScreen(final Context context) { - AppContext.getJPEGQueue().clear(); + AppContext.getAppState().JPEGQueue.clear(); new Handler().postDelayed(new Runnable() { @Override public void run() { final byte[] jpegByteArray = NotifyImageGenerator.getDefaultScreen(context); if (jpegByteArray != null) { - AppContext.getJPEGQueue().add(jpegByteArray); + AppContext.getAppState().JPEGQueue.add(jpegByteArray); } } }, 500); diff --git a/app/src/main/java/info/dvkr/screenstream/JpegStreamer.java b/app/src/main/java/info/dvkr/screenstream/JpegStreamer.java index f5f6d4a6..596bbd6f 100644 --- a/app/src/main/java/info/dvkr/screenstream/JpegStreamer.java +++ b/app/src/main/java/info/dvkr/screenstream/JpegStreamer.java @@ -22,7 +22,7 @@ private class JpegStreamerThread extends Thread { public void run() { while (!isInterrupted()) { if (!isThreadRunning) break; - currentJPEG = AppContext.getJPEGQueue().poll(); + currentJPEG = AppContext.getAppState().JPEGQueue.poll(); if (currentJPEG == null) { try { @@ -43,7 +43,7 @@ private void sendLastJPEGToClients() { sleepCount = 0; synchronized (lock) { if (!isThreadRunning) return; - for (final Client currentClient : AppContext.getClientQueue()) + for (final Client currentClient : AppContext.getAppState().clientQueue) currentClient.sendClientData(HTTPServer.SERVER_OK, Client.CLIENT_IMAGE, lastJPEG); } } @@ -55,8 +55,8 @@ void addClient(final Socket clientSocket) { try { final Client newClient = new Client(clientSocket); newClient.sendClientData(HTTPServer.SERVER_OK, Client.CLIENT_HEADER, null); - AppContext.getClientQueue().add(newClient); - AppContext.getAppState().clients.set(AppContext.getClientQueue().size()); + AppContext.getAppState().clientQueue.add(newClient); + AppContext.getAppViewState().clients.set(AppContext.getAppState().clientQueue.size()); } catch (IOException e) { FirebaseCrash.report(e); } @@ -78,11 +78,11 @@ void stop(final int reason, final byte[] clientNotifyImage) { isThreadRunning = false; jpegStreamerThread.interrupt(); - for (Client currentClient : AppContext.getClientQueue()) + for (Client currentClient : AppContext.getAppState().clientQueue) currentClient.sendClientData(reason, Client.CLIENT_IMAGE, clientNotifyImage); - AppContext.getClientQueue().clear(); - AppContext.getAppState().clients.set(0); + AppContext.getAppState().clientQueue.clear(); + AppContext.getAppViewState().clients.set(0); } } } diff --git a/app/src/main/java/info/dvkr/screenstream/MainActivity.java b/app/src/main/java/info/dvkr/screenstream/MainActivity.java index 6682b96d..d5bd421a 100644 --- a/app/src/main/java/info/dvkr/screenstream/MainActivity.java +++ b/app/src/main/java/info/dvkr/screenstream/MainActivity.java @@ -8,6 +8,7 @@ import android.databinding.DataBindingUtil; import android.graphics.Color; import android.media.projection.MediaProjection; +import android.media.projection.MediaProjectionManager; import android.os.Bundle; import android.support.design.widget.Snackbar; import android.support.v7.app.AlertDialog; @@ -21,18 +22,19 @@ import com.google.firebase.crash.FirebaseCrash; +import java.util.concurrent.ConcurrentLinkedQueue; + import info.dvkr.screenstream.databinding.ActivityMainBinding; import static info.dvkr.screenstream.AppContext.getAppSettings; import static info.dvkr.screenstream.AppContext.getAppState; +import static info.dvkr.screenstream.AppContext.getAppViewState; import static info.dvkr.screenstream.AppContext.getServerAddress; -import static info.dvkr.screenstream.AppContext.isStreamRunning; import static info.dvkr.screenstream.AppContext.isWiFiConnected; import static info.dvkr.screenstream.ForegroundService.SERVICE_ACTION; import static info.dvkr.screenstream.ForegroundService.SERVICE_MESSAGE; import static info.dvkr.screenstream.ForegroundService.SERVICE_MESSAGE_EMPTY; import static info.dvkr.screenstream.ForegroundService.SERVICE_MESSAGE_EXIT; -import static info.dvkr.screenstream.ForegroundService.SERVICE_MESSAGE_GET_CURRENT; import static info.dvkr.screenstream.ForegroundService.SERVICE_MESSAGE_HAS_NEW; import static info.dvkr.screenstream.ForegroundService.SERVICE_MESSAGE_HTTP_OK; import static info.dvkr.screenstream.ForegroundService.SERVICE_MESSAGE_HTTP_PORT_IN_USE; @@ -42,9 +44,9 @@ import static info.dvkr.screenstream.ForegroundService.SERVICE_MESSAGE_STOP_STREAMING; import static info.dvkr.screenstream.ForegroundService.SERVICE_MESSAGE_UPDATE_PIN_STATUS; import static info.dvkr.screenstream.ForegroundService.SERVICE_PERMISSION; -import static info.dvkr.screenstream.ForegroundService.getHttpServerStatus; import static info.dvkr.screenstream.ForegroundService.getMediaProjection; import static info.dvkr.screenstream.ForegroundService.getProjectionManager; +import static info.dvkr.screenstream.ForegroundService.getServiceMessages; import static info.dvkr.screenstream.ForegroundService.setMediaProjection; public final class MainActivity extends AppCompatActivity { @@ -59,7 +61,7 @@ public final class MainActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main); - activityMainBinding.setAppState(getAppState()); + activityMainBinding.setAppState(getAppViewState()); snackbarPortInUse = Snackbar.make(activityMainBinding.mainView, R.string.snackbar_port_in_use, Snackbar.LENGTH_INDEFINITE) .setAction(R.string.settings, new View.OnClickListener() { @@ -74,61 +76,60 @@ public void onClick(View view) { broadcastReceiverFromService = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - if (intent.getAction().equals(SERVICE_ACTION)) { - final int serviceMessage = intent.getIntExtra(SERVICE_MESSAGE, SERVICE_MESSAGE_EMPTY); - - // Service ask to get new message - if (serviceMessage == SERVICE_MESSAGE_HAS_NEW) - startService(new Intent(MainActivity.this, ForegroundService.class) - .putExtra(SERVICE_MESSAGE, SERVICE_MESSAGE_GET_CURRENT)); - - if (serviceMessage == SERVICE_MESSAGE_START_STREAMING) - tryStartStreaming(); - - if (serviceMessage == SERVICE_MESSAGE_STOP_STREAMING) - stopStreaming(); - - if (serviceMessage == SERVICE_MESSAGE_EXIT) { - applicationClose(); - } - - if (serviceMessage == SERVICE_MESSAGE_HTTP_PORT_IN_USE) { - if (!snackbarPortInUse.isShown()) snackbarPortInUse.show(); - } - - if (serviceMessage == SERVICE_MESSAGE_HTTP_OK) { - if (snackbarPortInUse.isShown()) snackbarPortInUse.dismiss(); - } - - if (serviceMessage == SERVICE_MESSAGE_IMAGE_GENERATOR_ERROR) { - stopStreaming(); - if (!isFinishing()) - new AlertDialog.Builder(MainActivity.this) - .setTitle(getString(R.string.error)) - .setMessage(getString(R.string.unknown_format)) - .setIcon(R.drawable.ic_warning_24dp) - .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - dialog.dismiss(); - } - }) - .show(); - - } - } + if (intent.getAction().equals(SERVICE_ACTION) && + intent.getIntExtra(SERVICE_MESSAGE, SERVICE_MESSAGE_EMPTY) == SERVICE_MESSAGE_HAS_NEW) + processServiceMessages(); } }; } + private void processServiceMessages() { + final ConcurrentLinkedQueue serviceMessages = getServiceMessages(); + while (serviceMessages != null && !serviceMessages.isEmpty()) { + final int serviceMessage = serviceMessages.poll(); +// Log.wtf(">>>>>>>>>>> serviceMessage", "" + serviceMessage); + switch (serviceMessage) { + case SERVICE_MESSAGE_START_STREAMING: + tryStartStreaming(); + break; + case SERVICE_MESSAGE_STOP_STREAMING: + stopStreaming(); + break; + case SERVICE_MESSAGE_EXIT: + applicationClose(); + break; + case SERVICE_MESSAGE_HTTP_PORT_IN_USE: + if (!snackbarPortInUse.isShown()) snackbarPortInUse.show(); + break; + case SERVICE_MESSAGE_HTTP_OK: + if (snackbarPortInUse.isShown()) snackbarPortInUse.dismiss(); + break; + case SERVICE_MESSAGE_IMAGE_GENERATOR_ERROR: + stopStreaming(); + if (!isFinishing()) + new AlertDialog.Builder(this) + .setTitle(getString(R.string.error)) + .setMessage(getString(R.string.unknown_format)) + .setIcon(R.drawable.ic_warning_24dp) + .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + dialog.dismiss(); + } + }) + .show(); + + break; + } + } + } + @Override protected void onStart() { super.onStart(); registerReceiver(broadcastReceiverFromService, new IntentFilter(SERVICE_ACTION), SERVICE_PERMISSION, null); + processServiceMessages(); - startService(new Intent(this, ForegroundService.class) - .putExtra(SERVICE_MESSAGE, SERVICE_MESSAGE_GET_CURRENT)); - - if (getHttpServerStatus() == HTTPServer.SERVER_ERROR_PORT_IN_USE) { + if (AppContext.getAppState().httpServerStatus == HTTPServer.SERVER_ERROR_PORT_IN_USE) { snackbarPortInUse.show(); } } @@ -173,7 +174,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { case REQUEST_CODE_SETTINGS: final boolean isServerPortChanged = getAppSettings().updateSettings(); if (isServerPortChanged) { - getAppState().serverAddress.set(getServerAddress()); + getAppViewState().serverAddress.set(getServerAddress()); startService(new Intent(this, ForegroundService.class) .putExtra(SERVICE_MESSAGE, SERVICE_MESSAGE_RESTART_HTTP)); @@ -186,7 +187,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { } public void onToggleButtonClick(View v) { - if (isStreamRunning()) { + if (getAppState().isStreamRunning) { stopStreaming(); } else { ((ToggleButton) v).setChecked(false); @@ -201,14 +202,14 @@ private void applicationClose() { } private void updatePinStatus(final boolean isServerPortChanged) { - getAppState().pinAutoHide.set(getAppSettings().isPinAutoHide()); + getAppViewState().pinAutoHide.set(getAppSettings().isPinAutoHide()); final boolean newIsPinEnabled = getAppSettings().isEnablePin(); final String newPin = getAppSettings().getUserPin(); - if (newIsPinEnabled != getAppState().pinEnabled.get() || !newPin.equals(getAppState().streamPin.get())) { - getAppState().pinEnabled.set(newIsPinEnabled); - getAppState().streamPin.set(newPin); + if (newIsPinEnabled != getAppViewState().pinEnabled.get() || !newPin.equals(getAppViewState().streamPin.get())) { + getAppViewState().pinEnabled.set(newIsPinEnabled); + getAppViewState().streamPin.set(newPin); if (!isServerPortChanged) { startService(new Intent(this, ForegroundService.class) @@ -218,13 +219,19 @@ private void updatePinStatus(final boolean isServerPortChanged) { } private void tryStartStreaming() { - if (!isWiFiConnected() || isStreamRunning()) return; - if (getHttpServerStatus() != HTTPServer.SERVER_OK) return; - startActivityForResult(getProjectionManager().createScreenCaptureIntent(), REQUEST_CODE_SCREEN_CAPTURE); + if (!isWiFiConnected() || getAppState().isStreamRunning) return; + if (AppContext.getAppState().httpServerStatus != HTTPServer.SERVER_OK) return; + + final MediaProjectionManager projectionManager = getProjectionManager(); + if (projectionManager == null) return; + + startActivityForResult(projectionManager.createScreenCaptureIntent(), REQUEST_CODE_SCREEN_CAPTURE); } private void startStreaming(final int resultCode, final Intent data) { - final MediaProjection mediaProjection = getProjectionManager().getMediaProjection(resultCode, data); + final MediaProjectionManager projectionManager = getProjectionManager(); + if (projectionManager == null) return; + final MediaProjection mediaProjection = projectionManager.getMediaProjection(resultCode, data); if (mediaProjection == null) return; setMediaProjection(mediaProjection); @@ -239,12 +246,14 @@ private void startStreaming(final int resultCode, final Intent data) { } private void stopStreaming() { - if (!isStreamRunning() || getMediaProjection() == null) return; + if (!getAppState().isStreamRunning || getMediaProjection() == null) return; startService(new Intent(this, ForegroundService.class) .putExtra(SERVICE_MESSAGE, SERVICE_MESSAGE_STOP_STREAMING)); - if (getAppSettings().isAutoChangePin()) getAppSettings().generateAndSaveNewPin(); + if (getAppSettings().isEnablePin() && getAppSettings().isAutoChangePin()) + getAppSettings().generateAndSaveNewPin(); + updatePinStatus(false); } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index b004c9ef..9a201abe 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -7,7 +7,7 @@ + type="info.dvkr.screenstream.AppViewState" />