T

# Projeto exemplo: VideoWallpaperApp (Kotlin) Este documento contém os arquivos principais para um app Android que: 1) permite ao usuário escolher um vídeo do dispositivo; 2) guarda a URI com permissão persistente; 3) fornece um WallpaperService que reproduz esse vídeo como papel de parede animado (sem áudio e em loop). --- ## 1) README (instruções rápidas) 1. Importar esse projeto no Android Studio (Kotlin, minSdkVersion 21+ recomendado). 2. Rodar no dispositivo (emulador pode não suportar live wallpaper). 3. No app, toque em "Escolher vídeo" e selecione um vídeo pela interface do sistema (Ação `ACTION_OPEN_DOCUMENT`). 4. Depois de escolher, toque em "Definir como live wallpaper" — o Android abrirá a tela de escolha de live wallpaper já apontando para o serviço. Observações: use `takePersistableUriPermission(...)` (feito no exemplo) para manter acesso ao arquivo. O serviço usa `MediaPlayer` e a `SurfaceHolder` para desenhar o vídeo. --- ## 2) app/src/main/java/com/example/videowallpaper/MainActivity.kt ```kotlin package com.example.videowallpaper import android.app.WallpaperManager import android.content.ComponentName import android.content.Context import android.content.Intent import android.net.Uri import android.os.Bundle import android.provider.Settings import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import com.example.videowallpaper.databinding.ActivityMainBinding class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding private val prefsName = "video_wallpaper_prefs" private val keyUri = "video_uri" private val pickVideo = registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri: Uri? -> uri?.let { // Persistir permissão contentResolver.takePersistableUriPermission(it, Intent.FLAG_GRANT_READ_URI_PERMISSION) getSharedPreferences(prefsName, Context.MODE_PRIVATE) .edit() .putString(keyUri, it.toString()) .apply() binding.tvStatus.text = "Vídeo salvo: ${it.lastPathSegment}" } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) binding.btnChoose.setOnClickListener { // Tip: documentos persistentes -> use "video/*" pickVideo.launch(arrayOf("video/*")) } binding.btnSetWallpaper.setOnClickListener { // Abrir a tela para trocar o live wallpaper apontando para o serviço val intent = Intent(WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER) intent.putExtra( WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT, ComponentName(this, VideoWallpaperService::class.java) ) startActivity(intent) } // Mostra status val saved = getSharedPreferences(prefsName, Context.MODE_PRIVATE).getString(keyUri, null) binding.tvStatus.text = if (saved != null) "Vídeo selecionado" else "Nenhum vídeo selecionado" } } ``` --- ## 3) app/src/main/java/com/example/videowallpaper/VideoWallpaperService.kt ```kotlin package com.example.videowallpaper import android.content.Context import android.content.SharedPreferences import android.media.MediaPlayer import android.net.Uri import android.service.wallpaper.WallpaperService import android.view.SurfaceHolder class VideoWallpaperService : WallpaperService() { override fun onCreateEngine(): Engine { return VideoEngine() } inner class VideoEngine : Engine(), SurfaceHolder.Callback, MediaPlayer.OnPreparedListener { private var mediaPlayer: MediaPlayer? = null private val prefsName = "video_wallpaper_prefs" private val keyUri = "video_uri" override fun onSurfaceCreated(holder: SurfaceHolder) { super.onSurfaceCreated(holder) holder.addCallback(this) } override fun onSurfaceDestroyed(holder: SurfaceHolder) { super.onSurfaceDestroyed(holder) releasePlayer() } override fun surfaceCreated(holder: SurfaceHolder) { // Não iniciar aqui — aguardar onVisibilityChanged(true) } override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { // sem-op } override fun surfaceDestroyed(holder: SurfaceHolder) { releasePlayer() } override fun onVisibilityChanged(visible: Boolean) { if (visible) startOrResume() else pausePlayer() } private fun startOrResume() { val prefs = applicationContext.getSharedPreferences(prefsName, Context.MODE_PRIVATE) val uriString = prefs.getString(keyUri, null) ?: return val uri = Uri.parse(uriString) if (mediaPlayer == null) { mediaPlayer = MediaPlayer() try { mediaPlayer?.apply { setSurface(surfaceHolder.surface) setDataSource(applicationContext, uri) isLooping = true setVolume(0f, 0f) // sem áudio setOnPreparedListener(this@VideoEngine) prepareAsync() } } catch (e: Exception) { e.printStackTrace() releasePlayer() } } else { mediaPlayer?.start() } } private fun pausePlayer() { mediaPlayer?.pause() } override fun onPrepared(mp: MediaPlayer) { mp.start() } private fun releasePlayer() { try { mediaPlayer?.stop() } catch (_: Exception) {} mediaPlayer?.release() mediaPlayer = null } private val surfaceHolder: SurfaceHolder get() = this@VideoEngine.surfaceHolder } } ``` --- ## 4) app/src/main/AndroidManifest.xml ```xml ``` --- ## 5) app/src/main/res/xml/wallpaper.xml ```xml ``` --- ## 6) app/src/main/res/layout/activity_main.xml ```xml

Comentários

Postagens mais visitadas deste blog

Atualização 1

P

Paula