Статьи

Интерфейс Android: добавление мультимедиа в приложение

Эта статья является частью нашего Академического курса под названием Android UI Design — Основы .

В этом курсе вы познакомитесь с основами дизайна пользовательского интерфейса Android. Вы поймете пользовательский ввод, представления и макеты, а также адаптеры и фрагменты. Проверьте это здесь !

1. Обзор

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

Современные смартфоны и планшеты имеют все большую емкость, поэтому мы можем хранить музыкальные файлы, видеофайлы, изображения и т. Д. Важна не только емкость, но и камера высокого разрешения, позволяющая делать впечатляющие фотографии. В этом контексте Multimedia API играет важную роль.

2. Мультимедийный API

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

аудио

  • MP3
  • MIDI
  • Ворбис (эс: ​​мкв)

видео

  • H.263
  • MPEG-4 SP

Изображений

  • JPEG
  • GIF
  • PNG

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

Все классы, предоставляемые Android SDK, которые мы можем использовать для добавления мультимедийных возможностей в наши приложения, находятся в пакете android.media . В этом пакете класс сердца называется MediaPlayer . Этот класс имеет несколько методов, которые мы можем использовать для воспроизведения аудио и видео файлов, хранящихся на нашем устройстве или передаваемых с удаленного сервера.

Этот класс реализует конечный автомат с четко определенными состояниями, и мы должны знать их перед воспроизведением файла. Упрощая диаграмму состояний, как показано в официальной документации, мы можем определить эти макро-состояния:

  • Состояние бездействия: когда мы создаем новый экземпляр класса MediaPlayer.
  • Состояние инициализации: это состояние срабатывает, когда мы используем setDataSource для установки источника информации, который должен использовать MediaPlayer .
  • Подготовленное состояние: В этом состоянии подготовительные работы завершены. Мы можем войти в это состояние, вызывая метод prepareAsync или prepareAsync . В первом случае после возврата метода состояние переходит в состояние « Prepared . В асинхронном режиме мы должны реализовать прослушиватель, который будет уведомлен, когда система будет готова и состояние перейдет в состояние « Prepared . Мы должны помнить, что при вызове метода prepare все приложение может зависнуть, прежде чем метод вернется, потому что метод может занять много времени, прежде чем он завершит свою работу, особенно когда данные передаются с удаленного сервера. Мы должны избегать вызова этого метода в главном потоке, потому что это может вызвать проблему ANR (приложение не отвечает). Когда MediaPlayer находится в подготовленном состоянии, мы можем воспроизвести наш файл, приостановить или остановить его.
  • Завершенное состояние: достигнут конец потока.

Мы можем воспроизвести файл несколькими способами:

1
2
3
4
5
6
// Raw audio file as resource
MediaPlayer mp = MediaPlayer.create(this, R.raw.audio_file);
// Local file
MediaPlayer mp1 = MediaPlayer.create(this, Uri.parse("file:///...."));
// Remote file
MediaPlayer mp2 = MediaPlayer.create(this, Uri.parse("http://website.com"));

или мы можем использовать setDataSource следующим образом:

1
2
MediaPlayer mp3 = new MediaPlayer();
mp3.setDataSource("http://www.website.com");

После того, как мы создали наш MediaPlayer мы можем «подготовить» его:

1
mp3.prepare();

и наконец мы можем сыграть это:

1
mp3.start();

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

01
02
03
04
05
06
07
08
09
10
// Remote file
MediaPlayer mp2 = MediaPlayer.create(this, Uri.parse("http://website.com"));
mp2.setAudioStreamType(AudioManager.STREAM_MUSIC);
mp2.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
    @Override
    public void onCompletion(MediaPlayer mp) {
        mp.start();
    }
});
mp2.prepareAsync();

Мы использовали слушателя, чтобы получать уведомления, когда MediaPlayer находится в подготовленном состоянии, чтобы мы могли начать воспроизведение. В конце, когда нам больше не нужен экземпляр MediaPlayer , мы должны выпустить его:

