Search code examples
androidimagewallpaper

Inserting wallpapers in Android


I'm trying to add a custom wallpaper to the default set of wallpapers in Android. Using the emulator (2.3.3 virtual device) I've found them inside /system/app/Launcher2.apk . I've pulled the APK and decoded it with apktool, added the wallpaper inside the wallpaper folder, and then recoded the APK again with apktool. But I'm unable to push the new apk to the emulator.

On a system terminal, with the emulator on, I use "adb remount" to make the filesystem writeable and then use "adb push" to push the file, but I get a "failed to copy: directory not empty" error. If I try using "adb install", I get this:

    1159 KB/s (5598893 bytes in 4.714s)
    pkg: /data/local/tmp/Launcher2.apk
    Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]

I'm not sure what the error is, but I'm afraid that the only solution may be recompiling Android from source and it may be overkill for what I want to do.

The only reason I'm trying to insert a wallpaper into the system itself is because it seems that the default wallpapers and user wallpapers are treated differently. I have this very simple wallpaper of a clear sky with a cloud at the bottom; it's mostly a blue gradient with a darker blue at the top and a lighter blue at the bottom. A very similar image from the default wallpaper set is displayed just fine but when I try to set my image as a wallpaper I get noticeable color banding, whereas the default image does not.

I tried pulling the default wallpaper from the APK and then pushing it to the emulator as a regular pic in the DCIM folder, and when I set it as a user-defined wallpaper I noticed that it's not displayed quite like as if I had picked it from the default set: you have to crop it first just like any other image, but when picking the whole image I realized that the default wallpapers are actually cropped, but not as much as the default selection when setting up a wallpaper. That is, when choosing a default wallpaper, what is shown is actually less than what is shown when putting that same image in the SD card and choosing it as a wallpaper manually.

I'm just trying to understand how Android works with wallpapers, to see if I'm just doing something wrong with the image or if it's an actual problem with Android and need to "trick it" somehow. The original image is a 800x480 JPG, reescaled proportionally and cropped to 480x320 with GIMP (it's meant for a device with a 240x320 screen). On my computer the image is displayed fine.

original image Original image

resized image Resized image

Wallpaper from the default set Wallpaper from the default set I used for comparison

Notice that the wallpaper from the default set is 640x480. Reescaling my image to 640x480 didn't work either.

I know this is actually 2 questions rather than just one, but I wasn't sure of the best way to explain my problem. Thanks for understanding.


Solution

  • On AOSP (Gingerbread and earlier), the resulting quality difference between wallpapers included in the Launcher (as resources in the apk) to the ones that the user can set from a file in the SD card (normally through the Camera/Gallery app) is actually due to the fact that the ones from the SD card is somewhat downsampled when it went through the stock CropImage activity which restrict the image to a specific output resolution based on the values returned from getWallpaperDesiredMinimumWidth() and getWallpaperDesiredMinimumHeight() API calls.

    The ones included in the Launcher are set directly using a call to WallpaperManager.setResource(), passing in the full-sized bitmap file from the resource, while in the CropImage case, they are set through WallpaperManager.setBitmap(), passing in the downsampled in-memory Bitmap object.

    It seems that if you use (or write on your own) an app that use the WallpaperManager.setStream() API after selecting a file from the SD card (instead of the deferring to CropImage), you should get the same wallpaper quality result as the ones in the Launcher.

    Notice that on ICS, the CropImage activity has been revamped to use BitmapRegionDecoder (among other things) so that the previous limitation might no longer apply.