2010-09-09 15 views
5

Piszę animowaną tapetę, która tworzy efekt na tle. Chcę, aby użytkownik mógł wybrać tło z jednej z tapet systemowych i zdjęć z aparatu. Chciałbym, aby użytkownik mógł nacisnąć przycisk w menu Ustawienia, aby lista opcji była wyświetlana, podobnie jak ustawienie tapety na ekranie głównym, bez opcji tapety na żywo. Gdy użytkownik przejdzie przez opcje i wybierze rzeczywisty obraz, załaduję go na moje płótno.Wybieranie tła dla tapety na żywo

Jak to zrobić?

Nie mogę znaleźć interfejsu API w dowolnym miejscu, aby uzyskać listę tapet.

Udało mi się wymyślić listę dostawców tapet wykorzystujących Intents. Dostaję następnie listę dostawców tapet na żywo również za pomocą Intents i usuwam te z mojej pierwszej listy. Podaje mi listę dostawców tapet, które nie są dostępne.

Co teraz? Czy są inne sposoby, aby to zrobić, czego mi brakuje?

Proszę o pomoc.

Odpowiedz

25

Robię to poprzez umieszczenie preferencji w ustawieniach xml w ten sposób (mój jest flash_setting.xml);

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

Stworzyłem klasę niestandardową wziąć uzyskać OnPreferenceClick słuchaczem i oglądania dla użytkownika kliknięcie preferencje jako tak (jest to wezwanie mySettings.java) (proszę pamiętać, że rutynowe getRealPathFromURI nie jest moja i była znaleźć gdzie indziej tutaj);


Twoja klasa powinna rozpocząć poprzez rozszerzenie PreferenceActivity i wdrażaniu zmian słuchacza Sharedpreference

public class flashSettings extends PreferenceActivityimplements SharedPreferences.OnSharedPreferenceChangeListener {  

link do nazwy preferencji i zarejestrować słuchacza

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

Dalej będziemy ustawić na słuchacza preferencji do słuchania "image_custom". Po kliknięciu rozpoczniemy nowy zamiar wyświetlenia selektora zdjęć. Zaczynamy od StartActivityForResult, abyśmy mogli odzyskać URI obrazu z zamierzenia.

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; 
    } 
});} 

Następnie czekamy na działanie, aby zwrócić wynik i parsujemy URI do prawdziwej ścieżki.

@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(); 
}} 

Poniższy fragment kodu został odnaleziony na tym miejscu (przez PercyPercy na this thread), a ja w tym nie tylko pod względem kompletności. Działa to jednak doskonale.

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);} 

Upewnij się, że implementujemy wymagane przesłonięcia;

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

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

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

Następnie w swojej głównej działalności usługowej tapety można wyodrębnić ścieżkę obrazu z udostępnionych preferencji.

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

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

Oto dość nieoczyszczona procedura ładowania obrazu.Próbowałem wprowadzić pułapkę błędów na wypadek, gdyby plik został usunięty, zmieniono jego nazwę lub karta SD zostanie zamontowana (stąd utracisz swój obraz). Próbowałem również wprowadzić kilka prostych sprawdzeń orientacji urządzenia. Jestem pewien, że możesz zrobić to lepiej.

Istnieje również kilka sprawdzeń Samplesize, aby nie przekraczać budżetu maszyny wirtualnej. Jest to najważniejsza część tego kodu, aby zapobiec przymykaniu sił i zdecydowanie należy ją uwzględnić.

Zadzwonię również do tej procedury, gdy orientacja telefonu zostanie zmieniona, tak aby tło zmieniało się za każdym razem.

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 = ""; 
    } 

Mam nadzieję, że to pomoże. Zajęło mi to wiek absolutny, aby wymyślić to wszystko i wiem, że nadal istnieją pewne obszary, które mogę udoskonalić, ale przynajmniej powinienem zacząć.

Jeśli ktoś ma sugestie, jak ulepszyć ten kod, to ja mam uszy.

+0

Czy to zapewnić taką samą listę tapet, które użytkownik widzi na ekranie głównym? To jest to czego chcę. Użytkownik musi mieć możliwość wybrania z systemu tapet i tapet dostarczonych przez inne aplikacje, bez żywych tapet. – DarthNoodles

+0

Umożliwia to przeglądanie każdego obrazu na karcie SD. Jeśli pobierzesz darmowy Droid X Livewallpaper od wabbittdevs, to właśnie to poczujesz. To stąd pochodzi powyższy kod. – Dean

+0

Pobrałem i sprawdziłem. Nie tego chcę. Na ekranie głównym urządzenia naciśnij "menu" i wybierz "tapetę". Oto lista, którą chcę mieć użytkownik, bez animowanych tapet. Na moim urządzeniu otrzymuję na żywo tapety, zdjęcia i tapety HTC. Emulator wyświetla na żywo tapetę, zdjęcia i tapety oraz pozycję "Tapeta" dostarczoną przez próbkę Home. Są to działania, które spełniają intencje ACTION_SET_WALLPAPER. Wygląda na to, że tego, czego chcę, nie można łatwo zrobić za pomocą interfejsu API. – DarthNoodles

0

Nie, to najlepszy sposób, aby to osiągnąć. Wszystko, co reaguje na android.intent.action.SET_WALLPAPER, będzie dostawcą tapet w takiej czy innej formie. Problem polega na tym, że nadanie im tej listy przejmuje kontrolę od równania. Zasadniczo po wybraniu czegoś od innego dostawcy rozwiążesz Live Wallpaper. Prawdopodobnie można to obejść dzięki niektórym twórczym ustawieniom manifestu i niektórym wywołaniom typu "startActivityForResult".

Po wybiorą coś choć to prosta sprawa coś takiego w swoim 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); 
     } 
    } 
} 
Powiązane problemy