package com.example.qahelper
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.Context
import android.content.Intent
import android.hardware.display.DisplayManager
import android.hardware.display.VirtualDisplay
import android.media.AudioAttributes
import android.media.AudioPlaybackCaptureConfiguration
import android.media.MediaRecorder
import android.media.projection.MediaProjection
import android.media.projection.MediaProjectionManager
import android.os.Build
import android.os.Environment
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import androidx.core.app.NotificationCompat
import java.io.File
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*
import kotlin.concurrent.thread
class ScreenRecordService : Service() {
private lateinit var mediaProjectionManager: MediaProjectionManager
private var mediaProjection: MediaProjection? = null
private var virtualDisplay: VirtualDisplay? = null
private lateinit var mediaRecorder: MediaRecorder
private val mediaProjectionCallback = object : MediaProjection.Callback() {
override fun onStop() {
super.onStop()
stopRecording()
stopSelf()
}
}
override fun onCreate() {
super.onCreate()
mediaProjectionManager = getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
createNotificationChannel()
startForeground(NOTIFICATION_ID, createNotification())
thread { startRecording(intent) }
return START_STICKY
}
private fun startRecording(intent: Intent?) {
intent?.let {
val resultCode = it.getIntExtra("resultCode", -1)
val data: Intent? = it.getParcelableExtra("data")
if (data != null) {
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data)
mediaProjection?.registerCallback(mediaProjectionCallback, Handler(Looper.getMainLooper()))
setupMediaRecorder()
createVirtualDisplay()
try {
mediaRecorder.start()
} catch (e: IllegalStateException) {
e.printStackTrace()
stopSelf()
}
} else { stopSelf() }
} ?: stopSelf()
}
private fun setupMediaRecorder() {
mediaRecorder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
MediaRecorder(this)
} else {
@Suppress("DEPRECATION")
MediaRecorder()
}
val displayMetrics = resources.displayMetrics
val videoPath = generateFilePath()
mediaRecorder.apply {
// >
setAudioSource(MediaRecorder.AudioSource.VOICE_UPLINK)
setVideoSource(MediaRecorder.VideoSource.SURFACE)
setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
setOutputFile(videoPath)
setVideoSize(displayMetrics.widthPixels, displayMetrics.heightPixels)
setVideoEncoder(MediaRecorder.VideoEncoder.H264)
setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
setVideoEncodingBitRate(8 * 1024 * 1024)
setVideoFrameRate(30)
}
// >
val config = AudioPlaybackCaptureConfiguration.Builder(mediaProjection!!)
.addMatchingUsage(AudioAttributes.USAGE_MEDIA)
.addMatchingUsage(AudioAttributes.USAGE_GAME)
.build()
mediaRecorder.setAudioPlaybackCaptureConfig(config)
try {
mediaRecorder.prepare()
} catch (e: IOException) {
e.printStackTrace()
}
}
private fun generateFilePath(): String {
val moviesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)
val appDir = File(moviesDir, "QAHelperRecords")
if (!appDir.exists()) {
appDir.mkdirs()
}
val sdf = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault())
return File(appDir, "record_${sdf.format(Date())}.mp4").absolutePath
}
private fun createVirtualDisplay() {
val displayMetrics = resources.displayMetrics
virtualDisplay = mediaProjection?.createVirtualDisplay(
"ScreenRecordService", displayMetrics.widthPixels, displayMetrics.heightPixels, displayMetrics.densityDpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mediaRecorder.surface, null, null
)
}
override fun onDestroy() {
super.onDestroy()
stopRecording()
}
private fun stopRecording() {
try {
mediaProjection?.unregisterCallback(mediaProjectionCallback)
mediaRecorder.stop()
mediaRecorder.reset()
mediaRecorder.release()
virtualDisplay?.release()
mediaProjection?.stop()
} catch (e: Exception) { e.printStackTrace() }
}
private fun createNotification(): Notification {
return NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("화면 녹화 중")
.setContentText("앱이 화면을 녹화하고 있습니다.")
.setSmallIcon(R.mipmap.ic_launcher)
.build()
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
CHANNEL_ID, "Screen Record Channel", NotificationManager.IMPORTANCE_DEFAULT
)
getSystemService(NotificationManager::class.java).createNotificationChannel(channel)
}
}
override fun onBind(intent: Intent?): IBinder? = null
companion object {
private const val NOTIFICATION_ID = 1
private const val CHANNEL_ID = "ScreenRecordChannel"
}
}
< /code>
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
}
android {
namespace = "com.example.qahelper"
compileSdk = 36
defaultConfig {
applicationId = "com.example.qahelper"
minSdk = 29
targetSdk = 36
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
}
< /code>
screenRecordService.kt:103:23 неразрешенная ссылка 'setaudioplaybackcaptureconfig'. /> Я проверил код, но проблема не была обнаружена.
Я только что получил справочную ошибку. < /P>
Подробнее здесь: https://stackoverflow.com/questions/797 ... tureconfig
Неразрешенная ссылка 'setaudoplaybackcaptureconfig' ⇐ Android
Форум для тех, кто программирует под Android
-
Anonymous
1757835707
Anonymous
package com.example.qahelper
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.Context
import android.content.Intent
import android.hardware.display.DisplayManager
import android.hardware.display.VirtualDisplay
import android.media.AudioAttributes
import android.media.AudioPlaybackCaptureConfiguration
import android.media.MediaRecorder
import android.media.projection.MediaProjection
import android.media.projection.MediaProjectionManager
import android.os.Build
import android.os.Environment
import android.os.Handler
import android.os.IBinder
import android.os.Looper
import androidx.core.app.NotificationCompat
import java.io.File
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*
import kotlin.concurrent.thread
class ScreenRecordService : Service() {
private lateinit var mediaProjectionManager: MediaProjectionManager
private var mediaProjection: MediaProjection? = null
private var virtualDisplay: VirtualDisplay? = null
private lateinit var mediaRecorder: MediaRecorder
private val mediaProjectionCallback = object : MediaProjection.Callback() {
override fun onStop() {
super.onStop()
stopRecording()
stopSelf()
}
}
override fun onCreate() {
super.onCreate()
mediaProjectionManager = getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
createNotificationChannel()
startForeground(NOTIFICATION_ID, createNotification())
thread { startRecording(intent) }
return START_STICKY
}
private fun startRecording(intent: Intent?) {
intent?.let {
val resultCode = it.getIntExtra("resultCode", -1)
val data: Intent? = it.getParcelableExtra("data")
if (data != null) {
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data)
mediaProjection?.registerCallback(mediaProjectionCallback, Handler(Looper.getMainLooper()))
setupMediaRecorder()
createVirtualDisplay()
try {
mediaRecorder.start()
} catch (e: IllegalStateException) {
e.printStackTrace()
stopSelf()
}
} else { stopSelf() }
} ?: stopSelf()
}
private fun setupMediaRecorder() {
mediaRecorder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
MediaRecorder(this)
} else {
@Suppress("DEPRECATION")
MediaRecorder()
}
val displayMetrics = resources.displayMetrics
val videoPath = generateFilePath()
mediaRecorder.apply {
// >
setAudioSource(MediaRecorder.AudioSource.VOICE_UPLINK)
setVideoSource(MediaRecorder.VideoSource.SURFACE)
setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
setOutputFile(videoPath)
setVideoSize(displayMetrics.widthPixels, displayMetrics.heightPixels)
setVideoEncoder(MediaRecorder.VideoEncoder.H264)
setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
setVideoEncodingBitRate(8 * 1024 * 1024)
setVideoFrameRate(30)
}
// >
val config = AudioPlaybackCaptureConfiguration.Builder(mediaProjection!!)
.addMatchingUsage(AudioAttributes.USAGE_MEDIA)
.addMatchingUsage(AudioAttributes.USAGE_GAME)
.build()
mediaRecorder.setAudioPlaybackCaptureConfig(config)
try {
mediaRecorder.prepare()
} catch (e: IOException) {
e.printStackTrace()
}
}
private fun generateFilePath(): String {
val moviesDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)
val appDir = File(moviesDir, "QAHelperRecords")
if (!appDir.exists()) {
appDir.mkdirs()
}
val sdf = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault())
return File(appDir, "record_${sdf.format(Date())}.mp4").absolutePath
}
private fun createVirtualDisplay() {
val displayMetrics = resources.displayMetrics
virtualDisplay = mediaProjection?.createVirtualDisplay(
"ScreenRecordService", displayMetrics.widthPixels, displayMetrics.heightPixels, displayMetrics.densityDpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mediaRecorder.surface, null, null
)
}
override fun onDestroy() {
super.onDestroy()
stopRecording()
}
private fun stopRecording() {
try {
mediaProjection?.unregisterCallback(mediaProjectionCallback)
mediaRecorder.stop()
mediaRecorder.reset()
mediaRecorder.release()
virtualDisplay?.release()
mediaProjection?.stop()
} catch (e: Exception) { e.printStackTrace() }
}
private fun createNotification(): Notification {
return NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("화면 녹화 중")
.setContentText("앱이 화면을 녹화하고 있습니다.")
.setSmallIcon(R.mipmap.ic_launcher)
.build()
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
CHANNEL_ID, "Screen Record Channel", NotificationManager.IMPORTANCE_DEFAULT
)
getSystemService(NotificationManager::class.java).createNotificationChannel(channel)
}
}
override fun onBind(intent: Intent?): IBinder? = null
companion object {
private const val NOTIFICATION_ID = 1
private const val CHANNEL_ID = "ScreenRecordChannel"
}
}
< /code>
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
}
android {
namespace = "com.example.qahelper"
compileSdk = 36
defaultConfig {
applicationId = "com.example.qahelper"
minSdk = 29
targetSdk = 36
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = "11"
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
}
< /code>
screenRecordService.kt:103:23 неразрешенная ссылка 'setaudioplaybackcaptureconfig'. /> Я проверил код, но проблема не была обнаружена.
Я только что получил справочную ошибку. < /P>
Подробнее здесь: [url]https://stackoverflow.com/questions/79764154/unresolved-reference-setaudioplaybackcaptureconfig[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия