Buat Wallpaper Animasi Android

Saya perlu menampilkan informasi teknis di layar ponsel tentang kondisinya, lebih tepatnya, tentang kondisinya di test pool. Saya selalu ingin melihat informasi ini, yaitu di layar Utama, dan tanpa gerakan tubuh tambahan.


Hanya ada dua cara yang tidak akan mempengaruhi eksekusi aplikasi lain: Widget atau Wallpaper hidup. Saya memilih Wallpaper hidup, mereka juga "wallpaper hidup", karena mereka secara otomatis masuk ke semua halaman layar Utama, dan bahkan ke layar Kunci. Artikel ini memberikan tips praktis tentang cara membuat wallpaper hidup.


Mencari kebenaran


Dokumentasi tentang kucing "wallpaper hidup" menangis. Sejak pengumuman pertama (dan satu-satunya) di blog yang terjadi lebih dari 9 tahun yang lalu, Google belum membuat contoh atau codelab tunggal yang dapat dipahami tentang topik ini. Saya harus mengerti.


Dasar-dasar pertama. Mekanika internal Android sedemikian rupa sehingga kita hanya dapat menginstal aplikasi pada perangkat, dan perangkat semua aplikasi adalah sama. Karena "wallpaper hidup" juga merupakan aplikasi, pilihan komponen kontrol tidak bagus, dan kita harus berharap itu akan menjadi Layanan. Menemukannya mudah: itu WallpaperService .


Ada beberapa contoh "wallpaper hidup", dan siklus hidupnya akan berbeda dari Aktivitas atau Tampilan. Dengan demikian, harus ada satu lagi kelas dasar. Ini adalah WallpaperService.Engine (dan itu pasti bagian dalam untuk WallpaperService !). Jika Anda melihat lebih dekat, itu akan menjadi penyedia acara siklus hidup yang sama seperti Aktivitas, Layanan, dan lainnya yang menyukainya.


Siklus hidup "wallpaper hidup" terlihat seperti ini:


onCreate (SurfaceHolder surfaceHolder)
onSurfaceCreated (pemegang SurfaceHolder)
onSurfaceChanged (dudukan SurfaceHolder, format int, lebar int, tinggi int)
onVisibilityChanged (boolean terlihat)
onSurfaceRedrawNeeded (pemegang SurfaceHolder)
onSurfaceDestroyed (pemegang SurfaceHolder)
onDestroy ()


Dari daftar ini menjadi jelas ketika Anda dapat / perlu menggambar ulang gambar (atau mulai menggambar kembali jika Anda memiliki animasi), dan kapan saatnya untuk menghentikan semua aktivitas dan tidak membuang-buang baterai.


Metode onSurfaceRedrawNeeded () menonjol dari yang lain, baca di bawah ini. Ada juga metode isVisible () untuk membantu (yang di Kotlin berubah menjadi properti isVisible ).


Sekarang Anda dapat membangun konstruktor ini. Saya akan mulai dari akhir.


Gambar


Kita harus menggambar diri kita di atas Kanvas , kita tidak akan memiliki tata letak dan inflater. Cara mendapatkan Kanvas dari SurfaceHolder dan cara menggambar di atasnya berada di luar cakupan artikel ini, ada contoh sederhana di bawah ini.


 fun dummyDraw(c: Canvas) { c.save() c.drawColor(Color.CYAN) c.restore() } // surfaceHolder property is actually a call to the getSurfaceHolder() method fun drawSynchronously() = drawSynchronously(surfaceHolder) fun drawSynchronously(holder: SurfaceHolder) { if (!isVisible) return var c: Canvas? = null try { c = holder.lockCanvas() c?.let { dummyDraw(it) } } finally { c?.let { holder.unlockCanvasAndPost(it) } } } 

Metode Siklus Hidup Engine


