From 278e631b6d3deb8582aa2a5d4172259e498ee788 Mon Sep 17 00:00:00 2001
From: SheTieJun <375105540@qq.com>
Date: Thu, 21 Mar 2024 16:52:04 +0800
Subject: [PATCH] =?UTF-8?q?:white=5Fcheck=5Fmark:=20=E6=9B=B4=E6=96=B0demo?=
=?UTF-8?q?=20=E5=85=BC=E5=AE=B934?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/build.gradle.kts | 3 +-
app/src/main/AndroidManifest.xml | 13 +-
.../java/me/shetj/mp3recorder/MainActivity.kt | 34 +----
.../record/activity/mix/RecordActivity.kt | 7 +-
.../record/activity/mix/RecordPage.kt | 35 ++---
.../record/utils/LocalMusicQUtils.kt | 133 ++++++++++++------
.../mp3recorder/record/utils/RecordUtils.kt | 48 +++----
.../bg_record_pop_content.9.png | Bin 0 -> 5899 bytes
.../main/res/drawable/bg_circle_record.xml | 2 +-
.../main/res/layout/activity_main_test.xml | 8 --
.../main/res/layout/activity_my_record.xml | 4 +-
app/src/main/res/values/styles.xml | 2 +-
settings.gradle.kts | 1 -
13 files changed, 142 insertions(+), 148 deletions(-)
create mode 100644 app/src/main/res/drawable-xxhdpi/bg_record_pop_content.9.png
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 181e99c..c12ebf5 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -10,6 +10,7 @@ plugins {
androidApplication("me.shetj.mp3recorder"){
defaultConfig {
+ minSdk = 24
ndk {
this.abiFilters.addAll(listOf("armeabi-v7a", "arm64-v8a", "x86_64", "x86"))
}
@@ -37,9 +38,7 @@ dependencies {
implementation(project(":recorder-mix"))
implementation(project(":recorder-sim"))
implementation(project(":recorder-core"))
- implementation(project(":recorder-ui"))
implementation(project(":recorder-st"))
implementation("com.github.SheTieJun:BaseKit:85dc1cb78d")
ksp(libs.androidx.room.compiler)
- implementation("com.github.SheTieJun:OrangeDialog:0.0.2")
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index d0452cf..f0c2c04 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,8 +3,13 @@
>
-
-
+
+
+
+
+
@@ -18,7 +23,7 @@
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/icon_record_app"
android:supportsRtl="true"
- android:theme="@style/BaseTheme.MD3">
+ android:theme="@style/AppTheme">
diff --git a/app/src/main/java/me/shetj/mp3recorder/MainActivity.kt b/app/src/main/java/me/shetj/mp3recorder/MainActivity.kt
index 788151a..9ea9563 100644
--- a/app/src/main/java/me/shetj/mp3recorder/MainActivity.kt
+++ b/app/src/main/java/me/shetj/mp3recorder/MainActivity.kt
@@ -1,7 +1,6 @@
package me.shetj.mp3recorder
-import android.Manifest
import android.animation.ObjectAnimator
import android.content.Context
import android.graphics.Color
@@ -14,19 +13,16 @@ import androidx.core.animation.doOnEnd
import androidx.core.splashscreen.SplashScreen
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.lifecycle.lifecycleScope
-import kotlinx.coroutines.NonCancellable.start
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import me.shetj.base.BaseKit
-import me.shetj.base.ktx.hasPermission
+import me.shetj.base.fix.FixPermission
import me.shetj.base.ktx.setAppearance
-import me.shetj.base.ktx.showToast
import me.shetj.base.ktx.start
import me.shetj.base.mvvm.viewbind.BaseBindingActivity
import me.shetj.base.mvvm.viewbind.BaseViewModel
import me.shetj.mp3recorder.databinding.ActivityMainTestBinding
import me.shetj.mp3recorder.record.activity.mix.RecordActivity
-import me.shetj.recorder.ui.RecorderPopup
class MainActivity : BaseBindingActivity() {
private var splashScreen: SplashScreen? =null
@@ -60,34 +56,14 @@ class MainActivity : BaseBindingActivity
super.onCreate(savedInstanceState)
}
- private val recorderPopup: RecorderPopup by lazy {
- RecorderPopup(this, needPlay = false, maxTime = (10 * 1000).toLong()) {
- it.showToast()
- }
- }
-
override fun initBaseView() {
- hasPermission(
- Manifest.permission.WRITE_EXTERNAL_STORAGE,
- Manifest.permission.READ_EXTERNAL_STORAGE,
- Manifest.permission.RECORD_AUDIO,
- isRequest = true
- )
mBinding.btnDemo3.setOnClickListener {
- if (hasPermission(
- Manifest.permission.WRITE_EXTERNAL_STORAGE,
- Manifest.permission.READ_EXTERNAL_STORAGE,
- Manifest.permission.RECORD_AUDIO, isRequest = true
- )
- ) {
+ if (FixPermission.checkReadMediaFile(this, isRequest = true)) {
start()
}
}
- mBinding.btnDemo4.setOnClickListener {
- recorderPopup.showPop()
- }
mBinding.msg.apply {
append("获取当前手机录音最佳参数:")
append("最佳采样率:${getBestSampleRate()}\n")
@@ -129,10 +105,4 @@ class MainActivity : BaseBindingActivity
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
-
- override fun onBackPressed() {
- if (recorderPopup.onBackPress()) {
- super.onBackPressed()
- }
- }
}
diff --git a/app/src/main/java/me/shetj/mp3recorder/record/activity/mix/RecordActivity.kt b/app/src/main/java/me/shetj/mp3recorder/record/activity/mix/RecordActivity.kt
index c9b06b5..ebecba8 100644
--- a/app/src/main/java/me/shetj/mp3recorder/record/activity/mix/RecordActivity.kt
+++ b/app/src/main/java/me/shetj/mp3recorder/record/activity/mix/RecordActivity.kt
@@ -17,6 +17,7 @@ import me.shetj.mp3recorder.R
import me.shetj.mp3recorder.record.RecordingNotification
import me.shetj.mp3recorder.record.utils.EventCallback
import kotlinx.coroutines.delay
+import me.shetj.base.fix.FixPermission
import me.shetj.base.ktx.launch
@@ -96,11 +97,7 @@ class RecordActivity : BaseActivity(), EventCallback {
}
private fun canRecord() {
- hasPermission(
- Manifest.permission.READ_EXTERNAL_STORAGE,
- Manifest.permission.WRITE_EXTERNAL_STORAGE,
- Manifest.permission.RECORD_AUDIO, isRequest = true
- )
+ FixPermission.checkReadMediaFile(this,true)
}
override fun onBackPressed() {
diff --git a/app/src/main/java/me/shetj/mp3recorder/record/activity/mix/RecordPage.kt b/app/src/main/java/me/shetj/mp3recorder/record/activity/mix/RecordPage.kt
index 81a33bd..8929d21 100644
--- a/app/src/main/java/me/shetj/mp3recorder/record/activity/mix/RecordPage.kt
+++ b/app/src/main/java/me/shetj/mp3recorder/record/activity/mix/RecordPage.kt
@@ -15,6 +15,7 @@ import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatButton
import androidx.lifecycle.lifecycleScope
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.flow.MutableSharedFlow
@@ -22,7 +23,6 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.shetj.base.ktx.logI
import me.shetj.base.tools.app.ArmsUtils
-import me.shetj.dialog.OrangeDialog
import me.shetj.mp3recorder.R
import me.shetj.mp3recorder.databinding.PageRecordMixBinding
import me.shetj.mp3recorder.record.bean.MusicQ
@@ -195,10 +195,6 @@ open class RecordPage(
}
- override fun onReset() {
- super.onReset()
- }
-
override fun needPermission() {
callback.onEvent(3)
}
@@ -245,13 +241,13 @@ open class RecordPage(
* 是否录制新内容
*/
private fun showRecordNewDialog() {
- OrangeDialog.Builder(context)
+ MaterialAlertDialogBuilder(context)
.setTitle("录音已保存")
- .setContent("录音已保存。是否继续录制下一条?")
- .setNegativeText("查看本条")
- .setOnNegativeCallBack { _, _ -> callback.onEvent(1) }
- .setPositiveText("录下一条")
- .setonPositiveCallBack { _, _ ->
+ .setMessage("录音已保存。是否继续录制下一条?")
+ .setNegativeButton("查看本条"){
+ _, _ -> callback.onEvent(1)
+ }
+ .setPositiveButton("录下一条"){ _, _ ->
setRecord(null)
ArmsUtils.makeText("上条录音已保存至“我的录音”")
}
@@ -326,18 +322,17 @@ open class RecordPage(
* 展示重新录制
*/
private fun showRerecordDialog() {
- OrangeDialog.Builder(context)
+ MaterialAlertDialogBuilder(context)
.setTitle("重新录制")
- .setContent("确定删除当前的录音,并重新录制吗?")
- .setNegativeText("取消").setOnNegativeCallBack { _, _ -> recordUtils!!.stopFullRecord() }
- .setPositiveText("重录").setonPositiveCallBack { _, _ ->
+ .setMessage("确定删除当前的录音,并重新录制吗?")
+ .setNegativeButton("取消") { _, _ -> recordUtils!!.stopFullRecord() }
+ .setPositiveButton("重录") { _, _ ->
//可自行判断是否删除老的文件
oldRecord?.audioLength = 0
oldRecord?.audio_url = ""
setRecord(oldRecord)
recordUtils!!.reset()
recordUtils!!.setTime(0)
-
}
.show()
}
@@ -347,11 +342,11 @@ open class RecordPage(
*/
private fun showTipDialog() {
onPause()//先暂停
- OrangeDialog.Builder(context)
+ MaterialAlertDialogBuilder(context)
.setTitle("温馨提示")
- .setContent("确定要停止录音吗?")
- .setNegativeText("停止录音").setOnNegativeCallBack { _, _ -> recordUtils!!.stopFullRecord() }
- .setPositiveText("继续录音").setonPositiveCallBack { _, _ -> recordUtils!!.startOrPause() }
+ .setMessage("确定要停止录音吗?")
+ .setNegativeButton("停止录音") { _, _ -> recordUtils!!.stopFullRecord() }
+ .setPositiveButton("继续录音") { _, _ -> recordUtils!!.startOrPause() }
.show()
}
diff --git a/app/src/main/java/me/shetj/mp3recorder/record/utils/LocalMusicQUtils.kt b/app/src/main/java/me/shetj/mp3recorder/record/utils/LocalMusicQUtils.kt
index c9f2c6e..a194c56 100644
--- a/app/src/main/java/me/shetj/mp3recorder/record/utils/LocalMusicQUtils.kt
+++ b/app/src/main/java/me/shetj/mp3recorder/record/utils/LocalMusicQUtils.kt
@@ -1,16 +1,20 @@
-
package me.shetj.mp3recorder.record.utils
import android.annotation.SuppressLint
+import android.content.ContentResolver
import android.content.ContentUris
import android.content.Context
+import android.database.Cursor
import android.net.Uri
+import android.os.Build
+import android.os.Bundle
+import android.os.CancellationSignal
import android.provider.MediaStore
-import me.shetj.mp3recorder.record.bean.MusicQ
-import java.util.*
-import java.util.concurrent.TimeUnit
+import androidx.annotation.RequiresApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
+import me.shetj.mp3recorder.record.bean.MusicQ
+import java.util.*
/**
@@ -24,60 +28,103 @@ object LocalMusicQUtils {
@SuppressLint("Range")
@JvmStatic
fun loadFileData(context: Context): Flow> {
- return flow{
- val resolver = context.contentResolver
+ return flow {
val projection = arrayOf(
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Audio.Media.DURATION,
- MediaStore.Audio.Media.SIZE
- )
-
-// Show only videos that are at least 5 minutes in duration.
- val selection = "${MediaStore.Video.Media.DURATION} >= ?"
- val selectionArgs = arrayOf(
- TimeUnit.MILLISECONDS.convert(2, TimeUnit.MINUTES).toString()
+ MediaStore.Audio.Media.SIZE,
+ MediaStore.Audio.Media.ALBUM,
+ MediaStore.Audio.Media.DATE_ADDED,
+ MediaStore.Audio.Media.ARTIST
)
-
-// Display videos in alphabetical order based on their display name.
- val sortOrder = "${MediaStore.Video.Media.DISPLAY_NAME} ASC"
-
- val cursor = context.contentResolver.query(
- MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
- null,
- null,
- null,
- null
- )!!
- val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)
val musicList = ArrayList()
- if (cursor.moveToFirst()) {
- do {
- val title =
- cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME))
-// val size = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.SIZE))
-// val url = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA))
- val id = cursor.getLong(idColumn)
- val contentUri: Uri = ContentUris.withAppendedId(
- MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id
- )
- val duration =
- cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION))
- val album =
- cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM))
- if (duration in 60000..2000000) {
+ createCursor(
+ contentResolver = context.contentResolver,
+ collection = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
+ projection = projection,
+ orderBy = MediaStore.Images.Media.DATE_ADDED,
+ orderAscending = false,
+ limit = 1000,
+ offset = 0
+ )?.use { cursor ->
+ val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID)
+ if (cursor.moveToFirst()) {
+ do {
+ val title =
+ cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME))
+ val id = cursor.getLong(idColumn)
+ val contentUri: Uri = ContentUris.withAppendedId(
+ MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id
+ )
+ val duration =
+ cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION))
+ val album =
+ cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM))
val music = MusicQ()
music.name = title
music.url = contentUri
music.duration = duration
music.imgUrl = album
musicList.add(music)
- }
- } while (cursor.moveToNext())
+ } while (cursor.moveToNext())
+ }
}
- cursor.close()
emit(musicList)
}
+ }
+
+
+
+
+ private fun createCursor(
+ contentResolver: ContentResolver,
+ collection: Uri,
+ projection: Array,
+ orderBy: String,
+ orderAscending: Boolean,
+ limit: Int = 20,
+ offset: Int = 0
+ ): Cursor? = when {
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
+ val selection = createSelectionBundle(orderBy, orderAscending, limit, offset)
+ contentResolver.query(collection, projection, selection, CancellationSignal())
+ }
+
+ else -> {
+ val orderDirection = if (orderAscending) "ASC" else "DESC"
+ var order = when (orderBy) {
+ "ALPHABET" -> "${MediaStore.Audio.Media.TITLE}, ${MediaStore.Audio.Media.ARTIST} $orderDirection"
+ else -> "${MediaStore.Audio.Media.DATE_ADDED} $orderDirection"
+ }
+ order += " LIMIT $limit OFFSET $offset"
+ contentResolver.query(collection, projection, null, null, order)
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.O)
+ fun createSelectionBundle(
+ orderBy: String,
+ orderAscending: Boolean,
+ limit: Int = 20,
+ offset: Int = 0
+ ): Bundle = Bundle().apply {
+ putInt(ContentResolver.QUERY_ARG_LIMIT, limit)
+ putInt(ContentResolver.QUERY_ARG_OFFSET, offset)
+ when (orderBy) {
+ "ALPHABET" -> putStringArray(
+ ContentResolver.QUERY_ARG_SORT_COLUMNS,
+ arrayOf(MediaStore.Files.FileColumns.TITLE)
+ )
+ else -> putStringArray(
+ ContentResolver.QUERY_ARG_SORT_COLUMNS,
+ arrayOf(MediaStore.Files.FileColumns.DATE_ADDED)
+ )
+ }
+ val orderDirection =
+ if (orderAscending) ContentResolver.QUERY_SORT_DIRECTION_ASCENDING else ContentResolver.QUERY_SORT_DIRECTION_DESCENDING
+ putInt(ContentResolver.QUERY_ARG_SORT_DIRECTION, orderDirection)
}
+
}
\ No newline at end of file
diff --git a/app/src/main/java/me/shetj/mp3recorder/record/utils/RecordUtils.kt b/app/src/main/java/me/shetj/mp3recorder/record/utils/RecordUtils.kt
index 9413ccf..7a9e07e 100644
--- a/app/src/main/java/me/shetj/mp3recorder/record/utils/RecordUtils.kt
+++ b/app/src/main/java/me/shetj/mp3recorder/record/utils/RecordUtils.kt
@@ -1,4 +1,3 @@
-
package me.shetj.mp3recorder.record.utils
import android.content.Context
@@ -11,13 +10,12 @@ import android.view.View
import android.widget.Toast
import androidx.core.content.ContextCompat.getSystemService
import androidx.lifecycle.MutableLiveData
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import me.shetj.base.BaseKit
+import me.shetj.base.ktx.logD
import me.shetj.base.ktx.logI
import me.shetj.base.tools.app.Utils
import me.shetj.base.tools.file.EnvironmentStorage
-import me.shetj.dialog.OrangeDialog
-import me.shetj.dialog.SingleChoiceCallback
-import me.shetj.dialog.orangeSingeDialog
import me.shetj.mp3recorder.record.RecordingNotification
import me.shetj.ndk.lame.LameUtils
import me.shetj.player.PlayerListener
@@ -34,7 +32,7 @@ import kotlin.math.sqrt
*/
class RecordUtils(
private val callBack: SimRecordListener?
-) : RecordListener, PermissionListener,PCMListener {
+) : RecordListener, PermissionListener, PCMListener {
private var bgmUrl: Uri? = null
private var listener: PlayerListener? = null
@@ -83,36 +81,27 @@ class RecordUtils(
mRecorder?.setOutputFile(saveFile, !TextUtils.isEmpty(file))
mRecorder?.start()
}
+
RecordState.PAUSED -> {
mRecorder?.resume()
}
+
RecordState.RECORDING -> {
mRecorder?.pause()
}
+
else -> {}
}
}
fun showChangeDialog(context: Context) {
- orangeSingeDialog(
- context = context,
- title = "切换录音工具",
- content = "建议不要在录音中进行切换,切换时会自动默认完成",
- items = arrayOf("MixRecorder", "SimRecorder", "STRecorder"),
- selectIndex = getSelectPosition(recorderType),
- singleChoiceCallBack = object : SingleChoiceCallback {
- override fun invoke(
- dialog: OrangeDialog,
- itemView: View,
- which: Int,
- text: CharSequence?
- ): Boolean {
- updateRecorderType(which)
- dialog.dismiss()
- return true
- }
+ MaterialAlertDialogBuilder(context)
+ .setTitle("切换录音工具")
+ .setMessage("建议不要在录音中进行切换,切换时会自动默认完成")
+ .setSingleChoiceItems(arrayOf("MixRecorder", "SimRecorder", "STRecorder"), getSelectPosition(recorderType)) { dialog, which ->
+ updateRecorderType(which)
+ dialog.dismiss()
}
- )
}
fun getRecorderTypeName(): String {
@@ -173,6 +162,7 @@ class RecordUtils(
it.isEnableVBR(false) // 请不要使用,虽然可以正常播放,但是会时间错误获取会错误,暂时没有解决方法
it.setFilter(3000, 200)
}
+
BaseRecorder.RecorderType.SIM -> it.buildSim(Utils.app)
BaseRecorder.RecorderType.ST -> it.buildST()
}
@@ -190,7 +180,7 @@ class RecordUtils(
}
fun startOrPauseBGM() {
- mRecorder?.let { recorder->
+ mRecorder?.let { recorder ->
if (recorder.isPlayMusic()) {
if (recorder.isPauseMusic()) {
recorder.resumeMusic()
@@ -226,7 +216,7 @@ class RecordUtils(
*/
fun setTime(startTime: Long) {
mRecorder?.setCurDuration(startTime)
- callBack?.onRecording(startTime , -1)
+ callBack?.onRecording(startTime, -1)
}
/**
@@ -271,7 +261,7 @@ class RecordUtils(
}
override fun onRecording(time: Long, volume: Int) {
- callBack?.onRecording((startTime + time) , volume)
+ callBack?.onRecording((startTime + time), volume)
}
override fun onPause() {
@@ -311,11 +301,11 @@ class RecordUtils(
}
override fun onBeforePCMToMp3(pcm: ShortArray): ShortArray {
- val pcmdb =calculateRealVolume(pcm, pcm.size)
- Log.d("onBeforePCMToMp3","修改PCM前DB:$pcmdb" )
+ val pcmdb = calculateRealVolume(pcm, pcm.size)
+ "修改PCM前DB:$pcmdb".logD("onBeforePCMToMp3")
val adjustVoice = BytesTransUtil.adjustVoice(pcm, 3)
val afterdb = calculateRealVolume(adjustVoice, adjustVoice.size)
- Log.d("onBeforePCMToMp3","修改PCM后DB:$afterdb" )
+ "修改PCM后DB:$afterdb".logD("onBeforePCMToMp3")
return adjustVoice
}
diff --git a/app/src/main/res/drawable-xxhdpi/bg_record_pop_content.9.png b/app/src/main/res/drawable-xxhdpi/bg_record_pop_content.9.png
new file mode 100644
index 0000000000000000000000000000000000000000..3c7b30bafd38ac295b49826ee40947d4f4572405
GIT binary patch
literal 5899
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
literal 0
HcmV?d00001
diff --git a/app/src/main/res/drawable/bg_circle_record.xml b/app/src/main/res/drawable/bg_circle_record.xml
index d559469..4be7bd3 100644
--- a/app/src/main/res/drawable/bg_circle_record.xml
+++ b/app/src/main/res/drawable/bg_circle_record.xml
@@ -2,7 +2,7 @@
-
-
-
-
+ />
\ No newline at end of file
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index d011475..6795ad5 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -1,7 +1,7 @@
-