Выбор фона для живых обоев - PullRequest
5 голосов
/ 09 сентября 2010

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

Как мне это сделать?

Я нигде не могу найти API для получения списка обоев.

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

И что теперь? Есть ли другие способы сделать это, что мне не хватает?

Пожалуйста, помогите.

Ответы [ 2 ]

25 голосов
/ 14 сентября 2010

Я делаю это, помещая предпочтение в XML-файл настроек следующим образом (у меня есть flash_setting.xml);

<Preference
    android:key="image_custom"
    android:title="Choose Background"
    android:summary="Select a Custom Image"
     />

Я создал пользовательский класс, чтобы взять прослушиватель get OnPreferenceClick и наблюдать за пользователемщелкнув по предпочтению следующим образом (это называется mySettings.java) (обратите внимание, что подпрограмма getRealPathFromURI не моя и была найдена в другом месте здесь);


Ваш класс должен начинаться с расширения PreferenceActivity иреализация прослушивателя изменений Sharedpreference

public class flashSettings extends PreferenceActivityimplements SharedPreferences.OnSharedPreferenceChangeListener {    

Ссылка на имя предпочтения и регистрация прослушивателя

@Override
protected void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    getPreferenceManager().setSharedPreferencesName(
            fingerflashpro.SHARED_PREFS_NAME);
    addPreferencesFromResource(R.xml.flash_settings);      getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(
            this);

Далее мы установим прослушиватель по предпочтению для прослушивания 'image_custom'.Когда она нажата, мы начнем новое намерение отобразить средство выбора фотографий.Мы начнем с StartActivityForResult, чтобы мы могли получить URI изображения обратно из намерения.

getPreferenceManager().findPreference("image_custom").setOnPreferenceClickListener(new OnPreferenceClickListener()
{
    @Override
    public boolean onPreferenceClick(Preference preference)
    {
        Display display = getWindowManager().getDefaultDisplay(); 
        int width = display.getWidth();
        int height = display.getHeight();
        Toast.makeText(getBaseContext(), "Select Image - " + (width) + " x " + height , Toast.LENGTH_LONG).show(); 
        Intent photoPickerIntent = new Intent(Intent.ACTION_PICK); 
        photoPickerIntent.setType("image/*");
        startActivityForResult(photoPickerIntent, 1);
        return true;
    }
});}

Затем мы ждем, пока действие вернет результат, и проанализируем URI для реального пути.

@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data) { 
super.onActivityResult(requestCode, resultCode, data); 
if (requestCode == 1) {
if (resultCode == Activity.RESULT_OK) { 
  Uri selectedImage = data.getData();   
  String RealPath;
  SharedPreferences customSharedPreference = getSharedPreferences(fingerflashpro.SHARED_PREFS_NAME, Context.MODE_PRIVATE); 
  SharedPreferences.Editor editor = customSharedPreference.edit ();
  RealPath = getRealPathFromURI (selectedImage);
  editor.putString("image_custom", RealPath); 
  editor.commit(); 
}}

Следующий фрагмент кода был найден на этом сайте (PercyPercy на этой теме ), и я включаю его только для полноты.Тем не менее, он работает отлично.

public String getRealPathFromURI(Uri contentUri) {          
String [] proj={MediaColumns.DATA};  
Cursor cursor = managedQuery( contentUri,  
        proj, // Which columns to return  
        null,       // WHERE clause; which rows to return (all rows)  
        null,       // WHERE clause selection arguments (none)  
        null); // Order-by clause (ascending by name)  
int column_index = cursor.getColumnIndexOrThrow(MediaColumns.DATA);  
cursor.moveToFirst();  
return cursor.getString(column_index);}

Убедитесь, что мы реализуем необходимые переопределения;

@Override
protected void onResume() {
    super.onResume();
}

@Override
protected void onDestroy() {
    getPreferenceManager().getSharedPreferences().
       unregisterOnSharedPreferenceChangeListener(this);
    super.onDestroy();
}

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
        String key) {
}}

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

@Override
    public void onSharedPreferenceChanged(SharedPreferences prefs,
            String key) {

        imageBg = prefs.getString("image_custom", "Bad Image");
            getBackground();}

Вот довольно грубая процедура загрузки изображения.Я попытался вставить сообщение об ошибке на случай, если файл будет удален, переименован или смонтирована SD-карта (следовательно, вы потеряете свой образ).Я также попытался ввести некоторые грубые проверки ориентации устройства.Я уверен, что вы можете сделать лучше.

Там также есть некоторая проверка Samplesize, чтобы вы не превышали бюджет виртуальной машины.Это самая важная часть этого кода для предотвращения принудительного закрытия и должна быть обязательно включена.

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

void getBackground() { 
        if (this.cvwidth == 0 || this.cvheight == 0 || this.visibleWidth == 0) {
               this.cvwidth = 480;
               this.cvheight = 854;
               this.visibleWidth = 480;}
        if(new File(imageBg).exists()) {
                int SampleSize = 1;
             do {
                 BitmapFactory.Options options = new BitmapFactory.Options();
                 options.inJustDecodeBounds = true;
                 bg = BitmapFactory.decodeFile(imageBg, options);
                SampleSize = (int) (Math.ceil(options.outWidth/(this.visibleWidth * 2))*2);
                options.inJustDecodeBounds = false;
                 try {options.inSampleSize = SampleSize;
                     bg = BitmapFactory.decodeFile(imageBg, options);}
                    catch (OutOfMemoryError e) {
                        SampleSize = SampleSize * 2;
                        }
                } while (bg == null);

           bg = Bitmap.createScaledBitmap(bg, this.cvwidth/2, this.cvheight, true);}
        else {bg = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
            bg = Bitmap.createScaledBitmap(bg, this.cvwidth/2, this.cvheight, true);}
        LoadText = "";
    } 

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

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

0 голосов
/ 06 декабря 2012

Нет, это в значительной степени лучший способ сделать это.Все, что отвечает на android.intent.action.SET_WALLPAPER, будет поставщиком обоев той или иной формы.Проблема в том, что предоставление им этого списка выведет вас из-под контроля.По сути, если они выберут что-то у другого провайдера, ваши живые обои будут отключены.Вероятно, вы могли бы обойти это с некоторыми творческими настройками манифеста или с некоторыми вызовами типа «startActivityForResult».

После того, как они выбирают что-то, хотя это просто вопрос чего-то подобного в вашем WallpaperService.Engine:

@Override
public void onSurfaceChanged( SurfaceHolder holder, int format, int width, int height )
{
    super.onSurfaceChanged( holder, format, width, height );
    if( isVisible() )
    {
    mSurfaceHolder = holder;
    final Drawable drawable = WallpaperManager.getInstance( getBaseContext() ).getFastDrawable();
    mSurfaceHolder.setFormat( RenderThread.pixFormat );
    Canvas c = mSurfaceHolder.lockCanvas();
    if( c != null )
        {
            drawable.draw( c );
            mSurfaceHolder.unlockCanvasAndPost( c );
        }
    }
}
...