diff --git a/Neues Textdokument.txt b/Neues Textdokument.txt deleted file mode 100644 index e69de29..0000000 diff --git a/app/build.gradle b/app/build.gradle index 1e4e000..10ac6d2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -40,4 +40,21 @@ dependencies { testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' + + + // OpenCV (from: https://github.com/QuickBirdEng/opencv-android) + def opencv_version = "4.5.3.0" + implementation "com.quickbirdstudios:opencv:${opencv_version}" + + implementation "androidx.lifecycle:lifecycle-extensions:2.0.0" + + + // Required for CameraX + def camerax_version = "1.2.2" + implementation "androidx.camera:camera-core:${camerax_version}" + implementation "androidx.camera:camera-camera2:${camerax_version}" + implementation "androidx.camera:camera-lifecycle:${camerax_version}" + implementation "androidx.camera:camera-video:${camerax_version}" + implementation "androidx.camera:camera-view:${camerax_version}" + implementation "androidx.camera:camera-extensions:${camerax_version}" } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 339f7bf..45d2346 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,11 +2,13 @@ + + + + - - + android:exported="true"> + \ No newline at end of file diff --git a/app/src/main/java/com/example/ueberwachungssystem/Detection/AudioRecorder.java b/app/src/main/java/com/example/ueberwachungssystem/Detection/AudioRecorder.java new file mode 100644 index 0000000..aa16846 --- /dev/null +++ b/app/src/main/java/com/example/ueberwachungssystem/Detection/AudioRecorder.java @@ -0,0 +1,74 @@ +package com.example.ueberwachungssystem.Detection; + +import android.content.Context; +import android.media.MediaPlayer; +import android.media.MediaRecorder; +import android.widget.Toast; + +import java.io.File; +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class AudioRecorder { + private final Context context; + private MediaRecorder mediaRecorder = null; + private boolean isRecording = false; + private File outputDir; // Default: in app files directory + + + public AudioRecorder (Context context) { + this.context = context; + this.outputDir = context.getFilesDir(); + } + + public void startRecording() { + // Handle logic + if (outputDir == null) + return; + if (isRecording) + return; + isRecording = true; + + // Setup Audio Recorder for output Format: 3GP + mediaRecorder = new MediaRecorder(); + mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); + mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); + mediaRecorder.setOutputFile(outputDir + "/" + generateFileName() + ".3gp"); + mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); + try { + mediaRecorder.prepare(); + } catch (IOException e) { + e.printStackTrace(); + } + mediaRecorder.start(); + } + + public void stopRecording() { + if (mediaRecorder != null) { + mediaRecorder.stop(); + mediaRecorder.reset(); + mediaRecorder.release(); + mediaRecorder = null; + isRecording = false; + Toast.makeText(context, "audio recording saved", Toast.LENGTH_SHORT).show(); + } + } + + public boolean isRecording(){ + return isRecording; + } + + public void setOutputDir(File outputDir) { + this.outputDir = outputDir; + } + + private String generateFileName(){ + // Get the current timestamp + LocalDateTime currentTime = LocalDateTime.now(); + // Define the format for the timestamp + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"); + // Return the timestamp as a string + return currentTime.format(formatter); + } +} diff --git a/app/src/main/java/com/example/ueberwachungssystem/Detection/DetectionReport.java b/app/src/main/java/com/example/ueberwachungssystem/Detection/DetectionReport.java new file mode 100644 index 0000000..96f9dbf --- /dev/null +++ b/app/src/main/java/com/example/ueberwachungssystem/Detection/DetectionReport.java @@ -0,0 +1,38 @@ +package com.example.ueberwachungssystem.Detection; + +import android.util.Log; + +import java.util.Calendar; + +/** Detection Report Class */ +public class DetectionReport { + public String timeStamp; + public String detectionType; + public float detectedValue; + public boolean detectionState; + + public DetectionReport(boolean detectionState, String detectionType, float detectedAmplitude) { + this.timeStamp = String.valueOf(Calendar.getInstance().getTime()); + this.detectionType = detectionType; + this.detectedValue = detectedAmplitude; + this.detectionState = detectionState; + + //this.detectorID = detectorID; + } + + + /** Get Detection Report in String format */ + public String toString() { + String state = "State: " + "[" + this.detectionState + "]"; + String time = "Time: " + "[" + this.timeStamp + "]"; + String type = "Type: " + "[" + this.detectionType + "]"; + String value = "Value: " + "[" + this.detectedValue + "]"; + + return String.join("\t", state, time, type, value); + } + + /** Debug Report */ + public void log(String tag) { + Log.d(tag, this.toString()); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/ueberwachungssystem/Detection/Detector.java b/app/src/main/java/com/example/ueberwachungssystem/Detection/Detector.java new file mode 100644 index 0000000..826878b --- /dev/null +++ b/app/src/main/java/com/example/ueberwachungssystem/Detection/Detector.java @@ -0,0 +1,76 @@ +package com.example.ueberwachungssystem.Detection; + +import android.os.CountDownTimer; + +import androidx.annotation.NonNull; +import androidx.camera.core.ExperimentalGetImage; + + +abstract public class Detector { + private OnDetectionListener listener; + private boolean isDetecting = false; + private boolean extendViolation = false; + + // Countdown parameters + private final int COUNTDOWN_TIME = 10000; // milliseconds + private final int COUNTDOWN_POLLING_TIME = 100; // milliseconds + + /** Constructor - takes context of current activity */ + public Detector() {} + + + /** On Detection Listener - runs when violation is reported */ + public interface OnDetectionListener { + void onDetection(@NonNull DetectionReport detectionReport); + } + public void setOnDetectionListener(@NonNull OnDetectionListener listener) { + this.listener = listener; + } + + /** Triggers onDetectionListener - call this to trigger violation/alarm */ + public void reportViolation(String detectionType, float amplitude) { + if (listener != null) { + if (!isDetecting) { + isDetecting = true; + DetectionReport detectionReport = new DetectionReport(true, detectionType, amplitude); + listener.onDetection(detectionReport); + startDetectionTimer(detectionType, amplitude); + } else { + extendViolation = true; + } + } else { + isDetecting = false; + extendViolation = false; + } + } + + private void startDetectionTimer(String detectionType, float amplitude) { + isDetecting = true; + new CountDownTimer((long) COUNTDOWN_TIME, COUNTDOWN_POLLING_TIME) { + @Override + public void onTick(long millisUntilFinished) { + if (extendViolation) { + extendViolation = false; + startDetectionTimer(detectionType, amplitude); + this.cancel(); + } + } + @Override + public void onFinish() { + isDetecting = false; + DetectionReport detectionReport = new DetectionReport(false, detectionType, amplitude); + listener.onDetection(detectionReport); + } + }.start(); + } + + public void extendViolation(){ + this.extendViolation = true; + } + + /** Starts Detection (abstract method: needs to be overridden in child class) */ + public abstract void startDetection(); + + /** Stops Detection (abstract method: needs to be overridden in child class) */ + public abstract void stopDetection(); +} \ No newline at end of file diff --git a/app/src/main/java/com/example/ueberwachungssystem/Detection/DetectorService.java b/app/src/main/java/com/example/ueberwachungssystem/Detection/DetectorService.java new file mode 100644 index 0000000..af2d440 --- /dev/null +++ b/app/src/main/java/com/example/ueberwachungssystem/Detection/DetectorService.java @@ -0,0 +1,160 @@ +package com.example.ueberwachungssystem.Detection; + +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.camera.core.ExperimentalGetImage; +import androidx.lifecycle.LifecycleService; + +import java.io.File; + +@ExperimentalGetImage +public class DetectorService extends LifecycleService { + public ServiceBinder serviceBinder = new ServiceBinder(); + private DetectorService.OnDetectionListener listener; + private boolean isServiceRunning = false; + + VideoDetector videoDetector = null; + AudioRecorder audioRecorder = null; + + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + if (isServiceRunning) + return START_NOT_STICKY; + + + // Setup Service classes: + videoDetector = new VideoDetector(this); + videoDetector.setOnDetectionListener(new Detector.OnDetectionListener() { + @Override + public void onDetection(@NonNull DetectionReport detectionReport) { + passToServiceListener(detectionReport); + } + }); + + audioRecorder = new AudioRecorder(this); + + + + isServiceRunning = true; + return super.onStartCommand(intent, flags, startId); + } + + @Override + public void onDestroy() { + super.onDestroy(); + isServiceRunning = false; + } + + /** Service methods */ + public class ServiceBinder extends Binder { + public DetectorService getBoundService() { + // Return an instance of the TestService + return DetectorService.this; + } + } + @Nullable + @Override + public IBinder onBind(Intent intent) { + super.onBind(intent); + return serviceBinder; + } + + + /** Video Detection */ + public void startVideoDetection() { + if(videoDetector != null) + videoDetector.startDetection(); + } + public void stopVideoDetection() { + if(videoDetector != null) + videoDetector.stopDetection(); + } + public boolean isVideoDetectionRunning() { + if(videoDetector != null) + return videoDetector.isDetecting(); + return false; + } + public void debugVideoProcessing(ImageView input, ImageView output) { + if(videoDetector != null) + videoDetector.debugProcessing(input, output); + } + + /** Audio Detection */ + public void startAudioDetection() { + + } + public void stopAudioDetection() { + + } + + /** Motion Detection */ + public void startMotionDetection() { + + } + public void stopMotionDetection() { + + } + + /** Video Recording */ + public void startVideoRecording() { + if(videoDetector != null) + videoDetector.startRecording(); + } + public void stopVideoRecording() { + if(videoDetector != null) + videoDetector.stopRecording(); + } + public boolean isVideoRecordingRunning() { + if(videoDetector != null) + return videoDetector.isRecording(); + return false; + } + public void setVideoRecordingDir(File outputDir) { + if (videoDetector != null) + videoDetector.setOutputDir(outputDir); + } + + /** Audio Recording */ + public void startAudioRecording() { + if(audioRecorder != null) + audioRecorder.startRecording(); + } + public void stopAudioRecording() { + if(audioRecorder != null) + audioRecorder.stopRecording(); + } + public boolean isAudioRecordingRunning() { + if(videoDetector != null) + return audioRecorder.isRecording(); + return false; + } + public void setAudioRecordingDir(File outputDir) { + if (audioRecorder != null) + audioRecorder.setOutputDir(outputDir); + } + + + + + /** pass Detection Report to Service Detection Listener and trigger it */ + public void passToServiceListener(DetectionReport detectionReport) { + if (listener != null) { + listener.onDetection(detectionReport); + } + } + + + /** On Detection Listener - runs when violation is reported */ + public interface OnDetectionListener { + void onDetection(@NonNull DetectionReport detectionReport); + } + public void setOnDetectionListener(@NonNull DetectorService.OnDetectionListener listener) { + this.listener = listener; + } +} diff --git a/app/src/main/java/com/example/ueberwachungssystem/Detection/OpenCVHelper.java b/app/src/main/java/com/example/ueberwachungssystem/Detection/OpenCVHelper.java new file mode 100644 index 0000000..7a6cb28 --- /dev/null +++ b/app/src/main/java/com/example/ueberwachungssystem/Detection/OpenCVHelper.java @@ -0,0 +1,109 @@ +package com.example.ueberwachungssystem.Detection; + +import android.graphics.Bitmap; +import android.media.Image; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.camera.core.ExperimentalGetImage; +import androidx.camera.core.ImageProxy; + +import org.opencv.android.Utils; +import org.opencv.core.Core; +import org.opencv.core.CvType; +import org.opencv.core.Mat; +import org.opencv.core.MatOfPoint; +import org.opencv.core.Scalar; +import org.opencv.core.Size; +import org.opencv.imgproc.Imgproc; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +@ExperimentalGetImage +public class OpenCVHelper { + + /** OpenCV helper methods **/ + public static Mat addGaussianBlur(Mat inputMat, Size kernelSize){ + Mat outputMat = new Mat(); + Imgproc.GaussianBlur(inputMat, outputMat, kernelSize, 0); + return outputMat; + } + + public static Mat addBlur(Mat inputMat, Size kernelSize){ + Mat outputMat = new Mat(); + Imgproc.blur(inputMat, outputMat, kernelSize); + return outputMat; + } + + public static Mat extractYChannel(@NonNull ImageProxy imgProxy) { + Image img = imgProxy.getImage(); + + assert img != null; + ByteBuffer yBuffer = img.getPlanes()[0].getBuffer(); + byte[] yData = new byte[yBuffer.remaining()]; + yBuffer.get(yData); + + Mat yMat = new Mat(img.getHeight(), img.getWidth(), CvType.CV_8UC1); + yMat.put(0, 0, yData); + + return yMat; + } + + public static Mat thresholdPixels(Mat inputMat, Mat previousImage, int threshold){ + Mat diffImage = new Mat(); + Core.absdiff(inputMat, previousImage, diffImage); + Mat binaryMat = new Mat(); + Imgproc.threshold(diffImage, binaryMat, threshold, 255, Imgproc.THRESH_BINARY); + return binaryMat; + } + + + public static Mat thresholdContourArea(Mat inputMat, float areaThreshold){ + List contours = new ArrayList<>(); + Mat hierarchy = new Mat(); + Imgproc.findContours(inputMat, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); + + Mat outputMat = new Mat(inputMat.size(), inputMat.type(), new Scalar(0)); + // Iterate over the contours and draw only the larger contours on the outputMat + for (MatOfPoint contour : contours) { + double contourArea = Imgproc.contourArea(contour); + if (contourArea > areaThreshold) { + Imgproc.drawContours(outputMat, Collections.singletonList(contour), 0, new Scalar(255), -1); + } + } + // Apply the outputMat as a mask to the dilatedImage + Mat maskedImage = new Mat(); + inputMat.copyTo(maskedImage, outputMat); + return outputMat; + } + + public static Mat dilateBinaryMat(Mat inputMat, Size kernelSize){ + Mat dilatedMat = new Mat(); + Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, kernelSize); + Imgproc.dilate(inputMat, dilatedMat, kernel); + return dilatedMat; + } + + public static int countNonZeroPixels(Mat inputImage) { + if (inputImage != null) + return Core.countNonZero(inputImage); + else + return 0; + } + + + public static void debugMat(Mat mat, ImageView imageView) { + if (imageView == null || mat == null) + return; + + Bitmap bitmap = Bitmap.createBitmap(mat.cols(), mat.rows(), Bitmap.Config.ARGB_8888); + Utils.matToBitmap(mat, bitmap); + + // Display the bitmap in an ImageView + imageView.setImageBitmap(bitmap); + } +} diff --git a/app/src/main/java/com/example/ueberwachungssystem/Detection/VideoDetector.java b/app/src/main/java/com/example/ueberwachungssystem/Detection/VideoDetector.java new file mode 100644 index 0000000..9018ddf --- /dev/null +++ b/app/src/main/java/com/example/ueberwachungssystem/Detection/VideoDetector.java @@ -0,0 +1,327 @@ +package com.example.ueberwachungssystem.Detection; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.pm.PackageManager; +import android.graphics.ImageFormat; +import android.media.Image; +import android.os.CountDownTimer; +import android.util.Log; +import android.view.Display; +import android.view.Surface; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.camera.core.CameraSelector; +import androidx.camera.core.ExperimentalGetImage; +import androidx.camera.core.ImageAnalysis; +import androidx.camera.core.ImageProxy; +import androidx.camera.core.Preview; +import androidx.camera.core.VideoCapture; +import androidx.camera.lifecycle.ProcessCameraProvider; +import androidx.camera.view.PreviewView; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.lifecycle.LifecycleOwner; + +import com.google.common.util.concurrent.ListenableFuture; + +import org.opencv.android.OpenCVLoader; +import org.opencv.core.Mat; +import org.opencv.core.Size; + +import java.io.File; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.concurrent.ExecutionException; + + +/** + * Video Detector inherits some methods from abstract Detector class (more info there) + * USE FROM MAIN ACTIVITY: + * VideoDetector vd = new VideoDetector(this); + * */ + + +@ExperimentalGetImage +public class VideoDetector extends Detector { + // Calling Activity + private final Context context; + + // Camera Provider + private ProcessCameraProvider cameraProvider; + private ImageAnalysis imageAnalysis; + private VideoCapture videoCapture; + //private Preview preview; + + // Logic + private boolean isDetecting = false; + private boolean isRecording = false; + private boolean allowReportViolation = false; + + // Image Processing + private Mat previousImage = null; + + // Debugging + private ImageView inputImageView = null; + private ImageView outputImageView = null; + + // Recorder + private File outputDir; // Default: in app files directory + + + // Parameters + private static final float ALARM_THRESHOLD = 0f; // Percent of pixels changed + private static final float AREA_THRESHOLD = 10f; + private static final int DILATE_ITERATIONS = 2; + private static final float START_DELAY = 20000; // milliseconds + private static final android.util.Size IMAGE_RES = new android.util.Size(640, 480); + + + + /** Constructor */ + public VideoDetector(Context context) { + super(); + this.context = context; + this.imageAnalysis = setupImageAnalysis(); + this.videoCapture = setupVideoCapture(); + this.outputDir = context.getFilesDir(); + //this.preview = new Preview.Builder().build(); + } + + /** Get States */ + public boolean isDetecting() { + return isDetecting; + } + public boolean isRecording(){ + return isRecording; + } + + + /** Starts the Video Detection */ + @Override + public void startDetection() { + // Check States + if (isDetecting) + return; + // Configure Image Analysis + imageAnalysis = setupImageAnalysis(); + // Open CV startup check + if (!OpenCVLoader.initDebug()) { + Log.e("OpenCV", "Unable to load OpenCV!"); + return; + } else + Log.d("OpenCV", "OpenCV loaded Successfully!"); + // Get Process Camera Provider and start + final ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(context); + cameraProviderFuture.addListener(() -> { + try { + cameraProvider = cameraProviderFuture.get(); + isDetecting = true; + bindCameraProvider(); + } catch (ExecutionException | InterruptedException e) {} + }, ContextCompat.getMainExecutor(context)); + // Disable Violation Calling for Setup Time + startViolationTimer(START_DELAY); + } + + /** Starts the Recorder */ + @SuppressLint("RestrictedApi") + public void startRecording() { + // Check States + if (isRecording){ + return; + } + + videoCapture = setupVideoCapture(); + + final ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(context); + cameraProviderFuture.addListener(() -> { + try { + cameraProvider = cameraProviderFuture.get(); + isRecording = true; + bindCameraProvider(); + + File vidFile = new File(context.getFilesDir() + "/" + generateFileName() + ".mp4"); + if (ActivityCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { + return; + } + videoCapture.startRecording( + new VideoCapture.OutputFileOptions.Builder(vidFile).build(), + context.getMainExecutor(), + new VideoCapture.OnVideoSavedCallback() { + @Override + public void onVideoSaved(@NonNull VideoCapture.OutputFileResults outputFileResults) { + isRecording = false; + Toast.makeText(context, "video recording saved", Toast.LENGTH_SHORT).show(); + } + @Override + public void onError(int videoCaptureError, @NonNull String message, @Nullable Throwable cause) { + isRecording = false; + Toast.makeText(context, "video recording failed", Toast.LENGTH_SHORT).show(); + } + } + ); + } catch (ExecutionException | InterruptedException ignored) {} + }, ContextCompat.getMainExecutor(context)); + } + + /** Stops the Video Detection */ + @Override + public void stopDetection() { + if (!isDetecting || imageAnalysis == null) + return; + cameraProvider.unbind(imageAnalysis); + isDetecting = false; + allowReportViolation = false; + } + + /** Stops the Recording */ + @SuppressLint("RestrictedApi") + public void stopRecording(){ + if(!isRecording) + return; + + videoCapture.stopRecording(); + cameraProvider.unbind(videoCapture); + isRecording = false; + } + + /** Bind Camera Provider */ + private void bindCameraProvider() { + // Specify which Camera to use + CameraSelector cameraSelector = new CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build(); + cameraProvider.unbindAll(); + cameraProvider.bindToLifecycle((LifecycleOwner) context, cameraSelector, imageAnalysis, videoCapture); + } + + /** Setup Use Cases */ + private ImageAnalysis setupImageAnalysis() { + // Configure and create Image Analysis + ImageAnalysis.Builder builder = new ImageAnalysis.Builder(); + builder.setTargetResolution(IMAGE_RES); + builder.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST); + builder.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_YUV_420_888); + builder.setTargetRotation(Surface.ROTATION_90); + ImageAnalysis imageAnalysis = builder.build(); + // Set Analyzer + imageAnalysis.setAnalyzer(ContextCompat.getMainExecutor(context), imageProxy -> { + if (imageProxy.getFormat() == ImageFormat.YUV_420_888) { + Image image = imageProxy.getImage(); + assert image != null; + + // Violation Handling + Mat processed = processImage(imageProxy); + + int n = OpenCVHelper.countNonZeroPixels(processed); + int pixelCount = image.getWidth() * image.getHeight(); + float percentChanged = (float) n / pixelCount; + + // Violation Condition + if (percentChanged * 100 > ALARM_THRESHOLD) { + if (allowReportViolation) + reportViolation("Video", percentChanged); + } + } + imageProxy.close(); + }); + return imageAnalysis; + } + + @SuppressLint("RestrictedApi") + private VideoCapture setupVideoCapture() { + int rotation = getDisplayRotation(); + return new VideoCapture.Builder() + .setTargetRotation(rotation) + .build(); + } + + /** Process Image to be used for Motion Detection */ + private Mat processImage(ImageProxy imageProxy){ + if (imageProxy == null) + return null; + // Image Transformation + Mat imageMat = OpenCVHelper.extractYChannel(imageProxy); + // Show Input Image + if (inputImageView != null) + OpenCVHelper.debugMat(imageMat, inputImageView); + // Preprocess Image + Mat preprocessed = imageMat; + preprocessed = OpenCVHelper.addGaussianBlur(preprocessed, new Size(21, 21)); + preprocessed = OpenCVHelper.addBlur(preprocessed, new Size(3, 3)); + // Set Previous Image + if (previousImage == null) { + previousImage = preprocessed; + return null; + } + // Process Image + Mat processed = preprocessed.clone(); + processed = OpenCVHelper.thresholdPixels(processed, previousImage, 25); + + for(int i = 0; i < DILATE_ITERATIONS; i++) + processed = OpenCVHelper.dilateBinaryMat(processed, new Size(3,3)); + + processed = OpenCVHelper.thresholdContourArea(processed, AREA_THRESHOLD); + // Output + previousImage = preprocessed.clone(); + // Show Output Image + if (outputImageView != null) + OpenCVHelper.debugMat(processed, outputImageView); + return processed; + } + + + /** Debug input and result of processing */ + public void debugProcessing(@NonNull ImageView inputImageView, @NonNull ImageView outputImageView){ + this.inputImageView = inputImageView; + this.outputImageView = outputImageView; + } + + /** + private void setPreviewView(@NonNull PreviewView previewView) { + // Create Preview + if (this.preview != null) + this.preview.setSurfaceProvider(previewView.getSurfaceProvider()); + } + */ + + + /** Generate File Name */ + private String generateFileName(){ + // Get the current timestamp + LocalDateTime currentTime = LocalDateTime.now(); + // Define the format for the timestamp + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"); + // Return the timestamp as a string + return currentTime.format(formatter); + } + + + /** Get current Display Rotation */ + private int getDisplayRotation() { + WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display display = windowManager.getDefaultDisplay(); + return display.getRotation(); + } + + /** Start delay until Violation Report is allowed */ + private void startViolationTimer(float setupTime) { + new CountDownTimer((long) (START_DELAY), 100) { + @Override + public void onTick(long millisUntilFinished) { + } + @Override + public void onFinish() { + allowReportViolation = true; + } + }.start(); + } + + public void setOutputDir(File outputDir) { + this.outputDir = outputDir; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java b/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java index d43bc98..1f2a68a 100644 --- a/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java +++ b/app/src/main/java/com/example/ueberwachungssystem/MainActivity.java @@ -3,7 +3,11 @@ package com.example.ueberwachungssystem; import android.annotation.SuppressLint; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; +import android.net.wifi.WifiInfo; +import android.net.wifi.WifiManager; import android.os.Bundle; +import android.view.MenuItem; +import android.widget.Toast; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -19,44 +23,38 @@ import java.nio.ByteOrder; @SuppressLint("SetTextI18n") public class MainActivity extends AppCompatActivity { - TextView tvMessages; - TextView tvConnectionInfos; + WifiCommunication communication; PermissionRequest permission; - public static String SERVER_IP = ""; - public static final int SERVER_PORT = 1234; - //private static final int PERMISSION_REQUEST_CODE = 123; - float i=0; - boolean communicationRunning = false; - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - tvMessages = findViewById(R.id.tvMessages); - tvConnectionInfos = findViewById(R.id.tvConnectionInfos); - try { - SERVER_IP = getLocalIpAddress(); - tvConnectionInfos.setText("Connection Infos: \n Own IP-Adress: " + SERVER_IP+ " Port: " + SERVER_PORT); - } catch (UnknownHostException e) { - e.printStackTrace(); + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); } - Button btnSend = findViewById(R.id.btnSend); - btnSend.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - i++; - communication.sendTrue(String.valueOf(i)); - } - }); + @Override + protected void onResume() { + super.onResume(); + if (!communicationRunning){ + communication = new WifiCommunication(MainActivity.this, SERVER_PORT); + communicationRunning = true; + } + permission = new PermissionRequest(MainActivity.this); + permission.rechtePruefen(); + } + + @Override + protected void onPause() { + super.onPause(); + //communication.stopCommunication(); } public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.options_menu, menu); return true; } public boolean onOptionsItemSelected(MenuItem item) { - Toast.makeText(this, "Selected Item: " +item.getTitle(), Toast.LENGTH_SHORT).show(); + Toast.makeText(this, "Selected Item: " + item.getTitle(), Toast.LENGTH_SHORT).show(); PopUpClass popUpClass; switch (item.getItemId()) { case R.id.Rechteverwaltung: @@ -78,21 +76,6 @@ public class MainActivity extends AppCompatActivity { return super.onOptionsItemSelected(item); } } - - protected void onResume() { - super.onResume(); - if (!communicationRunning){ - communication = new WifiCommunication(MainActivity.this, SERVER_PORT); - communicationRunning = true; - } - permission = new PermissionRequest(MainActivity.this); - permission.rechtePruefen(); - } - @Override - protected void onPause() { - super.onPause(); - //communication.stopCommunication(); - } private String getLocalIpAddress() throws UnknownHostException { WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE); assert wifiManager != null; @@ -101,3 +84,4 @@ public class MainActivity extends AppCompatActivity { return InetAddress.getByAddress(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(ipInt).array()).getHostAddress(); } } + diff --git a/app/src/main/java/com/example/ueberwachungssystem/PermissionHandler.java b/app/src/main/java/com/example/ueberwachungssystem/PermissionHandler.java new file mode 100644 index 0000000..2ffcc72 --- /dev/null +++ b/app/src/main/java/com/example/ueberwachungssystem/PermissionHandler.java @@ -0,0 +1,43 @@ +package com.example.ueberwachungssystem; + + +import android.app.Activity; +import android.content.Context; +import android.content.pm.PackageManager; +import android.widget.Toast; + +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +public class PermissionHandler { + private final Context context; + private static final int PERMISSION_REQUEST_CODE = 23409; + private static final String[] permissions = new String[]{ + android.Manifest.permission.CAMERA, + android.Manifest.permission.RECORD_AUDIO + }; + + public PermissionHandler(Context context) { + this.context = context; + } + + public boolean hasPermissions() { + boolean permissionState = true; + for (String permission: permissions) { + permissionState = permissionState && ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED; + } + return permissionState; + } + + public void getPermissions() { + if (!hasPermissions()) + ActivityCompat.requestPermissions((Activity) context, permissions, PERMISSION_REQUEST_CODE); + } + + public void showPermissionToast() { + if (hasPermissions()) + Toast.makeText(context, "permissions available", Toast.LENGTH_SHORT).show(); + else + Toast.makeText(context, "permissions missing", Toast.LENGTH_SHORT).show(); + } +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 37e0909..c5abe55 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,37 +1,41 @@ - - - + + -