рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдореЗрдВ рд░рд┐рдВрдЧрдЯреЛрди рдХреА рдкрд╕рдВрдж рдХреЗ рд╕рд╛рде рдЕрдкрдирд╛ рд╕рдВрд╡рд╛рдж рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдореБрдЭреЗ рдпрд╣рд╛рдВ рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП рд▓реЗ рдЧрдпрд╛ред рддреБрд░рдВрдд 2 рдХрд╛рд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП - рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╕рдорд░реНрдерди рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рдХреЛрдИ RingtonePreference
рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП PreferenceFragmentCompat
FrakmentCompat рдореЗрдВ рдорд╛рдирдХ рд╕рдВрд╡рд╛рдж рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╡рд┐рдлрд▓ рд╣реЛ рдЬрд╛рдПрдЧрд╛ред рдФрд░ рджреВрд╕рд░реА рдмрд╛рдд, рдорд╛рдирдХ рдзреБрдиреЛрдВ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдореБрдЭреЗ рд╡рд╣рд╛рдВ рдХреЗ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рд╕реЗ рдХреБрдЫ рдзреНрд╡рдирд┐рдпреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рдерд╛ред рдЗрд╕рд▓рд┐рдП рдЖрдкрдХрд╛ рд╕рдВрд╡рд╛рдж рд▓рд┐рдЦрдирд╛ рддрдп рд╣реБрдЖред
рдореИрдВ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рд╕рдВрд╡рд╛рдж рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХрд╛ рдкреНрд░рджрд░реНрд╢рди рдХрд░реВрдВрдЧрд╛: рдПрдХ рд╕реНрдХреНрд░реАрди рдкрд░ "рдкреНрд▓реЗ рд░рд┐рдВрдЧрдЯреЛрди" рдмрдЯрди рд╣реЛрддрд╛ рд╣реИ, рдЬрд┐рд╕ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдиреЗ рд╕реЗ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдореЗрдВ рд╕реЗрдЯ рд░рд┐рдВрдЧрдЯреЛрди рдмрдЬрддреА рд╣реИ, рдФрд░ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рд╕реНрдХреНрд░реАрди рдХреЗ рд▓рд┐рдП рдПрдХ рд▓рд┐рдВрдХ:
рдореИрдВ рдЗрди рджреЛ рд╕реНрдХреНрд░реАрди рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХрд╛ рд╡рд░реНрдгрди рдирд╣реАрдВ рдХрд░реВрдВрдЧрд╛ - рд╕рдм рдХреБрдЫ рд╣рдореЗрд╢рд╛ рдХреА рддрд░рд╣ рд╣реИред рдмрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЕрдВрдд рдореЗрдВ рдЖрд╡реЗрджрди рдХреЛрдб рдХреЗ рд╕рд╛рде рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХрд╛ рдПрдХ рд▓рд┐рдВрдХ рд╣реЛрдЧрд╛ред
рддреЛ, рдЖрдЗрдП рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рд╕реНрдХреНрд░реАрди рдХреЗ рд╡рд┐рд╡рд░рдг рдХреЗ рд╕рд╛рде xml рдлрд╝рд╛рдЗрд▓ рд╕реЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╕рд╛рдордЧреНрд░реА рдХреЗ рд╕рд╛рде res/xml
рдореЗрдВ settings.xml
рдлрд╝рд╛рдЗрд▓ рд░рдЦреЗрдВ:
<?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <Preference android:key="ringtone" android:title="Ringtone"/> </PreferenceScreen>
рдФрд░ рдЕрдм рдЗрди рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЛ рд╣рдорд╛рд░реЗ рдЯреБрдХрдбрд╝реЗ рдореЗрдВ рдЬреЛрдбрд╝реЗрдВ:
class SettingsFragment : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.settings, rootKey) } }
рд▓реЙрдиреНрдЪ рдХрд░реЗрдВ, рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рд╕реНрдХреНрд░реАрди рдЦреЛрд▓реЗрдВ, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рджреЗрдЦреЗрдВ:
рдкрд░рд┐рдЪрдп рдпрд╣рд╛рдВ рд╕рдорд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ, рд╣рдо рд▓реЗрдЦ рдХреЗ рдЙрджреНрджреЗрд╢реНрдп рдкрд░ рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВред рдпреЛрдЬрдирд╛ рдпрд╣ рд╣реИ: рдЬрдм рдЖрдк "рд░рд┐рдВрдЧрдЯреЛрдиреНрд╕" рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдПрдХ рд░рд┐рдВрдЧрдЯреЛрди рд░рд┐рдВрдЧрдЯреЛрди рдХреА рд╕реВрдЪреА рдФрд░ рдУрдХреЗ рдФрд░ рд░рджреНрдж рдХрд░реЗрдВ рдмрдЯрди рдХреЗ рд╕рд╛рде рдЦреБрд▓рддреА рд╣реИ, рдЬрдм рдЖрдк рдПрдХ рд░рд┐рдВрдЧрдЯреЛрди рдХрд╛ рдЪрдпрди рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдЦреЗрд▓рддрд╛ рд╣реИ (рдорд╛рдирдХ RingtonePreference
рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ), рдЬрдм рдЖрдк рдУрдХреЗ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдореЗрдВ рд╕рд╣реЗрдЬрд╛ рдЬрд╛рддрд╛ рд╣реИред
рддреЛ, рдПрдХ рд╕рдВрд╡рд╛рдж рдЯреБрдХрдбрд╝рд╛ рдмрдирд╛рдПрдБ:
class RingtonePreferenceDialog : DialogFragment() { private val prefKey: String get() = arguments?.getString(ARG_PREF_KEY) ?: throw IllegalArgumentException("ARG_PREF_KEY not set") companion object { private const val ARG_PREF_KEY = "ARG_PREF_KEY" fun create(prefKey: String): RingtonePreferenceDialog { val fragment = RingtonePreferenceDialog() fragment.arguments = Bundle().apply { putString(ARG_PREF_KEY, prefKey) } return fragment } } }
prefKey
рд╣рдо рдЙрд╕ рдХреБрдВрдЬреА рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдЬрд┐рд╕рдХреЗ рджреНрд╡рд╛рд░рд╛ рд╡рд░реНрддрдорд╛рди рд░рд┐рдВрдЧрдЯреЛрди рдХреЛ рдирд┐рдХрд╛рд▓рд╛ рдЬрд╛рдПрдЧрд╛, рдФрд░ рд╡рд╣рд╛рдВ рдЗрд╕реЗ OK рдмрдЯрди рджрдмрд╛рдХрд░ рд░рд┐рдХреЙрд░реНрдб рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рдЖрдЧреЗ рдХреЗ рдХрд╛рдо рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рд╕рд╣рд╛рдпрдХ рд╡рд░реНрдЧ Ringtone
рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЗрд╕реЗ рд╣рдорд╛рд░реЗ рдЯреБрдХрдбрд╝реЗ рдХреЗ рдЕрдВрджрд░ рдШреЛрд╖рд┐рдд рдХрд░реЗрдВ:
private data class Ringtone(val title: String, val uri: Uri)
рдФрд░ рдПрдХ рд╕рд╣рд╛рдпрдХ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦреЗрдВ рдЬреЛ рдПрдВрдбреНрд░реЙрдЗрдб рдореЗрдВ рд╕рднреА рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рд░рд┐рдВрдЧрдЯреЛрди рдХреЛ рдмрд╛рд╣рд░ рдирд┐рдХрд╛рд▓ рджреЗрдЧрд╛, рдФрд░ Ringtone
рд╕реЗ рд╕реВрдЪреА Ringtone
рд╡рд╛рдкрд╕ Ringtone
:
private fun getAndroidRingtones(): List<Ringtone> { val ringtoneManager = RingtoneManager(context) val cursor = ringtoneManager.cursor return (0 until cursor.count).map { cursor.moveToPosition(it) Ringtone( title = cursor.getString(RingtoneManager.TITLE_COLUMN_INDEX), uri = ringtoneManager.getRingtoneUri(it) ) } }
рдпрд╣рд╛рдБ ringtoneManager.cursor
рд╕рднреА рдЙрдкрд▓рдмреНрдз рд░рд┐рдВрдЧрдЯреЛрди рдХреЗ рд╕рд╛рде рдХрд░реНрд╕рд░ рд▓реМрдЯрд╛рдПрдЧрд╛, рд╣рдо рдмрд╕ рд╕рднреА рддрддреНрд╡реЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рд╣рдорд╛рд░реЗ рд╕рд╣рд╛рдпрдХ рд╡рд░реНрдЧ рдХреЗ Ringtone
(рдпрд╣ рдЙрдирдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ) рдореЗрдВ рдореИрдк рдХрд░рддреЗ рд╣реИрдВред
рдкрд╣рд▓реЗ, рдЪрд▓реЛ рд░рд┐рдВрдЧрдЯреЛрди рдХреА рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рд╕реВрдЪреА рдХреЗ рд╕рд╛рде рдХрд╛рдо рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░реЗрдВ - рдмрд╛рдж рдореЗрдВ рд╣рдорд╛рд░реЗ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реЛрдЧрд╛ред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, onCreateDialog
рд╡рд┐рдзрд┐ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рдХреЗ рдПрдХ рд╕рдВрд╡рд╛рдж рдмрдирд╛рдПрдВ:
private var ringtones: List<Ringtone> = emptyList() private var currentUri: Uri? = null override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { ringtones = getAndroidRingtones() currentUri = getCurrentRingtoneUri() val currentPosition = ringtones.indexOfFirst { currentUri == it.uri } return AlertDialog.Builder(context!!) .setPositiveButton(android.R.string.ok) { _, _ -> saveCurrentUri() } .setNegativeButton(android.R.string.cancel) { _, _ -> dialog.dismiss() } .setSingleChoiceItems(adapter, currentPosition) { _, which -> currentUri = ringtones[which].uri } .create() }
рдПрдХ рд╕рдВрд╡рд╛рдж рдореЗрдВ рддрддреНрд╡реЛрдВ рдХреА рд╕реВрдЪреА рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдПрдбреЗрдкреНрдЯрд░ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ; рдЗрд╕реЗ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
private val adapter by lazy { SimpleAdapter( context, ringtones.map { mapOf("title" to it.title) }, R.layout.simple_list_item_single_choice, arrayOf("title"), intArrayOf(R.id.text1) ) }
рдФрд░ рдЖрдкрдХреЛ рдЪрдпрдирд┐рдд рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рд╕рд╣рд╛рдпрдХ рд╡рд┐рдзрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рдЗрд╕реЗ рддрдм рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдЬрдм рдЖрдк рдУрдХреЗ рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВрдЧреЗ):
private fun saveCurrentUri() { PreferenceManager.getDefaultSharedPreferences(context) .edit() .putString(prefKey, currentUri?.toString()) .apply() }
рдпрд╣ рд╣рдорд╛рд░реЗ рддрддреНрд╡ рдХреЛ рд╕рдВрд╡рд╛рдж рд╕реЗ рдмрд╛рдВрдзрддрд╛ рд╣реИ, рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣рдо рд╕рдВрд╡рд╛рдж рдХреЗ рд╕рд╛рде рдлрд╛рдЗрд▓ рдореЗрдВ рдПрдХ рд╕рд╣рд╛рдпрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ:
fun Preference.connectRingtoneDialog(fragmentManager: FragmentManager?) = setOnPreferenceClickListener { RingtonePreferenceDialog.create(key).apply { fragmentManager?.let { show(it, "SOUND") } } true }
рдФрд░ findPreference("ringtone").connectRingtoneDialog(fragmentManager)
рд╣рдорд╛рд░реЗ SettingsFragment
findPreference("ringtone").connectRingtoneDialog(fragmentManager)
, рдЕрдм рдЗрд╕реЗ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП:
class SettingsFragment : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.settings, rootKey) findPreference("ringtone").connectRingtoneDialog(fragmentManager) } }
рдпрджрд┐ рд╣рдо рдЕрдм рд╕реЗрдЯрд┐рдВрдЧ рд╕реНрдХреНрд░реАрди рдкрд░ рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ "рд░рд┐рдВрдЧрдЯреЛрдиреНрд╕" рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджреЗрдЦреЗрдВрдЧреЗ:
рдЕрдм рд╕рдВрд╕рд╛рдзрдиреЛрдВ рд╕реЗ рд░рд┐рдВрдЧрдЯреЛрди рдХреЛ рд╣рдорд╛рд░реЗ рд╕рдВрд╡рд╛рдж рдореЗрдВ рдЬреЛрдбрд╝реЗрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ res/raw
рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рдПрдХ sample.mp3
рд░рд┐рдВрдЧрдЯреЛрди рд╣реИ, рдФрд░ рд╣рдо рдЗрд╕реЗ рд╕реВрдЪреА рдореЗрдВ рд╕рдмрд╕реЗ рдКрдкрд░ рджрд┐рдЦрд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рд╕рдВрд╡рд╛рдж рд╡рд░реНрдЧ рдореЗрдВ рдПрдХ рдФрд░ рд╡рд┐рдзрд┐ рдЬреЛрдбрд╝реЗрдВ:
private fun getResourceRingtones(): List<Ringtone> = listOf( Ringtone( title = "Sample ringtone", uri = Uri.parse("${ContentResolver.SCHEME_ANDROID_RESOURCE}://${context!!.packageName}/raw/sample") ) )
рдФрд░ onCreateDialog
рд╡рд┐рдзрд┐ рдореЗрдВ рдкрд╣рд▓реА рдкрдВрдХреНрддрд┐ рдмрджрд▓реЗрдВ:
ringtones = getResourceRingtones() + getAndroidRingtones()
рд╣рдо рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ, рджреЗрдЦреЛ, рдЖрдирдиреНрджрд┐рдд рд╣реЛрддреЗ рд╣реИрдВ рдХрд┐ рд╕рдм рдХреБрдЫ рдЗрддрдирд╛ рд╕рд░рд▓ рд╣реИ:
рдпрд╣ рд░рд┐рдВрдЧрдЯреЛрди рдХреЗ рд▓рд┐рдП "рдкреВрд░реНрд╡рд╛рд╡рд▓реЛрдХрди" рдЬреЛрдбрд╝рдирд╛ рд░рд╣рддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдлрд╝реАрд▓реНрдб рджрд░реНрдЬ рдХрд░реЗрдВ:
private var playingRingtone: android.media.Ringtone? = null
рдФрд░ setSingleChoiceItems
рд▓рд┐рдП рдХреЙрд▓рдмреИрдХ рд╡рд┐рдзрд┐ рдХреЛ рдереЛрдбрд╝рд╛ рдмрджрд▓реЗрдВ:
playingRingtone?.stop() ringtones[which].also { currentUri = it.uri playingRingtone = it.uri?.let { RingtoneManager.getRingtone(context, it) } playingRingtone?.play() }
рдпрд╣рд╛рдВ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ: рд╣рдо рд╡рд░реНрддрдорд╛рди рд░рд┐рдВрдЧрдЯреЛрди рдХреЛ рдЦреЗрд▓рдирд╛ рдмрдВрдж рдХрд░ рджреЗрддреЗ рд╣реИрдВ (рдпрджрд┐ рдпрд╣ рд╢реВрдиреНрдп рдирд╣реАрдВ рд╣реИ), рдЪрдпрдирд┐рдд рдХреЛ рд╡рд░реНрддрдорд╛рди рдПрдХ рдХреЗ рд░реВрдк рдореЗрдВ рд╕реЗрдЯ рдХрд░реЗрдВ, рдФрд░ рдкреНрд▓реЗрдмреИрдХ рд╢реБрд░реВ рдХрд░реЗрдВред рдЕрдм рдЬрдм рдЖрдк рд╕рдВрд╡рд╛рдж рдореЗрдВ рдПрдХ рд░рд┐рдВрдЧрдЯреЛрди рдХрд╛ рдЪрдпрди рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдЦреЗрд▓ рд╣реЛрдЧрд╛ред рдбрд╛рдпрд▓реЙрдЧ рдмрдВрдж рд╣реЛрдиреЗ рдкрд░ рдкреНрд▓реЗрдмреИрдХ рдХреЛ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП onPause
рд╡рд┐рдзрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ:
override fun onPause() { super.onPause() playingRingtone?.stop() }
рдЦреИрд░, рд╡рд╣ рд╕рдм рдЬреЛ рдореБрдЦреНрдп рд╕реНрдХреНрд░реАрди рдкрд░ рдмрдЯрди рдХреЛ рд░рд┐рдВрдЧрдЯреЛрди рдХреЗ рд▓рд┐рдП рд╕рдВрд▓рдЧреНрди рдХрд░рдирд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕ рддрд░рд╣:
findViewById<Button>(R.id.playRingtone).setOnClickListener { val ringtone = PreferenceManager.getDefaultSharedPreferences(this) .getString("ringtone", null) ?.let { RingtoneManager.getRingtone(this, Uri.parse(it)) } if (ringtone == null) { Toast.makeText(this, "Select ringtone in settings", Toast.LENGTH_SHORT).show() } else { ringtone.play() } }
рд╡рд╣ рд╕рдм рд╣реИред рдЬреИрд╕рд╛ рдХрд┐ рд╡рд╛рджрд╛ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдпрд╣рд╛рдВ рд╕реНрд░реЛрдд рдХреЛрдб рд▓рд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ ред