1
mp2.release();

2.1. Использование камеры Android

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

В методе onCreate нашей Activity мы должны настроить прослушиватель Button и при нажатии для onCreate намерения:

1
2
3
4
5
6
7
8
9
Button b = (Button) findViewById(R.id.btn1);
b.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
         // Here we fire the intent to start the camera
        Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        startActivityForResult(i, 100);
      }
});

В методе onActivityResult мы извлекаем сделанный снимок и показываем результат:

1
2
3
4
5
6
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // This is called when we finish taking the photo
       Bitmap bmp = (Bitmap) data.getExtras().get("data");
       iv.setImageBitmap(bmp);
}

Запустив приложение мы имеем:

фигура 1

фигура 1

фигура 2

фигура 2

В приведенном выше примере мы использовали эмулированную камеру.

3. Графика

К настоящему времени мы говорили о стандартных компонентах, которые мы можем использовать в нашем пользовательском интерфейсе. Это хорошо, но этого недостаточно, когда мы хотим разработать игру или приложение, которое требует графического содержимого. Android SDK предоставляет набор API для рисования пользовательской 2D и 3D графики. Когда мы пишем приложение, которое требует графики, мы должны учитывать, насколько интенсивно использование графики. Другими словами, может быть приложение, которое использует довольно статичную графику без сложных эффектов, и может быть другое приложение, которое использует интенсивные графические эффекты, такие как игры.

В соответствии с этим использованием, мы можем использовать различные методы:

Самым простым способом использования 2D-графики является расширение класса View и переопределение метода onDraw . Мы можем использовать эту технику, когда нам не нужно графически интенсивное приложение.

В этом случае мы можем использовать класс Canvas для создания 2D-графики. Этот класс предоставляет набор методов, начинающихся с draw* которые можно использовать для рисования различных фигур, таких как:

  • линии
  • круг
  • прямоугольник
  • овальный
  • картина
  • дуга

Например, давайте предположим, что мы хотим нарисовать прямоугольник. Мы создаем пользовательское представление и затем переопределяем метод onDraw . Здесь мы рисуем прямоугольник:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class TestView extends View {
    public TestView(Context context) {
        super(context);
    }
    public TestView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
 
    }
    public TestView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
 
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint p = new Paint();
        p.setColor(Color.GREEN);
        p.setStrokeWidth(1);
        p.setStyle(Paint.Style.STROKE);
        canvas.drawRect(5, 5, 120, 120, p);
        invalidate();
    }
}

Как видно из приведенного выше кода, в методе onDraw мы использовали метод drawRect Canvas . Обратите внимание, что мы использовали другой класс под названием Paint . Этот класс определяет, как будет нарисована форма; он определяет его цвет, если он должен быть заполнен, ширину границы и так далее.

В этом случае макет выглядит так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >
 
    <com.swa.customview.TestView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
 
</RelativeLayout>

Запустив приложение, мы имеем:

Рисунок 3

Рисунок 3

Предположим, мы хотим залить прямоугольник цветом градиента, поэтому метод onDraw становится:

01
02
03
04
05
06
07
08
09
10
11
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Paint p = new Paint();
    p.setColor(Color.GREEN);
    p.setStrokeWidth(1);
    p.setStyle(Paint.Style.FILL_AND_STROKE);
    LinearGradient lg = new LinearGradient(0F, 0F, 115F,115F, Color.GREEN,  Color.YELLOW, TileMode.CLAMP);
    p.setShader(lg);
    canvas.drawRect(5, 5, 120, 120, p);
    invalidate();
}

Запустив приложение мы имеем:

Рисунок 4

Рисунок 4

Как мы уже говорили, начиная с Android 3.0 (API 11), мы можем использовать аппаратное ускорение. В этом случае, если мы хотим использовать его, мы должны изменить Manifest.xml и добавить следующую строку:

1
<application android:hardwareAccelerated="true" >

или мы можем использовать его на уровне Activity .

