Пользователи Android всегда в поиске приложений, которые могут изменить поведение своих устройств новыми и инновационными способами. Платформа Android дает разработчикам большую свободу в создании таких приложений. В этом руководстве вы узнаете, как создать приложение, которое рандомизирует мелодию звонка телефона Android при каждом получении вызова.
Предпосылки
Если вы хотите следовать, убедитесь, что у вас установлена последняя версия Android Studio. Вы можете получить его с сайта Android Developer .
Поскольку это промежуточное руководство, я не буду подробно останавливаться на основах. Я предполагаю, что вы уже создали одно или несколько приложений для Android и знакомы с основами Android SDK.
1. Создайте новый проект
Запустите Android Studio и создайте новый проект. Установите имя приложения в RingtoneRandomizer . Убедитесь, что вы выбрали уникальное имя пакета.

Это приложение может работать на всех телефонах с уровнем API 8 или выше, поэтому установите минимальный SDK для Android 2.2 .

Далее выберите « Добавить бездействие» и нажмите « Готово» .

2. Редактировать Манифест
Наше приложение будет нуждаться в следующих разрешениях:
-
android.permission.READ_PHONE_STATEдля обнаружения входящих звонков -
android.permission.WRITE_SETTINGSчтобы изменить настройку рингтона по умолчанию -
android.permission.READ_EXTERNAL_STORAGEчтобы получить список доступных мелодий
Добавьте следующее в AndroidManifest.xml :
|
1
2
3
|
<uses-permission android:name=»android.permission.READ_PHONE_STATE»/>
<uses-permission android:name=»android.permission.WRITE_SETTINGS»/>
<uses-permission android:name=»android.permission.READ_EXTERNAL_STORAGE»/>
|
Это приложение имеет одно действие, чтобы позволить пользователю активировать / деактивировать поведение изменения мелодии звонка.
|
1
2
3
4
5
6
|
<activity android:name=».MainActivity» >
<intent-filter>
<action android:name=»android.intent.action.MAIN» />
<category android:name=»android.intent.category.LAUNCHER» />
</intent-filter>
</activity>
|
Он также имеет BroadcastReceiver для обнаружения изменений состояния вызова. Как показано ниже, намеренное действие, которое он слушает, является android.intent.action.PHONE_STATE .
|
1
2
3
4
5
6
7
|
<receiver
android:name=».RingReceiver»
android:enabled=»true»>
<intent-filter>
<action android:name=»android.intent.action.PHONE_STATE»/>
</intent-filter>
</receiver>
|
3. Отредактируйте strings.xml
Файл strings.xml содержит строки, используемые приложением. Обновите values / strings.xml, как показано ниже:
|
1
2
3
4
5
6
7
8
9
|
<?xml version=»1.0″ encoding=»utf-8″?>
<resources>
<string name=»app_name»>Ringtone Randomizer</string>
<string name=»activate»>Activate Ringtone Randomizer</string>
<string name=»deactivate»>Deactivate Ringtone Randomizer</string>
<string name=»list_of_ringtones»>Ringtones available on this device:</string>
</resources>
|
4. Создайте макет деятельности
Activity нужны следующие представления:
-
ToggleButtonдля активации / деактивации рандомизатора рингтона -
ListViewдля отображения всех доступных мелодий -
TextViewкоторый действует как метка
Создайте файл с именем layout / activity_main.xml и замените его содержимое следующим. Как видите, макет довольно прост и понятен.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
<?xml version=»1.0″ encoding=»utf-8″?>
<LinearLayout xmlns:android=»http://schemas.android.com/apk/res/android»
android:orientation=»vertical» android:layout_width=»match_parent»
android:layout_height=»match_parent»
android:padding=»16dp»
>
<ToggleButton
android:layout_width=»match_parent»
android:layout_height=»wrap_content»
android:textOff=»@string/activate»
android:textOn=»@string/deactivate»
android:id=»@+id/toggle»
/>
<TextView
android:layout_width=»match_parent»
android:layout_height=»wrap_content»
android:text=»@string/list_of_ringtones»
android:textStyle=»bold»
/>
<ListView
android:layout_width=»match_parent»
android:layout_height=»match_parent»
android:id=»@+id/list_of_ringtones»
/>
</LinearLayout>
|
5. Создать RingtoneHelper Helper Class
Чтобы избежать работы с RingtoneManager непосредственно в Activity или BroadcastReceiver , мы собираемся создать вспомогательный класс с именем RingtoneHelper .
|
1
2
3
|
public class RingtoneHelper {
}
|
Класс RingtoneHelper будет иметь два статических метода, которые используют класс RingtoneManager .
fetchAvailableRingtones
Метод fetchAvailableRingtones извлекает список доступных рингтонов, возвращая объекты List Ringtone .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
public static List<Ringtone> fetchAvailableRingtones(Context context){
List<Ringtone> ringtones = new ArrayList<>();
RingtoneManager mgr = new RingtoneManager(context);
mgr.setType(RingtoneManager.TYPE_RINGTONE);
int n = mgr.getCursor().getCount();
for(int i=0;i<n;i++){
ringtones.add(mgr.getRingtone(i));
}
return ringtones;
}
|
В методе fetchAvailableRingtones мы начинаем с создания экземпляра класса RingtoneManager . Объект RingtoneManager может перечислить все звуки, доступные на устройстве. Это включает в себя звуки для сигналов тревоги и других уведомлений.
Мы используем метод setType чтобы установить его тип в TYPE_RINGTONE как нас интересуют только мелодии звонка.
Затем мы вызываем метод getCount чтобы узнать, сколько рингтонов доступно, и вызываем метод getRingtone в цикле for , добавляя каждый рингтон в ringtones .
changeRingtone
Метод changeRingtone отвечает за изменение мелодии устройства, основной функции нашего приложения.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
public static void changeRingtone(Context context){
SharedPreferences preferences = context.getSharedPreferences(«randomizer», Context.MODE_PRIVATE);
if(!preferences.getBoolean(«active», false))
return;
RingtoneManager mgr = new RingtoneManager(context);
Random random = new Random(System.currentTimeMillis());
int n = random.nextInt(mgr.getCursor().getCount());
RingtoneManager.setActualDefaultRingtoneUri(context,
RingtoneManager.TYPE_RINGTONE, mgr.getRingtoneUri(n));
}
|
Сначала мы проверяем в SharedPreferences ли пользователь рандомизатор рингтонов. Затем мы используем класс Random чтобы выбрать случайное число, которое меньше количества доступных мелодий.
Метод getRingtoneUri вызывается для извлечения URI соответствующего рингтона и передачи его в метод setActualDefaultRingtoneUri для изменения рингтона.
6. Создайте широковещательный приемник
Создайте новый класс с именем RingReceiver который наследуется от BroadcastReceiver . Новый класс будет иметь только один метод с именем onReceive . В этом методе все, что мы делаем, это вызываем метод changeRingtone вспомогательного класса, если changeRingtone следующие критерии:
- действие полученного
IntentравноTelephonyManager.ACTION_PHONE_STATE_CHANGED - значение ключа поиска
EXTRA_STATEравноTelephonyManager.EXTRA_STATE_RINGING
Вот как должен выглядеть класс RingReceiver :
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
public class RingReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
String callState = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (callState.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
RingtoneHelper.changeRingtone(context);
}
}
}
}
|
7. Создать активность
Создайте новый класс с именем MainActivity который наследуется от Activity . Мы переопределяем метод onCreate и выполняем следующие действия:
- вызовите
setContentViewдля использования макета, определенного в activity_main.xml - вызовите метод
fetchAvailableRingtonesвспомогательного класса для заполненияListмелодий - инициализировать
ListView - инициализировать
ToggleButton
Класс MainActivity теперь должен выглядеть примерно так:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
public class MainActivity extends Activity {
private ListView listOfRingtones;
private ToggleButton toggleRandomizer;
private List<Ringtone> ringtones;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listOfRingtones = (ListView)findViewById(R.id.list_of_ringtones);
toggleRandomizer = (ToggleButton)findViewById(R.id.toggle);
ringtones = RingtoneHelper.fetchAvailableRingtones(this);
initializeList();
initializeToggle();
}
}
|
initializeToggle
В методе initializeToggle мы устанавливаем состояние кнопки переключения на основе boolean значения с именем active в SharedPreferences . Это значение установлено в false по умолчанию.
Мы также добавляем OnCheckedChangeListener к кнопке переключения, чтобы обновить значение в SharedPreferences . Для этого putBoolean методы putBoolean и commit Editor .
|
01
02
03
04
05
06
07
08
09
10
11
12
|
private void initializeToggle(){
final SharedPreferences preferences = getSharedPreferences(«randomizer», Context.MODE_PRIVATE);
boolean active = preferences.getBoolean(«active», false);
toggleRandomizer.setChecked(active);
toggleRandomizer.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
preferences.edit().putBoolean(«active», isChecked).commit();
}
});
}
|
initializeList
Метод initializeList создает Adapter на основе List мелодий звонка. Используйте android.R.layout.simple_list_item_1 в качестве макета элементов ListView . Это не что иное, как TextView . Он должен отображать заголовок рингтона, используя метод getTitle класса getTitle . Это должно быть сделано внутри метода getView , после его переопределения.
Как только Adapter будет готов, назначьте его ListView с помощью метода setAdapter в ListView .
|
01
02
03
04
05
06
07
08
09
10
11
12
13
|
private void initializeList(){
ArrayAdapter<Ringtone> adapter = new ArrayAdapter<Ringtone>(this,
android.R.layout.simple_list_item_1, ringtones) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView item = (TextView)super.getView(position, convertView, parent);
item.setText(ringtones.get(position).getTitle(MainActivity.this));
return item;
}
};
listOfRingtones.setAdapter(adapter);
}
|
8. Скомпилируйте и запустите
Наше приложение готово для развертывания на телефоне Android. Вы должны видеть все мелодии звонка, доступные на вашем телефоне, при запуске приложения. Нажмите на кнопку переключения, чтобы активировать рандомизатор.

Позвони себе с другого телефона пару раз. При первом вызове будет воспроизводиться ваш оригинальный рингтон. Со следующего звонка вы услышите случайный рингтон каждый раз.
Обратите внимание, что это приложение меняет мелодию звонка по умолчанию вашего телефона. Если вы назначили определенную мелодию для контакта или группы контактов, эта мелодия будет по-прежнему использоваться.
Вывод
Теперь вы знаете, как использовать функциональность, доступную в классе RingtoneManager . Вы также узнали, как обнаружить входящие звонки. Не стесняйтесь использовать это приложение для рандомизации других уведомлений аналогичным образом. Посетите веб-сайт Android Developer, чтобы узнать больше о классе RingtoneManager .