Статьи

Создайте живые обои на Android с помощью анимированного GIF

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

Если вы предпочитаете использовать готовое решение, а не кодировать его самостоятельно, попробуйте элемент GIF Live Wallpaper на Envato Market. Это позволяет вам создавать свои собственные Android-приложения Live Wallpaper на основе анимированных GIF-файлов.

GIF Live Wallpaper пункт на рынке Envato

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

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

Несмотря на то, что подойдет любой анимированный GIF, я предлагаю вам скачать хороший cinemagraph . Cinemagraph — это не что иное, как анимированный GIF, обычно созданный из видео, который легко зацикливается. Вы можете найти много хороших на Flickr .

Для этого урока я использую cinemagraph, созданный пользователем Flickr djandyw.com, так как он доступен по лицензии Creative Commons.

Запустите Android Studio, создайте новый проект и назовите его GIFWallpaper . Выберите уникальное имя пакета, если вы планируете опубликовать это приложение в Google Play.

Установите минимальный SDK для API 8: Android 2.2 (Froyo) .

В нашем приложении не будет Activity , поэтому выберите « Добавить нет активности» и нажмите « Готово» .

Живые обои нуждаются в файле, который описывает это. Создайте новый файл XML с именем res / xml / wallpaper.xml и замените его содержимое следующим XML:

1
2
3
4
5
6
<?xml version=»1.0″ encoding=»UTF-8″?>
<wallpaper
  xmlns:android=»http://schemas.android.com/apk/res/android»
    android:label=»GIF Wallpaper»
    android:thumbnail=»@drawable/ic_launcher»>
</wallpaper>

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

Для запуска в качестве живых обоев нашему приложению требуется только одно разрешение: android.permission.BIND_WALLPAPER .

Живые обои запускаются как Service который может получать действие намерения android.service.wallpaper.WallpaperService . Назовите Service GIFWallpaperService и добавьте его в манифест проекта AndroidManifest.xml .

01
02
03
04
05
06
07
08
09
10
11
12
13
<service
    android:name=».GIFWallpaperService»
    android:enabled=»true»
    android:label=»GIF Wallpaper»
    android:permission=»android.permission.BIND_WALLPAPER» >
    <intent-filter>
        <action android:name=»android.service.wallpaper.WallpaperService»/>
    </intent-filter>
    <meta-data
        android:name=»android.service.wallpaper»
        android:resource=»@xml/wallpaper» >
    </meta-data>
</service>

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

1
2
3
4
<uses-feature
    android:name=»android.software.live_wallpaper»
    android:required=»true» >
</uses-feature>

Скопируйте анимированный GIF, который вы скачали с Flickr, в папку ресурсов проекта. Я назвал GIF girl.gif .

Создайте новый класс Java и назовите его GIFWallpaperService.java . Этот класс должен расширять класс WallpaperService .

1
2
3
public class GIFWallpaperService extends WallpaperService {
     
}

Поскольку WallpaperService является абстрактным классом, вы должны переопределить его метод onCreateEngine и вернуть экземпляр вашего собственного Engine , который может визуализировать кадры GIF.

Чтобы использовать анимированный GIF, вы должны сначала преобразовать его в объект Movie . Для этого вы можете использовать метод decodeStream класса Movie . Как только объект Movie был создан, передайте его в качестве параметра конструктору пользовательского Engine .

Вот как должен выглядеть метод onCreateEngine :

01
02
03
04
05
06
07
08
09
10
11
12
@Override
public WallpaperService.Engine onCreateEngine() {
    try {
        Movie movie = Movie.decodeStream(
                getResources().getAssets().open(«girl.gif»));
 
        return new GIFWallpaperEngine(movie);
    }catch(IOException e){
        Log.d(«GIF», «Could not load asset»);
        return null;
    }
}

Давайте начнем работать над Engine сейчас. Создайте класс с именем GIFWallpaperEngine внутри класса GIFWallpaperService и сделайте так, чтобы он расширял WallpaperService.Engine .

