Advertisement
thief_g

Sample code for CameraX

Jun 3rd, 2023
1,345
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 24.94 KB | Source Code | 0 0
  1. package com.example.camerax
  2.  
  3. import android.Manifest
  4. import android.app.ProgressDialog
  5. import android.content.ContentValues
  6. import android.content.pm.PackageManager
  7. import android.os.Build
  8. import android.os.Bundle
  9. import android.os.Environment
  10. import android.os.Handler
  11. import android.os.HandlerThread
  12. import android.os.SystemClock
  13. import android.provider.MediaStore
  14. import android.util.Log
  15. import android.util.Size
  16. import android.view.View
  17. import android.widget.Chronometer
  18. import android.widget.Toast
  19. import androidx.appcompat.app.AppCompatActivity
  20. import androidx.camera.core.Camera
  21. import androidx.camera.core.CameraSelector
  22. import androidx.camera.core.ImageCapture
  23. import androidx.camera.core.ImageCaptureException
  24. import androidx.camera.core.Preview
  25. import androidx.camera.lifecycle.ProcessCameraProvider
  26. import androidx.camera.video.MediaStoreOutputOptions
  27. import androidx.camera.video.Quality
  28. import androidx.camera.video.QualitySelector
  29. import androidx.camera.video.Recorder
  30. import androidx.camera.video.Recording
  31. import androidx.camera.video.VideoCapture
  32. import androidx.camera.video.VideoRecordEvent
  33. import androidx.core.app.ActivityCompat
  34. import androidx.core.content.ContextCompat
  35. import androidx.core.content.PermissionChecker
  36. import com.example.camerax.databinding.ActivityMainBinding
  37. import com.otaliastudios.transcoder.Transcoder
  38. import com.otaliastudios.transcoder.TranscoderListener
  39. import com.otaliastudios.transcoder.TranscoderOptions
  40. import com.otaliastudios.transcoder.common.TrackStatus
  41. import com.otaliastudios.transcoder.strategy.DefaultAudioStrategy
  42. import com.otaliastudios.transcoder.strategy.DefaultVideoStrategy
  43. import com.otaliastudios.transcoder.strategy.TrackStrategy
  44. import com.otaliastudios.transcoder.validator.DefaultValidator
  45. import org.mp4parser.muxer.Movie
  46. import org.mp4parser.muxer.Track
  47. import org.mp4parser.muxer.builder.DefaultMp4Builder
  48. import org.mp4parser.muxer.container.mp4.MovieCreator
  49. import org.mp4parser.muxer.tracks.AppendTrack
  50. import java.io.File
  51. import java.io.FileOutputStream
  52. import java.text.SimpleDateFormat
  53. import java.util.Locale
  54. import java.util.concurrent.ExecutorService
  55. import java.util.concurrent.Executors
  56. import java.util.concurrent.Future
  57.  
  58.  
  59. class MainActivity : AppCompatActivity() {
  60.     private lateinit var mainBinding: ActivityMainBinding
  61.     private var mIsVideoRecording: Boolean = false
  62.     private var mImageCapture: ImageCapture? = null
  63.     private lateinit var mImageCaptureExecutor: ExecutorService
  64.     private lateinit var mCameraSelector:CameraSelector
  65.  
  66.     private var mVideoCapture: VideoCapture<Recorder>? = null
  67.     private var mRecording: Recording? = null
  68.     private var quality = Quality.HD
  69.     private val qualitySelector = QualitySelector.from(quality)
  70.     private var recorderBuilder = Recorder.Builder()
  71.     private var recorder = Recorder.Builder().build()
  72.     private var mIsVideoPaused: Boolean = false
  73.     private  lateinit var mChronometer: Chronometer
  74.     private var isFlashOn: Boolean = false
  75.     private lateinit var camera: Camera
  76.     private var mIsCameraSwitched: Boolean = false
  77.     private lateinit var mVideoFileList: MutableList<File>
  78.     private lateinit var progressDialogue: ProgressDialog
  79.     private var timeWhenPaused: Long  = 0
  80.     private var cameraSwitchCount:Int = 0
  81.     private var mBackgroundThreadHandler: HandlerThread? = null
  82.     private var mBackgroundHandler: Handler? = null
  83.     private var mTranscodeFuture: Future<Void>? = null
  84.     private val mTranscodeVideoStrategy: TrackStrategy? = null
  85.     private val mTranscodeAudioStrategy: TrackStrategy? = null
  86.     private var outputFile = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES), "merged_video.mp4")
  87.     private var rotatedFile = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES), "Merged_VIDEO.mp4")
  88.     private lateinit var mScreenSize: Size
  89.  
  90.     override fun onCreate(savedInstanceState: Bundle?) {
  91.         super.onCreate(savedInstanceState)
  92.         mainBinding = ActivityMainBinding.inflate(layoutInflater)
  93.         setContentView(mainBinding.root)
  94.  
  95.         mImageCaptureExecutor = Executors.newSingleThreadExecutor()
  96.  
  97.         progressDialogue = ProgressDialog(this)
  98.  
  99.  
  100.         mVideoFileList = mutableListOf()
  101.         mChronometer = mainBinding.chronometer
  102.         mChronometer.visibility = View.GONE
  103.         mainBinding.rlPauseResumeStop.visibility = View.GONE
  104.  
  105.         checkPermissions()
  106.  
  107.         mainBinding.ivStartStop.setOnClickListener {
  108.             if (mIsVideoRecording) {
  109.                 mainBinding.ivTakePicture.visibility = View.VISIBLE
  110.                 mIsVideoRecording = false
  111.                 cameraSwitchCount = 0
  112.                 stopRecording()
  113.  
  114.             } else {
  115.                 mainBinding.ivTakePicture.visibility = View.GONE
  116.                 mIsVideoRecording = true
  117.                 startRecordingVideo()
  118.             }
  119.         }
  120.  
  121.         timeWhenPaused = 0
  122.         mainBinding.ivPauseResume.setOnClickListener {
  123.             if (mIsVideoPaused) {
  124.                 mIsVideoPaused = false
  125.                 mRecording!!.resume()
  126.  
  127.             } else {
  128.                 mIsVideoPaused = true
  129.                 mRecording!!.pause()
  130.             }
  131.         }
  132.  
  133.         mainBinding.ivSwitchCamera.setOnClickListener {
  134.             mIsCameraSwitched = true
  135.             cameraSwitchCount++
  136.             if (mIsVideoRecording) {
  137.                 stopRecording()
  138.                 switchCamera()
  139.                 startRecordingVideo()
  140.  
  141.             } else {
  142.                 switchCamera()
  143.             }
  144.         }
  145.         mainBinding.ivTakePicture.setOnClickListener {
  146.             takePhoto() // it will also save the photo
  147.         }
  148.  
  149.         mainBinding.ivFlash.setOnClickListener {
  150.             onFlashButtonClicked()
  151.         }
  152.  
  153.     }
  154.  
  155.     /**
  156.      * this method is responsible for the switch of the camera
  157.      */
  158.     private fun switchCamera() {
  159.         if ( mCameraSelector == CameraSelector.DEFAULT_BACK_CAMERA) {
  160.             camera.cameraControl.enableTorch(false)
  161.             mCameraSelector =  CameraSelector.DEFAULT_FRONT_CAMERA
  162.  
  163.             mainBinding.ivFlash.setBackgroundResource(R.drawable.ic_flash_off_icon)
  164.         } else {
  165.             mCameraSelector =  CameraSelector.DEFAULT_BACK_CAMERA
  166.         }
  167.         startCamera()
  168.     }
  169.  
  170.     /**
  171.      * this method will be invoked on click of flash button and turnOn/turnOff flash light accordingly
  172.      */
  173.     private fun onFlashButtonClicked() {
  174.         if(camera.cameraInfo.hasFlashUnit()) {
  175.             if (isFlashOn) {
  176.                 isFlashOn = false
  177.                 mainBinding.ivFlash.setBackgroundResource(R.drawable.ic_flash_off_icon)
  178.                 camera.cameraControl.enableTorch(isFlashOn)
  179.             } else {
  180.                 isFlashOn = true
  181.                 mainBinding.ivFlash.setBackgroundResource(R.drawable.ic_flash_icon)
  182.                 camera.cameraControl.enableTorch(isFlashOn)
  183.             }
  184.         } else {
  185.             isFlashOn = false
  186.             mainBinding.ivFlash.setBackgroundResource(R.drawable.ic_flash_off_icon)
  187.             Toast.makeText(this, "Flash is not available", Toast.LENGTH_SHORT).show()
  188.         }
  189.     }
  190.  
  191.     /**
  192.      * this method will start the camera preview
  193.      */
  194.     private fun startCamera() {
  195.         val preview = Preview.Builder()
  196.             .build()
  197.             .also {
  198.                 it.setSurfaceProvider(mainBinding.cameraPreview.surfaceProvider)
  199.             }
  200.         val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
  201.         if(mIsCameraSwitched) {
  202.             recorder = Recorder.Builder().build()
  203.         }
  204.         if (ActivityCompat.checkSelfPermission(
  205.                 this,
  206.                 Manifest.permission.CAMERA
  207.             ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
  208.                 this,
  209.                 Manifest.permission.WRITE_EXTERNAL_STORAGE
  210.             ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
  211.                 this,
  212.                 Manifest.permission.READ_EXTERNAL_STORAGE
  213.             ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
  214.                 this,
  215.                 Manifest.permission.RECORD_AUDIO
  216.             ) != PackageManager.PERMISSION_GRANTED
  217.         ) {
  218.             ActivityCompat.requestPermissions(
  219.                 this,
  220.                 arrayOf(
  221.                     Manifest.permission.CAMERA,
  222.                     Manifest.permission.WRITE_EXTERNAL_STORAGE,
  223.                     Manifest.permission.READ_EXTERNAL_STORAGE,
  224.                     Manifest.permission.RECORD_AUDIO
  225.                 ),
  226.                 REQUEST_CAMERA_PERMISSION
  227.             )
  228.             return
  229.         }
  230.  
  231.         mVideoCapture = VideoCapture.withOutput(recorder)
  232.         cameraProviderFuture.addListener({
  233.             val cameraProvider = cameraProviderFuture.get()
  234.             mImageCapture = ImageCapture.Builder()
  235.                 .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
  236.                 .build()
  237.  
  238.             try {
  239.  
  240.                 cameraProvider.unbindAll()
  241.                 camera = cameraProvider.bindToLifecycle(this, mCameraSelector,mImageCapture,mVideoCapture,preview)
  242.                 mScreenSize = QualitySelector.getResolution(camera.cameraInfo, Quality.HIGHEST)!!
  243.  
  244.             } catch (e: Exception) {
  245.                 Log.d("MainActivity", "Use case binding failed")
  246.             }
  247.  
  248.         }, ContextCompat.getMainExecutor(this))
  249.  
  250.     }
  251.  
  252.     /**
  253.      * this method will take the photo and save it to Gallery
  254.      */
  255.     private fun takePhoto() {
  256.         mImageCapture?.let{
  257.  
  258.             val imageFileName = SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(System.currentTimeMillis())
  259.             val contentValues = ContentValues().apply {
  260.                 put(MediaStore.MediaColumns.DISPLAY_NAME, imageFileName)
  261.                 put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
  262.                 if(Build.VERSION.SDK_INT > Build.VERSION_CODES.P) {
  263.                     put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/CameraX-Image")
  264.                 }
  265.             }
  266.             val outputFileOptions = ImageCapture.OutputFileOptions
  267.                 .Builder(contentResolver, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues
  268.                 ).build()
  269.             it.takePicture(
  270.                 outputFileOptions,
  271.                 mImageCaptureExecutor,
  272.                 object : ImageCapture.OnImageSavedCallback {
  273.                     override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults){
  274.                         startCamera()
  275.                     }
  276.  
  277.                     override fun onError(exception: ImageCaptureException) {
  278.                         Toast.makeText(
  279.                             mainBinding.root.context,
  280.                             "Error occurred in taking photo",
  281.                             Toast.LENGTH_LONG
  282.                         ).show()
  283.                         Log.d("MainActivity", "Error taking photo:$exception")
  284.                     }
  285.  
  286.                 })
  287.  
  288.             Toast.makeText( this@MainActivity , "The image has been saved to Gallery", Toast.LENGTH_SHORT).show()
  289.  
  290.         }
  291.     }
  292.  
  293.     /**
  294.      * this method will start the recording of video
  295.      */
  296.     private fun startRecordingVideo() {
  297.         mainBinding.ivStartStop.setBackgroundResource(R.drawable.ic_stop_video_icon)
  298.         mVideoCapture!!.let {
  299.             try {
  300.                 if (ActivityCompat.checkSelfPermission(
  301.                         this,
  302.                         Manifest.permission.CAMERA
  303.                     ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
  304.                         this,
  305.                         Manifest.permission.WRITE_EXTERNAL_STORAGE
  306.                     ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
  307.                         this,
  308.                         Manifest.permission.READ_EXTERNAL_STORAGE
  309.                     ) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
  310.                         this,
  311.                         Manifest.permission.RECORD_AUDIO
  312.                     ) != PackageManager.PERMISSION_GRANTED
  313.                 ) {
  314.                     ActivityCompat.requestPermissions(
  315.                         this,
  316.                         arrayOf(
  317.                             Manifest.permission.CAMERA,
  318.                             Manifest.permission.WRITE_EXTERNAL_STORAGE,
  319.                             Manifest.permission.READ_EXTERNAL_STORAGE,
  320.                             Manifest.permission.RECORD_AUDIO
  321.                         ),
  322.                         REQUEST_CAMERA_PERMISSION
  323.                     )
  324.                     return
  325.                 }
  326.                 val contentValues = ContentValues().apply {
  327.                     put(MediaStore.MediaColumns.DISPLAY_NAME, "VID_${System.currentTimeMillis()}")
  328.                     put(MediaStore.MediaColumns.MIME_TYPE, "video/mp4")
  329.                 }
  330.                 val mediaStoreOutputOptions = MediaStoreOutputOptions
  331.                     .Builder(contentResolver, MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
  332.                     .setContentValues(contentValues)
  333.                     .build()
  334.                 mRecording = mVideoCapture!!.output
  335.                     .prepareRecording(this, mediaStoreOutputOptions)
  336.                     .apply {
  337.                         // Enable Audio for recording
  338.                         if (PermissionChecker.checkSelfPermission(this@MainActivity, Manifest.permission.RECORD_AUDIO) ==
  339.                             PermissionChecker.PERMISSION_GRANTED ) {
  340.                             withAudioEnabled()
  341.                         }
  342.                     }
  343.                     .start(ContextCompat.getMainExecutor(this)) { recordEvent ->
  344.                         when(recordEvent) {
  345.                             is VideoRecordEvent.Start -> {
  346.                                 mainBinding.ivPauseResume.visibility = View.VISIBLE
  347.                                 mChronometer.visibility = View.VISIBLE
  348.                                 mChronometer.base = SystemClock.elapsedRealtime()
  349.                                 mChronometer.start()
  350.                             }
  351.                             is VideoRecordEvent.Pause -> {
  352.                                 mIsVideoPaused = true
  353.                                 mainBinding.ivPauseResume.setBackgroundResource(R.drawable.ic_resume_icon)
  354.                                 timeWhenPaused = mChronometer.base - SystemClock.elapsedRealtime()
  355.                                 mChronometer.stop()
  356.                             }
  357.                             is VideoRecordEvent.Finalize -> {
  358.                                 if (!recordEvent.hasError()) {
  359.  
  360.                                     val savedUri = recordEvent.outputResults.outputUri
  361.  
  362.                                     if (savedUri != null) {
  363.                                         val projection = arrayOf(MediaStore.Video.Media.DATA)
  364.                                         val cursor = contentResolver.query(savedUri, projection, null, null, null)
  365.                                         cursor?.use {
  366.                                             if (it.moveToFirst()) {
  367.                                                 val filePath = it.getString(it.getColumnIndexOrThrow(MediaStore.Video.Media.DATA))
  368.                                                 val videoFile = File(filePath)
  369.  
  370.  
  371.                                                 if(videoFile.exists()) {
  372.                                                     mVideoFileList.add(videoFile)
  373.                                                     Toast.makeText(this,  videoFile.absolutePath, Toast.LENGTH_SHORT).show()
  374.                                                 }
  375.                                             }
  376.                                         }
  377.                                     }
  378.                                     if(!mIsVideoRecording){
  379.                                         mergeVideosUsingTranscoder(mVideoFileList)
  380.                                     }
  381.                                 } else {
  382.                                     mRecording?.close()
  383.                                     mRecording = null
  384.                                     Log.e("MainActivity", "Video capture ends with error: ${recordEvent.error}")
  385.                                 }
  386.  
  387.                             }
  388.                             is VideoRecordEvent.Resume -> {
  389.                                 mIsVideoPaused = false
  390.                                 mainBinding.ivPauseResume.setBackgroundResource(R.drawable.ic_pause_icon)
  391.                                 mChronometer.base = SystemClock.elapsedRealtime() + timeWhenPaused
  392.                                 mChronometer.start()
  393.                             }
  394.                         }
  395.                     }
  396.  
  397.             } catch (e: Exception) {
  398.                 e.printStackTrace()
  399.             }
  400.         }
  401.  
  402.     }
  403.  
  404.     private fun stopRecording() {
  405.         mainBinding.ivStartStop.setBackgroundResource(R.drawable.ic_start_video_icon)
  406.         mRecording!!.stop()
  407.         mChronometer.stop()
  408.         mChronometer.visibility = View.GONE
  409.         if(!mIsVideoRecording) {
  410.             mainBinding.ivPauseResume.visibility = View.GONE
  411.             startCamera()
  412.         }
  413.     }
  414.  
  415.     private fun mergeVideos(videoFiles: List<File>) {
  416.         try {
  417.             progressDialogue.setMessage("Merging Videos..")
  418.             progressDialogue.show()
  419.             val movieList = mutableListOf<Movie>()
  420.             for (videoFile  in videoFiles) {
  421.  
  422.  
  423.                 val movie = MovieCreator.build(videoFile.absolutePath)
  424.                 movieList.add(movie)
  425.             }
  426.             val videoTracks = mutableListOf<Track>()
  427.             val audioTracks = mutableListOf<Track>()
  428.  
  429.             for (movie in movieList) {
  430.                 for (track in movie.tracks) {
  431.                     if (track.handler == "vide") {
  432.                         videoTracks.add(track)
  433.                     }
  434.                     if (track.handler == "soun") {
  435.                         audioTracks.add(track)
  436.                     }
  437.                 }
  438.             }
  439.  
  440.             val mergedMovie = Movie()
  441.             if (videoTracks.size > 0) {
  442.                 mergedMovie.addTrack(AppendTrack(*videoTracks.toTypedArray()))
  443.             }
  444.  
  445.             if (audioTracks.size > 0) {
  446.                 mergedMovie.addTrack(AppendTrack(*audioTracks.toTypedArray()))
  447.             }
  448.  
  449.             val container = DefaultMp4Builder().build(mergedMovie)
  450.             val fileChannel = FileOutputStream(outputFile).channel
  451.             container.writeContainer(fileChannel)
  452.             fileChannel.close()
  453.             progressDialogue.cancel()
  454.  
  455.             Toast.makeText(this, "Videos merged successfully", Toast.LENGTH_SHORT).show()
  456.  
  457.         } catch (e : Exception) {
  458.             Log.e(TAG, e.message.toString())
  459.         }
  460.  
  461.     }
  462.  
  463.     /**
  464.      * this method used for merging multiple videos using Transcoder library
  465.      * @param videoFilesList
  466.      */
  467.     private fun mergeVideosUsingTranscoder(videoFiles: List<File>) {
  468.         progressDialogue.setMessage("Merging Videos..")
  469.         progressDialogue.show()
  470.         val builder: TranscoderOptions.Builder =
  471.             Transcoder.into(rotatedFile.absolutePath)
  472.         for(videoFile in videoFiles) {
  473.             builder.addDataSource(videoFile.absolutePath)
  474.         }
  475.  
  476.         // use DefaultVideoStrategy.exact(2560, 1440).build()  to restore 75% size of the video
  477.         //  use DefaultVideoStrategy.exact(mScreenSize.height, mScreenSize.width).build()  to restore 50% size of the video
  478.  
  479.         val strategy: DefaultVideoStrategy = DefaultVideoStrategy.exact(2560, 1440).build()
  480.  
  481.         mTranscodeFuture = builder
  482.             .setAudioTrackStrategy(DefaultAudioStrategy.builder().build())
  483.             .setVideoTrackStrategy(strategy)
  484.             .setVideoRotation(0)
  485.             .setListener(object : TranscoderListener{
  486.  
  487.                 override fun onTranscodeProgress(progress: Double) {}
  488.  
  489.                 override fun onTranscodeCompleted(successCode: Int) {
  490.                     Toast.makeText(this@MainActivity, "Video Merged Successfully", Toast.LENGTH_SHORT).show()
  491.                 }
  492.  
  493.                 override fun onTranscodeCanceled() {
  494.                     Toast.makeText(this@MainActivity, "Video rotation cancelled", Toast.LENGTH_SHORT).show()
  495.                 }
  496.  
  497.                 override fun onTranscodeFailed(exception: Throwable) {
  498.                     Toast.makeText(this@MainActivity, exception.message, Toast.LENGTH_SHORT).show()
  499.                 }
  500.  
  501.             })
  502.             .setValidator(object : DefaultValidator() {
  503.                 override fun validate(videoStatus: TrackStatus, audioStatus: TrackStatus): Boolean {
  504.                     //  mIsAudioOnly = !videoStatus.isTranscoding
  505.                     return super.validate(videoStatus, audioStatus)
  506.                 }
  507.  
  508.             }).transcode()
  509.         progressDialogue.cancel()
  510.     }
  511.  
  512.     /**
  513.      * this method will check camera and other required permission to run the app
  514.      */
  515.     private  fun checkPermissions() {
  516.         if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
  517.             && ContextCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
  518.             && ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED
  519.             && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
  520.         ) {
  521.             mCameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
  522.             startCamera()
  523.  
  524.         } else {
  525.             if (shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE )) {
  526.                 Toast.makeText(this, "app needs permission to be able to save videos", Toast.LENGTH_SHORT)
  527.                     .show()
  528.             }
  529.             requestPermissions(
  530.                 arrayOf(Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO,Manifest.permission.READ_EXTERNAL_STORAGE),
  531.                 REQUEST_CAMERA_PERMISSION
  532.             )
  533.         }
  534.  
  535.     }
  536.  
  537.     /**
  538.      * this method receives the status of the permissions granted
  539.      * @param1 requestCode
  540.      * @param2: permissions
  541.      * @param3: grantResults
  542.      */
  543.     override fun onRequestPermissionsResult(
  544.         requestCode: Int,
  545.         permissions: Array<String?>,
  546.         grantResults: IntArray,
  547.     ) {
  548.         super.onRequestPermissionsResult(requestCode, permissions, grantResults)
  549.         if (requestCode == REQUEST_CAMERA_PERMISSION) {
  550.             for(results in grantResults) {
  551.                 if (results == PackageManager.PERMISSION_DENIED) {
  552.                     // close the app
  553.                     Toast.makeText(
  554.                         this@MainActivity,
  555.                         "Sorry!!!, you can't use this app without granting permission",
  556.                         Toast.LENGTH_LONG
  557.                     ).show()
  558.                     finish()
  559.                 }
  560.             }
  561.         }
  562.  
  563.     }
  564.  
  565.     override fun onPause() {
  566.         super.onPause()
  567.         Log.e(TAG, "onPause()")
  568.         stopBackgroundThread()
  569.  
  570.     }
  571.  
  572.     /**
  573.      * this will start the background thread to run the processes
  574.      */
  575.     private fun startBackgroundThread() {
  576.         mBackgroundThreadHandler = HandlerThread("Camera Background")
  577.         mBackgroundThreadHandler!!.start()
  578.         mBackgroundHandler = Handler(mBackgroundThreadHandler!!.looper)
  579.     }
  580.  
  581.     /**
  582.      * this will stop the background thread if all the background processes are executed
  583.      */
  584.     private fun stopBackgroundThread() {
  585.         mBackgroundThreadHandler!!.quitSafely()
  586.         try {
  587.             mBackgroundThreadHandler!!.join()
  588.             mBackgroundThreadHandler = null
  589.             mBackgroundHandler = null
  590.         } catch (e: InterruptedException) {
  591.             e.printStackTrace()
  592.         }
  593.     }
  594.  
  595.     override fun onStop() {
  596.         super.onStop()
  597.         Log.e(TAG, "onStop()")
  598.  
  599.     }
  600.  
  601.     override fun onRestart() {
  602.         super.onRestart()
  603.         Log.e(TAG, "onRestart()")
  604.  
  605.     }
  606.  
  607.     override fun onResume() {
  608.         super.onResume()
  609.         Log.e(TAG, "onResume()")
  610.         startBackgroundThread()
  611.  
  612.         if(mIsVideoRecording) {
  613.             mRecording!!.resume()
  614.             mChronometer.start()
  615.         }
  616.     }
  617.     override fun onDestroy() {
  618.         super.onDestroy()
  619.         if(mIsVideoRecording) {
  620.             mRecording!!.stop()
  621.             mChronometer.stop()
  622.         }
  623.     }
  624.     companion object {
  625.         const val TAG = "MainActivity"
  626.         const val REQUEST_CAMERA_PERMISSION: Int = 0
  627.         const val STORAGE_PERMISSION_CODE: Int = 1
  628.         const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"
  629.     }
  630. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement