Освой Android играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Обои главного экрана

Метод setWallpaper() (устар.)
WallpaperManager
Очистить обои
Изменение существующих обоев

Чтобы поместить изображение своего любимого кота в качестве обоев главного экрана, нужно проделать три вещи:

  • Спросить разрешения у кота
  • Использовать изображение как Bitmap, ресурс или поток
  • вызвать метод для установки обоев

Метод setWallpaper() (устар.)

В старых версиях Android был метод getApplicationContext().setWallpaper(bitmap), который сейчас объявлен устаревшим. Раньше здесь был код для этого примера. Но я его удалил. Но с другой стороны, он работал по другому принципу и не растягивал картинку, как это происходит сейчас (см. примеры ниже).

WallpaperManager

Теперь рассмотрим современный вариант установки обоев. За смену обоев отвечает класс WallpaperManager. Алгоритм остался прежним - спрашиваем разрешение у кота, устанавливаем необходимое разрешение (не путать с разрешением, которое было получено от кота) в манифесте и пишем код для нажатия кнопки.

Установим необходимое разрешение в манифесте:


<uses-permission android:name="android.permission.SET_WALLPAPER" />

В папку res/raw поместите изображение, которое хотите добавить в качестве обоев. Добавим на экран активности кнопку, с помощью которой будем устанавливать новые обои.


val button: Button = findViewById(R.id.button)
button.setOnClickListener {
    val wallpaperManager = WallpaperManager.getInstance(this)
    wallpaperManager.setResource(R.raw.cat)
}

Очистить обои

Если необходимо очистить установленные обои и вернуться к системным обоям по умолчанию, то вызывайте метод clear() или clearWallpaper.


wallpaperManager.clear()
Дальше идут старые примеры на Java, написанные в 2017 году. Не стал ничего менять, так как больше к этой теме не возвращался.

Изменение существующих обоев

В официальной документации Google нашёл интересный пример изменения текущих обоев при помощи цветовых фильтров. Возьмём за основу предыдущий пример и добавим ещё одну кнопку, которая будет в случайном порядке выбирать цветовой фильтр и напишем код:


package ru.alexanderklimov.wallpaper;

import android.app.WallpaperManager;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ImageView;

import java.io.IOException;


public class MainActivity extends AppCompatActivity {

    final static private int[] mColors = {Color.BLUE, Color.GREEN, Color.RED,
            Color.LTGRAY, Color.MAGENTA, Color.CYAN, Color.YELLOW, Color.WHITE};
    private WallpaperManager mWallpaperManager;
    private Drawable mWallpaperDrawable;
    private ImageView mImageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        mWallpaperManager = WallpaperManager
                .getInstance(getApplicationContext());
        mWallpaperDrawable = mWallpaperManager.getDrawable();

        mImageView = (ImageView) findViewById(R.id.imageView);
        mImageView.setDrawingCacheEnabled(true);
        // выводим картинку обоев в свой ImageView
        mImageView.setImageDrawable(mWallpaperDrawable);
    }


    // Щелчок первой кнопки для выбора эффекта
    public void onRandomClick(View v) {
        int color = (int) Math.floor(Math.random() * mColors.length);
        mWallpaperDrawable.setColorFilter(mColors[color],
                PorterDuff.Mode.MULTIPLY);
        mImageView.setImageDrawable(mWallpaperDrawable);
        mImageView.invalidate();
    }

    // Щелчок второй кнопки для установки обоев
    public void onClick(View v) {
        try {
            mWallpaperManager.setBitmap(mImageView.getDrawingCache());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Обратите внимание, что в данном примере в ImageView загружаются текущие обои через метод getDrawable(), в нашем случае это были обои от предыдущего примера. Нажав несколько раз на кнопку для выбора фильтра, я остановился на зелёном варианте. По-моему получилось симпатично.

Wallpaper Wallpaper

Намерение для установки обоев

Нашёл в интернете пример вызова намерения для установки обоев.


Intent intent = new Intent(Intent.ACTION_ATTACH_DATA);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setDataAndType(uri, "image/*");
intent.putExtra("mimeType", "image/*");
this.startActivity(Intent.createChooser(intent, "Set as:"));

Для примера нужно откуда-то получить Uri и вставить в пример. В таком варианте не пробовал.

Напишем другой вариант с учётом версий устройства.


package ru.alexanderklimov.as14;

import android.app.Activity;
import android.app.WallpaperManager;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;

import java.io.FileNotFoundException;
import java.io.IOException;


public class MainActivity extends AppCompatActivity {

    private static final int RQS_OPEN_IMAGE = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
    }

    public void onClick(View v) {

        Intent intent = new Intent();

        if (Build.VERSION.SDK_INT >=
                Build.VERSION_CODES.KITKAT) {
            intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
        } else {
            intent.setAction(Intent.ACTION_GET_CONTENT);
        }

        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("image/*");

        startActivityForResult(intent, RQS_OPEN_IMAGE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK) {
            if (requestCode == RQS_OPEN_IMAGE) {
                Uri wallpaperUri = data.getData();
                Toast.makeText(this, wallpaperUri.toString(), Toast.LENGTH_LONG).show();

                Bitmap newBitmap = loadBitmap(wallpaperUri);
                changeWallpaper(newBitmap);
            }
        }
    }

    private Bitmap loadBitmap(Uri uri) {

        Bitmap bitmap = null;

        try {
            bitmap = BitmapFactory.decodeStream(
                    getBaseContext().getContentResolver().openInputStream(uri));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        return bitmap;
    }

    private void changeWallpaper(Bitmap bitmap){
        if(bitmap != null){
            WallpaperManager wallpaperManager =
                    WallpaperManager.getInstance(getApplicationContext());

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if(wallpaperManager.isWallpaperSupported()){
                    try {
                        wallpaperManager.setBitmap(bitmap);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }else{
                    Toast.makeText(MainActivity.this,
                            "Смена обоев не поддерживается",
                            Toast.LENGTH_LONG).show();
                }
            }else{
                try {
                    wallpaperManager.setBitmap(bitmap);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }else{
            Toast.makeText(MainActivity.this, "Нет картинки", Toast.LENGTH_LONG).show();
        }
    }
}

На относительно новых устройствах мы используем новое действие для намерения ACTION_OPEN_DOCUMENT. С его помощью можно выбрать картинку из разных мест. Выбранное изображение через Uri возвращается назад в приложение.

Обратите внимание, что в Android 6 появился новый метод isWallpaperSupported().

Реклама