delete old file
This commit is contained in:
parent
4b2eb8def9
commit
e0b84683d0
|
@ -123,7 +123,6 @@ class MainActivity : AppCompatActivity() {
|
||||||
putExtra("useFrontCamera", useFrontCamera)
|
putExtra("useFrontCamera", useFrontCamera)
|
||||||
}
|
}
|
||||||
startForegroundService(serviceIntent)
|
startForegroundService(serviceIntent)
|
||||||
// startService(serviceIntent)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun stopRecordingService() {
|
private fun stopRecordingService() {
|
||||||
|
@ -131,7 +130,6 @@ class MainActivity : AppCompatActivity() {
|
||||||
val serviceIntent = Intent(this, RecordingService::class.java).apply {
|
val serviceIntent = Intent(this, RecordingService::class.java).apply {
|
||||||
action = RecordingService.ACTION_STOP_RECORDING
|
action = RecordingService.ACTION_STOP_RECORDING
|
||||||
}
|
}
|
||||||
stopForeground(STOP_FOREGROUND_DETACH)
|
|
||||||
stopService(serviceIntent)
|
stopService(serviceIntent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,236 +0,0 @@
|
||||||
package com.urkob.wittrail_android
|
|
||||||
|
|
||||||
import android.app.Notification
|
|
||||||
import android.app.NotificationChannel
|
|
||||||
import android.app.NotificationManager
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.app.Service
|
|
||||||
import android.content.Intent
|
|
||||||
import android.media.MediaScannerConnection
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.IBinder
|
|
||||||
import android.provider.MediaStore
|
|
||||||
import android.util.Log
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.camera.core.CameraSelector
|
|
||||||
import androidx.camera.core.Preview
|
|
||||||
import androidx.camera.lifecycle.ProcessCameraProvider
|
|
||||||
import androidx.camera.video.MediaStoreOutputOptions
|
|
||||||
import androidx.camera.video.Recorder
|
|
||||||
import androidx.camera.video.Recording
|
|
||||||
import androidx.camera.video.VideoCapture
|
|
||||||
import androidx.core.app.NotificationCompat
|
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture
|
|
||||||
import java.io.File
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.Locale
|
|
||||||
import java.util.concurrent.ExecutorService
|
|
||||||
import java.util.concurrent.Executors
|
|
||||||
|
|
||||||
|
|
||||||
class RecordingServices : Service() {
|
|
||||||
private lateinit var cameraExecutor: ExecutorService
|
|
||||||
private lateinit var cameraProviderFuture: ListenableFuture<ProcessCameraProvider>
|
|
||||||
private var recording: Recording? = null
|
|
||||||
private lateinit var videoCapture: VideoCapture<Recorder>
|
|
||||||
|
|
||||||
private val notificationChannelId = "RECORDING_CHANNEL"
|
|
||||||
private val notificationId = 1
|
|
||||||
private var videoFile: File? = null
|
|
||||||
|
|
||||||
override fun onCreate() {
|
|
||||||
super.onCreate()
|
|
||||||
cameraExecutor = Executors.newSingleThreadExecutor()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBind(intent: Intent): IBinder? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun bindCamera() {
|
|
||||||
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
|
|
||||||
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
|
|
||||||
|
|
||||||
// You need to build the use cases. For example:
|
|
||||||
val previewUseCase = Preview.Builder().build()
|
|
||||||
val videoCaptureUseCase = VideoCapture.withOutput(Recorder.Builder().build())
|
|
||||||
|
|
||||||
try {
|
|
||||||
cameraProvider.unbindAll()
|
|
||||||
cameraProvider.bindToLifecycle(this, cameraSelector, previewUseCase, videoCaptureUseCase)
|
|
||||||
} catch (exc: Exception) {
|
|
||||||
Log.e(TAG, "Use case binding failed", exc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startRecording() {
|
|
||||||
val mediaStoreOutputOptions = MediaStoreOutputOptions.Builder(contentResolver, MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val outputOptions = VideoCapture.OutputFileOptions.Builder(videoFile).build()
|
|
||||||
// Start recording
|
|
||||||
videoCapture.startRecording(outputOptions, cameraExecutor, object : VideoCapture.OnVideoSavedCallback {
|
|
||||||
fun onVideoSaved(outputFileResults: VideoCapture.OutputFileResults) {
|
|
||||||
val savedUri = outputFileResults.savedUri ?: Uri.fromFile(videoFile)
|
|
||||||
Log.d(TAG, "Video File Saved at $savedUri")
|
|
||||||
// Here you can handle the saved video file
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onError(videoCaptureError: Int, message: String, cause: Throwable?) {
|
|
||||||
Log.e(TAG, "Video capture error: $message", cause)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private val captureListener = object : VideoCapture.OnVideoSavedCallback {
|
|
||||||
fun onVideoSaved(file: File) {
|
|
||||||
Log.d(TAG, "Video File: $file")
|
|
||||||
// Here you can handle the saved video file
|
|
||||||
}
|
|
||||||
fun onError(videoCaptureError: Int, message: String, cause: Throwable?) {
|
|
||||||
Log.e(TAG, "Video capture error: $message", cause)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
super.onDestroy()
|
|
||||||
cameraExecutor.shutdown()
|
|
||||||
recording?.stop() // Stop the recording
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function to create a file
|
|
||||||
private fun createFile(baseFolder: File, format: String, extension: String) =
|
|
||||||
File(baseFolder, SimpleDateFormat(format, Locale.US)
|
|
||||||
.format(System.currentTimeMillis()) + extension)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "RecordingService"
|
|
||||||
private const val FILENAME = "yyyy-MM-dd-HH-mm-ss-SSS"
|
|
||||||
private const val VIDEO_EXTENSION = ".mp4"
|
|
||||||
private val outputDirectory: File by lazy {
|
|
||||||
getOutputDirectory()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method to get the output directory
|
|
||||||
private fun getOutputDirectory(): File {
|
|
||||||
val mediaDir = externalMediaDirs.firstOrNull()?.let {
|
|
||||||
File(it, resources.getString(R.string.app_name)).apply { mkdirs() }
|
|
||||||
}
|
|
||||||
return if (mediaDir != null && mediaDir.exists())
|
|
||||||
mediaDir else filesDir
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
|
||||||
createNotificationChannel()
|
|
||||||
startForeground(notificationId, createNotification())
|
|
||||||
|
|
||||||
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
|
|
||||||
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
|
|
||||||
|
|
||||||
val previewUseCase = Preview.Builder().build()
|
|
||||||
val videoCaptureUseCase = VideoCapture.withOutput(Recorder.Builder().build())
|
|
||||||
|
|
||||||
try {
|
|
||||||
cameraProvider.unbindAll()
|
|
||||||
cameraProvider.bindToLifecycle(this, cameraSelector, previewUseCase, videoCaptureUseCase)
|
|
||||||
} catch (exc: Exception) {
|
|
||||||
Log.e(TAG, "Use case binding failed", exc)
|
|
||||||
}
|
|
||||||
|
|
||||||
cameraProviderFuture = ProcessCameraProvider.getInstance(this)
|
|
||||||
cameraProviderFuture.addListener(Runnable {
|
|
||||||
val cameraProvider = cameraProviderFuture.get()
|
|
||||||
bindCamera()
|
|
||||||
}, ContextCompat.getMainExecutor(this))
|
|
||||||
|
|
||||||
return START_STICKY
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startCamera() {
|
|
||||||
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
|
|
||||||
|
|
||||||
val preview = Preview.Builder()
|
|
||||||
.build()
|
|
||||||
.also {
|
|
||||||
it.setSurfaceProvider(viewBinding.viewFinder.surfaceProvider)
|
|
||||||
}
|
|
||||||
|
|
||||||
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
|
|
||||||
|
|
||||||
val videoCapture = VideoCapture.withOutput(Recorder.Builder().build())
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
|
||||||
cameraProvider.unbindAll()
|
|
||||||
cameraProvider.bindToLifecycle(
|
|
||||||
this, cameraSelector, preview)
|
|
||||||
|
|
||||||
cameraProvider.bindToLifecycle(
|
|
||||||
this, cameraSelector, preview, imageCapture, videoCapture)
|
|
||||||
} catch (exc: Exception) {
|
|
||||||
Log.e(TAG, "Use case binding failed", exc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun stopRecording() {
|
|
||||||
try {
|
|
||||||
Log.d("RecordingService", "Recording stopped. File saved at: ${videoFile?.absolutePath}")
|
|
||||||
// Now scan the file
|
|
||||||
videoFile?.let { file ->
|
|
||||||
Log.d("RecordingService", "Recording stopped. File saved at: ${file.absolutePath}")
|
|
||||||
scanFile(file) // Use 'let' to ensure videoFile is not null when calling scanFile
|
|
||||||
}
|
|
||||||
} catch (e: RuntimeException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
Toast.makeText(this, "Recording stop failed: ${e.message}", Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun scanFile(file: File) {
|
|
||||||
MediaScannerConnection.scanFile(
|
|
||||||
this@`RecordingService.txt`,
|
|
||||||
arrayOf(file.absolutePath),
|
|
||||||
null
|
|
||||||
) { path: String?, uri: Uri? ->
|
|
||||||
Log.d("RecordingService", "Scanned $path:")
|
|
||||||
Log.d("RecordingService", "-> Uri = $uri")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun createNotification(): Notification {
|
|
||||||
val notificationIntent = Intent(this, MainActivity::class.java)
|
|
||||||
// val pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0)
|
|
||||||
|
|
||||||
val pendingIntent = PendingIntent.getActivity(
|
|
||||||
this, 0, notificationIntent,
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_IMMUTABLE else 0
|
|
||||||
)
|
|
||||||
|
|
||||||
return NotificationCompat.Builder(this, notificationChannelId)
|
|
||||||
.setContentTitle("Recording Service")
|
|
||||||
.setContentText("Recording in progress...")
|
|
||||||
.setSmallIcon(android.R.drawable.ic_dialog_info)
|
|
||||||
.setContentIntent(pendingIntent)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createNotificationChannel() {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
val serviceChannel = NotificationChannel(
|
|
||||||
notificationChannelId,
|
|
||||||
"Foreground Service Channel",
|
|
||||||
NotificationManager.IMPORTANCE_DEFAULT
|
|
||||||
)
|
|
||||||
|
|
||||||
val manager = getSystemService(NotificationManager::class.java)
|
|
||||||
manager.createNotificationChannel(serviceChannel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue