XML FrameLayout has lowered my OpenGL SurfaceView

2019-07-02 21:32发布

问题:

I have extended the GLSurfaceView and implemented my own GLSurfaceView.Renderer to create my first relatively simple 2D OpenGLES game for android.

I have been testing my game using the following code on the activities onCreate method which sets the surface view as the content view, from which I have obtained a constant 60fps.

60fps activity :

mGLView = new OpenGLTest1SurfaceView(this);
setContentView(mGLView);

However now I have moved to an XML layout so I can place an admob overlay in the bottom right corner of the screen,

admob xml :

<Frame Layout...
<...OpenGLTest1SurfaceView...
<com.google.ads.adView...

admob activity :

setContentView(R.layout.main);

Now I the application fluctuates between 43fps and 60fps at seemingly random intervals. I have looked at the LogCat and the GC is not running excessively (once every 20seconds or so).

  • Should I have expected a lower frame rate when moving my surface view into an XML layout?
  • Is there an alternative method for showing admob adverts without using an XML layout?
  • Is there anything I could do to identify why my applications FPS lowers at particular times?

Any help would be greatly appreciated because I would like to be able to monetize my OpenGL applications in the near future.

回答1:

GLSurfaceView being a SurfaceView has a little bit different way of being represented in a window.

"the SurfaceView punches a hole in its window to allow its surface to be displayed. The view hierarchy will take care of correctly compositing with the Surface any siblings of the SurfaceView that would normally appear on top of it. This can be used to place overlays such as buttons on top of the Surface, though note however that it can have an impact on performance since a full alpha-blended composite will be performed each time the Surface changes."

First step you need to draw AdMobView in a separate window (layer) on top of your main window. Here is an example of how you do it:

View topLocker = lockDownWindow.getChildAt(0);

WindowManager.LayoutParams windowParams = new WindowManager.LayoutParams();
windowParams.gravity = Gravity.TOP;
windowParams.x = 0;
windowParams.y = 0;
windowParams.height = WindowManager.LayoutParams.MATCH_PARENT;
windowParams.width = WindowManager.LayoutParams.MATCH_PARENT;
windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
    | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
windowParams.format = PixelFormat.TRANSLUCENT;
windowParams.windowAnimations = 0;

WindowManager wm = getWindowManager();
wm.addView(yourAwesomView, windowParams);

"yourAwesomeView" here is a layout containing adView. Beware you have to properly configure flags for window to let your touches slip to background window. Also you're resposible for removing this window.

Another advice I may have is to try disabling default background in your theme since your GLSurfaceView is on top of it, you don't want extra draws behind it.

in your theme add

<item name="android:windowBackground">@null</item>

Hope this helps.



回答2:

To answer one of those points, you can definitely create and AdMob ad and put it into your view hierarchy programmatically, you probably just need to give it a gravity of "bottom" or something so that it stays at the bottom of the FrameLayout.

  AdView adView = new AdView(this, AdSize.BANNER, INSERT_ADMOB_ID_HERE);
  AdRequest adRequest = new AdRequest();
  adRequest.addTestDevice(AdRequest.TEST_EMULATOR);
  adView.loadAd(adRequest);
  // Add the adView into your view hierarchy using addView
  layout.addView(adView);


回答3:

I read about something similar awhile ago, the solution was to put the overlay in a separate window, on top of the glsurfaceview.



回答4:

I don't remember where, but I defiantly read some place in android that when you are updating a view, such as your OpenGLTest1SurfaceView, screen invalidation is fired on the rect that your view is taking so if you place the admobe above it your fps will fall down. If you place the admobe beside it you will be fine.