Skip to content

Commit

Permalink
Update notification images
Browse files Browse the repository at this point in the history
  • Loading branch information
dkrivoruchko committed Sep 14, 2016
1 parent 0eb43c7 commit c6b6569
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 47 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
# ScreenStream
Screen Stream over HTTP - an Android mobile app: https://play.google.com/store/apps/details?id=info.dvkr.screenstream
**Screen Stream over HTTP** - an Android mobile app: [Screen Stream over HTTP](https://play.google.com/store/apps/details?id=info.dvkr.screenstream)

The application allows viewing the device screen in your web browser.
The main idea is to show your device screen during presentations and demos.
No need of any additional software except for this app and a web browser.

It uses MJPEG to encode screen images and send them through network socket. So it works with any desktop or mobile browser which supports MJPEG (Chrome, Safari, EDGE, Firefox).

The program works only via WiFi connection, so your device has to be connected to WiFi. No Internet required, however, there must be a network connection between the client and the device.
The number of client connections is unlimited, but be aware that each of them requires some CPU resources to send data.
The number of client connections is unlimited, but be aware that each of them requires some CPU resources to send data.

It uses Android Cast feature and requires at least Android 5.0 to operate.

**Known problems**
1. On some devices system return image in unknown format. Mostly on devices with no official Android 5.0 or above. Possible Android bug. App will show an error message. Trying to find some workaround.
2. On some devices no notification icon showing but notification is present. Android bug: 213309.

If there are any issues or ideas feel free to contact me.
2 changes: 1 addition & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ android {

dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:design:24.2.0'
compile 'com.android.support:design:24.2.1'
compile 'com.google.firebase:firebase-crash:9.4.0'
compile 'org.greenrobot:eventbus:3.0.0'
}
Expand Down
16 changes: 0 additions & 16 deletions app/src/main/java/info/dvkr/screenstream/data/ImageGenerator.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package info.dvkr.screenstream.data;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.hardware.display.DisplayManager;
Expand All @@ -20,7 +19,6 @@
import java.io.IOException;

import info.dvkr.screenstream.service.ForegroundService;
import info.dvkr.screenstream.utils.NotifyImageGenerator;

import static info.dvkr.screenstream.ScreenStreamApplication.getAppData;
import static info.dvkr.screenstream.ScreenStreamApplication.getAppPreference;
Expand Down Expand Up @@ -148,19 +146,5 @@ public void stop() {
isThreadRunning = false;
}
}

public void addDefaultScreen(final Context context) {
getAppData().getImageQueue().clear();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
final byte[] jpegByteArray = NotifyImageGenerator.getDefaultScreen(context);
if (jpegByteArray != null) {
getAppData().getImageQueue().add(jpegByteArray);
}
}
}, 500);

}
}

Original file line number Diff line number Diff line change
@@ -1,50 +1,66 @@
package info.dvkr.screenstream.utils;
package info.dvkr.screenstream.data;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Handler;
import android.support.annotation.Nullable;

import com.google.firebase.crash.FirebaseCrash;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import info.dvkr.screenstream.R;
import info.dvkr.screenstream.data.BusMessages;

import static info.dvkr.screenstream.ScreenStreamApplication.getAppData;
import static info.dvkr.screenstream.ScreenStreamApplication.getAppPreference;

public final class NotifyImageGenerator {
private static int sCurrentScreenSizeX;
private static byte[] sCurrentDefaultScreen;
private Context mContext;
private int mCurrentScreenSizeX;
private byte[] mCurrentDefaultScreen;

public static byte[] getDefaultScreen(final Context context) {
if (sCurrentScreenSizeX != getAppData().getScreenSize().x)
sCurrentDefaultScreen = null;
if (sCurrentDefaultScreen != null) return sCurrentDefaultScreen;

sCurrentDefaultScreen = generateImage(context.getString(R.string.image_generator_press),
context.getString(R.string.main_activity_start_stream).toUpperCase(),
context.getString(R.string.image_generator_on_device));

sCurrentScreenSizeX = getAppData().getScreenSize().x;
return sCurrentDefaultScreen;
public NotifyImageGenerator(final Context context) {
mContext = context;
}

public void addDefaultScreen() {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (mCurrentScreenSizeX != getAppData().getScreenSize().x) {
mCurrentDefaultScreen = null;
}
if (mCurrentDefaultScreen == null) {
mCurrentDefaultScreen = generateImage(mContext.getString(R.string.image_generator_press),
mContext.getString(R.string.main_activity_start_stream).toUpperCase(),
mContext.getString(R.string.image_generator_on_device));
mCurrentScreenSizeX = getAppData().getScreenSize().x;
}
if (mCurrentDefaultScreen != null) {
getAppData().getImageQueue().add(mCurrentDefaultScreen);
}
}
}, 500);
}

