Статьи

Создать рингтон рандомизатор на Android

Пользователи Android всегда в поиске приложений, которые могут изменить поведение своих устройств новыми и инновационными способами. Платформа Android дает разработчикам большую свободу в создании таких приложений. В этом руководстве вы узнаете, как создать приложение, которое рандомизирует мелодию звонка телефона Android при каждом получении вызова.

Если вы хотите следовать, убедитесь, что у вас установлена ​​последняя версия Android Studio. Вы можете получить его с сайта Android Developer .

Поскольку это промежуточное руководство, я не буду подробно останавливаться на основах. Я предполагаю, что вы уже создали одно или несколько приложений для Android и знакомы с основами Android SDK.

Запустите Android Studio и создайте новый проект. Установите имя приложения в RingtoneRandomizer . Убедитесь, что вы выбрали уникальное имя пакета.

Это приложение может работать на всех телефонах с уровнем API 8 или выше, поэтому установите минимальный SDK для Android 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>

Файл 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>

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>

Чтобы избежать работы с RingtoneManager непосредственно в Activity или BroadcastReceiver , мы собираемся создать вспомогательный класс с именем RingtoneHelper .

1
2
3
public class RingtoneHelper {
     
}

Класс RingtoneHelper будет иметь два статических метода, которые используют класс RingtoneManager .

Метод 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 отвечает за изменение мелодии устройства, основной функции нашего приложения.

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 для изменения рингтона.

Создайте новый класс с именем 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);
            }
        }
    }
}

Создайте новый класс с именем 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 мы устанавливаем состояние кнопки переключения на основе 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 создает 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);
}

Наше приложение готово для развертывания на телефоне Android. Вы должны видеть все мелодии звонка, доступные на вашем телефоне, при запуске приложения. Нажмите на кнопку переключения, чтобы активировать рандомизатор.

Вот как может выглядеть конечный результат

Позвони себе с другого телефона пару раз. При первом вызове будет воспроизводиться ваш оригинальный рингтон. Со следующего звонка вы услышите случайный рингтон каждый раз.

Обратите внимание, что это приложение меняет мелодию звонка по умолчанию вашего телефона. Если вы назначили определенную мелодию для контакта или группы контактов, эта мелодия будет по-прежнему использоваться.

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