Android Tutorial Android Live Wallpaper tutorial

Using the new LiveWallpaper library you can now create your own live wallpapers. The user can set live wallpapers by long pressing on the home screen and choosing Wallpapers - Live Wallpapers.

Creating a live wallpaper is not too difficult.

A service is responsible for handling the wallpaper events and drawing the wallpaper.

There can be several instances of the same wallpaper at the same time. For example the user can set your wallpaper as the home screen wallpaper and also see a demo of your wallpaper in the wallpaper preview dialog.

LiveWallpaper library contains two objects: LWManager and LWEngine.
LWManager is responsible for raising the events.
The first parameter of each event is of type LWEngine. LWEngine represents a specific wallpaper instance.
LWEngine includes a Canvas property which is used to draw the wallpaper.
When you finish drawing you must call LWEngine.Refresh or LWEngine.RefreshAll. Otherwise the drawing will not appear.

The following example draws a blue background. Red circles are drawn when the user touches the screen:
B4X:
Sub Process_Globals
   Dim lwm As LWManager
End Sub

Sub Service_Create
   lwm.Initialize("lwm", True)
End Sub

Sub LWM_SizeChanged (Engine As LWEngine)
   Engine.Canvas.DrawColor(Colors.Blue)
   Engine.RefreshAll
End Sub

Sub LWM_Touch (Engine As LWEngine, Action As Int, X As Float, Y As Float)
   Engine.Canvas.DrawCircle(X, Y, 20dip, Colors.Red, True, 0)
   Engine.Rect.Left = X - 20dip
   Engine.Rect.Right = X + 20dip
   Engine.Rect.Top = Y - 20dip
   Engine.Rect.Bottom = Y + 20dip
   Engine.Refresh(Engine.Rect)
End Sub
SS-2011-11-15_11.11.45.png


As there could be several different engines, it is convenient to work with the local engine.
LWEngine includes a Tag property which you can use to store data specific to that engine.

LWManager includes an internal timer that you can use if you need to do animations. The Tick event will only be raised for visible wallpapers. This is important to conserve battery.

For example the following code draws the time on the wallpaper:
B4X:
Sub Process_Globals
   Dim lwm As LWManager
End Sub

Sub Service_Create
   lwm.Initialize("lwm", True)
   lwm.StartTicking(1000) 'tick every second
End Sub

Sub LWM_Tick (Engine As LWEngine)
   Engine.Canvas.DrawColor(Colors.Black) 'Erase the background
   Engine.Canvas.DrawText(DateTime.Time(DateTime.Now), _
      300dip, 100dip, Typeface.DEFAULT_BOLD, 40, Colors.White, "LEFT")
   Engine.RefreshAll
End Sub
SS-2011-11-15_11.23.06.png


Offsets
On most devices the wallpaper virtual size is wider than a single screen. When the user moves to a different screen the offset changes.
You can use the OffsetChanged event to handle those changes.
LWEngine.FullWallpaperWidth / Height return the full size of the wallpaper.
LWEngine.CurrentOffsetX / Y return the current position.
Note that the wallpaper scrolls less than the foreground layer with the icons.

The LiveWallpaperImage demonstrates how to use those properties to display an image over the full wallpaper.

LWManager events

SizeChanged - Raised when the engine is first ready and when the screen size changes (for example when the orientation changes).
VisibilityChanged - Raised when a wallpaper becomes visible or invisible.
Touch - Raised when the user touches the wallpaper.
Tick - The internal timer tick event.
OffsetChanged - Raised when the wallpaper offsets change.
EngineDestroyed - Raised when an engine is destroyed.

Configuration
Live wallpapers require some configuration.
1. You should add the inner service declaration to the manifest editor (Project -> Manifest Editor):
B4X:
AddApplicationText(
<!-- ******** Add the internal service declaration - you can change android:label  ******* -->
<service
        android:label="My Livewallpaper"
        android:name="anywheresoftware.b4a.objects.WallpaperInternalService"
        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" />
</service>
)
It is also recommended to change minSdkVersion to 7 (at the beginning of the manifest editor code).

2. Add wallpaper.xml to Objects\res\xml folder and set it to be readonly (otherwise it will be deleted during compilation).
You can find this file in both attached examples.

3. Your service must be named WallpaperService. Note that there is an additional service inside the library named anywheresoftware.b4a.objects.WallpaperInternalService. The internal service connects to your service.

Examples
LiveWallpaperImage - The user can select an image from the activity. This image is set as the wallpaper. When the user changes the wallpaper offset the image is updated accordingly.

LiveWallpaperBall - A bouncing smiley. Clicking on the smiley will change its direction.
Before running the examples you need to set Object\res\xml\wallpaper.xml to be readonly. Otherwise it will be deleted.

Note that it is recommended to test live wallpapers in Release mode (the wallpaper will fail in debug mode when the process is started by the OS).
 

Attachments

  • LiveWallpaperBall.zip
    8.3 KB · Views: 2,225
  • LiveWallpaperImage.zip
    8 KB · Views: 2,432
Last edited:

walterf25

Expert
Licensed User
Longtime User
Live WallPaper

well off the top of my head i was thinking of using a GIF file, and then use the gif library, but since i'm not too familiar with this wallpaper library, i thought i would ask and see if get some examples first!

thanks,
Walter
 

NeoTechni

Well-Known Member
Licensed User
Longtime User
Sorry... but how to do that in the code?, for example in the LiveWallpaperImage code, to save the imagen, so I will not need to select the imagen each time I restart the tablet, isnt?

PS: I dont have to much experience with the code...

Thank you!

This should help
Files - Basic4android Wiki

Also, since your LWP just crashes inside my large app, but not on it's own
I've decided to just put it in it's own APK and have the larger app handle the updates.
 

walterf25

Expert
Licensed User
Longtime User
Live WallPaper

Hello, how do you make a live wallpaper that when you swipe from one screen to the left or the right you can see the live wallpaper kind of scroll also, so far the only ones i have been able to make are pretty much static, you do not see them move left or right to be able to see the details to the left or right, does anyone know?

thanks,
Walter
 

walterf25

Expert
Licensed User
Longtime User
Unexpected error

Hello Erel, i just installed basic4android version 2.0 on my new laptop, i have been working on some live wallpaper apps for the past few weeks, for some reason when i load the live wallpaper apps on my phone using my new laptop i get this error, i'm not sure what's going on, since this laptop is new i had to install the Android SDK latest version, i'm not sure if this has anything to do with this issue!

** Activity (main) Create, isFirst = true **


** Activity (main) Resume **


** Activity (main) Pause, UserClosed = false **


** Service (wallpaperservice) Create **


wallpaperservice_service_create (B4A line: 35)


lwm.Initialize("lwm", False)
java.lang.NoSuchFieldError: anywheresoftware.b4a.BA.isService
at anywheresoftware.b4a.objects.WallpaperInternalService$LWManager.Initialize(WallpaperInternalService.java:62)
at com.dandre.shootingstar.wallpaperservice._service_create(wallpaperservice.java:310)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:170)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:154)
at com.dandre.shootingstar.wallpaperservice.onCreate(wallpaperservice.java:38)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2021)
at android.app.ActivityThread.access$2500(ActivityThread.java:124)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1022)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3806)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)

In the configure path menu i tried setting different platform levels, i tried android-8, android-10, android-12, android-13 and 14 and i still get the same error, i need to figure out what is giving me this error, the same app runs just fine on my old laptop, but i need to transfer everything to my new laptop.
I really need your help on this Erel!

thanks,
Walter
 

walterf25

Expert
Licensed User
Longtime User
Live WallPaper error

don't i feel stupid, thanks Erel, that solved the issue.
I know i should probably start another thread for this, but on your live wallpaper tutorial on the livewallpaperball app, is it possible to set an image as the background instead of just drawing a rectangle filled with color, and is it possible to add more than one smiley at a time?

Trying to figure out how to do multipple particles, i found a tutorial in java where you can simulate bubbles starting from the bottom of the screen and continue going up, is this possible with this library Erel?

thanks,
Walter
 

NeoTechni

Well-Known Member
Licensed User
Longtime User
If you mean building it into the library:
I feel that'd bloat the library.
That's something we can do, that shouldn't be in the library

If you mean can you make a wallpaper using the lib, to have that effect:
Yes
 

walterf25

Expert
Licensed User
Longtime User
Bubbles

yes, i mean building a live wallpaper with that effect, NeoTechni, would you mind sharing some code to accomplish this, i don't want the whole code, at least justs how to get started, so far i have only been able to create live wallpapers using various images loading them into an array and displaying them one after the next to create some sort of animation, but am not too happy with how that looks, i would like to create live wallpapers where i can add animation to static image.

I'd really appreciate it if you can point me in the right direction.

thanks
 

walterf25

Expert
Licensed User
Longtime User
Canvas

@ Erel, i changed the code in the
B4X:
Sub DrawBackground (Engine As LWEngine)
bmp.Initialize(File.DirAssets, "image1.jpg")
   Engine.canvas.drawcolor(backgroundcolor)
   Engine.RefreshAll
End Sub

to this

B4X:
Sub DrawBackground (Engine As LWEngine)
bmp.Initialize(File.DirAssets, "image1.jpg")
   Engine.Canvas.DrawBitmap(bmp, Null, Engine.Rect)
   Engine.RefreshAll
End Sub

but it doesn't draw the bitmap continuosly, what am i doing wrong?
 

walterf25

Expert
Licensed User
Longtime User
canvas

Never mind i have figured it out, Erel maybe you can point me in the right direction as to how to accomplish the bubbles effect, i would like to simulate bubbles starting from the bottom of the screen and go up all the way to the top, any ideas?
 

NeoTechni

Well-Known Member
Licensed User
Longtime User
Never mind i have figured it out, Erel maybe you can point me in the right direction as to how to accomplish the bubbles effect, i would like to simulate bubbles starting from the bottom of the screen and go up all the way to the top, any ideas?

Create a custom type that keeps track of the bubble's X/Y coordinate, speed, and which bubble graphic to use (I assume you'll want more than 1)
Use a list to store the bubbles.

When the X position of the wallpaper changes, draw the screen
When the timer ticks, increment the bubble's X/Y coordinates by the speed, draw the screen

I recommend using PNG's with anti-aliased transparency for the edges. But for weaker devices, GIF will do.

To draw the screen, just draw all the images centered at their X/Y coordinates (X-width/2, y-height/2)

If you need more help, feel free to PM me.
 

walterf25

Expert
Licensed User
Longtime User
Live Wallpaper Engine question

Hi Erel, is it possible to declare two different variables such
B4X:
dim lwm as LWManager
dim lwm1 as LWManager
and use both to draw views at different speeds, currently i'm working on a live wallpaper where i have 20 different jpg frames as the background, and i need to add for example a dragon fly, flying accross the screen, i'm using a sprite sheet for the dragon fly it contains about 7 frames, but i need to create the effect of the dragon fly moving it's wings faster than the background image, i tried using a different timer but that doesn't work because the lwm_tick is set to 42 milliseconds, and if i have a different timer to let's say tick every 5 milliseconds, still the lwm_tick sub will not see the variables inside the other timer change until every 42 milliseconds, can you or someone slap me in the face and show me how to do this?

thanks everyone,
Walter
 

NeoTechni

Well-Known Member
Licensed User
Longtime User
change the lwm tick time to half, and only increment the background every other frame. Update the dragon fly every frame.
 

NeoTechni

Well-Known Member
Licensed User
Longtime User
How do we use the Action parameter for touch events?

I get that 0=down, 1=up, 2=move for finger 1
But for finger 2, it's 261=down 262=up, and 2=move
for finger 3, it's 517=down 518=up, and 2=move
for finger 4, it's 773=down 774=up, and 2=move
for finger 5, it's 1029=down 1030=up, and 2=move
and so forth and so forth (I don't know the rest, do you?)

But them all using 2 for move, makes it impossible to tell which finger is moving

Hi Neo, how are you, is this the only way to do this, please tell me is not?

That'd be the easiest way
 
Top