public static byte[] getClientNotifyImage(final Context context, final String reason) {
public byte[] getClientNotifyImage(final String reason) {
if (BusMessages.MESSAGE_ACTION_HTTP_RESTART.equals(reason))
return generateImage(context.getString(R.string.image_generator_settings_changed), "", context.getString(R.string.image_generator_go_to_new_address));
return generateImage(mContext.getString(R.string.image_generator_settings_changed),
"", mContext.getString(R.string.image_generator_go_to_new_address));

if (BusMessages.MESSAGE_ACTION_PIN_UPDATE.equals(reason))
return generateImage(context.getString(R.string.image_generator_settings_changed), "", context.getString(R.string.image_generator_reload_this_page));
return generateImage(mContext.getString(R.string.image_generator_settings_changed),
"", mContext.getString(R.string.image_generator_reload_this_page));
return null;
}


@Nullable
private static byte[] generateImage(final String text1, final String text2, final String text3) {
final Bitmap bitmap = Bitmap.createBitmap(getAppData().getScreenSize().x,
getAppData().getScreenSize().y,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import info.dvkr.screenstream.data.BusMessages;
import info.dvkr.screenstream.data.HttpServer;
import info.dvkr.screenstream.data.ImageGenerator;
import info.dvkr.screenstream.utils.NotifyImageGenerator;
import info.dvkr.screenstream.data.NotifyImageGenerator;
import info.dvkr.screenstream.view.MainActivity;

import static info.dvkr.screenstream.ScreenStreamApplication.getAppData;
Expand All @@ -40,6 +40,9 @@
public final class ForegroundService extends Service {
private static ForegroundService sServiceInstance;

private static final int NOTIFICATION_START_STREAMING = 10;
private static final int NOTIFICATION_STOP_STREAMING = 11;

private static final String EXTRA_SERVICE_MESSAGE = "info.dvkr.screenstream.extras.EXTRA_SERVICE_MESSAGE";
private static final String SERVICE_MESSAGE_PREPARE_STREAMING = "SERVICE_MESSAGE_PREPARE_STREAMING";

Expand All @@ -53,6 +56,7 @@ public final class ForegroundService extends Service {
private MediaProjection.Callback mProjectionCallback;
private HttpServer mHttpServer;
private ImageGenerator mImageGenerator;
private NotifyImageGenerator mNotifyImageGenerator;
private ForegroundServiceHandler mForegroundServiceTaskHandler;
private BroadcastReceiver mLocalNotificationReceiver;
private BroadcastReceiver mBroadcastReceiver;
Expand Down Expand Up @@ -98,7 +102,9 @@ public void onStop() {
};
mHttpServer = new HttpServer();
mImageGenerator = new ImageGenerator();
mImageGenerator.addDefaultScreen(getApplicationContext());
getAppData().getImageQueue().clear();
mNotifyImageGenerator = new NotifyImageGenerator(getApplicationContext());
mNotifyImageGenerator.addDefaultScreen();

// Starting thread Handler
final HandlerThread looperThread =
Expand Down Expand Up @@ -178,7 +184,9 @@ public void onReceive(Context context, Intent intent) {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (SERVICE_MESSAGE_PREPARE_STREAMING.equals(intent.getStringExtra(EXTRA_SERVICE_MESSAGE))) {
if (!isServicePrepared) startForeground(110, getNotificationStart());
if (!isServicePrepared) {
startForeground(NOTIFICATION_START_STREAMING, getNotificationStart());
}
isServicePrepared = true;
}
return START_NOT_STICKY;
Expand All @@ -205,13 +213,15 @@ public void onMessageEvent(BusMessages busMessage) {
serviceStopStreaming();
break;
case MESSAGE_ACTION_HTTP_RESTART:
mHttpServer.stop(NotifyImageGenerator.getClientNotifyImage(getApplicationContext(), MESSAGE_ACTION_HTTP_RESTART));
mImageGenerator.addDefaultScreen(getApplicationContext());
getAppData().getImageQueue().clear();
mHttpServer.stop(mNotifyImageGenerator.getClientNotifyImage(MESSAGE_ACTION_HTTP_RESTART));
mNotifyImageGenerator.addDefaultScreen();
mHttpServer.start();
break;
case MESSAGE_ACTION_PIN_UPDATE:
mHttpServer.stop(NotifyImageGenerator.getClientNotifyImage(getApplicationContext(), MESSAGE_ACTION_PIN_UPDATE));
mImageGenerator.addDefaultScreen(getApplicationContext());
getAppData().getImageQueue().clear();
mHttpServer.stop(mNotifyImageGenerator.getClientNotifyImage(MESSAGE_ACTION_PIN_UPDATE));
mNotifyImageGenerator.addDefaultScreen();
mHttpServer.start();
break;
default:
Expand All @@ -223,17 +233,18 @@ private void serviceStartStreaming() {
if (getAppData().isStreamRunning()) return;
stopForeground(true);
mForegroundServiceTaskHandler.obtainMessage(ForegroundServiceHandler.HANDLER_START_STREAMING).sendToTarget();
startForeground(120, getNotificationStop());
startForeground(NOTIFICATION_STOP_STREAMING, getNotificationStop());
if (mMediaProjection != null) mMediaProjection.registerCallback(mProjectionCallback, null);
}

private void serviceStopStreaming() {
if (!getAppData().isStreamRunning()) return;
stopForeground(true);
mForegroundServiceTaskHandler.obtainMessage(ForegroundServiceHandler.HANDLER_STOP_STREAMING).sendToTarget();
startForeground(110, getNotificationStart());
startForeground(NOTIFICATION_START_STREAMING, getNotificationStart());
if (mMediaProjection != null) mMediaProjection.unregisterCallback(mProjectionCallback);
mImageGenerator.addDefaultScreen(getApplicationContext());
getAppData().getImageQueue().clear();
mNotifyImageGenerator.addDefaultScreen();

if (getAppPreference().isEnablePin() && getAppPreference().isAutoChangePin()) {
getAppPreference().generateAndSaveNewPin();
Expand Down

0 comments on commit c6b6569

Please sign in to comment.