Android loading progress screen

Since android has a not insignificant loading time if you have a bunch of assets, there is a long white screen on first launch. Is there any way to have a progress bar while the unzip runs? I gave a search and couldn’t find any code for it.

there’s a function that you can override in your application activity:

public void onLoadPercent(float percent)

the resource loader will send values till 0.8 then in the c++ side you can use:

ofxAndroidNotifyLoadPercent(percent);

to send the rest of the progress if you are loading anything in setup or similar.

In the main layout in res/layout/main_layout.xml you can add an init screen on top of the GL view with a progress bar and increment it from your activity, once the progress arrives to 100% you can hide that view which will reveal the GL one.

hey @arturo and suggestions for which way we should init the Java views? If I try to do them the old fashioned way it throws a null pointer. i.e. findViewById(R.id.VIEWNAM) or via a LayoutInflater

I tried pulling the current FrameLayout from the Window and I still can’t seem to access the ProgressBar I have in my Layout. I even tried pulling the FrameLayout and adding the view Programmatically with no success.

Any thoughts?

Hi @theDANtheMAN.

Did you ever solve this? I’m having the same problem trying to access the Java views.

I am succesfully using the Android views. What is the problem? Do you get an error message?

Hi @Rancs ,

Thanks for answering. At the end I finished using an alert box with text but I would like to know how to use different layouts and hide and show them from OF during runtime. I add one layout on the main_layout.xml and then try to access it from OFActivity onCreate method with “setContentView/findById” but it’s not working. Should I create them on the fly?

Hi @pelayo,

I will share with you below, some code for a textview defined in the layout xml. (Please note that we still use here oF 0.8.0. Hope something not changed in a later version )


MAIN_LAYOUT.XML

android:id="@+id/oftextview"
style="@android:style/TextAppearance.Medium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Loading" />

OFANDROID.JAVA

private static RelativeLayout rlayout;
private static TextView textview;

private static void addTextview() {
    OFAndroid.ofActivity.runOnUiThread(new Runnable(){
        public void run() {
            try {
                OFAndroid.rlayout.addView(OFAndroid.textview);
            } catch(Exception e) {}
        }
    });
}

private static void removeTextview() {
    OFAndroid.ofActivity.runOnUiThread(new Runnable(){
        public void run() {
            try {
                OFAndroid.rlayout.removeView(OFAndroid.textview);
            } catch(Exception e) {}
        }
    });
}

public static void setupGL(int version)    {
    //add these 3 lines to the end of this void.
    //I see now that this void is changed in of 0.8.4. I hope everything works. YOU MAY NEED TO ADD THESE 3 LINES TO THE END OF VOID initView() IN THE NEW VERION OF OPENFRAMEWORKS!
    rlayout = (RelativeLayout) OFAndroid.ofActivity.findViewById(OFAndroid.ofActivity.getResources().getIdentifier("relativeLayout1", "id", packageName));
    textview = (TextView)OFAndroid.ofActivity.findViewById(OFAndroid.ofActivity.getResources().getIdentifier("oftextview", "id", packageName));
    OFAndroid.rlayout.removeView(OFAndroid.textview);
}

TESTAPP.H

    void addTextview();
    void removeTextview();

TESTAPP.CPP

void testApp::addTextview() {
    ofGetJNIEnv()->CallStaticVoidMethod(ofGetJavaOFAndroid(), ofGetJNIEnv()->GetStaticMethodID(ofGetJavaOFAndroid(), "addTextview", "()V"));
}

void testApp::removeTextview() {
    ofGetJNIEnv()->CallStaticVoidMethod(ofGetJavaOFAndroid(), ofGetJNIEnv()->GetStaticMethodID(ofGetJavaOFAndroid(), "removeTextview", "()V"));
}

Then call addTextview() in the beginning of testApp.cpp to show the TextView.
(Then you can call addTextview() and removeTextview() from anywhere in the C++ side.)

Please let me know if it works.

Thanks @Rancs. I understand now you are modifiying OFAndroid.java I was trying to make it work on OFActivity.java. I’ll try your way.

I was wondering why this is not working on the onCreate() method there:

OFActivity.java

View view = getLayoutInflater().inflate(R.layout.main_layout,null);
setContentView(view);
		
TextView loadingText = (TextView) view.findViewById(R.id.oftextview);
view.removeView(loadingText);

It would be cleaner and will help in developing addons for ofAndroid instead of having to work with a different modified version of OFAndroid on each project.

@pelayo So, will you not have a different modified version of OFActivity on each project?

@rancs Yes. I mean the OFActivity.java file that is part of the project srcJava, so every project has its own but OFAndroid.java is part of ofAndroidLib.

