11package com.hiennv.flutter_callkit_incoming
22
3+ import android.content.BroadcastReceiver
34import android.content.Context
5+ import android.content.Intent
6+ import android.content.IntentFilter
47import android.media.AudioAttributes
58import android.media.AudioManager
6- import android.media.MediaPlayer
79import android.media.Ringtone
810import android.media.RingtoneManager
911import android.net.Uri
1012import android.os.*
1113import android.text.TextUtils
12- import androidx.annotation.RequiresApi
1314
1415class CallkitSoundPlayerManager (private val context : Context ) {
1516
@@ -18,14 +19,35 @@ class CallkitSoundPlayerManager(private val context: Context) {
1819
1920 private var ringtone: Ringtone ? = null
2021
21- @RequiresApi(Build .VERSION_CODES .LOLLIPOP )
22+ private var isPlaying: Boolean = false
23+
24+
25+ inner class ScreenOffCallkitIncomingBroadcastReceiver : BroadcastReceiver () {
26+ override fun onReceive (context : Context , intent : Intent ) {
27+ if (isPlaying){
28+ stop()
29+ }
30+ }
31+ }
32+
33+ private var screenOffCallkitIncomingBroadcastReceiver = ScreenOffCallkitIncomingBroadcastReceiver ()
34+
35+
36+ init {
37+ val filter = IntentFilter (Intent .ACTION_SCREEN_OFF )
38+ context.registerReceiver(screenOffCallkitIncomingBroadcastReceiver, filter)
39+ }
40+
41+
2242 fun play (data : Bundle ) {
2343 this .prepare()
2444 this .playSound(data)
2545 this .playVibrator()
46+ this .isPlaying = true
2647 }
2748
2849 fun stop () {
50+ this .isPlaying = false
2951 ringtone?.stop()
3052 vibrator?.cancel()
3153
@@ -34,8 +56,10 @@ class CallkitSoundPlayerManager(private val context: Context) {
3456 }
3557
3658 fun destroy () {
37- ringtone?.stop()
59+ this .isPlaying = false
60+ context.unregisterReceiver(screenOffCallkitIncomingBroadcastReceiver)
3861
62+ ringtone?.stop()
3963 vibrator?.cancel()
4064
4165 ringtone = null
@@ -75,7 +99,6 @@ class CallkitSoundPlayerManager(private val context: Context) {
7599 }
76100 }
77101
78- @RequiresApi(Build .VERSION_CODES .LOLLIPOP )
79102 private fun playSound (data : Bundle ? ) {
80103 val sound = data?.getString(
81104 CallkitConstants .EXTRA_CALLKIT_RINGTONE_PATH ,
@@ -88,51 +111,25 @@ class CallkitSoundPlayerManager(private val context: Context) {
88111 }
89112 try {
90113 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()
114+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .LOLLIPOP ) {
115+ val attribution = AudioAttributes .Builder ()
116+ .setContentType(AudioAttributes .CONTENT_TYPE_SONIFICATION )
117+ .setUsage(AudioAttributes .USAGE_NOTIFICATION_RINGTONE )
118+ .setLegacyStreamType(AudioManager .STREAM_RING )
119+ .build()
120+ ringtone?.setAudioAttributes(attribution)
121+ }else {
122+ ringtone?.streamType = AudioManager .STREAM_RING
123+ }
124+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .P ) {
125+ ringtone?.isLooping = true
100126 }
127+ ringtone?.play()
101128 } catch (e: Exception ) {
102129 e.printStackTrace()
103130 }
104131 }
105132
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- // }
135-
136133 private fun getRingtoneUri (fileName : String ): Uri ? {
137134 if (TextUtils .isEmpty(fileName)) {
138135 return getDefaultRingtoneUri()
@@ -175,36 +172,39 @@ class CallkitSoundPlayerManager(private val context: Context) {
175172 } catch (e: Exception ) {
176173 // getActualDefaultRingtoneUri can throw an exception on some devices
177174 // for custom ringtones
178- return null
175+ return getSafeSystemRingtoneUri()
179176 }
180177 }
181178
182179 private fun getSafeSystemRingtoneUri (): Uri ? {
183- val defaultUri = RingtoneManager .getActualDefaultRingtoneUri(
184- context,
185- RingtoneManager .TYPE_RINGTONE
186- )
180+ try {
181+ val defaultUri = RingtoneManager .getActualDefaultRingtoneUri(
182+ context,
183+ RingtoneManager .TYPE_RINGTONE
184+ )
187185
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
186+ val rm = RingtoneManager (context)
187+ rm.setType(RingtoneManager .TYPE_RINGTONE )
188+ val cursor = rm.cursor
189+ if (defaultUri != null && cursor != null ) {
190+ while (cursor.moveToNext()) {
191+ val uri = rm.getRingtoneUri(cursor.position)
192+ if (uri == defaultUri) {
193+ cursor.close()
194+ return defaultUri
195+ }
197196 }
198197 }
199- }
200198
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
199+ // Default isn't system-provided → fallback to first available
200+ if (cursor != null && cursor.moveToFirst()) {
201+ val fallback = rm.getRingtoneUri(cursor.position)
202+ cursor.close()
203+ return fallback
204+ }
205+ } catch (e: Exception ) {
206+ e.printStackTrace()
206207 }
207-
208208 return null
209209 }
210210}
0 commit comments