Semua metode siklus hidup kecuali onSurfaceRedrawNeeded tidak memerlukan penggambaran ulang segera. Oleh karena itu, nada yang baik adalah untuk menggambar ulang antrian.


 override fun onSurfaceCreated(holder: SurfaceHolder?) { super.onSurfaceCreated(holder) redrawHandler.planRedraw() } override fun onSurfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) { super.onSurfaceChanged(holder, format, width, height) redrawHandler.planRedraw() } override fun onVisibilityChanged(visible: Boolean) { super.onVisibilityChanged(visible) redrawHandler.planRedraw() } override fun onSurfaceDestroyed(holder: SurfaceHolder?) { super.onSurfaceDestroyed(holder) redrawHandler.omitRedraw() } override fun onDestroy() { super.onDestroy() redrawHandler.omitRedraw() } override fun onSurfaceRedrawNeeded(holder: SurfaceHolder) { super.onSurfaceRedrawNeeded(holder) redrawHandler.omitRedraw() drawSynchronously(holder) // do it immediately, don't plan } 

Perhatikan onSurfaceRedrawNeeded , yang memberi kita panggilan ke panggilan balik SurfaceHolder dengan nama yang sama , yang terjadi saat mengubah ukuran dan acara serupa. Callback ini memungkinkan Anda untuk menggambar ulang segera, tanpa memungkinkan pengguna untuk menampilkan gambar lama (dan sudah salah). Sistem menjamin bahwa hingga pengembalian dari metode ini terjadi, output ke layar akan dijeda.


Penjadwal


Saya suka mendefinisikan ulang Handler, dan tidak menjalankan Runnable di dalamnya. Menurut saya, sangat elegan.


Jika Anda memiliki animasi atau pembaruan rutin, Anda perlu membuat antrian pesan secara teratur (postAtTime () dan postDelayed () untuk membantu Anda). Jika data diperbarui secara sporadis, cukup panggil planRedraw() untuk memperbaruinya.


 val redrawHandler = RedrawHandler() inner class RedrawHandler : Handler(Looper.getMainLooper()) { private val redraw = 1 fun omitRedraw() { removeMessages(redraw) } fun planRedraw() { omitRedraw() sendEmptyMessage(redraw) } override fun handleMessage(msg: Message) { when (msg.what) { redraw -> drawSynchronously() else -> super.handleMessage(msg) } } } 

Layanan & mesin


Mareshka dari Service and Engine ini dirakit seperti ini:


 class FooBarWallpaperService : WallpaperService() { override fun onCreateEngine() = FooBarEngine() inner class FooBarEngine : Engine() { .... } } 

AndroidManifest dan mantra lainnya


Saya menyebut mantra dalam pengembangan perangkat lunak yang tidak mungkin dimengerti, tetapi perlu mengulangi dengan tepat.


Di .../app/src/main/res/xml harus ada file XML dengan deskripsi "wallpaper hidup". Nama file ini harus ditentukan dalam AndroidManifest (lihat kata foobarwallpaper dalam contoh di bawah ini)


 <?xml version="1.0" encoding="UTF-8"?> <wallpaper xmlns:android="http://schemas.android.com/apk/res/android" android:thumbnail="@drawable/some_drawable_preview" android:description="@string/wallpaper_description" /> 

Jangan kehilangan permission , meta-data dan intent-filter dalam deskripsi Layanan:


 <service android:name=".FooBarWallpaperService" android:enabled="true" android:label="Wallpaper Example" android:permission="android.permission.BIND_WALLPAPER"> <meta-data android:name="android.service.wallpaper" android:resource="@xml/foobarwallpaper" > </meta-data> <intent-filter> <action android:name="android.service.wallpaper.WallpaperService"> </action> </intent-filter> </service> 

Bagaimana cara menambahkan


"Wallpaper hidup" bersembunyi, karena itu sebuah petunjuk. Saya menggambarkan tampilannya di Samsung saya.


Untuk memulai, tekan lama di suatu tempat di layar Utama, telepon akan masuk ke mode pengaturan desktop, ikon Wallpaper akan muncul.


Kami klik pada ikon Wallpaper , beberapa bagian, kita perlu Wallpaper saya , klik pada tulisan Lihat semua di sudut kanan atas bagian, daftar terbuka di layar penuh.


Kami menekan "tiga poin" dari panggilan menu, di dalamnya item LIve wallpaper (saya punya satu), daftar "wallpaper hidup" yang tersedia muncul.


Pilih wallpaper kami, dan pilih "Layar awal dan kunci".


"Pratinjau" akan muncul, yang sudah ditarik oleh aplikasi kami (untuk mengenali momen ini, ada metode isPreview () ), klik Tetapkan sebagai wallpaper ... Dan kami tidak melihat apa-apa, karena kami kembali ke daftar wallpaper yang tersedia.


Klik "Rumah" dan nikmati.


Dan kemudian Android Watch ?!


Pengamatan yang menarik di sepanjang jalan adalah bahwa Faces di Android Watch dibuat dengan cara yang persis sama (dengan akurasi bahwa mereka memiliki kelas dasar sendiri dengan implementasi mereka sendiri): Service + Engine yang sama, hampir metadata yang sama dan filter maksud untuk Layanan dalam manifes (dalam dimana kata wallpaper muncul empat kali :), Anda juga perlu menulis sheduler Anda sendiri berdasarkan Handler .


Di kelas dasar Watch Face ada onDraw() , tempat Canvas dilewatkan, dan ada yang tidak invalidate() untuk memanggilnya. Tapi ini bukan perbedaan mendasar, tetapi bagian yang diimplementasikan dari boilerplate.


Tidak seperti Wallpaper Animasi, ada beberapa contoh untuk Menonton Wajah, Anda dapat menggali mereka (tautan di sini , di awal).


Apa yang terjadi


Screenshot untuk aplikasi yang melukis layar hijau tidak masuk akal. Namun beberapa foto yang berdasarkan ini ternyata dilakukan untuk stand pertarungan, di bawah spoiler.


Beberapa gambar



Stiker adalah sistem pendeteksi masalah yang tersisa dari generasi sebelumnya.


Ucapan Terima Kasih


Jika bukan karena dua artikel ini, saya akan berkeliaran di kegelapan lebih lama. Saya tidak bisa membayangkan bagaimana mereka bisa ditulis pada tahun 2010 dengan dokumentasi berkualitas seperti itu ?!


Kirill Grouchnikov, Wallpaper hidup
Vogella, Wallpaper Animasi Android - Tutorial


Kode sumber


GitHub

Source: https://habr.com/ru/post/id460951/


All Articles