i haven’t done this in a while but it can definetly (and should) be done without modifying the OF classes. what i have from the latest project where i used this is in OFActivity:


    
    @Override
    public void onLoadPercent(float percent){
        if(!onCreateDone) percent-=.1;
        percent=Math.max(percent, 0)*100;
        final float percentf = percent;
        instance.runOnUiThread(new Runnable() {
            
            @Override
            public void run() {
                ProgressBar loadBar = (ProgressBar)instance.findViewById(R.id.loadProgressBar);
                if(loadBar!=null) loadBar.setProgress((int) (percentf));
            }
        });
    }


    
    public static void onLoadFinished(){

        instance.runOnUiThread(new Runnable() {
            
            @Override
            public void run() {
                View glSurface = instance.findViewById(R.id.of_gl_surface);
                if(glSurface!=null) glSurface.setVisibility(View.VISIBLE);
                View loading = instance.findViewById(R.id.loading);
                if(loading!=null) loading.setVisibility(View.GONE);
                View logo = instance.findViewById(R.id.logo);
                if(logo!=null) logo.setVisibility(View.GONE);
                View loadProgressBar = instance.findViewById(R.id.loadProgressBar);
                if(loadProgressBar!=null) loadProgressBar.setVisibility(View.GONE);
            }
        });
    }

and this is the main_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout android:id="@+id/relativeLayout1" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android">
    <cc.openframeworks.OFGLSurfaceView android:id="@+id/of_gl_surface"
         android:layout_width="fill_parent"
         android:layout_height="fill_parent"/>
        <!-- add here other views' layouts -->

    <ImageView
        android:id="@+id/loading"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="@drawable/tiled_bg" />
    
    <LinearLayout
        android:layout_width="220dp"
        android:layout_height="220dp"
        android:layout_centerInParent="true"
        android:orientation="vertical" >
        
        <ImageView
            android:id="@+id/logo"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:src="@drawable/load_logo" />
    
        <ProgressBar
            android:id="@+id/loadProgressBar"
            style="?android:attr/progressBarStyleHorizontal"
            android:progressDrawable="@drawable/progressbar_drawable"
            android:layout_width="fill_parent"
            android:layout_height="match_parent"
            android:layout_weight="20"
            android:indeterminate="false"
            android:max="100"
            android:progress="0"
            android:visibility="visible" />

    </LinearLayout>

    </RelativeLayout>

I use the loading textview on all apps so i don’t think it is a app-spesific thing.

Hi @arturo,

What’s the “instance” variable in your code? I’m trying simply hiding the text to know how to get access to the layout elements without luck.

main_layout.xml

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout android:id="@+id/relativeLayout1"
        			android:layout_width="fill_parent" 
        			android:layout_height="fill_parent" 
        			xmlns:android="http://schemas.android.com/apk/res/android">
    	<cc.openframeworks.OFGLSurfaceView  android:id="@+id/of_gl_surface"
 											android:layout_width="fill_parent"
 											android:layout_height="fill_parent"/>
    	<!-- add here other views' layouts -->
    	<TextView
        			android:id="@+id/oftextview"
					style="@android:style/TextAppearance.Medium"
					android:layout_width="wrap_content"
					android:layout_height="wrap_content"
					android:layout_centerHorizontal="true"
					android:layout_centerVertical="true"
					android:text="Loading" />
    </RelativeLayout>

OFActivity.java

@Override
    public void onCreate(Bundle savedInstanceState)
    { 
        
		super.onCreate(savedInstanceState);
		
		String packageName = getPackageName();
        ofApp = new OFAndroid(packageName,this);

        final Activity instance =  (Activity) ofApp.getContext();
        // final Activity instance =  (Activity) this; // not working also
        instance.runOnUiThread(new Runnable() {
            @Override
            public void run() {
            	TextView loading = (TextView) instance.findViewById(R.id.oftextview);
            	if(loading!=null) loading.setVisibility(View.GONE);
            }
        });
        
    }

this is what i have:


public class OFActivity extends cc.openframeworks.OFActivity{

    private static OFActivity instance;
    boolean onCreateDone=false;
    public OFAndroid ofApp;
    
    @Override
    public void onCreate(Bundle savedInstanceState)
    { 
        super.onCreate(savedInstanceState);
        
        instance = this;

        ofApp = new OFAndroid(getPackageName(),this);
        

        onCreateDone = true;
    }
..
}

as i said i haven0t touched this in a while so there might be something that has to be done diferently but the logic is mostly: wait for loadProgress to be called and then hide the progress layout there.

Thanks @arturo and @Rancs!

I got a project working now with your information that can access layout elements.

The problem was that I was testing trying to access the layouts from the onCreate() method in OFActivity. After making the calls to the java functions that accessed the layouts from ofApp.cpp or onResume() and onPause() everything worked fine.