ライブ壁紙のバッテリー消費が激しい

1,180 views
Skip to first unread message

石田 岳志

unread,
Jan 5, 2013, 12:05:19 PM1/5/13
to android-g...@googlegroups.com
ライブ壁紙を作ってGooglePlayに公開している者です。
ユーザーから「バッテリーの消費が笑ってしまうほど激しい」という意見をいただきました。
ライブ壁紙なのである程度は仕方がないとは思っていましたが、予想以上に消費が激しいです。
何がいけないのでしょうか。

handler.postDelayed(drawRunnable, time);で遅延をしています。
この遅延時間を大きくすれば改善されるのでしょうか?

ご教授よろしくお願いします。
package jp.tnct.animationwallpaper;


import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Handler;
import android.service.wallpaper.WallpaperService;
import android.view.Display;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.WindowManager;

public class Main extends WallpaperService
{
    Handler handler = new Handler();
    public Engine onCreateEngine()
    {
        //描画用の自作Engineクラスを返す
        return new LiveEngine();
    }
   
    //描画を行うEngineクラス
    public class LiveEngine extends Engine
    {
        //イメージ
        private Bitmap[] imgMiku1 = new Bitmap[9];
        private Bitmap[] imgMiku2 = new Bitmap[4];
       
        //表示状態
        private boolean visible;
        //座標
        private int imgX;
        private int imgY;  
       
        private int frameIndex1 = 0;
        private int frameIndex2 = 0;
        //アニメーションの遅延時間
        private int[] waitTimes1 = {1000, 38, 100, 5, 2000, 100, 100, 150, 100};
        private int[] waitTimes2 = {100, 72, 92, 100};
        //アニメーションのモーションの種類
        private int motionFlag = 1;
               
        //コンストラクタ
        public LiveEngine()
        {
            imgMiku1[0] = BitmapFactory.decodeResource(getResources(), R.drawable.miku01);
            imgMiku1[1] = BitmapFactory.decodeResource(getResources(), R.drawable.miku07);
            imgMiku1[2] = BitmapFactory.decodeResource(getResources(), R.drawable.miku08);
            imgMiku1[3] = BitmapFactory.decodeResource(getResources(), R.drawable.miku09);
            imgMiku1[4] = BitmapFactory.decodeResource(getResources(), R.drawable.miku10);
            imgMiku1[5] = BitmapFactory.decodeResource(getResources(), R.drawable.miku11);
            imgMiku1[6] = BitmapFactory.decodeResource(getResources(), R.drawable.miku02);
            imgMiku1[7] = BitmapFactory.decodeResource(getResources(), R.drawable.miku13);
            imgMiku1[8] = BitmapFactory.decodeResource(getResources(), R.drawable.miku01);
           
            imgMiku2[0] = BitmapFactory.decodeResource(getResources(), R.drawable.miku01);
            imgMiku2[1] = BitmapFactory.decodeResource(getResources(), R.drawable.miku02);
            imgMiku2[2] = BitmapFactory.decodeResource(getResources(), R.drawable.miku03);
            imgMiku2[3] = BitmapFactory.decodeResource(getResources(), R.drawable.miku01);
           
            //座標を取得
            WindowManager wm
                = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
            Display display = wm.getDefaultDisplay();
            this.imgX = display.getWidth()/2 - imgMiku1[0].getWidth()/2;
            this.imgY = display.getHeight() - imgMiku1[0].getHeight();
        }
       
        //描画用のRunnableオブジェクト
        private final Runnable drawRunnable = new Runnable()
        {
            public void run()
            {
                if(motionFlag == 1)
                {
                    motion1();
                }
                else if(motionFlag == 2)
                {
                    motion2();
                }
            }
        };
       
        public void motion1()
        {
            drawFrame(imgMiku1[frameIndex1], imgX, imgY, 100);

            frameIndex1++;
            if(frameIndex1 < imgMiku1.length)
            {
                handler.postDelayed(drawRunnable, waitTimes1[frameIndex1]);
            }
            else
            {
                frameIndex1 = 0;
            }           
        }
       
        public void motion2()
        {
            drawFrame(imgMiku2[frameIndex2], imgX, imgY, 100);

            frameIndex2++;
            if(frameIndex2 < imgMiku2.length)
            {
                handler.postDelayed(drawRunnable, waitTimes2[frameIndex2]);
            }
            else
            {
                frameIndex2 = 0;
            }           
        }
       