4. Drawable

В Android Drawable — это графический объект, который можно отобразить на экране. С точки зрения API все объекты Drawable производными от класса Drawable . Они играют важную роль в программировании на Android, и мы можем использовать XML для их создания. Они отличаются от стандартных виджетов, потому что они не являются интерактивными, то есть они не реагируют на прикосновения пользователя.

Изображения, цвета, формы, объекты, которые изменяют свой аспект в соответствии с их состоянием, объекты, которые можно анимировать, — все это объекты для рисования. В Android в каталоге res есть подкаталог, зарезервированный для Drawable , он называется res/drawable .

Рисунок 5

Рисунок 5

Под drawable мы можем добавить двоичные файлы, такие как изображения или файлы XML.

Как мы видели в предыдущих статьях , мы можем создать несколько каталогов в соответствии с плотностью экрана, которую мы хотим поддерживать. Эти каталоги имеют имя вроде drawable-<> .

Это очень полезно, когда мы используем изображения; в этом случае нам нужно создать несколько версий изображения: например, мы можем создать изображение для экрана с высоким разрешением или другое для экрана со средним разрешением. Как только мы R.drawable.file_name наш файл в каталог drawable , мы можем ссылаться на него в нашем классе, используя R.drawable.file_name . Хотя очень просто добавить двоичный файл в один из этих каталогов, это вопрос копирования и вставки, если мы хотим использовать XML-файл, мы должны его создать.

Есть несколько типов рисования:

  • Битовая карта
  • Девять патч
  • Список слоев
  • Государственный список
  • Список уровней
  • Переходный
  • Вставка для рисования
  • Клип для рисования
  • Масштабируемый
  • Форма нарисованная

Интересным аспектом является то, что мы можем создавать такие элементы, используя XML или непосредственно из кода. Существует соответствие между показанными выше элементами и классом API. Мы можем добавить суффикс Drawable и создать соответствующее имя класса: например, если соответствующий класс BitmapDrawable BitmapBitmapDrawable и так далее.

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

4.1. Форма нарисованная

Это общая форма. Используя XML, мы должны создать файл с элементом shape в качестве root. Этот элемент в качестве атрибута называется android:shape где мы определяем тип фигуры, такой как прямоугольник, овал, линия и кольцо. Мы можем настроить форму, используя дочерние элементы, такие как:

Имя элемента Описание
gradient Укажите цвет градиента для фигуры.
solid Укажите цвет фона формы.
stroke Укажите границу фигуры.
corners Укажите угловой радиус фигуры.
padding Укажите отступы для формы.
size Укажите ширину и высоту фигуры.

Таблица 1

Например, предположим, что мы хотим создать овал со сплошным цветом фона. Мы создаем файл XML с именем, например, oval.xml :

01
02
03
04
05
06
07
08
09
10
    android:shape="oval" >
 
    <solid android:color="#FF0000" />
 
    <size
        android:height="100dp"
        android:width="120dp" />
 
</shape>

Таким образом, мы создаем овальную форму, имеющую красный цвет фона и размер 120dpx100dp. Тогда мы можем сослаться на это в нашем файле макета:

1
2
3
4
5
<ImageView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_centerInParent="true"
 android:src="@drawable/oval" />

Запустив приложение, мы получим:

Рисунок 6

Рисунок 6

Например, мы можем предположить, что хотим изменить внешний вид виджета « Button . Мы хотим создать прямоугольник с закругленными углами и в качестве фона цвет градиента. Мы определяем фигуру в файле XML с именем round_corner.xml и добавляем ее в drawable dir:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
    android:shape="rectangle" >
 
    <stroke
        android:width="2dp"
        android:color="#00FF00" />
 
    <gradient
        android:angle="-90"
        android:endColor="#FFFFFF"
        android:startColor="#00FF00"
        android:type="linear" />
 
    <corners android:radius="3dp" />
 
    <padding
        android:bottom="4dp"
        android:left="4dp"
        android:right="4dp"
        android:top="4dp" />
 