Добавьте следующие поля в этот новый класс:

  • frameDuration : это целое число представляет задержку между операциями перерисовки. Значение 20 дает вам 50 кадров в секунду.
  • visible : этот логический параметр сообщает движку, visible ли в данный момент живые обои на экране. Это важно, потому что мы не должны рисовать обои, когда они не видны.
  • movie : это анимированный GIF в виде объекта Movie .
  • holder : это относится к объекту SurfaceHolder доступному для двигателя. Он должен быть инициализирован путем переопределения метода onCreate .
  • handler : Это объект Handler который будет использоваться для запуска Runnable который отвечает за фактическое рисование обоев.

Теперь ваш класс должен выглядеть так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
private class GIFWallpaperEngine extends WallpaperService.Engine {
    private final int frameDuration = 20;
 
    private SurfaceHolder holder;
    private Movie movie;
    private boolean visible;
    private Handler handler;
 
    public GIFWallpaperEngine(Movie movie) {
        this.movie = movie;
        handler = new Handler();
    }
 
    @Override
    public void onCreate(SurfaceHolder surfaceHolder) {
        super.onCreate(surfaceHolder);
        this.holder = surfaceHolder;
    }
}

Затем создайте метод с именем draw который рисует содержимое анимированного GIF. Давайте разберем этот метод:

  • Сначала мы проверяем, установлена ​​ли visible переменная в true . Мы продолжим только если это так.
  • Используйте метод SurfaceHolder lockCanvas чтобы получить Canvas для рисования.
  • Нарисуйте рамку анимированного GIF на Canvas после масштабирования и позиционирования.
  • Когда все рисование закончено, передайте Canvas обратно в SurfaceHolder .
  • Обновите текущий кадр анимированного GIF- setTime метода setTime объекта Movie .
  • Вызовите метод снова, используя handler после ожидания frameDuration миллисекундах.

Метод draw никогда не вызывается напрямую. Он всегда вызывается с использованием Handler и объекта Runnable . Поэтому давайте сделаем объект Runnable полем класса и назовем его drawGIF .

Добавьте следующий код в класс GIFWallpaperService :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
private Runnable drawGIF = new Runnable() {
    public void run() {
        draw();
    }
};
 
private void draw() {
    if (visible) {
        Canvas canvas = holder.lockCanvas();
        canvas.save();
            // Adjust size and position so that
            // the image looks good on your screen
            canvas.scale(3f, 3f);
            movie.draw(canvas, -100, 0);
        canvas.restore();
        holder.unlockCanvasAndPost(canvas);
        movie.setTime((int) (System.currentTimeMillis() % movie.duration()));
 
        handler.removeCallbacks(drawGIF);
        handler.postDelayed(drawGIF, frameDuration);
    }
}

Метод onVisibilityChanged автоматически вызывается при изменении видимости обоев. Нам нужно переопределить его и, в зависимости от значения visible аргумента, запустить или остановить drawGIF . Метод removeCallbacks Handler используется для остановки любых ожидающих drawGIF .

1
2
3
4
5
6
7
8
9
@Override
public void onVisibilityChanged(boolean visible) {
    this.visible = visible;
    if (visible) {
        handler.post(drawGIF);
    } else {
        handler.removeCallbacks(drawGIF);
    }
}

Наконец, переопределите метод onDestroy в Engine чтобы остановить все ожидающие drawGIF если обои отключены.

1
2
3
4
5
@Override
public void onDestroy() {
    super.onDestroy();
    handler.removeCallbacks(drawGIF);
}

Ваши живые обои теперь готовы. Скомпилируйте его и установите на свое устройство Android. После установки вы сможете найти обои в списке доступных обоев.

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

Если GIF выглядит слишком маленьким или он расположен неправильно, вернитесь к методу draw и отрегулируйте масштаб и положение.

Теперь вы знаете, как использовать анимированный GIF для создания живых обоев. Не стесняйтесь экспериментировать с большим количеством картинок. Если вы планируете публиковать свои живые обои в Google Play, убедитесь, что у вас есть разрешение автора на коммерческое использование анимированного GIF. Посетите веб-сайт Android Developer, чтобы узнать больше о классе WallpaperService .