        //Engine生成時に呼び出される
        @Override
        public void onCreate(SurfaceHolder surfaceHolder)
        {      
            super.onCreate(surfaceHolder);
            // タッチイベントを有効
            setTouchEventsEnabled(true);
        }
       
        //Engine破棄時に呼び出される
        @Override
        public void onDestroy()
        {
            super.onDestroy();
            //描画用のハンドラを用意
            handler.removeCallbacks(drawRunnable);

            for(int i=0; i<imgMiku1.length; i++)
            {
                // Bitmapデータの解放
                if(imgMiku1[i] != null)
                {
                    imgMiku1[i].recycle();
                    imgMiku1[i] = null;
                }  
            }
            for(int i=0; i<imgMiku2.length; i++)
            {
                // Bitmapデータの解放
                if(imgMiku2[i] != null)
                {
                    imgMiku2[i].recycle();
                    imgMiku2[i] = null;
                }  
            }
        }
       
        //表示状態変更時に呼び出される
        @Override
        public void onVisibilityChanged(boolean visible)
        {
            this.visible = visible;
            if(visible)
            {
                  drawFrame(imgMiku1[0], imgX, imgY, 100);
            }
            else
            {
                handler.removeCallbacks(drawRunnable);   
            }
        }

        //サーフェイス生成時に呼び出される
        @Override
        public void onSurfaceCreated(SurfaceHolder surfaceHolder)
        {
            super.onSurfaceCreated(surfaceHolder);
        }
       
        //サーフェイス変更時に呼び出される
        @Override
        public void onSurfaceChanged(SurfaceHolder holder,int format, int width , int height)
        {
            super.onSurfaceChanged(holder, format, width, height);
            drawFrame(imgMiku1[0], imgX, imgY, 100);
        }

        //サーフェイス破棄時に呼び出される
        @Override
        public void onSurfaceDestroyed(SurfaceHolder holder)
        {
            super.onSurfaceCreated(holder);
            visible = false;
          
            handler.removeCallbacks(drawRunnable);
            for(int i=0; i<imgMiku1.length; i++)
            {
                // Bitmapデータの解放
                if(imgMiku1[i] != null)
                {
                    imgMiku1[i].recycle();
                    imgMiku1[i] = null;
                }      
            }
            handler.removeCallbacks(drawRunnable);
            for(int i=0; i<imgMiku2.length; i++)
            {
                // Bitmapデータの解放
                if(imgMiku2[i] != null)
                {
                    imgMiku2[i].recycle();
                    imgMiku2[i] = null;
                }      
            }

        }
      
        public void onTouchEvent(MotionEvent event)
        {
            super.onTouchEvent(event);

            switch(event.getAction())
            {
            case MotionEvent.ACTION_UP:
                motionFlag = 1;
                frameIndex1 = 0;
                handler.postDelayed(drawRunnable, waitTimes1[frameIndex1]);
                break;
            }
        }

        //オフセット変更時に呼び出される
        @Override
        public void onOffsetsChanged(float xOffset, float yOffset, float xStep, float yStep, int xPixels, int yPixels)
        {
            motionFlag = 2;
            frameIndex2 = 0;
            handler.postDelayed(drawRunnable, waitTimes2[frameIndex2]);   
        }

        //キャンバスで描画を行う
        private void drawFrame(Bitmap img, int x, int y, int time)
        {
            SurfaceHolder holder = getSurfaceHolder();
            Canvas canvas = null;
            try
            {
                //キャンバスをロック
                canvas = holder.lockCanvas();
                if(canvas != null)
                {
                    //描画
                    canvas.drawColor(Color.WHITE);
                    canvas.drawBitmap(img, x, y, null);
                }
            }
            finally
            {
                //Canvas アンロック
                if(canvas != null)
                {
                    holder.unlockCanvasAndPost(canvas);
                }
            }
          
            if(visible)
            {
                handler.postDelayed(drawRunnable, time);
            }
            //次の描画をセット
            handler.removeCallbacks(drawRunnable);
        }
    }
}

XBG

unread,
Jan 6, 2013, 3:17:18 AM1/6/13
to android-g...@googlegroups.com
どうすれば省電力になるか丸投げで聞くより、自分でどこかの数値をコンフィグしてテストしてその辺をユーザが設定できるようにするのが良いと思います。

石田 岳志

unread,
Jan 6, 2013, 4:06:10 AM1/6/13
to android-g...@googlegroups.com
なるほど。ユーザーに設定してもらうという発想はありませんでした。ありがとうございます!
Reply all
Reply to author
Forward
0 new messages