Is it possible to set an animated gif file as live wallpaper in android?

后端 未结 2 1803
时光说笑
时光说笑 2020-11-29 19:01

I\'m new to Android platform. I wish to develop a live wallpaper application. When i was searched regarding this in search Engine\'s, many of them created a

2条回答
  •  悲哀的现实
    2020-11-29 19:50

    See this article: How to set gif as android live wallpaper - techprpr - Medium

    Jens answer use "Movie" class, but Movie class is deprecated in android api 28

    so when api >= 28, I use AnimatedImageDrawable instead

    Setup live wallpaper like Jens answer, and I change wallpaper service code:

    wallpaper service: AnimWallpaper

    public class AnimWallpaper extends WallpaperService {
        @Override
        public Engine onCreateEngine() {
            return new CustomEngine();
        }
    
        class CustomEngine extends Engine {
            UseAnim useAnim;
    
            public CustomEngine() {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                    useAnim = new UseAnim(getApplicationContext(), getSurfaceHolder(), R.raw.gif2);
                }
            }
    
            @Override
            public void onVisibilityChanged(boolean visible) {
                super.onVisibilityChanged(visible);
                if (visible) {
                    useAnim.restart();
                } else {
                    useAnim.stop();
                }
            }
    
            @Override
            public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                super.onSurfaceChanged(holder, format, width, height);
                useAnim.updateScaleAndPadding2(width, height);
                useAnim.restart();
            }
    
    
            @Override
            public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) {
                super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep, xPixelOffset, yPixelOffset);
                useAnim.restart();
            }
    
            @Override
            public void onDestroy() {
                super.onDestroy();
                useAnim.stop();
            }
        }
    
    }
    

    UseAnim

    class UseAnim {
        SurfaceHolder holder;
        Runnable startRunnable;
        AnimatedImageDrawable gif;
        float fps = 60;
        Handler handler = new Handler();
    
        @RequiresApi(api = Build.VERSION_CODES.P)
        public UseAnim(Context ctx, SurfaceHolder holder, int gifResId) {
            this.holder = holder;
            final ImageDecoder.Source src = ImageDecoder.createSource(ctx.getResources(), gifResId);
            startRunnable = new Runnable() {
                @Override
                public void run() {
                    start();
                }
            };
    
            new Handler().post(new Runnable() {
                @Override
                public void run() {
                    try {
                        UseAnim.this.gif = (AnimatedImageDrawable) ImageDecoder.decodeDrawable(src);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
    
                    UseAnim.this.gif.start();
                }
            });
        }
    
        public void restart() {
            stop();
            start();
        }
    
        float scale = -1;
    
        public void start() {
            // since get gif with AnimatedImageDrawable must be in handler.post, so gif maybe null
            if (gif != null) {
                Canvas canvas = null;
                try {
                    if (scale == -1) {
                        updateScaleAndPadding();
                    }
    
                    canvas = holder.lockCanvas();
    
                    if (canvas != null) {
                        canvas.translate(horiPadding, vertiPadding);
                        canvas.scale(scale, scale);
                        gif.draw(canvas);
                    }
                } finally {
                    if (canvas != null) {
                        holder.unlockCanvasAndPost(canvas);
                    }
                }
            }
    
            handler.removeCallbacks(startRunnable);
            handler.postDelayed(startRunnable, (long) (1000L / fps));
        }
    
        public void stop() {
            handler.removeCallbacks(startRunnable);
        }
    
        int horiPadding;
        int vertiPadding;
    
        private void updateScaleAndPadding() {
            Canvas canvas = null;
            try {
                canvas = holder.lockCanvas();
                int cw = canvas.getWidth();
                int ch = canvas.getHeight();
    
                updateScaleAndPadding2(cw, ch);
            } finally {
                if (canvas != null) {
                    holder.unlockCanvasAndPost(canvas);
                }
            }
        }
    
        public void updateScaleAndPadding2(int cw, int ch) {
            if (gif != null) {
                int gifW = gif.getIntrinsicWidth();
                int gifH = gif.getIntrinsicHeight();
                if (gifW * 1f / gifH > cw * 1f / ch) {
                    scale = ch * 1f / gifH;
                } else {
                    scale = cw * 1f / gifW;
                }
    
                horiPadding = (int) ((cw - gifW * scale) / 2);
                vertiPadding = (int) ((ch - gifH * scale) / 2);
            }
        }
    }
    

提交回复
热议问题