Мой код ниже продолжает сбои на Android Studio и на устройстве без журналов. Я все проверил и даже проверил похожие посты, но ни один, похоже, не отвечает на мой вопрос. Я пишу приложение, которое записывает аудио и хранит на устройстве.import android.Manifest
import android.R
import android.app.AlertDialog
import android.content.pm.PackageManager
import android.graphics.Color
import android.graphics.Typeface
import android.media.MediaRecorder
import android.os.Bundle
import android.util.Log
import android.util.TypedValue
import android.view.Gravity
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.LinearLayout
import android.widget.Spinner
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.zshift.zwriteai.DatabaseHelper
import com.zshift.zwriteai.Project
import com.zshift.zwriteai.Recording
import java.io.File
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
class AudioRecordActivity : AppCompatActivity() {
private var mediaRecorder: MediaRecorder? = null
private var audioFile: String? = null
private var recordButton: Button? = null
private var isRecording = false
private var dbHelper: DatabaseHelper? = null
private var projectSpinner: Spinner? = null
private var selectedProjectId = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Initialize database
dbHelper = DatabaseHelper(this)
// Request permissions
checkPermissions()
// Initialize UI
setupUI()
}
private fun setupUI() {
// Create main layout
val mainLayout = LinearLayout(this)
mainLayout.orientation = LinearLayout.VERTICAL
mainLayout.setBackgroundColor(Color.parseColor("#CF9FFF")) // Light Purple
mainLayout.setPadding(dpToPx(16), dpToPx(16), dpToPx(16), dpToPx(16))
// Create title text view
val titleTextView = TextView(this)
titleTextView.text = "Record Audio"
titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 30f)
titleTextView.setTextColor(Color.BLACK)
titleTextView.setTypeface(Typeface.DEFAULT_BOLD)
titleTextView.gravity = Gravity.CENTER
val titleParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT
)
titleParams.setMargins(0, 0, 0, dpToPx(20)) // Add some bottom margin
mainLayout.addView(titleTextView, titleParams)
// Create Project Spinner
val projectLabel = TextView(this)
projectLabel.text = "Select Project:"
projectLabel.setTextColor(Color.BLACK)
mainLayout.addView(projectLabel)
projectSpinner = Spinner(this)
val projects: MutableList = dbHelper?.allProjects!!.toMutableList()
if (projects.isEmpty()) {
val defaultProject: Project = Project()
defaultProject.id = -1
defaultProject.name = "No Projects Available"
projects.add(defaultProject)
}
val projectAdapter: ArrayAdapter =
ArrayAdapter(this, R.layout.simple_spinner_item, projects)
projectAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item)
projectSpinner!!.adapter = projectAdapter
mainLayout.addView(projectSpinner)
// Create record button
recordButton = Button(this)
recordButton!!.text = "Start Recording"
recordButton!!.setBackgroundColor(Color.parseColor("#E6E6FA")) // Lavender
recordButton!!.setTextColor(Color.BLACK)
val recordButtonParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT
)
mainLayout.addView(recordButton, recordButtonParams)
// Set click listener for the record button
recordButton!!.setOnClickListener {
if (isRecording) {
stopRecording()
} else {
startRecording()
}
}
// Set the main layout as the content view
setContentView(mainLayout)
}
private fun checkPermissions(): Boolean {
val isAudioPermissionGranted = ContextCompat.checkSelfPermission(
this,
Manifest.permission.RECORD_AUDIO
) == PackageManager.PERMISSION_GRANTED
val isAudioReadPermissionGranted = ContextCompat.checkSelfPermission(
this,
Manifest.permission.READ_MEDIA_AUDIO
) == PackageManager.PERMISSION_GRANTED
val isStoragePermissionGranted = ContextCompat.checkSelfPermission(
this,
Manifest.permission.MANAGE_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED
if (isAudioPermissionGranted && isStoragePermissionGranted && isAudioReadPermissionGranted) {
return true
} else {
if (ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.RECORD_AUDIO
) ||
ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.MANAGE_EXTERNAL_STORAGE
)
||
ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.READ_MEDIA_AUDIO
)
) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
AlertDialog.Builder(this)
.setTitle("Permission needed")
.setMessage("This app needs the Audio and Storage permissions to record audio.")
.setPositiveButton("OK") { dialog, which ->
requestPermissions()
}
.setNegativeButton("Cancel", null)
.create()
.show()
} else {
// No explanation needed, we can request the permission.
requestPermissions()
}
return false
}
}
private fun requestPermissions() {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.RECORD_AUDIO, Manifest.permission.MANAGE_EXTERNAL_STORAGE, Manifest.permission.READ_MEDIA_AUDIO),
PERMISSION_REQUEST_CODE
)
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == PERMISSION_REQUEST_CODE) {
if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
// Permissions granted, initialize UI
setupUI()
} else {
// Permissions denied, show a message and exit
Toast.makeText(
this,
"Permissions are required for this app to function. Please enable them in settings.",
Toast.LENGTH_LONG
).show()
finish()
}
}
}
private fun startRecording() {
if (!checkPermissions()) {
Toast.makeText(this, "Permissions not granted", Toast.LENGTH_SHORT).show()
return
}
if (projectSpinner!!.selectedItem == null) {
Toast.makeText(this, "Please select a project.", Toast.LENGTH_SHORT).show()
return
}
val selectedProject: Project = projectSpinner!!.selectedItem as Project
selectedProjectId = selectedProject.id
if (selectedProjectId == -1) {
Toast.makeText(
this,
"No projects available. Please create a project first.",
Toast.LENGTH_SHORT
).show()
return
}
// Get the next recording number for the selected project
val nextRecordingNumber: Int = dbHelper!!.getNextRecordingNumber(selectedProjectId)
// Set the output file name
val sdf = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault())
val timestamp = sdf.format(Date())
val fileName = "recording_$timestamp.3gp" // .3gp is a common audio format
audioFile = File(filesDir, fileName).absolutePath
mediaRecorder = MediaRecorder(this)
mediaRecorder!!.setAudioSource(MediaRecorder.AudioSource.MIC)
mediaRecorder!!.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP) // Use .3gp format
mediaRecorder!!.setOutputFile(audioFile)
mediaRecorder!!.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB) // Use AMR_NB encoder
try {
mediaRecorder!!.prepare()
mediaRecorder!!.start()
isRecording = true
recordButton!!.text = "Stop Recording"
Toast.makeText(this, "Recording started...", Toast.LENGTH_SHORT).show()
} catch (e: IOException) {
Log.e(TAG, "Error starting recording: " + e.message)
Toast.makeText(this, "Error starting recording: " + e.message, Toast.LENGTH_LONG).show()
cleanupMediaRecorder()
}
}
private fun stopRecording() {
if (mediaRecorder != null) {
try {
mediaRecorder!!.stop()
mediaRecorder!!.release()
isRecording = false
recordButton!!.text = "Start Recording"
Toast.makeText(this, "Recording stopped.", Toast.LENGTH_SHORT).show()
// Save recording to database
saveRecordingToDatabase(audioFile)
} catch (e: IllegalStateException) {
Log.e(TAG, "Error stopping recording: " + e.message)
Toast.makeText(this, "Error stopping recording.", Toast.LENGTH_SHORT).show()
} finally {
cleanupMediaRecorder()
}
} else {
Toast.makeText(this, "No recording to stop.", Toast.LENGTH_SHORT).show()
}
}
private fun cleanupMediaRecorder() {
if (mediaRecorder != null) {
mediaRecorder!!.release()
mediaRecorder = null
}
}
private fun saveRecordingToDatabase(filename: String?) {
val recording: Recording = Recording()
recording.projectId = selectedProjectId
recording.filename = filename
recording.timestamp = Date()
recording.recordingNumber = dbHelper!!.getNextRecordingNumber(selectedProjectId) // Get and set recording number
val recordingId: Long = dbHelper!!.addRecording(recording)
if (recordingId != -1L) {
Log.d(
TAG,
"Recording saved to database with ID: $recordingId"
)
} else {
Log.e(TAG, "Failed to save recording to database.")
Toast.makeText(this, "Failed to save recording.", Toast.LENGTH_SHORT).show()
}
}
// Helper method to convert dp to pixels
private fun dpToPx(dp: Int): Int {
return (dp * resources.displayMetrics.density).toInt()
}
override fun onDestroy() {
super.onDestroy()
cleanupMediaRecorder()
}
companion object {
private const val PERMISSION_REQUEST_CODE = 123
private const val TAG = "AudioRecordActivity"
}
}
Подробнее здесь: https://stackoverflow.com/questions/796 ... est-kotlin
Приложение сбоя по запросу разрешения [Kotlin] ⇐ Android
Форум для тех, кто программирует под Android
-
Anonymous
1746451497
Anonymous
Мой код ниже продолжает сбои на Android Studio и на устройстве без журналов. Я все проверил и даже проверил похожие посты, но ни один, похоже, не отвечает на мой вопрос. Я пишу приложение, которое записывает аудио и хранит на устройстве.import android.Manifest
import android.R
import android.app.AlertDialog
import android.content.pm.PackageManager
import android.graphics.Color
import android.graphics.Typeface
import android.media.MediaRecorder
import android.os.Bundle
import android.util.Log
import android.util.TypedValue
import android.view.Gravity
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.LinearLayout
import android.widget.Spinner
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.zshift.zwriteai.DatabaseHelper
import com.zshift.zwriteai.Project
import com.zshift.zwriteai.Recording
import java.io.File
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
class AudioRecordActivity : AppCompatActivity() {
private var mediaRecorder: MediaRecorder? = null
private var audioFile: String? = null
private var recordButton: Button? = null
private var isRecording = false
private var dbHelper: DatabaseHelper? = null
private var projectSpinner: Spinner? = null
private var selectedProjectId = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Initialize database
dbHelper = DatabaseHelper(this)
// Request permissions
checkPermissions()
// Initialize UI
setupUI()
}
private fun setupUI() {
// Create main layout
val mainLayout = LinearLayout(this)
mainLayout.orientation = LinearLayout.VERTICAL
mainLayout.setBackgroundColor(Color.parseColor("#CF9FFF")) // Light Purple
mainLayout.setPadding(dpToPx(16), dpToPx(16), dpToPx(16), dpToPx(16))
// Create title text view
val titleTextView = TextView(this)
titleTextView.text = "Record Audio"
titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 30f)
titleTextView.setTextColor(Color.BLACK)
titleTextView.setTypeface(Typeface.DEFAULT_BOLD)
titleTextView.gravity = Gravity.CENTER
val titleParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT
)
titleParams.setMargins(0, 0, 0, dpToPx(20)) // Add some bottom margin
mainLayout.addView(titleTextView, titleParams)
// Create Project Spinner
val projectLabel = TextView(this)
projectLabel.text = "Select Project:"
projectLabel.setTextColor(Color.BLACK)
mainLayout.addView(projectLabel)
projectSpinner = Spinner(this)
val projects: MutableList = dbHelper?.allProjects!!.toMutableList()
if (projects.isEmpty()) {
val defaultProject: Project = Project()
defaultProject.id = -1
defaultProject.name = "No Projects Available"
projects.add(defaultProject)
}
val projectAdapter: ArrayAdapter =
ArrayAdapter(this, R.layout.simple_spinner_item, projects)
projectAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item)
projectSpinner!!.adapter = projectAdapter
mainLayout.addView(projectSpinner)
// Create record button
recordButton = Button(this)
recordButton!!.text = "Start Recording"
recordButton!!.setBackgroundColor(Color.parseColor("#E6E6FA")) // Lavender
recordButton!!.setTextColor(Color.BLACK)
val recordButtonParams = LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT
)
mainLayout.addView(recordButton, recordButtonParams)
// Set click listener for the record button
recordButton!!.setOnClickListener {
if (isRecording) {
stopRecording()
} else {
startRecording()
}
}
// Set the main layout as the content view
setContentView(mainLayout)
}
private fun checkPermissions(): Boolean {
val isAudioPermissionGranted = ContextCompat.checkSelfPermission(
this,
Manifest.permission.RECORD_AUDIO
) == PackageManager.PERMISSION_GRANTED
val isAudioReadPermissionGranted = ContextCompat.checkSelfPermission(
this,
Manifest.permission.READ_MEDIA_AUDIO
) == PackageManager.PERMISSION_GRANTED
val isStoragePermissionGranted = ContextCompat.checkSelfPermission(
this,
Manifest.permission.MANAGE_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED
if (isAudioPermissionGranted && isStoragePermissionGranted && isAudioReadPermissionGranted) {
return true
} else {
if (ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.RECORD_AUDIO
) ||
ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.MANAGE_EXTERNAL_STORAGE
)
||
ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.READ_MEDIA_AUDIO
)
) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
AlertDialog.Builder(this)
.setTitle("Permission needed")
.setMessage("This app needs the Audio and Storage permissions to record audio.")
.setPositiveButton("OK") { dialog, which ->
requestPermissions()
}
.setNegativeButton("Cancel", null)
.create()
.show()
} else {
// No explanation needed, we can request the permission.
requestPermissions()
}
return false
}
}
private fun requestPermissions() {
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.RECORD_AUDIO, Manifest.permission.MANAGE_EXTERNAL_STORAGE, Manifest.permission.READ_MEDIA_AUDIO),
PERMISSION_REQUEST_CODE
)
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == PERMISSION_REQUEST_CODE) {
if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
// Permissions granted, initialize UI
setupUI()
} else {
// Permissions denied, show a message and exit
Toast.makeText(
this,
"Permissions are required for this app to function. Please enable them in settings.",
Toast.LENGTH_LONG
).show()
finish()
}
}
}
private fun startRecording() {
if (!checkPermissions()) {
Toast.makeText(this, "Permissions not granted", Toast.LENGTH_SHORT).show()
return
}
if (projectSpinner!!.selectedItem == null) {
Toast.makeText(this, "Please select a project.", Toast.LENGTH_SHORT).show()
return
}
val selectedProject: Project = projectSpinner!!.selectedItem as Project
selectedProjectId = selectedProject.id
if (selectedProjectId == -1) {
Toast.makeText(
this,
"No projects available. Please create a project first.",
Toast.LENGTH_SHORT
).show()
return
}
// Get the next recording number for the selected project
val nextRecordingNumber: Int = dbHelper!!.getNextRecordingNumber(selectedProjectId)
// Set the output file name
val sdf = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault())
val timestamp = sdf.format(Date())
val fileName = "recording_$timestamp.3gp" // .3gp is a common audio format
audioFile = File(filesDir, fileName).absolutePath
mediaRecorder = MediaRecorder(this)
mediaRecorder!!.setAudioSource(MediaRecorder.AudioSource.MIC)
mediaRecorder!!.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP) // Use .3gp format
mediaRecorder!!.setOutputFile(audioFile)
mediaRecorder!!.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB) // Use AMR_NB encoder
try {
mediaRecorder!!.prepare()
mediaRecorder!!.start()
isRecording = true
recordButton!!.text = "Stop Recording"
Toast.makeText(this, "Recording started...", Toast.LENGTH_SHORT).show()
} catch (e: IOException) {
Log.e(TAG, "Error starting recording: " + e.message)
Toast.makeText(this, "Error starting recording: " + e.message, Toast.LENGTH_LONG).show()
cleanupMediaRecorder()
}
}
private fun stopRecording() {
if (mediaRecorder != null) {
try {
mediaRecorder!!.stop()
mediaRecorder!!.release()
isRecording = false
recordButton!!.text = "Start Recording"
Toast.makeText(this, "Recording stopped.", Toast.LENGTH_SHORT).show()
// Save recording to database
saveRecordingToDatabase(audioFile)
} catch (e: IllegalStateException) {
Log.e(TAG, "Error stopping recording: " + e.message)
Toast.makeText(this, "Error stopping recording.", Toast.LENGTH_SHORT).show()
} finally {
cleanupMediaRecorder()
}
} else {
Toast.makeText(this, "No recording to stop.", Toast.LENGTH_SHORT).show()
}
}
private fun cleanupMediaRecorder() {
if (mediaRecorder != null) {
mediaRecorder!!.release()
mediaRecorder = null
}
}
private fun saveRecordingToDatabase(filename: String?) {
val recording: Recording = Recording()
recording.projectId = selectedProjectId
recording.filename = filename
recording.timestamp = Date()
recording.recordingNumber = dbHelper!!.getNextRecordingNumber(selectedProjectId) // Get and set recording number
val recordingId: Long = dbHelper!!.addRecording(recording)
if (recordingId != -1L) {
Log.d(
TAG,
"Recording saved to database with ID: $recordingId"
)
} else {
Log.e(TAG, "Failed to save recording to database.")
Toast.makeText(this, "Failed to save recording.", Toast.LENGTH_SHORT).show()
}
}
// Helper method to convert dp to pixels
private fun dpToPx(dp: Int): Int {
return (dp * resources.displayMetrics.density).toInt()
}
override fun onDestroy() {
super.onDestroy()
cleanupMediaRecorder()
}
companion object {
private const val PERMISSION_REQUEST_CODE = 123
private const val TAG = "AudioRecordActivity"
}
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79605935/app-crashes-on-permission-request-kotlin[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия