diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5965fad..79fda6e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,7 +11,7 @@ - + diff --git a/app/src/main/java/com/bnyro/recorder/canvas_overlay/CanvasOverlay.kt b/app/src/main/java/com/bnyro/recorder/canvas_overlay/CanvasOverlay.kt index ea49467..7791ed0 100644 --- a/app/src/main/java/com/bnyro/recorder/canvas_overlay/CanvasOverlay.kt +++ b/app/src/main/java/com/bnyro/recorder/canvas_overlay/CanvasOverlay.kt @@ -94,7 +94,7 @@ class CanvasOverlay(context: Context) { y = 0 } - init { + fun show() { hideCanvas() try { if (canvasView.windowToken == null && canvasView.parent == null) { diff --git a/app/src/main/java/com/bnyro/recorder/services/AudioRecorderTile.kt b/app/src/main/java/com/bnyro/recorder/services/AudioRecorderTile.kt index 36c3c65..ca0b90f 100644 --- a/app/src/main/java/com/bnyro/recorder/services/AudioRecorderTile.kt +++ b/app/src/main/java/com/bnyro/recorder/services/AudioRecorderTile.kt @@ -1,6 +1,8 @@ package com.bnyro.recorder.services +import android.app.PendingIntent import android.content.Intent +import android.content.Intent.FLAG_ACTIVITY_NEW_TASK import android.os.Build import android.service.quicksettings.TileService import androidx.annotation.RequiresApi @@ -11,12 +13,23 @@ import com.bnyro.recorder.ui.MainActivity class AudioRecorderTile : TileService() { override fun onClick() { super.onClick() - val intent = Intent(this, MainActivity::class.java) .putExtra(MainActivity.EXTRA_ACTION_KEY, RecorderType.AUDIO.name) .apply { - flags = Intent.FLAG_ACTIVITY_NEW_TASK + flags = FLAG_ACTIVITY_NEW_TASK } - startActivityAndCollapse(intent) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + startActivityAndCollapse( + PendingIntent.getActivity( + this, PENDING_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE + ) + ) + } else { + startActivityAndCollapse(intent) + } + } + + companion object { + const val PENDING_INTENT_REQUEST_CODE = 20 } } diff --git a/app/src/main/java/com/bnyro/recorder/services/ScreenRecorderTile.kt b/app/src/main/java/com/bnyro/recorder/services/ScreenRecorderTile.kt index cfce5e5..bc44759 100644 --- a/app/src/main/java/com/bnyro/recorder/services/ScreenRecorderTile.kt +++ b/app/src/main/java/com/bnyro/recorder/services/ScreenRecorderTile.kt @@ -1,5 +1,6 @@ package com.bnyro.recorder.services +import android.app.PendingIntent import android.content.Intent import android.os.Build import android.service.quicksettings.TileService @@ -11,12 +12,24 @@ import com.bnyro.recorder.ui.MainActivity class ScreenRecorderTile : TileService() { override fun onClick() { super.onClick() - val intent = Intent(this, MainActivity::class.java) .putExtra(MainActivity.EXTRA_ACTION_KEY, RecorderType.VIDEO.name) .apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK } - startActivityAndCollapse(intent) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + startActivityAndCollapse( + PendingIntent.getActivity( + this, PENDING_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_IMMUTABLE + ) + ) + } else { + startActivityAndCollapse(intent) + } + } + + companion object { + const val PENDING_INTENT_REQUEST_CODE = 21 } } diff --git a/app/src/main/java/com/bnyro/recorder/ui/MainActivity.kt b/app/src/main/java/com/bnyro/recorder/ui/MainActivity.kt index 736098f..bdbfaa2 100644 --- a/app/src/main/java/com/bnyro/recorder/ui/MainActivity.kt +++ b/app/src/main/java/com/bnyro/recorder/ui/MainActivity.kt @@ -1,8 +1,14 @@ package com.bnyro.recorder.ui +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.media.projection.MediaProjectionManager import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.viewModels import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.fillMaxSize @@ -12,21 +18,30 @@ import androidx.compose.ui.Modifier import androidx.navigation.compose.rememberNavController import com.bnyro.recorder.enums.RecorderType import com.bnyro.recorder.enums.ThemeMode +import com.bnyro.recorder.ui.models.RecorderModel import com.bnyro.recorder.ui.models.ThemeModel import com.bnyro.recorder.ui.theme.RecordYouTheme class MainActivity : ComponentActivity() { private var initialRecorder = RecorderType.NONE private var exitAfterRecordingStart = false + private lateinit var mProjectionManager: MediaProjectionManager + private val recorderModel: RecorderModel by viewModels() + private lateinit var launcher: ActivityResultLauncher override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val themeModel: ThemeModel by viewModels() + launcher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + if (result.resultCode == Activity.RESULT_OK) { + recorderModel.startVideoRecorder(this, result) + } + } + mProjectionManager = + getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager - initialRecorder = intent?.getStringExtra(EXTRA_ACTION_KEY)?.let { - RecorderType.valueOf(it) - } ?: RecorderType.NONE - intent?.putExtra(EXTRA_ACTION_KEY, "") + processIntent(intent) setContent { RecordYouTheme( @@ -53,9 +68,29 @@ class MainActivity : ComponentActivity() { } } + override fun onNewIntent(intent: Intent) { + processIntent(intent) + super.onNewIntent(intent) + } + + private fun processIntent(intent: Intent) { + val initialRecorderType = intent.getStringExtra(EXTRA_ACTION_KEY)?.let { + RecorderType.valueOf(it) + } ?: RecorderType.NONE + initialRecorder = initialRecorderType + if (initialRecorderType == RecorderType.AUDIO) { + recorderModel.startAudioRecorder(this) + } else if (initialRecorderType == RecorderType.VIDEO) { + if (recorderModel.hasScreenRecordingPermissions(this)) { + launcher.launch(mProjectionManager.createScreenCaptureIntent()) + } + } + intent.removeExtra(EXTRA_ACTION_KEY) + } + override fun onPause() { super.onPause() - if (initialRecorder != RecorderType.NONE) { + if (initialRecorder == RecorderType.VIDEO) { exitAfterRecordingStart = true initialRecorder = RecorderType.NONE } @@ -65,7 +100,7 @@ class MainActivity : ComponentActivity() { super.onResume() if (exitAfterRecordingStart) { exitAfterRecordingStart = false - finish() + moveTaskToBack(true) } } diff --git a/app/src/main/java/com/bnyro/recorder/ui/components/RecorderController.kt b/app/src/main/java/com/bnyro/recorder/ui/components/RecorderController.kt index 8db9724..f99bdc1 100644 --- a/app/src/main/java/com/bnyro/recorder/ui/components/RecorderController.kt +++ b/app/src/main/java/com/bnyro/recorder/ui/components/RecorderController.kt @@ -31,7 +31,6 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -44,14 +43,12 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.bnyro.recorder.R import com.bnyro.recorder.enums.RecorderState -import com.bnyro.recorder.enums.RecorderType import com.bnyro.recorder.ui.common.ClickableIcon import com.bnyro.recorder.ui.models.RecorderModel @Composable fun RecorderController( - recordScreenMode: Boolean, - initialRecorder: RecorderType + recordScreenMode: Boolean ) { val recorderModel: RecorderModel = viewModel(LocalContext.current as ComponentActivity) val context = LocalContext.current @@ -71,19 +68,6 @@ fun RecorderController( mProjectionManager.createScreenCaptureIntent() ) } - LaunchedEffect(Unit) { - when (initialRecorder) { - RecorderType.AUDIO -> { - recorderModel.startAudioRecorder(context) - } - - RecorderType.VIDEO -> { - requestScreenRecording() - } - - RecorderType.NONE -> {} - } - } Column( modifier = Modifier.wrapContentSize(), horizontalAlignment = Alignment.CenterHorizontally diff --git a/app/src/main/java/com/bnyro/recorder/ui/models/RecorderModel.kt b/app/src/main/java/com/bnyro/recorder/ui/models/RecorderModel.kt index b713b11..23183f8 100644 --- a/app/src/main/java/com/bnyro/recorder/ui/models/RecorderModel.kt +++ b/app/src/main/java/com/bnyro/recorder/ui/models/RecorderModel.kt @@ -6,12 +6,10 @@ import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.ServiceConnection -import android.net.Uri import android.os.Build import android.os.Handler import android.os.IBinder import android.os.Looper -import android.provider.Settings import androidx.activity.result.ActivityResult import androidx.annotation.RequiresApi import androidx.compose.runtime.getValue @@ -31,7 +29,6 @@ import com.bnyro.recorder.util.PermissionHelper import com.bnyro.recorder.util.Preferences class RecorderModel : ViewModel() { - private val audioPermission = arrayOf(Manifest.permission.RECORD_AUDIO) private val supportsOverlay = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O var recorderState by mutableStateOf(RecorderState.IDLE) @@ -52,6 +49,7 @@ class RecorderModel : ViewModel() { recorderState = it } (recorderService as? ScreenRecorderService)?.prepare(activityResult!!) + if (supportsOverlay) canvasOverlay?.show() recorderService?.start() } @@ -73,7 +71,12 @@ class RecorderModel : ViewModel() { @SuppressLint("NewApi") fun startAudioRecorder(context: Context) { - if (!PermissionHelper.checkPermissions(context, audioPermission)) return + val audioPermission = mutableListOf(Manifest.permission.RECORD_AUDIO) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + audioPermission.add(Manifest.permission.POST_NOTIFICATIONS) + } + + if (!PermissionHelper.checkPermissions(context, audioPermission.toTypedArray())) return val serviceIntent = if (Preferences.prefs.getBoolean(Preferences.losslessRecorderKey, false)) { @@ -152,19 +155,6 @@ class RecorderModel : ViewModel() { @SuppressLint("NewApi") fun hasScreenRecordingPermissions(context: Context): Boolean { - val overlayEnabled = Preferences.prefs.getBoolean( - Preferences.showOverlayAnnotationToolKey, - false - ) - if (supportsOverlay && overlayEnabled && !Settings.canDrawOverlays(context)) { - val intent = Intent( - Settings.ACTION_MANAGE_OVERLAY_PERMISSION, - Uri.parse("package:" + context.packageName) - ) - context.startActivity(intent) - return false - } - val requiredPermissions = arrayListOf() val recordAudio = diff --git a/app/src/main/java/com/bnyro/recorder/ui/screens/HomeScreen.kt b/app/src/main/java/com/bnyro/recorder/ui/screens/HomeScreen.kt index 95496ba..742e447 100644 --- a/app/src/main/java/com/bnyro/recorder/ui/screens/HomeScreen.kt +++ b/app/src/main/java/com/bnyro/recorder/ui/screens/HomeScreen.kt @@ -43,7 +43,8 @@ fun HomeScreen( onNavigate: (Destination) -> Unit, recorderModel: RecorderModel = viewModel(LocalContext.current as ComponentActivity) ) { - val pagerState = rememberPagerState { 2 } + val pagerState = + rememberPagerState(initialPage = if (initialRecorder == RecorderType.VIDEO) 1 else 0) { 2 } val scope = rememberCoroutineScope() val view = LocalView.current Scaffold(modifier = Modifier.fillMaxSize(), topBar = { @@ -114,7 +115,7 @@ fun HomeScreen( state = pagerState, modifier = Modifier.fillMaxSize() ) { index -> - RecorderView(initialRecorder = initialRecorder, recordScreenMode = (index == 1)) + RecorderView(recordScreenMode = (index == 1)) } } } diff --git a/app/src/main/java/com/bnyro/recorder/ui/screens/RecorderScreen.kt b/app/src/main/java/com/bnyro/recorder/ui/screens/RecorderScreen.kt index 64f0aae..8f92ab6 100644 --- a/app/src/main/java/com/bnyro/recorder/ui/screens/RecorderScreen.kt +++ b/app/src/main/java/com/bnyro/recorder/ui/screens/RecorderScreen.kt @@ -10,7 +10,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.lifecycle.viewmodel.compose.viewModel import com.bnyro.recorder.enums.RecorderState -import com.bnyro.recorder.enums.RecorderType import com.bnyro.recorder.ui.common.ResponsiveRecordScreenLayout import com.bnyro.recorder.ui.components.RecorderController import com.bnyro.recorder.ui.components.RecorderPreview @@ -18,7 +17,6 @@ import com.bnyro.recorder.ui.models.RecorderModel @Composable fun RecorderView( - initialRecorder: RecorderType, recordScreenMode: Boolean ) { val recorderModel: RecorderModel = viewModel(LocalContext.current as ComponentActivity) @@ -39,7 +37,7 @@ fun RecorderView( RecorderPreview(recordScreenMode) }, PaneTwo = { - RecorderController(recordScreenMode, initialRecorder) + RecorderController(recordScreenMode) } ) }