2

I recently decided to update my older apps and bring them a little more up to date. In doing so I noticed an odd problem when running them on my new handset (Android O / API Level 29).

My App is essentially a single Activity using OpenGL. This is basically what happens when the app is first loaded...

  • Create Layout, Create a Splashscreen View, create custom GLSurfaceView
  • Add GLSurfaceView to Layout
  • Add Splashscreen to Layout
  • Start AsyncTask to load resources and do setup ops
  • GLSurfaceView dismisses Splashscreen to reveal renderer...

So, it all works perfectly well on my older devices (3 x handsets, 1 x tablet all running various versions of Android no higher than Lollipop).

However, on my Android 10 handset, all I get is a blank screen while the app starts. Just to be clear, there are no errors, the app itself works perfectly fine. After the usual startup time, the blank screen is dismissed and the app continues, it's just that the 'splashscreen' has now become a "blankscreen".

But Android Studio Layout Inspector tells a different story

Indeed, if I open the Layout Inspector in Android Studio, oddly it shows exactly what I would expect... the splashscreen with its text/graphics, but not on the actual device...

Some test code

In the following test code I replaced the resource loading / setup with a simple Thread.sleep just to create a longer delay so I could more easily inspect the output in Android Studio. This does still exhibit the problem...

@Override
protected void onCreate(Bundle savedInstanceState) {

    int[] deviceResolution = getDeviceResolution();
    width = deviceResolution[0];
    height = deviceResolution[1];

    layout = new RelativeLayout(this);

    splash = new Splash(getApplication(), width, height);

    myGLView = new CustomGLSurfaceView(this.getApplication());

    layout.addView(myGLView);

    layout.addView(splash);

    setContentView(layout);

    loadResource = new LoadResources(newBundle);

    loadResources.execute();

    super.onCreate(savedInstanceState);

}

class LoadResources AsyncTask<Void, Void, Void> {

    Bundle savedBundle;

    LoadResources(Bundle savedBundle){
        this.savedBundle=savedBundle;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected Void doInBackground(Void... params) {

        // Simulate some long-running task here.  While this is happening, splashscreen should be visible. And on older devices, it is.  Not on Android O handset (but OK in Android Studio Layout Inspector).
        try {
            Thread.sleep(30000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // Would typically make my calls here to load resources, and complete other setup tasks here
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);                

    }

}

** Other observations **

I know that Async is now deprecated and I'm also aware of other Splashscreen tecnhiques such as using a dedicated Activity. However due to the setup/complexity of the apps and given that it doesn't 'break' them per-se, I don't want to have to refactor the entire codebase (just yet anyway) any new apps going forward will use a different system for the splashscreen. What I'm really trying to understand here is why this now doesn't work as it used to. Is this a bug? Or a behavioural change that happened in an Android version somewhere down the line? Or maybe it's just me doing something wrong. If anyone has come across it, I'd be really interested to know of a fix/workaround.

** Other things I've tried **

In the above example, if I simply don't add 'myGLView' then the splashscreen shows, but of course the app then won't work. So I though about adding it in onPostExecute and then bringing the splashscreen view back to the front with splash.bringToFront(). This kind of works, but is messy. The splashscreen only shows for a brief second, and on devices that show it correctly there is a 'glitch' as the correctly displayed splashscreen is overlayed with the GL Renderer and then bought back to the front.

Zippy
  • 3,826
  • 5
  • 43
  • 96

1 Answers1

0

You are adding a view to an object which is not currently set in an Activity.

The better approach would be calling setContentView() first as well as the super method, then adding the multiple views in it.

So in your case, it'll be like:

super.onCreate(savedInstanceState);
setContentView(layout);

layout = new RelativeLayout(this);    

int[] deviceResolution = getDeviceResolution();
width = deviceResolution[0];
height = deviceResolution[1];

layout = new RelativeLayout(this);

splash = new Splash(getApplication(), width, height);

myGLView = new CustomGLSurfaceView(this.getApplication());

layout.addView(myGLView);

layout.addView(splash);

loadResource = new LoadResources(newBundle);

loadResources.execute();
Dev4Life
  • 2,328
  • 8
  • 22