Android 安卓&x27;壁纸服务。引擎问题,需要解决方法
在开发实时壁纸的过程中,我遇到了两个问题,希望找到最好的解决办法 问题1:Android 安卓&x27;壁纸服务。引擎问题,需要解决方法,android,live-wallpaper,Android,Live Wallpaper,在开发实时壁纸的过程中,我遇到了两个问题,希望找到最好的解决办法 问题1:wallperservice.Engine.onSurfaceCreated()和wallperservice.Engine.onSurfaceChanged()在wallperservice.Engine.onstroyed()之后调用 在某些情况下,在调用wallperservice.Engine.onSurfaceCreated()和wallperservice.Engine.onSurfaceChanged()之后
wallperservice.Engine.onSurfaceCreated()
和wallperservice.Engine.onSurfaceChanged()
在wallperservice.Engine.onstroyed()之后调用
在某些情况下,在调用wallperservice.Engine.onSurfaceCreated()
和wallperservice.Engine.onSurfaceChanged()
之后,Android调用wallperservice.Engine.onstroyed()
。它违反了文档定义的服务引擎执行协议
我目前的解决方案是使用显式标志(mAlreadyDestroyed
),默认情况下该标志为false,但在onDestroy()
回调中设置为true。wallperservice.Engine.onSurfaceCreated()
和wallperservice.Engine.onSurfaceChanged()
检查此标志,如果为真,则不执行任何操作。有人也面临过这个问题吗?你是如何解决的
以下是您可以用来检查此问题的简单代码:
public class LWService extends WallpaperService {
/**
* Will show the bug with calling {@link #onSurfaceCreated(SurfaceHolder)}
* and other surface callbacks after {@link #onDestroy()}.
*
*/
private class LWEngineTest1 extends Engine {
/**
* Will be set to <code>true</code> in {@link #onDestroy()}.
*/
private boolean mAlreadyDestroyed = false;
/**
* Log debug level message with adding object instance info to better
* LogCat readability.
*
* @param message
* message to log
*/
private void logD(final String message) {
Log.d("LW_BUG_TEST", this.toString() + ":" + message);
}
/**
* Log error level message with adding object instance info to better
* LogCat readability.
*
* @param message
* message to log
*/
private void logE(final String message) {
Log.e("LW_BUG_TEST", this.toString() + ":" + message);
}
@Override
public void onCreate(SurfaceHolder surfaceHolder) {
logD("onCreate()");
}
@Override
public void onDestroy() {
logD("onDestroy()");
mAlreadyDestroyed = true;
}
@Override
public void onSurfaceCreated(SurfaceHolder holder) {
logD("onSurfaceCreated()");
if (mAlreadyDestroyed) {
logE("onSurfaceCreated() after onDestroy()");
}
}
@Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
logD("onSurfaceChanged()");
if (mAlreadyDestroyed) {
logE("onSurfaceChanged() after onDestroy()");
}
}
@Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
logD("onSurfaceDestroyed()");
if (mAlreadyDestroyed) {
logE("onSurfaceDestroyed() after onDestroy()");
}
try {
// To reveal the bug, without this line you may not got the
// issue. Of course it is absolutely synthetic but allow to get
// the issue guaranteed
Thread.sleep(4000);
} catch (InterruptedException exc) {
}
}
}
@Override
public Engine onCreateEngine() {
return new LWEngineTest1();
}
}
public class LWService extends WallpaperService {
/**
* Will show the bug with non-conform to documentation (specification)
* {@link #onSurfaceDestroyed(SurfaceHolder)}.
*/
private class LWEngineTest2 extends Engine {
/**
* Log error level message with adding object instance info to better
* LogCat readability.
*
* @param message
* message to log
*/
private void logE(final String message) {
Log.e("LW_BUG_TEST", this.toString() + ":" + message);
}
@Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
if (holder.getSurface().isValid() && null == holder.lockCanvas()) {
logE("onSurfaceDestroyed() : uuups ... broken surface");
}
// If you have separate rendering thread it may already notice that
// surface already invalid and encounter problems due to that fact.
// E.g. eglSwapBuffers() may generate EGL_INVALID_NATIVE_WINDOW
// error.
// mRenderingThread.releaseSurface();
}
}
@Override
public Engine onCreateEngine() {
return new LWEngineTest1();
}
}
以下是我在三星Galaxy S(Android 2.2.1)上的日志。只需将此示例墙纸设置为当前墙纸,然后选择另一个(仅保留相关日志条目):
问题2:wallperservice.Engine.onsurfacedestromed()
在曲面实际销毁后调用
在某些情况下,Android可能会在surface被实际销毁后调用wallperservice.Engine.onSurfaceDestructed()
。它违反了SurfaceHolder.Callback.onsurfacedestromed()
规范。这个问题相当具体,即使在代码中出现,也可能会被忽略。如果有单独的渲染线程,您最多会注意到这个问题。渲染线程甚至在主应用程序的线程接收到所提到的wallperservice.Engine.onsurfacedestromed()
之前,也可能会注意到死掉的曲面。在我的OpenGL渲染中,当执行eglSwapBuffers()
时,我刚刚得到了EGL\u BAD\u NATIVE\u窗口
我目前的解决方案只是忽略指定的EGL错误,但我真的不喜欢这种解决方案。我的代码中充满了自检断言和错误条件检查,我不喜欢删除这些断言和检查(忽略特定的错误代码就是这样的事情)。是否存在解决此问题的方法
以下是您可以用来检查此问题的简单代码:
public class LWService extends WallpaperService {
/**
* Will show the bug with calling {@link #onSurfaceCreated(SurfaceHolder)}
* and other surface callbacks after {@link #onDestroy()}.
*
*/
private class LWEngineTest1 extends Engine {
/**
* Will be set to <code>true</code> in {@link #onDestroy()}.
*/
private boolean mAlreadyDestroyed = false;
/**
* Log debug level message with adding object instance info to better
* LogCat readability.
*
* @param message
* message to log
*/
private void logD(final String message) {
Log.d("LW_BUG_TEST", this.toString() + ":" + message);
}
/**
* Log error level message with adding object instance info to better
* LogCat readability.
*
* @param message
* message to log
*/
private void logE(final String message) {
Log.e("LW_BUG_TEST", this.toString() + ":" + message);
}
@Override
public void onCreate(SurfaceHolder surfaceHolder) {
logD("onCreate()");
}
@Override
public void onDestroy() {
logD("onDestroy()");
mAlreadyDestroyed = true;
}
@Override
public void onSurfaceCreated(SurfaceHolder holder) {
logD("onSurfaceCreated()");
if (mAlreadyDestroyed) {
logE("onSurfaceCreated() after onDestroy()");
}
}
@Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
logD("onSurfaceChanged()");
if (mAlreadyDestroyed) {
logE("onSurfaceChanged() after onDestroy()");
}
}
@Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
logD("onSurfaceDestroyed()");
if (mAlreadyDestroyed) {
logE("onSurfaceDestroyed() after onDestroy()");
}
try {
// To reveal the bug, without this line you may not got the
// issue. Of course it is absolutely synthetic but allow to get
// the issue guaranteed
Thread.sleep(4000);
} catch (InterruptedException exc) {
}
}
}
@Override
public Engine onCreateEngine() {
return new LWEngineTest1();
}
}
public class LWService extends WallpaperService {
/**
* Will show the bug with non-conform to documentation (specification)
* {@link #onSurfaceDestroyed(SurfaceHolder)}.
*/
private class LWEngineTest2 extends Engine {
/**
* Log error level message with adding object instance info to better
* LogCat readability.
*
* @param message
* message to log
*/
private void logE(final String message) {
Log.e("LW_BUG_TEST", this.toString() + ":" + message);
}
@Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
if (holder.getSurface().isValid() && null == holder.lockCanvas()) {
logE("onSurfaceDestroyed() : uuups ... broken surface");
}
// If you have separate rendering thread it may already notice that
// surface already invalid and encounter problems due to that fact.
// E.g. eglSwapBuffers() may generate EGL_INVALID_NATIVE_WINDOW
// error.
// mRenderingThread.releaseSurface();
}
}
@Override
public Engine onCreateEngine() {
return new LWEngineTest1();
}
}
下面是我在Acer A500(安卓3.1)上的日志。只需选择此壁纸进行预览,然后在预览活动中按“后退”按钮(仅保留相关日志条目):
我已经在Android问题跟踪(,)中报告了这两个问题,但实际上,更有趣的是知道如何为已经发布的Android版本解决这些问题。这就是为什么我在这里寻求任何人都可能知道的解决方案。虽然我已经有了自己的解决办法(可能对某些人有用),但我也想知道解决这些问题的另一种可能性
提前感谢。我在一台运行出色的Cynagen 7.0.3(姜饼2.3.3)上试用了您的代码。我看不出你看到的问题
以下是我通过Picker>Preview>Set Wallpaper后的日志结果:
08-24 07:47:04.261: DEBUG/LW_BUG_TEST(32534): LWService$LWEngineTest1@40630938:onCreate()
08-24 07:47:04.301: DEBUG/LW_BUG_TEST(32534): LWService$LWEngineTest1@40630938:onSurfaceCreated()
08-24 07:47:04.301: DEBUG/LW_BUG_TEST(32534): LWService$LWEngineTest1@40630938:onSurfaceChanged()
08-24 07:47:10.187: DEBUG/LW_BUG_TEST(32534): LWService$LWEngineTest1@4062d100:onCreate()
08-24 07:47:10.227: DEBUG/LW_BUG_TEST(32534): LWService$LWEngineTest1@4062d100:onSurfaceCreated()
08-24 07:47:10.227: DEBUG/LW_BUG_TEST(32534): LWService$LWEngineTest1@4062d100:onSurfaceChanged()
08-24 07:47:10.858: DEBUG/LW_BUG_TEST(32534): LWService$LWEngineTest1@40630938:onSurfaceDestroyed()
08-24 07:47:14.862: DEBUG/LW_BUG_TEST(32534): LWService$LWEngineTest1@40630938:onDestroy()
08-24 07:49:50.133: DEBUG/LW_BUG_TEST(32534): LWService$LWEngineTest1@4063eb20:onCreate()
08-24 07:49:50.173: DEBUG/LW_BUG_TEST(32534): LWService$LWEngineTest1@4063eb20:onSurfaceCreated()
08-24 07:49:50.173: DEBUG/LW_BUG_TEST(32534): LWService$LWEngineTest1@4063eb20:onSurfaceChanged()
08-24 07:49:54.157: DEBUG/LW_BUG_TEST(32534): LWService$LWEngineTest1@4063eb20:onSurfaceDestroyed()
08-24 07:49:58.161: DEBUG/LW_BUG_TEST(32534): LWService$LWEngineTest1@4063eb20:onDestroy()
然后,在设置完全无关的墙纸后,该实例将被销毁:
08-24 07:48:33.268: DEBUG/LW_BUG_TEST(32534): LWService$LWEngineTest1@4062d100:onSurfaceDestroyed()
08-24 07:48:37.272: DEBUG/LW_BUG_TEST(32534): LWService$LWEngineTest1@4062d100:onDestroy()
以下是我在Picker>Preview>Back(未设置壁纸)之后的结果:
有多个引擎可以并行执行。你必须管理它们。要检查这一点,只需为您创建的每个引擎添加一个id。您可以通过以下方式进行验证:
public class LWService extends WallpaperService {
static int engineCounter;
/**
* Will show the bug with calling {@link #onSurfaceCreated(SurfaceHolder)}
* and other surface callbacks after {@link #onDestroy()}.
*
*/
private class LWEngineTest1 extends Engine {
public int id;
public LWEngineTest1()
{
id=++engineCounter;
}
/**
* Will be set to <code>true</code> in {@link #onDestroy()}.
*/
private boolean mAlreadyDestroyed = false;
/**
* Log debug level message with adding object instance info to better
* LogCat readability.
*
* @param message
* message to log
*/
private void logD(final String message) {
Log.d("LW_BUG_TEST", this.toString() + ":" + message);
}
/**
* Log error level message with adding object instance info to better
* LogCat readability.
*
* @param message
* message to log
*/
private void logE(final String message) {
Log.e("LW_BUG_TEST", this.toString() + ":" + message);
}
@Override
public void onCreate(SurfaceHolder surfaceHolder) {
logD("onCreate() engineId="+id);
}
@Override
public void onDestroy() {
logD("onDestroy() engineId="+id);
mAlreadyDestroyed = true;
}
@Override
public void onSurfaceCreated(SurfaceHolder holder) {
logD("onSurfaceCreated() engineId="+id);
if (mAlreadyDestroyed) {
logE("onSurfaceCreated() after onDestroy()");
}
}
@Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
logD("onSurfaceChanged() engineId="+id);
if (mAlreadyDestroyed) {
logE("onSurfaceChanged() after onDestroy()");
}
}
@Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
logD("onSurfaceDestroyed() engineId="+id);
if (mAlreadyDestroyed) {
logE("onSurfaceDestroyed() after onDestroy()");
}
try {
// To reveal the bug, without this line you may not got the
// issue. Of course it is absolutely synthetic but allow to get
// the issue guaranteed
Thread.sleep(4000);
} catch (InterruptedException exc) {
}
}
}
@Override
public Engine onCreateEngine() {
return new LWEngineTest1();
}
}
我注意到,在不同的设备上,行为略有不同。因此,我建议您在不同的设备上测试您的解决方案。对不起,没有。不过我可能会在其他时间测试。