</shape>

и в файле макета мы имеем:

1
2
3
4
5
6
<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:background="@drawable/round_corner"
    android:text="Click me" />

Запустив приложение, мы имеем:

Рисунок 7

Рисунок 7

Как мы видим, просто используя XML, мы можем изменить фон виджета или создать фигуры.

4.2. Государственный список

Этот нарисованный объект может отображать несколько нарисованных объектов в зависимости от состояния объекта. Это очень полезно, когда мы хотим настроить некоторый объект, который имеет внутренние состояния. Например, виджет « Button является одним из этих объектов, он имеет несколько состояний: нажатие, фокусировка и т. Д.

В XML этот объект представлен тегом селектора. Этот тег имеет дочерние элементы item:

1
2
3
4
5
6
 
    <item android:drawable=""drawable1" android:state_pressed="true"/>
    <item android:drawable=""drawable2" android:state_focused="true"/>
 
</selector>

Давайте предположим, что мы хотим настроить виджет Button в нашем макете при его нажатии. Кроме того, мы хотим изменить его фон на красный цвет градиента. Итак, первое, что мы делаем, это определяем две фигуры:

1
2
3
4
5
 
    <solid android:color="#00FF00" />
 
</shape>

green.xml

1
2
3
4
5
6
7
8
9
 
    <gradient
        android:angle="-90"
        android:endColor="#FFFFFF"
        android:startColor="#AA0000"
        android:type="linear" />
 
</shape>

Как только у нас есть формы, мы можем назначить их различным состояниям объекта

1
2
3
4
5
6
 
    <item android:drawable="@drawable/red_gradient" android:state_pressed="true"/>
    <item android:drawable="@drawable/green"/>
 
</selector>

Таким образом, мы назначаем рисование red_gradient при нажатии кнопки и рисование зеленого цвета в состоянии по умолчанию. Запустив приложение мы имеем:

Рисунок 8

Рисунок 8

Рисунок 9

Рисунок 9

4,3. Девять патч

Nine-patch image — это специальное фоновое изображение, размер которого можно изменить, чтобы в нем можно было просматривать содержимое. Вы можете посмотреть здесь, если хотите получить больше информации. Его можно использовать, когда мы хотим создать изображение, но мы не знаем точный размер содержимого View .

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

Теперь мы можем запустить draw9patch.bat в каталоге инструментов. Теперь мы можем перетащить это изображение в открывшееся окно:

Рисунок 10

Рисунок 10

Окно разделено на две области: левая является «рабочим окном», а с правой стороны мы получаем конечный результат. Теперь нам нужно выбрать область изображения, которая может масштабироваться, мы можем сделать это, рисуя линии слева и сверху, как вы можете видеть на картинке:

Рисунок 11

Рисунок 11

Теперь мы устанавливаем область содержимого, выбирая правую и нижнюю часть изображения.

Рисунок 12

Рисунок 12

Мы видим на правой стороне конечный результат. Теперь мы можем сохранить нашу работу. Когда мы закончим, мы можем скопировать это изображение в res/drawable нашего проекта Android.

Чтобы увидеть конечный эффект, мы можем создать макет, подобный показанному ниже:

01
02
03
04
05
06
07
08
09
10
11
12
13
<Button
    android:id="@+id/btn1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/stdbox"
    android:text="This is a standard background with red border" />
<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@id/btn1"
    android:layout_marginTop="10dp"
    android:background="@drawable/box"
    android:text="This is a 9 patch background with red border" />

В первой кнопке мы использовали стандартное изображение — простое красное поле, как показано выше, в то время как во второй кнопке мы используем изображение с 9-patch .

Запустив пример, который мы имеем:

Рисунок 13

Рисунок 13

Вы можете заметить, что 9-patch изображения масштабируются лучше, чем стандартное изображение.

5. Загрузите исходный код

Это был урок о том, как использовать мультимедиа с Android. Вы можете скачать исходный код здесь: