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,240
  • LiveWallpaperImage.zip
    8 KB · Views: 2,454
Last edited:

magarcan

Active Member
Licensed User
Longtime User
Which device are you using?
I'm using a Samsung Galaxy S with Onecosmic's ICS ROM. Could this be the problem?

I've tested some other live wallpaper and detect correctly changing between Desktops...
 

FJS

Active Member
Licensed User
Longtime User
Help with this topic

I see, the readonly property of wallpaper.xml is removed when it is zipped. I've added a comment about it in the first post.

You will need to unzip the project again and set wallpaper.xml to be readonly.

I have the following error, and I dont know how to solve it. Could you help me??
I have follow the previous steps but...

thank you in advance for your support

Best regards
 

Attachments

  • Error2.jpg
    Error2.jpg
    65 KB · Views: 347

JonPM

Well-Known Member
Licensed User
Longtime User
is it possible to create a live wallpaper with 3d animated objects? any pointers?
 

boten

Active Member
Licensed User
Longtime User
Ok to call main activity, you must change the wallpaper.xml file, stored on

Objects/res/xml/wallpaper.xml

eg:

<?xml version="1.0" encoding="utf-8"?>
<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
android:thumbnail="@drawable/icon"
android:description="@string/description"
android:settingsActivity="com.gtr.test99.main" <--- this part load the preference of my wallpaper , com.gtr.test is the packagename of the livewallpaper .
/>

After change this don't forget to set this file wallpaper.xml READ ONLY....

Good luck

I tried to do what you prescribed. for testing puposes there was no "setting screen" in the main app. Yes, when choosing this LWP I got the "settings...] button, in addition to the "set wallpaper" button, and pressing the "settings..." brought back the main app (which it should)

My question is how to make it appear as "configure..." in the list of LWPs?
 

boten

Active Member
Licensed User
Longtime User
strange: "configure..." appears when running on phone, but does NOT appear when running on emulator.

addition: the "configure..." appears only when android:settingsActivity="xxx.yyy.main"

if I create another activity (say "setup") in the app and change wallpaper.xml to include:

android:settingsActivity="xxx.yyy.setup"

the "configure..." does not appear ??!!??
 
Last edited:

FJS

Active Member
Licensed User
Longtime User
Load pictures to live wallpaper

Good night,

Please, I would like to made a livewallpaper, with several pictures, like a "colage". The main idea is adding two pictures, xxx.jpg and yyy.jpg (with their propities) and then adding movements (increase the size, rotation, or lineal moment), but I dont know how to load and use it...

Please, do you have any example??

PS: it will be a sorprise for a friend

Thank you very much for your help and support

Best regards
 

boten

Active Member
Licensed User
Longtime User
@Erel,
stam1 is a very simple LWP - it shows the "settings..." button when activated and ALSO the "configure" option in the list of wallpapers. pressing either "settings..." or "configure" shows the main activity msgbox.
the wallpaper.xml file has the line:
android:settingsActivity="boten.stam1.main"


stam2 is very similar except that there's extra activity "parm", and its wallpaper.xml has the line:
android:settingsActivity="boten.stam2.parm"

both are READ ONLY.

stam2 does NOT shows the "configure" option in the wallpaper list, but DOES show "settings..." button. But when pressing it, the app stops unexpectedly (error in walpaper.livepicker).

The unfiltered log is also attached, line 25 points to the problem. Now how do I solve this?
 

Attachments

  • stam1.zip
    6.8 KB · Views: 384
  • stam2.zip
    7.3 KB · Views: 338
  • unfilterlog.zip
    1.2 KB · Views: 336

boten

Active Member
Licensed User
Longtime User
I'm on 1.7 - what to do there?
Tried to unmark "do not overwrite..." , compile once, then changed the xml file to reflect what is needed (as per the tutorial"), same problem.

my "new" androidmanifest.xml is:
B4X:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="boten.stam2"
      android:versionCode="1"
      android:versionName=""
     android:installLocation="internalOnly">
      <uses-sdk android:minSdkVersion="7" />
      <supports-screens
          android:largeScreens="true"
          android:normalScreens="true"
          android:smallScreens="true"
          android:anyDensity="true"/>
    <application android:icon="@drawable/icon" android:label="stam2">
       
        <activity android:windowSoftInputMode="stateHidden" android:launchMode="singleTop" android:name=".main"
                  android:label="stam2" android:screenOrientation="unspecified">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name="wallpaperservice"></service>
<receiver android:name="wallpaperservice$wallpaperservice_BR">
</receiver><activity android:windowSoftInputMode="stateHidden" android:launchMode="singleTop" android:name="parm" android:label="parm" android:screenOrientation="unspecified"></activity>

<!-- Add the internal service declaration (you can change android:label) -->
        <service android:name="wallpaperservice"></service>


   <service
            android:label="stam2" 
            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>
<!-- End of internal service declaration -->

    </application>
   

</manifest>
 
Last edited:

boten

Active Member
Licensed User
Longtime User
You should uncheck the "do not overwrite" option and compile your app. You will see the declaration in the manifest file.
That's what I did (my previous post). The "new" androidmanifet.xml DOES contain the lines:

B4X:
<activity android:windowSoftInputMode="stateHidden"
 android:launchMode="singleTop" android:name="parm"
  android:label="parm" android:screenOrientation="unspecified"></activity>
 
Top