Live WallPaper - How to Make Interactive Live Video Wallpapers Using Kotlin Android
Last updated Jan 23, 2020 Live Wallpapers are animated, interactive backgrounds for the Android home screen. A live wallpaper is similar to other Android applications and will use the same functionality
In this Example we are going to create Live Video Wall Paper
Let's Start
Step 1: Create new project "Live Video Wallpaper"
Step 2: Create VideoWallpaper service and add below code
import android.app.WallpaperManager;
import android.content.*;
import android.media.MediaPlayer;
import android.service.wallpaper.WallpaperService;
import android.text.TextUtils;
import android.view.SurfaceHolder;
import java.io.IOException;
public class WallPaper extends WallpaperService {
private static final String TAG = WallPaper.class.getName();
private static String sVideoPath;
String VIDEO_PARAMS_CONTROL_ACTION = "com.rrtutors.livevideowallpaper";
String ACTION = "action";
int ACTION_VOICE_SILENCE = 1;
int ACTION_VOICE_NORMAL = 2;
String IS_SILENCE = "is_silence";
/**
* @param context
*/
public void setVoiceSilence(Context context){
Intent intent = new Intent(VIDEO_PARAMS_CONTROL_ACTION);
intent.putExtra(ACTION, ACTION_VOICE_SILENCE);
context.sendBroadcast(intent);
}
/**
* @param context
*/
public void setVoiceNormal(Context context){
Intent intent = new Intent(VIDEO_PARAMS_CONTROL_ACTION);
intent.putExtra(ACTION, ACTION_VOICE_NORMAL);
context.sendBroadcast(intent);
}
/**
* @param context
*/
public void setToWallPaper(Context context, String videoPath){
try {
context.clearWallpaper();
} catch (IOException e) {
e.printStackTrace();
}
sVideoPath = videoPath;
Intent intent = new Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);
intent.putExtra(WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,new ComponentName(context,WallPaper.class));
context.startActivity(intent);
}
@Override
public Engine onCreateEngine() {
return new VideoWallpagerEngine();
}
class VideoWallpagerEngine extends Engine {
private MediaPlayer mMediaPlayer;
private BroadcastReceiver mVideoVoiceControlReceiver;
@Override
public void onCreate(SurfaceHolder surfaceHolder) {
super.onCreate(surfaceHolder);
IntentFilter intentFilter = new IntentFilter(VIDEO_PARAMS_CONTROL_ACTION);
mVideoVoiceControlReceiver = new VideoVoiceControlReceiver();
registerReceiver(mVideoVoiceControlReceiver,intentFilter);
}
@Override
public void onDestroy() {
unregisterReceiver(mVideoVoiceControlReceiver);
super.onDestroy();
}
@Override
public void onVisibilityChanged(boolean visible) {
if (visible){
mMediaPlayer.start();
}else {
mMediaPlayer.pause();
}
}
@Override
public void onSurfaceCreated(SurfaceHolder holder) {
super.onSurfaceCreated(holder);
if (TextUtils.isEmpty(sVideoPath)) {
throw new NullPointerException("videoPath must not be null ");
}else {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setSurface(holder.getSurface());
try {
mMediaPlayer.setDataSource(sVideoPath);
mMediaPlayer.setLooping(true);
mMediaPlayer.setVolume(0f, 0f);
mMediaPlayer.prepare();
mMediaPlayer.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
}
@Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
super.onSurfaceDestroyed(holder);
if (mMediaPlayer != null){
mMediaPlayer.release();
mMediaPlayer = null;
}
}
class VideoVoiceControlReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
int action = intent.getIntExtra(ACTION,-1);
switch (action){
case 1:
mMediaPlayer.setVolume(1.0f,1.0f);
break;
case 2:
mMediaPlayer.setVolume(0,0);
break;
}
}
}
}
}
|
Now Configure Service in Manifest file
<service android:name=".WallPaper" 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/videowallpaper" /> </service>
|
Here we need to create xml file with below code
videowallpaper.xml
<?xml version="1.0" encoding="utf-8"?>
<wallpaper xmlns:android="https://schemas.android.com/apk/res/android"
android:thumbnail="@mipmap/ic_launcher"
>
</wallpaper>
|
Add below permissions in Manifest file
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
|
Step 3:
Now add Required Resourses for the application, in this application i have added few mp4 files in raw folder
Step 4:
Now Its time to create our UI
updated activity_main
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#FF5722"
tools:context=".VideoListActivity">
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:text="Video Wallpaper"
android:gravity="center"
android:textColor="#FFF"
android:textSize="25sp"
android:background="#E70E57"
android:textStyle="bold"
/>
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_margin="10dp"
android:background="#FFF"
android:padding="2dp"
android:layout_height="200dp">
android:id="@+id/imageview1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
android:src="@android:drawable/ic_media_play"
/>
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_margin="10dp"
android:background="#FFF"
android:padding="2dp"
android:layout_height="200dp">
android:id="@+id/imageview2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
android:src="@android:drawable/ic_media_play"
/>
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_margin="10dp"
android:background="#FFF"
android:padding="2dp"
android:layout_height="200dp">
android:id="@+id/imageview3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
android:src="@android:drawable/ic_media_play"
/>
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_margin="10dp"
android:background="#FFF"
android:padding="2dp"
android:layout_height="200dp">
android:id="@+id/imageview4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
android:src="@android:drawable/ic_media_play"
/>
|
MainActivity.kt
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.ImageView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy.NONE
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.activity_main.view.*;
class MainActivity : AppCompatActivity(),View.OnClickListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Glide.with(this).load(R.raw.krish3).diskCacheStrategy(NONE).into(imageview1)
Glide.with(this).load(R.raw.thor_darkworld1).diskCacheStrategy(NONE).into(imageview2)
Glide.with(this).load(R.raw.thor_darkworld2).diskCacheStrategy(NONE).into(imageview3)
Glide.with(this).load(R.raw.chotabeem).diskCacheStrategy(NONE).into(imageview4)
imageview1.setOnClickListener(this)
imageview2.setOnClickListener(this)
imageview3.setOnClickListener(this)
imageview4.setOnClickListener(this)
}
override fun onClick(v: View?) {
val `in` = Intent(applicationContext, MainActivity::class.java)
when (v?.getId()) {
R.id.imageview1 -> `in`.putExtra("filename", "krish3.mp4")
R.id.imageview2 -> `in`.putExtra("filename", "thor_darkworld1.mp4")
R.id.imageview3 -> `in`.putExtra("filename", "thor_darkworld2.mp4")
R.id.imageview4 -> `in`.putExtra("filename", "chotabeem.mp4")
}
startActivity(`in`)
}
}
|
Now create SetWallPaperActivity
class WallPaperActivity : AppCompatActivity() {
private val IS_VIDEO1: String="is_video1"
lateinit var mVideoWallpaper:WallPaper;
lateinit var filename:String;
lateinit var mFile1:File;
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_wall_paper)
mVideoWallpaper = WallPaper()
filename = intent.getStringExtra("filename")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!checkPermissionForStorage()) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 300)
return
}
}
initFile()
}
private fun initFile() {
mFile1 = File(Environment.getExternalStorageDirectory().toString() + "/" + filename)
if (!(mFile1.exists())) {
try {
var idname = filename
idname = idname?.replace(".mp4", "")
val id = resources.getIdentifier(
idname,
"raw", "com.rrtutors.livevideowallpaper"
)
mFile1.createNewFile()
val `is` = resources.openRawResource(id)
writeMp4ToNative(mFile1, `is`)
} catch (e: IOException) {
e.printStackTrace()
}
}
// videoview.setVideoURI(Uri.fromFile(mFile1.getAbsoluteFile()))
// val m = MediaController(this)
// videoview.setMediaController(m)
// videoview.start()
}
private fun writeMp4ToNative(file: File, istr: InputStream) {
try {
val os = FileOutputStream(file)
var len = -1
val buffer = ByteArray(1024)
while ((istr.read(buffer)) != -1) {
os.write(buffer, 0, buffer.size)
}
os.flush()
os.close()
istr.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
fun setWallpaper(view: View) {
mVideoWallpaper.setToWallPaper(this, mFile1.getAbsolutePath())
}
fun setSilence(view: View) {
mVideoWallpaper.setVoiceSilence(this)
}
fun cancelSilence(view: View) {
mVideoWallpaper.setVoiceNormal(this)
}
fun toBack(view: View) {
finish()
}
private fun checkPermissionForStorage(): Boolean {
val result = ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.WRITE_EXTERNAL_STORAGE)
return result == PackageManager.PERMISSION_GRANTED
}
override fun onRequestPermissionsResult(requestCode: Int, @NonNull permissions: Array, @NonNull grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (checkPermissionForStorage()) {
initFile()
}
}
}
|
Step 5:
Now run the app and set your wall paper.
xmlns:app="https://schemas.android.com/apk/res-auto"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#FF5722"
tools:context=".VideoListActivity">
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:text="Video Wallpaper"
android:gravity="center"
android:textColor="#FFF"
android:textSize="25sp"
android:background="#E70E57"
android:textStyle="bold"
/>
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_margin="10dp"
android:background="#FFF"
android:padding="2dp"
android:layout_height="200dp">
android:id="@+id/imageview1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
android:src="@android:drawable/ic_media_play"
/>
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_margin="10dp"
android:background="#FFF"
android:padding="2dp"
android:layout_height="200dp">
android:id="@+id/imageview2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
android:src="@android:drawable/ic_media_play"
/>
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_margin="10dp"
android:background="#FFF"
android:padding="2dp"
android:layout_height="200dp">
android:id="@+id/imageview3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
android:src="@android:drawable/ic_media_play"
/>
android:layout_width="wrap_content"
android:layout_weight="1"
android:layout_margin="10dp"
android:background="#FFF"
android:padding="2dp"
android:layout_height="200dp">
android:id="@+id/imageview4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
android:src="@android:drawable/ic_media_play"
/>
MainActivity.kt
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.ImageView
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy.NONE
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.activity_main.view.*;
class MainActivity : AppCompatActivity(),View.OnClickListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Glide.with(this).load(R.raw.krish3).diskCacheStrategy(NONE).into(imageview1)
Glide.with(this).load(R.raw.thor_darkworld1).diskCacheStrategy(NONE).into(imageview2)
Glide.with(this).load(R.raw.thor_darkworld2).diskCacheStrategy(NONE).into(imageview3)
Glide.with(this).load(R.raw.chotabeem).diskCacheStrategy(NONE).into(imageview4)
imageview1.setOnClickListener(this)
imageview2.setOnClickListener(this)
imageview3.setOnClickListener(this)
imageview4.setOnClickListener(this)
}
override fun onClick(v: View?) {
val `in` = Intent(applicationContext, MainActivity::class.java)
when (v?.getId()) {
R.id.imageview1 -> `in`.putExtra("filename", "krish3.mp4")
R.id.imageview2 -> `in`.putExtra("filename", "thor_darkworld1.mp4")
R.id.imageview3 -> `in`.putExtra("filename", "thor_darkworld2.mp4")
R.id.imageview4 -> `in`.putExtra("filename", "chotabeem.mp4")
}
startActivity(`in`)
}
}
|
Now create SetWallPaperActivity
class WallPaperActivity : AppCompatActivity() {
private val IS_VIDEO1: String="is_video1"
lateinit var mVideoWallpaper:WallPaper;
lateinit var filename:String;
lateinit var mFile1:File;
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_wall_paper)
mVideoWallpaper = WallPaper()
filename = intent.getStringExtra("filename")
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!checkPermissionForStorage()) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 300)
return
}
}
initFile()
}
private fun initFile() {
mFile1 = File(Environment.getExternalStorageDirectory().toString() + "/" + filename)
if (!(mFile1.exists())) {
try {
var idname = filename
idname = idname?.replace(".mp4", "")
val id = resources.getIdentifier(
idname,
"raw", "com.rrtutors.livevideowallpaper"
)
mFile1.createNewFile()
val `is` = resources.openRawResource(id)
writeMp4ToNative(mFile1, `is`)
} catch (e: IOException) {
e.printStackTrace()
}
}
// videoview.setVideoURI(Uri.fromFile(mFile1.getAbsoluteFile()))
// val m = MediaController(this)
// videoview.setMediaController(m)
// videoview.start()
}
private fun writeMp4ToNative(file: File, istr: InputStream) {
try {
val os = FileOutputStream(file)
var len = -1
val buffer = ByteArray(1024)
while ((istr.read(buffer)) != -1) {
os.write(buffer, 0, buffer.size)
}
os.flush()
os.close()
istr.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
fun setWallpaper(view: View) {
mVideoWallpaper.setToWallPaper(this, mFile1.getAbsolutePath())
}
fun setSilence(view: View) {
mVideoWallpaper.setVoiceSilence(this)
}
fun cancelSilence(view: View) {
mVideoWallpaper.setVoiceNormal(this)
}
fun toBack(view: View) {
finish()
}
private fun checkPermissionForStorage(): Boolean {
val result = ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.WRITE_EXTERNAL_STORAGE)
return result == PackageManager.PERMISSION_GRANTED
}
override fun onRequestPermissionsResult(requestCode: Int, @NonNull permissions: Array, @NonNull grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (checkPermissionForStorage()) {
initFile()
}
}
}
|
Step 5:
Now run the app and set your wall paper.
-->