具有顶部视图的自定义ServiceView在6.5分钟后崩溃应用程序/电话

时间:2022-12-01 11:58:46

I'm writing a small game using a Custom SurfaceView. I wanted to put an AdMob view over the bottom portion of the SurfaceView, but after running the app for about six minutes, the app throws an error and then reboots the phone. I've replaced the AdMob view with a single button, and the error still occurs, so I assume the issues is caused by putting any view over the SurfaceView. If I remove any views from over the top of the SurfaceView, the game runs fine indefinitely.

我正在使用Custom SurfaceView编写一个小游戏。我想在SurfaceView的底部放置一个AdMob视图,但在运行应用程序大约六分钟后,应用程序抛出错误然后重新启动手机。我用一个按钮替换了AdMob视图,但错误仍然存​​在,所以我认为问题是由SurfaceView上的任何视图引起的。如果我从SurfaceView顶部删除任何视图,游戏将无限期运行。

I've tried using layouts other than RelativeLayout, but the problem persists. I'm wondering if anyone has run into this before, or has any other avenues to explore.

我尝试过使用RelativeLayout以外的布局,但问题仍然存在。我想知道是否有人之前遇到过这种情况,或者还有其他途径需要探索。

Custom SurfaceView:

public class AndroidFastRenderView extends SurfaceView implements Runnable
{
    private static final String TAG = "AndroidFastRenderView";
    AndroidGame game;
    Bitmap framebuffer;
    Thread renderThread = null;
    SurfaceHolder holder;
    volatile boolean running = false;

    public AndroidFastRenderView(AndroidGame game, Bitmap framebuffer)
    {
        super(game);
        this.game = game;
        this.framebuffer = framebuffer;
        this.holder = getHolder();
    }

    public AndroidFastRenderView(Context context)
    {
        super(context);
    }

    public void resume()
    {
        running = true;
        renderThread = new Thread(this);
        renderThread.start();
    }

    public void run()
    {
        Rect dstRect = new Rect(0,0,80,120);
        long startTime = System.nanoTime();
        while (running)
        {
            if(!holder.getSurface().isValid())
            {
                continue;
            }

            float deltaTime = (System.nanoTime() - startTime) / 1000000000.0f;
            startTime = System.nanoTime();

            game.getCurrentScreen().update(deltaTime);
            game.getCurrentScreen().present(deltaTime);

            Canvas canvas = null;

            canvas = holder.lockCanvas();

            if (canvas != null)
            {
                dstRect = canvas.getClipBounds();
                canvas.drawBitmap(framebuffer, null, dstRect, null);
                holder.unlockCanvasAndPost(canvas);
            }
        }
    }

    public void pause()
    {
        Log.e(TAG, "Paused");
        running = false;
        while(true)
        {
            try {
                renderThread.join();
                break;
            } catch (InterruptedException e) {
                // retry
            }
        }
    }

}

Building the Interface in the main activity:

在主要活动中构建接口:

public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);

    boolean isLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;

    int frameBufferWidth = isLandscape ? 120 : 80;
    int frameBufferHeight = isLandscape ? 80 : 120;

    Bitmap frameBuffer = Bitmap.createBitmap(frameBufferWidth, frameBufferHeight, Config.RGB_565);

    float scaleX = (float) frameBufferWidth / getWindowManager().getDefaultDisplay().getWidth();
    float scaleY = (float) frameBufferHeight / getWindowManager().getDefaultDisplay().getHeight();

    renderView  = new AndroidFastRenderView(this, frameBuffer);
    graphics    = new AndroidGraphics(getAssets(), frameBuffer);
    fileIO      = new AndroidFileIO(getAssets());
    audio       = new AndroidAudio(this);
    input       = new AndroidInput(this, renderView, scaleX, scaleY);
    screen      = this.getStartScreen();

    PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
    wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "GLGame");

    if (useAds)
    {
        //adView = new AdView(this, AdSize.SMART_BANNER, AD_UNIT_ID);

        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);

        //adView.setLayoutParams(params);

        RelativeLayout layout = new RelativeLayout(this);
        layout.addView(renderView);
        //layout.addView(adView);

        Button button = new Button(this);
        button.setLayoutParams(params);
        button.setText("Blargle");
        layout.addView(button);

        //adView.loadAd(new AdRequest());

        setContentView(layout);

    }
    else
    {
        setContentView(renderView);
    }
}

LogCat of the Error:

LogCat的错误:

01-25 13:50:18.084: E/SurfaceTextureClient(10342): dequeueBuffer failed (Broken pipe)
01-25 13:50:18.084: E/SurfaceHolder(10342): Exception locking surface
01-25 13:50:18.084: E/SurfaceHolder(10342): java.lang.IllegalArgumentException
01-25 13:50:18.084: E/SurfaceHolder(10342):     at android.view.Surface.lockCanvasNative(Native Method)
01-25 13:50:18.084: E/SurfaceHolder(10342):     at android.view.Surface.lockCanvas(Surface.java:88)
01-25 13:50:18.084: E/SurfaceHolder(10342):     at android.view.SurfaceView$4.internalLockCanvas(SurfaceView.java:754)
01-25 13:50:18.084: E/SurfaceHolder(10342):     at android.view.SurfaceView$4.lockCanvas(SurfaceView.java:734)
01-25 13:50:18.084: E/SurfaceHolder(10342):     at com.somethingutility.games.framework.impl.AndroidFastRenderView.run(AndroidFastRenderView.java:60)
01-25 13:50:18.084: E/SurfaceHolder(10342):     at java.lang.Thread.run(Thread.java:856)

This error repeats till the phone reboots.

重复此错误,直到手机重新启动。

1 个解决方案

#1


0  

Try to avoid displaying the AdView over the SurfaceView by specifically setting the renderRiew to be ABOVE the AdView:

尝试通过专门将renderRiew设置为超出AdView来避免在SurfaceView上显示AdView:

params.addRule(RelativeLayout.ABOVE, renderView.getId());

You might need to give the renderView an ID if it doesn't have one.

如果没有一个ID,您可能需要为renderView提供一个ID。

#1


0  

Try to avoid displaying the AdView over the SurfaceView by specifically setting the renderRiew to be ABOVE the AdView:

尝试通过专门将renderRiew设置为超出AdView来避免在SurfaceView上显示AdView:

params.addRule(RelativeLayout.ABOVE, renderView.getId());

You might need to give the renderView an ID if it doesn't have one.

如果没有一个ID,您可能需要为renderView提供一个ID。