Живые обои Android не отображаются

Я только начал изучать живые обои и сделал эту штучку.

дело в том, что мое приложение компилируется без проблем.

когда я открываю его в телефоне, он показывает обои в предварительном просмотре, но когда я нажимаю «установить как обои», он почему-то вылетает и возвращает передний экран, а мои обои становятся черными, но он не запускает их.

я предполагаю, что проблема где-то в onDestory() ..

public class Strips extends WallpaperService {

private StripsEngine engine;

@Override
public void onCreate() {
    super.onCreate();
    engine = new StripsEngine();
    engine.resume();

}

@Override
public void onDestroy() {
    super.onDestroy();
    engine.pause();
}

@Override
public Engine onCreateEngine() {

    return engine;
}

class StripsEngine extends Engine implements Runnable {
    private Thread t = null;
    private SurfaceHolder holder;
    private boolean clearToRun = false;
    private Paint paint = new Paint();
    private Paint paint2 = new Paint();
    private int frame;
    private float endX,endY;
    private int height, width;
    private Canvas c;


    StripsEngine() {
        holder = getSurfaceHolder();
        paint.setColor(Color.WHITE);
        paint.setStrokeWidth(30);
        paint.setAntiAlias(true);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStyle(Paint.Style.STROKE);
        paint2 = paint;
        paint2.setColor(Color.BLACK);
        paint2.setStrokeWidth(40);
        frame = 0;
    }

    void drawStrips() {

    }

    public void run() {
        // TODO Auto-generated method stub
        while (clearToRun) {
            if (!holder.getSurface().isValid()) {
                continue;
            }
            height = 800;
            width = 480; 

            endX = (frame) % (width + 10);
            endY = (frame / 3) % (height + 10);

            if (endX == 0)
                paint.setARGB(255,(int)(Math.random()*255), (int)(Math.random()*255),(int)(Math.random()*255));
            if (endY ==0)
                paint.setARGB(255,(int)(Math.random()*255), (int)(Math.random()*255),(int)(Math.random()*255));


            c = holder.lockCanvas();
            c.drawLine(endX-30, endY-10, endX , endY,paint);
            c.drawLine(endX-30, endY-10, endX , endY,paint);
            holder.unlockCanvasAndPost(c);
            frame = frame +2;
            }
    }
    public void pause() {
        clearToRun = false;
        while (true) {
            try {
                t.join();
            }
            catch (InterruptedException e) {
                e.printStackTrace();    
            }
            break;
        }
        t = null;
    }

    public void resume() {
        clearToRun = true;
        t = new Thread(this);

        t.start();
    }
}

}

07-06 17:14:43.869: E/Surface(478): ошибка при удалении буфера из очереди (Неизвестная ошибка: -19) 07-06 17:14:43.869: E/Surface(478): ошибка dequeueBuffer (нет такого устройства) 07-06 17:14:43.869: E/BaseSurfaceHolder(478): поверхность блокировки исключения 07-06 17:14:43.869: E/BaseSurfaceHolder(478): java.lang.IllegalArgumentException 07-06 17:14:43.869: E /BaseSurfaceHolder(478): в android.view.Surface.lockCanvasNative(собственный метод) 07-06 17:14:43.869: E/BaseSurfaceHolder(478): в android.view.Surface.lockCanvas(Surface.java:288) 07 -06 17:14:43.869: E/BaseSurfaceHolder(478): в com.android.internal.view.BaseSurfaceHolder.internalLockCanvas(BaseSurfaceHolder.java:132) 07-06 17:14:43.869: E/BaseSurfaceHolder(478): в com.android.internal.view.BaseSurfaceHolder.lockCanvas(BaseSurfaceHolder.java:112) 07-06 17:14:43.869: E/BaseSurfaceHolder(478): в com.mendel.strips.Strips$StripsEngine.run(Strips. java:81) 07-06 17:14:43.869: E/BaseSurfaceHolder(478): в java.lang.Thread.run(Thread.java :1096) 07-06 17:14:43.972: W/dalvikvm(478): threadid=15: поток завершается с необработанным исключением (группа=0x4001b188) 07-06 17:14:43.979: E/AndroidRuntime(478): неперехваченный обработчик: поток Thread-8 завершается из-за необработанного исключения 07-06 17:14:43.990: E/AndroidRuntime(478): java.lang.NullPointerException 07-06 17:14:43.990: E/AndroidRuntime(478): at com .mendel.strips.Strips$StripsEngine.run(Strips.java:82) 07-06 17:14:43.990: E/AndroidRuntime(478): в java.lang.Thread.run(Thread.java:1096) 07- 06 17:14:43.999: I/dalvikvm(478): threadid=7: реакция на сигнал 3 07-06 17:14:43.999: E/dalvikvm(478): невозможно открыть файл трассировки стека '/data/anr/ traces.txt': Отказано в доступе


person Daniel Mendel    schedule 06.07.2012    source источник
comment
ошибка, которая отображается в logcat...   -  person User    schedule 06.07.2012


Ответы (2)


Вероятно, это связано с тем, что холст, который вы запрашиваете с помощью holder.lockCanvas(), еще недоступен, поэтому он равен нулю, и вы получаете исключение NullPointerException.

