From 06c4a8cdd78077619bf43d6cccdcb199065ec1e0 Mon Sep 17 00:00:00 2001 From: n8fr8 Date: Thu, 7 Feb 2019 15:08:04 -0500 Subject: [PATCH 1/5] for #365 reduce camera resolution and remove one unneeded bitmap --- .../main/sensors/motion/MotionDetector.java | 31 ++++++----------- .../org/havenapp/main/ui/CameraFragment.java | 4 +-- .../motion => ui}/CameraViewHolder.java | 34 ++++++++++++++----- 3 files changed, 38 insertions(+), 31 deletions(-) rename src/main/java/org/havenapp/main/{sensors/motion => ui}/CameraViewHolder.java (92%) diff --git a/src/main/java/org/havenapp/main/sensors/motion/MotionDetector.java b/src/main/java/org/havenapp/main/sensors/motion/MotionDetector.java index e3daa135..04be1a3b 100644 --- a/src/main/java/org/havenapp/main/sensors/motion/MotionDetector.java +++ b/src/main/java/org/havenapp/main/sensors/motion/MotionDetector.java @@ -40,8 +40,6 @@ public class MotionDetector { private int motionSensitivity; // Output data - private boolean hasChanged; - private IMotionDetector detector; //private RenderScript renderScript; @@ -49,7 +47,7 @@ public class MotionDetector { private int detectColor = Color.YELLOW; public interface MotionListener { - public void onProcess(Bitmap oldBitmap, + public void onProcess( Bitmap newBitmap, Bitmap rawBitmap, boolean motionDetected); @@ -91,24 +89,18 @@ public void detect(byte[] rawOldPic, int[] newPicLuma = ImageCodec.N21toLuma(rawNewPic, width, height); if (rawOldPic != null) { - int[] oldPicLuma = ImageCodec.N21toLuma(rawOldPic, width, height); + detector.setThreshold(motionSensitivity); List changedPixels = - detector.detectMotion(oldPicLuma, newPicLuma, width, height); - hasChanged = false; - - int[] newPic = ImageCodec.lumaToGreyscale(newPicLuma, width, height); + detector.detectMotion(ImageCodec.N21toLuma(rawOldPic, width, height), newPicLuma, width, height); if (changedPixels != null) { - hasChanged = true; - - } + int[] newPic = ImageCodec.lumaToGreyscale(newPicLuma, width, height); + newPicLuma = null; - if (hasChanged) { - - Bitmap lastBitmap = ImageCodec.lumaToBitmapGreyscale(oldPicLuma, width, height); + System.gc(); for (int i = 0; i < newPic.length; i++) newPic[i] = Color.TRANSPARENT; @@ -118,6 +110,7 @@ public void detect(byte[] rawOldPic, } + Matrix mtx = new Matrix(); if (facingFront) { @@ -127,20 +120,19 @@ public void detect(byte[] rawOldPic, else mtx.postRotate(rotationDegrees); - Bitmap newBitmap = Bitmap.createBitmap(Bitmap.createBitmap(newPic, width, height, Bitmap.Config.ARGB_4444), 0, 0, width, height, mtx, true); + newPic = null; + Bitmap rawBitmap = convertImage(rawNewPic,width,height); - //Bitmap.createBitmap(Nv21Image.nv21ToBitmap(renderScript, rawNewPic, width, height),0,0,width,height,mtx,true); handler.post(() -> { for (MotionListener listener : listeners) { listener.onProcess( - lastBitmap, newBitmap, rawBitmap, - hasChanged); + true); } }); @@ -153,8 +145,7 @@ public void detect(byte[] rawOldPic, listener.onProcess( null, null, - null, - hasChanged); + false); } }); diff --git a/src/main/java/org/havenapp/main/ui/CameraFragment.java b/src/main/java/org/havenapp/main/ui/CameraFragment.java index 49ee4ecb..cbfa4446 100644 --- a/src/main/java/org/havenapp/main/ui/CameraFragment.java +++ b/src/main/java/org/havenapp/main/ui/CameraFragment.java @@ -18,11 +18,9 @@ import com.otaliastudios.cameraview.Audio; import com.otaliastudios.cameraview.CameraView; -import com.otaliastudios.cameraview.SizeSelector; import org.havenapp.main.PreferenceManager; import org.havenapp.main.R; -import org.havenapp.main.sensors.motion.CameraViewHolder; import androidx.fragment.app.Fragment; @@ -99,7 +97,7 @@ public void initCamera () if (cameraViewHolder == null) { cameraViewHolder = new CameraViewHolder(getActivity(), cameraView); - cameraViewHolder.addListener((oldBitmap, newBitmap, rawBitmap, motionDetected) -> { + cameraViewHolder.addListener((newBitmap, rawBitmap, motionDetected) -> { if (motionDetected) newImage.setImageBitmap(newBitmap); else diff --git a/src/main/java/org/havenapp/main/sensors/motion/CameraViewHolder.java b/src/main/java/org/havenapp/main/ui/CameraViewHolder.java similarity index 92% rename from src/main/java/org/havenapp/main/sensors/motion/CameraViewHolder.java rename to src/main/java/org/havenapp/main/ui/CameraViewHolder.java index fb87d1c5..eb7ac3ed 100644 --- a/src/main/java/org/havenapp/main/sensors/motion/CameraViewHolder.java +++ b/src/main/java/org/havenapp/main/ui/CameraViewHolder.java @@ -7,7 +7,7 @@ * Licensed under the MIT license. */ -package org.havenapp.main.sensors.motion; +package org.havenapp.main.ui; import android.app.Activity; import android.content.ComponentName; @@ -30,10 +30,13 @@ import com.otaliastudios.cameraview.Frame; import com.otaliastudios.cameraview.FrameProcessor; import com.otaliastudios.cameraview.Size; +import com.otaliastudios.cameraview.SizeSelector; import org.havenapp.main.PreferenceManager; import org.havenapp.main.Utils; import org.havenapp.main.model.EventTrigger; +import org.havenapp.main.sensors.motion.LuminanceMotionDetector; +import org.havenapp.main.sensors.motion.MotionDetector; import org.havenapp.main.service.MonitorService; import org.jcodec.api.android.AndroidSequenceEncoder; @@ -52,8 +55,6 @@ import androidx.annotation.NonNull; -import io.github.silvaren.easyrs.tools.Nv21Image; - public class CameraViewHolder { /** @@ -61,7 +62,8 @@ public class CameraViewHolder { */ private PreferenceManager prefs; - private final static int PREVIEW_INTERVAL = 200; + private final static int DETECTION_INTERVAL_MS = 300; + private final static int MAX_CAMERA_WIDTH = 800; private List listeners = new ArrayList<>(); @@ -135,10 +137,10 @@ public CameraViewHolder(Activity context, CameraView cameraView) { updateHandler, motionSensitivity); - task.addListener((sourceImage, detectedImage, rawBitmap, motionDetected) -> { + task.addListener((detectedImage, rawBitmap, motionDetected) -> { for (MotionDetector.MotionListener listener : listeners) - listener.onProcess(sourceImage,detectedImage,rawBitmap,motionDetected); + listener.onProcess(detectedImage,rawBitmap,motionDetected); if (motionDetected) { @@ -210,6 +212,22 @@ public void startCamera() { updateCamera(); + cameraView.setPlaySounds(false); + cameraView.setPreviewSize(new SizeSelector() { + @NonNull + @Override + public List select(@NonNull List source) { + ArrayList result = new ArrayList<>(); + + for (Size size : source) + { + if (size.getWidth() Date: Fri, 8 Feb 2019 09:12:08 -0500 Subject: [PATCH 2/5] more work on #365 - simplify display of motion detection - we are creating too many in memory bitmaps just for fancy UI that isn't that usable - this now displays a simple "motion detected" string instead of the change detection overlay --- .../main/sensors/motion/MotionDetector.java | 45 +++--- .../org/havenapp/main/ui/CameraFragment.java | 55 +++++-- .../havenapp/main/ui/CameraViewHolder.java | 135 ++++++++++-------- src/main/res/layout/camera_fragment.xml | 2 +- src/main/res/values/strings.xml | 1 + 5 files changed, 136 insertions(+), 102 deletions(-) diff --git a/src/main/java/org/havenapp/main/sensors/motion/MotionDetector.java b/src/main/java/org/havenapp/main/sensors/motion/MotionDetector.java index 04be1a3b..8c988d15 100644 --- a/src/main/java/org/havenapp/main/sensors/motion/MotionDetector.java +++ b/src/main/java/org/havenapp/main/sensors/motion/MotionDetector.java @@ -36,7 +36,6 @@ public class MotionDetector { // Input data private List listeners = new ArrayList<>(); - private Handler handler; private int motionSensitivity; // Output data @@ -58,14 +57,13 @@ public void addListener(MotionListener listener) { } public MotionDetector( - - Handler updateHandler, int motionSensitivity) { // this.renderScript = renderScript; - this.handler = updateHandler; this.motionSensitivity = motionSensitivity; detector = new LuminanceMotionDetector(); + + } public void setDetectColor (int detectColor) @@ -87,8 +85,8 @@ public void detect(byte[] rawOldPic, boolean facingFront) { int[] newPicLuma = ImageCodec.N21toLuma(rawNewPic, width, height); - if (rawOldPic != null) { + if (rawOldPic != null) { detector.setThreshold(motionSensitivity); List changedPixels = @@ -96,10 +94,10 @@ public void detect(byte[] rawOldPic, if (changedPixels != null) { + /* int[] newPic = ImageCodec.lumaToGreyscale(newPicLuma, width, height); newPicLuma = null; - System.gc(); for (int i = 0; i < newPic.length; i++) @@ -109,8 +107,6 @@ public void detect(byte[] rawOldPic, newPic[changedPixel] = detectColor; } - - Matrix mtx = new Matrix(); if (facingFront) { @@ -124,31 +120,26 @@ public void detect(byte[] rawOldPic, = Bitmap.createBitmap(Bitmap.createBitmap(newPic, width, height, Bitmap.Config.ARGB_4444), 0, 0, width, height, mtx, true); newPic = null; + */ Bitmap rawBitmap = convertImage(rawNewPic,width,height); - handler.post(() -> { - for (MotionListener listener : listeners) { - listener.onProcess( - newBitmap, - rawBitmap, - true); - } - - }); + for (MotionListener listener : listeners) { + listener.onProcess( + null, + rawBitmap, + true); + } } else { - //nothing changed - handler.post(() -> { - for (MotionListener listener : listeners) { - listener.onProcess( - null, - null, - false); - } - - }); + for (MotionListener listener : listeners) { + listener.onProcess( + null, + null, + false); + } + } } diff --git a/src/main/java/org/havenapp/main/ui/CameraFragment.java b/src/main/java/org/havenapp/main/ui/CameraFragment.java index cbfa4446..b2e94e3b 100644 --- a/src/main/java/org/havenapp/main/ui/CameraFragment.java +++ b/src/main/java/org/havenapp/main/ui/CameraFragment.java @@ -8,8 +8,11 @@ */ package org.havenapp.main.ui; +import android.graphics.Bitmap; import android.hardware.SensorEvent; import android.os.Bundle; +import android.os.Handler; +import android.os.Message; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -30,6 +33,41 @@ public final class CameraFragment extends Fragment { private ImageView newImage; private PreferenceManager prefs; private TextView txtCameraStatus; + private Bitmap lastBitmap; + + /** + * Handler used to update back the UI after motion detection + */ + private final Handler handler = new Handler() + { + @Override + public void handleMessage(Message msg) { + super.handleMessage(msg); + + if (!isDetached()) { + if (txtCameraStatus != null) { + + if (msg.what == 0) { + // newImage.setImageResource(R.drawable.blankimage); + txtCameraStatus.setText(""); + + } else if (msg.what == 1) { + // newImage.setImageBitmap(lastBitmap); + txtCameraStatus.setText(getString(R.string.motion_detected)); + + } + + + /** + if (cameraViewHolder.doingVideoProcessing()) { + txtCameraStatus.setText("Recording..."); + } else { + txtCameraStatus.setText(""); + }**/ + } + } + } + }; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, @@ -98,18 +136,11 @@ public void initCamera () cameraViewHolder = new CameraViewHolder(getActivity(), cameraView); cameraViewHolder.addListener((newBitmap, rawBitmap, motionDetected) -> { - if (motionDetected) - newImage.setImageBitmap(newBitmap); - else - newImage.setImageResource(R.drawable.blankimage); - - if (txtCameraStatus != null) { - if (cameraViewHolder.doingVideoProcessing()) { - txtCameraStatus.setText("Recording..."); - } else { - txtCameraStatus.setText(""); - } - } + + lastBitmap = rawBitmap; + + handler.sendEmptyMessage(motionDetected?1:0); + }); } diff --git a/src/main/java/org/havenapp/main/ui/CameraViewHolder.java b/src/main/java/org/havenapp/main/ui/CameraViewHolder.java index eb7ac3ed..ee277936 100644 --- a/src/main/java/org/havenapp/main/ui/CameraViewHolder.java +++ b/src/main/java/org/havenapp/main/ui/CameraViewHolder.java @@ -134,7 +134,6 @@ public CameraViewHolder(Activity context, CameraView cameraView) { prefs = new PreferenceManager(context); task = new MotionDetector( - updateHandler, motionSensitivity); task.addListener((detectedImage, rawBitmap, motionDetected) -> { @@ -142,51 +141,53 @@ public CameraViewHolder(Activity context, CameraView cameraView) { for (MotionDetector.MotionListener listener : listeners) listener.onProcess(detectedImage,rawBitmap,motionDetected); - if (motionDetected) { + if (motionDetected) + mEncodeVideoThreadPool.execute(() -> saveDetectedImage(rawBitmap)); - if (serviceMessenger != null) { - Message message = new Message(); - message.what = EventTrigger.CAMERA; + }); + /* + * We bind to the alert service + */ + this.context.bindService(new Intent(context, + MonitorService.class), mConnection, Context.BIND_ABOVE_CLIENT); + } - try { + private void saveDetectedImage (Bitmap rawBitmap) + { + if (serviceMessenger != null) { + Message message = new Message(); + message.what = EventTrigger.CAMERA; - File fileImageDir = new File(Environment.getExternalStorageDirectory(), prefs.getDefaultMediaStoragePath()); - fileImageDir.mkdirs(); + try { - String ts = new SimpleDateFormat(Utils.DATE_TIME_PATTERN, - Locale.getDefault()).format(new Date()); + File fileImageDir = new File(Environment.getExternalStorageDirectory(), prefs.getDefaultMediaStoragePath()); + fileImageDir.mkdirs(); - File fileImage = new File(fileImageDir, ts.concat(".detected.original.jpg")); - FileOutputStream stream = new FileOutputStream(fileImage); - rawBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream); + String ts = new SimpleDateFormat(Utils.DATE_TIME_PATTERN, + Locale.getDefault()).format(new Date()); - stream.flush(); - stream.close(); - message.getData().putString("path", fileImage.getAbsolutePath()); + File fileImage = new File(fileImageDir, ts.concat(".detected.original.jpg")); + FileOutputStream stream = new FileOutputStream(fileImage); + rawBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream); - //store the still match frame, even if doing video - serviceMessenger.send(message); + stream.flush(); + stream.close(); + message.getData().putString("path", fileImage.getAbsolutePath()); - if (prefs.getVideoMonitoringActive() && (!doingVideoProcessing)) { - recordVideo(); + //store the still match frame, even if doing video + serviceMessenger.send(message); - } + if (prefs.getVideoMonitoringActive() && (!doingVideoProcessing)) { + recordVideo(); - } catch (Exception e) { - // Cannot happen - Log.e("CameraViewHolder", "error creating image", e); - } } - } - - }); - /* - * We bind to the alert service - */ - this.context.bindService(new Intent(context, - MonitorService.class), mConnection, Context.BIND_ABOVE_CLIENT); - } + } catch (Exception e) { + // Cannot happen + Log.e("CameraViewHolder", "error creating image", e); + } + } + } public void setMotionSensitivity (int motionSensitivity ) @@ -242,16 +243,10 @@ public void process(@NonNull Frame frame) { if (frame.getData() != null && frame.getSize() != null) { - byte[] data = frame.getData(); - Size size = frame.getSize(); - int width = size.getWidth(); - int height = size.getHeight(); - int rot = getCorrectCameraOrientation(cameraView.getFacing(),frame.getRotation()); - if (!doingVideoProcessing) { - mDecodeThreadPool.execute(() -> processNewFrame(data, width, height, rot)); + mDecodeThreadPool.execute(() -> processNewFrame(frame)); } else { - mEncodeVideoThreadPool.execute(() -> recordNewFrame(data, width, height, rot)); + mEncodeVideoThreadPool.execute(() -> recordNewFrame(frame)); } } } @@ -300,25 +295,32 @@ public void updateCamera () private Matrix mtxVideoRotate; - private void recordNewFrame (byte[] data, int width, int height, int rotationDegrees) + private void recordNewFrame (Frame frame) { - Bitmap bitmap = MotionDetector.convertImage(data, width, height); - //Nv21Image.nv21ToBitmap(renderScript, data, width, height); + byte[] data = frame.getData(); + Size size = frame.getSize(); - bitmap = Bitmap.createBitmap(bitmap,0,0,width,height,mtxVideoRotate,true); + if (data != null && size != null) { + int width = size.getWidth(); + int height = size.getHeight(); + int rotationDegrees = getCorrectCameraOrientation(cameraView.getFacing(), frame.getRotation()); - try { - if (encoder != null) - encoder.encodeImage(bitmap); + Bitmap bitmap = MotionDetector.convertImage(data, width, height); - bitmap.recycle(); + bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, mtxVideoRotate, true); - } catch (Exception e) { - e.printStackTrace(); - } + try { + if (encoder != null) + encoder.encodeImage(bitmap); + + bitmap.recycle(); + } catch (Exception e) { + e.printStackTrace(); + } + } } @@ -343,18 +345,27 @@ private void finishVideoEncoding () } - private synchronized void processNewFrame (byte[] data, int width, int height, int rotationDegrees) + private void processNewFrame (Frame frame) { - task.detect( - lastPic, - data, - width, - height, - rotationDegrees, - cameraView.getFacing()==Facing.FRONT); - lastPic = data; + byte[] data = frame.getData(); + Size size = frame.getSize(); + if (data != null && size != null) { + int width = size.getWidth(); + int height = size.getHeight(); + int rotationDegrees = getCorrectCameraOrientation(cameraView.getFacing(), frame.getRotation()); + + task.detect( + lastPic, + data, + width, + height, + rotationDegrees, + cameraView.getFacing() == Facing.FRONT); + + lastPic = data; + } } diff --git a/src/main/res/layout/camera_fragment.xml b/src/main/res/layout/camera_fragment.xml index 12a67110..5286218e 100644 --- a/src/main/res/layout/camera_fragment.xml +++ b/src/main/res/layout/camera_fragment.xml @@ -56,7 +56,7 @@ android:layout_height="wrap_content" android:gravity="center" android:text="" - android:textColor="@color/DarkRed" + android:textColor="@color/Yellow" android:textSize="28sp" android:textStyle="bold" android:layout_gravity="center_horizontal|center_vertical" diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index c66f1ba7..1f3a3ef0 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -165,5 +165,6 @@ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_/ + MOTION DETECTED From 6fb03a474d4f82a5648a36487ddc210755827aac Mon Sep 17 00:00:00 2001 From: n8fr8 Date: Fri, 8 Feb 2019 17:43:28 -0500 Subject: [PATCH 3/5] improvements to visual feedback of sensor event - this is a replacement for the removal of the bitmap overall, which was causing OOMs and ANRs - this is much more functional, useful, though not quite as sexy :( --- .../havenapp/main/sensors/BumpMonitor.java | 1 + .../main/sensors/MicrophoneMonitor.java | 9 +++ .../havenapp/main/service/MonitorService.java | 14 ++++- .../org/havenapp/main/ui/CameraFragment.java | 61 +++++++++++++------ src/main/res/layout/camera_fragment.xml | 22 +------ src/main/res/values/strings.xml | 7 +++ 6 files changed, 75 insertions(+), 39 deletions(-) diff --git a/src/main/java/org/havenapp/main/sensors/BumpMonitor.java b/src/main/java/org/havenapp/main/sensors/BumpMonitor.java index 991c2499..0d321e51 100644 --- a/src/main/java/org/havenapp/main/sensors/BumpMonitor.java +++ b/src/main/java/org/havenapp/main/sensors/BumpMonitor.java @@ -83,6 +83,7 @@ public void onTrigger(TriggerEvent event) { */ Message message = new Message(); message.what = EventTrigger.BUMP; + message.getData().putString("path","BUMPED!"); try { if (serviceMessenger != null) { diff --git a/src/main/java/org/havenapp/main/sensors/MicrophoneMonitor.java b/src/main/java/org/havenapp/main/sensors/MicrophoneMonitor.java index 48538b54..53d74d70 100644 --- a/src/main/java/org/havenapp/main/sensors/MicrophoneMonitor.java +++ b/src/main/java/org/havenapp/main/sensors/MicrophoneMonitor.java @@ -134,6 +134,15 @@ public void onSignalReceived(short[] signal) { if (averageDB > mNoiseThreshold) { if (!MicrophoneTaskFactory.isRecording()) { + Message message = new Message(); + message.what = EventTrigger.MICROPHONE; + try { + if (serviceMessenger != null) + serviceMessenger.send(message); + } catch (RemoteException e) { + // Cannot happen + } + try { AudioRecorderTask audioRecorderTask = MicrophoneTaskFactory.makeRecorder(context); audioRecorderTask.setAudioRecorderListener(new AudioRecorderTask.AudioRecorderListener() { diff --git a/src/main/java/org/havenapp/main/service/MonitorService.java b/src/main/java/org/havenapp/main/service/MonitorService.java index abe31765..13d7eff4 100644 --- a/src/main/java/org/havenapp/main/service/MonitorService.java +++ b/src/main/java/org/havenapp/main/service/MonitorService.java @@ -15,6 +15,7 @@ import android.app.Service; import android.content.Intent; import android.graphics.Color; +import android.net.Uri; import android.os.Build; import android.os.Handler; import android.os.IBinder; @@ -26,6 +27,7 @@ import androidx.annotation.RequiresApi; import androidx.core.app.NotificationCompat; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.havenapp.main.HavenApp; import org.havenapp.main.MonitorActivity; @@ -292,11 +294,19 @@ private void stopSensors () /** * Sends an alert according to type of connectivity */ - public synchronized void alert(int alertType, String path) { + public void alert(int alertType, String value) { Date now = new Date(); boolean doNotification = false; + //for the UI visual + Intent iEvent = new Intent("event"); + iEvent.putExtra("type",alertType); + LocalBroadcastManager.getInstance(this).sendBroadcast(iEvent); + + if (TextUtils.isEmpty(value)) + return; + if (mLastEvent == null) { mLastEvent = new Event(); long eventId = HavenEventDB.getDatabase(getApplicationContext()) @@ -323,7 +333,7 @@ else if (mPrefs.getNotificationTimeMs() > 0 && mLastNotification != null) EventTrigger eventTrigger = new EventTrigger(); eventTrigger.setType(alertType); - eventTrigger.setPath(path); + eventTrigger.setPath(value); mLastEvent.addEventTrigger(eventTrigger); diff --git a/src/main/java/org/havenapp/main/ui/CameraFragment.java b/src/main/java/org/havenapp/main/ui/CameraFragment.java index b2e94e3b..5b9ead2e 100644 --- a/src/main/java/org/havenapp/main/ui/CameraFragment.java +++ b/src/main/java/org/havenapp/main/ui/CameraFragment.java @@ -8,6 +8,10 @@ */ package org.havenapp.main.ui; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.graphics.Bitmap; import android.hardware.SensorEvent; import android.os.Bundle; @@ -24,8 +28,10 @@ import org.havenapp.main.PreferenceManager; import org.havenapp.main.R; +import org.havenapp.main.model.EventTrigger; import androidx.fragment.app.Fragment; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; public final class CameraFragment extends Fragment { @@ -33,7 +39,6 @@ public final class CameraFragment extends Fragment { private ImageView newImage; private PreferenceManager prefs; private TextView txtCameraStatus; - private Bitmap lastBitmap; /** * Handler used to update back the UI after motion detection @@ -47,28 +52,45 @@ public void handleMessage(Message msg) { if (!isDetached()) { if (txtCameraStatus != null) { - if (msg.what == 0) { - // newImage.setImageResource(R.drawable.blankimage); - txtCameraStatus.setText(""); - - } else if (msg.what == 1) { - // newImage.setImageBitmap(lastBitmap); - txtCameraStatus.setText(getString(R.string.motion_detected)); - + if (msg.what == EventTrigger.CAMERA) { + if (cameraViewHolder.doingVideoProcessing()) { + txtCameraStatus.setText(getString(R.string.motion_detected) + + "\n" + getString(R.string.status_recording_video)); + } else { + txtCameraStatus.setText(getString(R.string.motion_detected)); + } + } + else if (msg.what == EventTrigger.POWER) { + txtCameraStatus.setText(getString(R.string.power_detected)); + } + else if (msg.what == EventTrigger.MICROPHONE) { + txtCameraStatus.setText(getString(R.string.sound_detected)); + } + else if (msg.what == EventTrigger.ACCELEROMETER || msg.what == EventTrigger.BUMP) { + txtCameraStatus.setText(getString(R.string.device_move_detected)); + } + else if (msg.what == EventTrigger.LIGHT) { + txtCameraStatus.setText(getString(R.string.status_light)); } - /** - if (cameraViewHolder.doingVideoProcessing()) { - txtCameraStatus.setText("Recording..."); - } else { - txtCameraStatus.setText(""); - }**/ } } } }; + BroadcastReceiver receiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + + int eventType = intent.getIntExtra("type",-1); + + //String path = intent.getData().getPath(); + + handler.sendEmptyMessage(eventType); + } + }; + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -96,6 +118,7 @@ public void onCreate(Bundle savedInstanceState) { @Override public void onPause() { super.onPause(); + LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(receiver); } @Override @@ -104,6 +127,10 @@ public void onResume() { initCamera(); cameraViewHolder.setMotionSensitivity(prefs.getCameraSensitivity()); + + IntentFilter filter = new IntentFilter(); + filter.addAction("event"); + LocalBroadcastManager.getInstance(getContext()).registerReceiver(receiver,filter ); } public void updateCamera () @@ -137,9 +164,7 @@ public void initCamera () cameraViewHolder.addListener((newBitmap, rawBitmap, motionDetected) -> { - lastBitmap = rawBitmap; - - handler.sendEmptyMessage(motionDetected?1:0); + handler.sendEmptyMessage(motionDetected?EventTrigger.CAMERA:-1); }); diff --git a/src/main/res/layout/camera_fragment.xml b/src/main/res/layout/camera_fragment.xml index 5286218e..ae9a742c 100644 --- a/src/main/res/layout/camera_fragment.xml +++ b/src/main/res/layout/camera_fragment.xml @@ -5,22 +5,6 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:foreground="@color/translucentOverlay25"> - - diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 1f3a3ef0..1ac40f0b 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -165,6 +165,13 @@ 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_/ + MOTION DETECTED + SOUND DETECTED + DEVICE MOVEMENT DETECTED + POWER CHANGE DETECTED + + Recording... + LIGHT DETECTED From c9ba5e545df94c163092edfaef9b1d6bd46be9bb Mon Sep 17 00:00:00 2001 From: n8fr8 Date: Sun, 10 Feb 2019 09:58:37 -0500 Subject: [PATCH 4/5] ensure strings aren't requested when there is no context --- .../org/havenapp/main/ui/CameraFragment.java | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/havenapp/main/ui/CameraFragment.java b/src/main/java/org/havenapp/main/ui/CameraFragment.java index 5b9ead2e..0d2fb6f8 100644 --- a/src/main/java/org/havenapp/main/ui/CameraFragment.java +++ b/src/main/java/org/havenapp/main/ui/CameraFragment.java @@ -40,6 +40,8 @@ public final class CameraFragment extends Fragment { private PreferenceManager prefs; private TextView txtCameraStatus; + private boolean isAttached = false; + /** * Handler used to update back the UI after motion detection */ @@ -49,7 +51,7 @@ public final class CameraFragment extends Fragment { public void handleMessage(Message msg) { super.handleMessage(msg); - if (!isDetached()) { + if (isAttached) { if (txtCameraStatus != null) { if (msg.what == EventTrigger.CAMERA) { @@ -91,6 +93,22 @@ public void onReceive(Context context, Intent intent) { } }; + @Override + public void onDetach() { + super.onDetach(); + isAttached = false; + LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(receiver); + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + isAttached = true; + IntentFilter filter = new IntentFilter(); + filter.addAction("event"); + LocalBroadcastManager.getInstance(getContext()).registerReceiver(receiver,filter ); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -118,7 +136,6 @@ public void onCreate(Bundle savedInstanceState) { @Override public void onPause() { super.onPause(); - LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(receiver); } @Override @@ -128,9 +145,7 @@ public void onResume() { cameraViewHolder.setMotionSensitivity(prefs.getCameraSensitivity()); - IntentFilter filter = new IntentFilter(); - filter.addAction("event"); - LocalBroadcastManager.getInstance(getContext()).registerReceiver(receiver,filter ); + } public void updateCamera () From bf09efa4a0317314dee89258b1dc3dbbaec9db0a Mon Sep 17 00:00:00 2001 From: n8fr8 Date: Sun, 10 Feb 2019 10:10:00 -0500 Subject: [PATCH 5/5] code cleanup; changed detection interval to 200ms from 300ms --- .../main/sensors/motion/MotionDetector.java | 19 +++--------------- .../havenapp/main/ui/CameraViewHolder.java | 20 +++++++------------ 2 files changed, 10 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/havenapp/main/sensors/motion/MotionDetector.java b/src/main/java/org/havenapp/main/sensors/motion/MotionDetector.java index 8c988d15..e32f47f2 100644 --- a/src/main/java/org/havenapp/main/sensors/motion/MotionDetector.java +++ b/src/main/java/org/havenapp/main/sensors/motion/MotionDetector.java @@ -41,12 +41,8 @@ public class MotionDetector { private IMotionDetector detector; - //private RenderScript renderScript; - - private int detectColor = Color.YELLOW; - public interface MotionListener { - public void onProcess( + void onProcess( Bitmap newBitmap, Bitmap rawBitmap, boolean motionDetected); @@ -58,17 +54,11 @@ public void addListener(MotionListener listener) { public MotionDetector( int motionSensitivity) { - // this.renderScript = renderScript; this.motionSensitivity = motionSensitivity; detector = new LuminanceMotionDetector(); + detector.setThreshold(motionSensitivity); - - } - - public void setDetectColor (int detectColor) - { - this.detectColor = detectColor; } public void setMotionSensitivity (int motionSensitivity) @@ -80,15 +70,12 @@ public void setMotionSensitivity (int motionSensitivity) public void detect(byte[] rawOldPic, byte[] rawNewPic, int width, - int height, - int rotationDegrees, - boolean facingFront) { + int height) { int[] newPicLuma = ImageCodec.N21toLuma(rawNewPic, width, height); if (rawOldPic != null) { - detector.setThreshold(motionSensitivity); List changedPixels = detector.detectMotion(ImageCodec.N21toLuma(rawOldPic, width, height), newPicLuma, width, height); diff --git a/src/main/java/org/havenapp/main/ui/CameraViewHolder.java b/src/main/java/org/havenapp/main/ui/CameraViewHolder.java index ee277936..1f2adcf6 100644 --- a/src/main/java/org/havenapp/main/ui/CameraViewHolder.java +++ b/src/main/java/org/havenapp/main/ui/CameraViewHolder.java @@ -62,7 +62,7 @@ public class CameraViewHolder { */ private PreferenceManager prefs; - private final static int DETECTION_INTERVAL_MS = 300; + private final static int DETECTION_INTERVAL_MS = 200; private final static int MAX_CAMERA_WIDTH = 800; private List listeners = new ArrayList<>(); @@ -102,7 +102,7 @@ public class CameraViewHolder { private Messenger serviceMessenger = null; //private Camera camera; private Activity context; - private MotionDetector task; + private MotionDetector motionDetector; AndroidSequenceEncoder encoder; private File videoFile; @@ -133,10 +133,10 @@ public CameraViewHolder(Activity context, CameraView cameraView) { prefs = new PreferenceManager(context); - task = new MotionDetector( + motionDetector = new MotionDetector( motionSensitivity); - task.addListener((detectedImage, rawBitmap, motionDetected) -> { + motionDetector.addListener((detectedImage, rawBitmap, motionDetected) -> { for (MotionDetector.MotionListener listener : listeners) listener.onProcess(detectedImage,rawBitmap,motionDetected); @@ -194,7 +194,7 @@ public void setMotionSensitivity (int { this. motionSensitivity = motionSensitivity; - task.setMotionSensitivity(motionSensitivity); + motionDetector.setMotionSensitivity(motionSensitivity); } public void addListener(MotionDetector.MotionListener listener) { @@ -304,10 +304,7 @@ private void recordNewFrame (Frame frame) if (data != null && size != null) { int width = size.getWidth(); int height = size.getHeight(); - int rotationDegrees = getCorrectCameraOrientation(cameraView.getFacing(), frame.getRotation()); - Bitmap bitmap = MotionDetector.convertImage(data, width, height); - bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, mtxVideoRotate, true); try { @@ -354,15 +351,12 @@ private void processNewFrame (Frame frame) if (data != null && size != null) { int width = size.getWidth(); int height = size.getHeight(); - int rotationDegrees = getCorrectCameraOrientation(cameraView.getFacing(), frame.getRotation()); - task.detect( + motionDetector.detect( lastPic, data, width, - height, - rotationDegrees, - cameraView.getFacing() == Facing.FRONT); + height); lastPic = data; }