@@ -4,45 +4,46 @@ import android.content.Context
44import android.media.AudioAttributes
55import android.media.AudioManager
66import android.media.MediaPlayer
7+ import android.media.Ringtone
78import android.media.RingtoneManager
89import android.net.Uri
910import android.os.*
1011import android.text.TextUtils
12+ import androidx.annotation.RequiresApi
1113
1214class CallkitSoundPlayerManager (private val context : Context ) {
1315
1416 private var vibrator: Vibrator ? = null
1517 private var audioManager: AudioManager ? = null
1618
17- private var mediaPlayer : MediaPlayer ? = null
19+ private var ringtone : Ringtone ? = null
1820
21+ @RequiresApi(Build .VERSION_CODES .LOLLIPOP )
1922 fun play (data : Bundle ) {
2023 this .prepare()
2124 this .playSound(data)
2225 this .playVibrator()
2326 }
2427
2528 fun stop () {
26- mediaPlayer?.stop()
27- mediaPlayer?.release()
29+ ringtone?.stop()
2830 vibrator?.cancel()
2931
30- mediaPlayer = null
32+ ringtone = null
3133 vibrator = null
3234 }
3335
3436 fun destroy () {
35- mediaPlayer ?.stop()
36- mediaPlayer?.release()
37+ ringtone ?.stop()
38+
3739 vibrator?.cancel()
3840
39- mediaPlayer = null
41+ ringtone = null
4042 vibrator = null
4143 }
4244
4345 private fun prepare () {
44- mediaPlayer?.stop()
45- mediaPlayer?.release()
46+ ringtone?.stop()
4647 vibrator?.cancel()
4748 }
4849
@@ -74,6 +75,7 @@ class CallkitSoundPlayerManager(private val context: Context) {
7475 }
7576 }
7677
78+ @RequiresApi(Build .VERSION_CODES .LOLLIPOP )
7779 private fun playSound (data : Bundle ? ) {
7880 val sound = data?.getString(
7981 CallkitConstants .EXTRA_CALLKIT_RINGTONE_PATH ,
@@ -85,41 +87,51 @@ class CallkitSoundPlayerManager(private val context: Context) {
8587 return
8688 }
8789 try {
88- mediaPlayer(uri)
90+ ringtone = RingtoneManager .getRingtone(context, uri)
91+ ringtone?.apply {
92+ audioAttributes = AudioAttributes .Builder ()
93+ .setUsage(AudioAttributes .USAGE_NOTIFICATION_RINGTONE )
94+ .setContentType(AudioAttributes .CONTENT_TYPE_SONIFICATION )
95+ .build()
96+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .P ) {
97+ isLooping = true
98+ }
99+ play()
100+ }
89101 } catch (e: Exception ) {
90102 e.printStackTrace()
91103 }
92104 }
93105
94- private fun mediaPlayer (uri : Uri ) {
95- mediaPlayer = MediaPlayer ()
96- if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .LOLLIPOP ) {
97- val attribution = AudioAttributes .Builder ()
98- .setContentType(AudioAttributes .CONTENT_TYPE_SONIFICATION )
99- .setUsage(AudioAttributes .USAGE_NOTIFICATION_RINGTONE )
100- .setLegacyStreamType(AudioManager .STREAM_RING )
101- .build()
102- mediaPlayer?.setAudioAttributes(attribution)
103- } else {
104- mediaPlayer?.setAudioStreamType(AudioManager .STREAM_RING )
105- }
106- setDataSource(uri)
107- mediaPlayer?.prepare()
108- mediaPlayer?.isLooping = true
109- mediaPlayer?.start()
110- }
111-
112- private fun setDataSource (uri : Uri ) {
113- if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .N ) {
114- val assetFileDescriptor =
115- context.contentResolver.openAssetFileDescriptor(uri, " r" )
116- if (assetFileDescriptor != null ) {
117- mediaPlayer?.setDataSource(assetFileDescriptor)
118- }
119- return
120- }
121- mediaPlayer?.setDataSource(context, uri)
122- }
106+ // private fun mediaPlayer(uri: Uri) {
107+ // mediaPlayer = MediaPlayer()
108+ // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
109+ // val attribution = AudioAttributes.Builder()
110+ // .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
111+ // .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
112+ // .setLegacyStreamType(AudioManager.STREAM_RING)
113+ // .build()
114+ // mediaPlayer?.setAudioAttributes(attribution)
115+ // } else {
116+ // mediaPlayer?.setAudioStreamType(AudioManager.STREAM_RING)
117+ // }
118+ // setDataSource(uri)
119+ // mediaPlayer?.prepare()
120+ // mediaPlayer?.isLooping = true
121+ // mediaPlayer?.start()
122+ // }
123+
124+ // private fun setDataSource(uri: Uri) {
125+ // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
126+ // val assetFileDescriptor =
127+ // context.contentResolver.openAssetFileDescriptor(uri, "r")
128+ // if (assetFileDescriptor != null) {
129+ // mediaPlayer?.setDataSource(assetFileDescriptor)
130+ // }
131+ // return
132+ // }
133+ // mediaPlayer?.setDataSource(context, uri)
134+ // }
123135
124136 private fun getRingtoneUri (fileName : String ): Uri ? {
125137 if (TextUtils .isEmpty(fileName)) {
@@ -166,4 +178,33 @@ class CallkitSoundPlayerManager(private val context: Context) {
166178 return null
167179 }
168180 }
181+
182+ private fun getSafeSystemRingtoneUri (): Uri ? {
183+ val defaultUri = RingtoneManager .getActualDefaultRingtoneUri(
184+ context,
185+ RingtoneManager .TYPE_RINGTONE
186+ )
187+
188+ val rm = RingtoneManager (context)
189+ rm.setType(RingtoneManager .TYPE_RINGTONE )
190+ val cursor = rm.cursor
191+ if (defaultUri != null && cursor != null ) {
192+ while (cursor.moveToNext()) {
193+ val uri = rm.getRingtoneUri(cursor.position)
194+ if (uri == defaultUri) {
195+ cursor.close()
196+ return defaultUri
197+ }
198+ }
199+ }
200+
201+ // Default isn't system-provided → fallback to first available
202+ if (cursor != null && cursor.moveToFirst()) {
203+ val fallback = rm.getRingtoneUri(cursor.position)
204+ cursor.close()
205+ return fallback
206+ }
207+
208+ return null
209+ }
169210}
0 commit comments