См. документацию lockCanvas()

Возвращенный Canvas можно использовать для рисования в растровом изображении поверхности. Нуль возвращается, если поверхность не была создана или не может быть отредактирована по иным причинам. Обычно вам потребуется реализовать Callback.surfaceCreated, чтобы узнать, когда поверхность доступна для использования.

Обновлять:

Согласно документу isValid(), который вы вызываете раньше - Does this object hold a valid surface? Returns true if it holds a physical surface, so lockCanvas() will succeed. Otherwise returns false.

В этот момент холст не должен быть нулевым. Но я нашел это, кажется, ошибка Android:

http://code.google.com/p/android/issues/detail?id=19245

Таким образом, вам, вероятно, придется попробовать подход Callback.surfaceCreated или, если ничего не работает, попробуйте тайм-аут, как предложил плакат (который удалил сообщение), но это действительно то, чего вам следует избегать, потому что это ненадежно и беспорядочно.

person User    schedule 06.07.2012
comment
Я не понимаю, где я должен это реализовать? в методе запуска я проверяю, действительна ли поверхность, прежде чем пытаться заблокировать холст, сразу после того, как у меня есть ifholder.getSurface().isValid() - person Daniel Mendel; 06.07.2012
comment
Вы правы, документация от isValid() говорит Does this object hold a valid surface? Returns true if it holds a physical surface, so lockCanvas() will succeed. Otherwise returns false. Таким образом, согласно этому, это должно быть успешным. Вы пытались отладить код, я просто угадываю номер строки, потому что ваш файл не завершен, поэтому я не могу знать, является ли эта строка доступом к холсту... может быть, на несколько строк раньше или позже - person User; 06.07.2012
comment
это все мой java-файл, я больше ничего не скрываю, но дело в том, что приложение показывает превью нормально только тогда, когда я нажимаю установить обои или назад, что ему нужно вызвать метод on destory, чем он вылетает - person Daniel Mendel; 06.07.2012
comment
Файл также содержит строки package и import и пробелы между ними... Просто посмотрите на строку 82, там объект нулевой. Если это холст, мы должны выяснить, почему он имеет значение null после того, как isValid() вернул true. - person User; 06.07.2012

Я получил ответ!

Я просмотрел образец живых обоев куба и скопировал структуру, вот код:

public class Strips extends WallpaperService {

private final Handler mHandler = new Handler();   
@Override
public void onCreate() {
    super.onCreate();

}

@Override
public void onDestroy() {
    super.onDestroy();
}

@Override
public Engine onCreateEngine() {

    return new StripsEngine();
}

class StripsEngine extends Engine   {
    private Thread t = null;
;
    private boolean clearToRun = false;
    private Paint paint = new Paint();
    private Paint paint2 = new Paint();
    private int frame;
    private float endX,endY;
    private int height, width;
    private Canvas c;

    private final Runnable mDrawStrip = new Runnable() {
        public void run() {
            drawFrame();
        }
    };


    StripsEngine() {
        paint.setColor(Color.WHITE);
        paint.setStrokeWidth(30);
        paint.setAntiAlias(true);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStyle(Paint.Style.STROKE);
        paint2 = paint;
        paint2.setColor(Color.BLACK);
        paint2.setStrokeWidth(40);
        frame = 0;
    }

     @Override
        public void onDestroy() {
            super.onDestroy();
            mHandler.removeCallbacks(mDrawStrip);
        }

     @Override
        public void onSurfaceCreated(SurfaceHolder holder) {
            super.onSurfaceCreated(holder);
        }

     @Override
        public void onSurfaceDestroyed(SurfaceHolder holder) {
            super.onSurfaceDestroyed(holder);
            clearToRun = false;
            mHandler.removeCallbacks(mDrawStrip);
        }


     @Override
        public void onVisibilityChanged(boolean visible) {
            clearToRun = visible;
            if (visible) {
                drawFrame();
            } else {
                mHandler.removeCallbacks(mDrawStrip);
            }
        }


    public void drawFrame() {
        // TODO Auto-generated method stub
     final SurfaceHolder holder = getSurfaceHolder();
       Canvas c = null;
       try {
           c = holder.lockCanvas();
           if (c != null) {
               // draw something
            height = 800;
            width = 480; 

            endX = (frame) % (width + 10);
            endY = (frame / 3) % (height + 10);


            if (endX == 0)
                paint.setARGB(255,(int)(Math.random()*255), (int)(Math.random()*255),(int)(Math.random()*255));
            if (endY ==0)
                paint.setARGB(255,(int)(Math.random()*255), (int)(Math.random()*255),(int)(Math.random()*255));

            c.drawLine(endX-30, endY-10, endX , endY,paint);
            frame = frame +2;
           }
       } finally {
           if (c != null) holder.unlockCanvasAndPost(c);
       }
         mHandler.removeCallbacks(mDrawStrip);
            if (clearToRun) {
                mHandler.postDelayed(mDrawStrip, 1000 / 25);
            }
    }

}

}
person Daniel Mendel    schedule 06.07.2012