Hiding the navigation bar in pure android native
Asked Answered
P

2

6

I've seen articles and articles on hiding the navigation bar for android application through java. However, what I would like to know, is how do I remove the navigation bar through a pure android c++ native-activity application for a full-screen application(game)(NO JAVA AT ALL!). Full-screen from the android manifest works at hiding the top bar, but the navigation bar stays visible.

This is the Navigation Bar that I wish to remove.

I've searched through books with no luck, there's is no actual documentation for native-activity and google searches result in nothing. There is only the comments inside some of the header files which are tiny comments that don't even help. It seems the topic regarding pure c++ android applications is a black spot yet a lot of games that are coming out on the market are written in c++.

I've also tried setting:

AConfiguration_setNavHidden(m_app->config, ACONFIGURATION_NAVHIDDEN_YES);

But it seems to do nothing, in fact all the AConfiguratin_setXXX seem to do nothing. Perhaps I'm calling it in the wrong place? I've been calling it during APP_CMD_INIT_WINDOW after creating the window. Where should I be calling this function?

Persevere answered 9/12, 2016 at 11:54 Comment(4)
AFAIK, you can not do it without calling Java APIs. You may have to call java methods via JNI from pure C++ code using GetMethodID and related functions. AConfiguration is probably not what you need — based on quick glance over docs, it is for editing Java Configuration object. You need to get jobject for your Activity, obtain JNIEnv and use it to call Java methods required for your task.Salinas
I just had a job interview today and I mentioned this problem, and apparently they had the same problem but solved it with pure c++. I forgot to ask them how they did it before I left, but it sounds like it is possible. My last resort, if I can't find an answer, is to partially use Java, like a normal human being. Thanks for your input though!Persevere
Using C++ to call Java methods with JNI is "pure C++" because you are not writing any Java code — just using JVM C++ API to call Java methods.Salinas
Yes I understand that "pure c++" is still using java calls. I just need the secret ingredient to hide the navigation. I know there is one, there has to be! What I meant by partially using java as a last resort, was hiding the navigation on the java.Persevere
P
5

So! If anyone is curious, I did come up with an answer from rummaging through one of Microsoft's teapot examples. And this is what I came up with:

public class NameOfActivity extends NativeActivity {

void setImmersiveSticky() {
    View decorView = getWindow().getDecorView();
    decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN
            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.activity_main);

    int SDK_INT = android.os.Build.VERSION.SDK_INT;
    if (SDK_INT >= 19) {
        setImmersiveSticky();

        View decorView = getWindow().getDecorView();
        decorView.setOnSystemUiVisibilityChangeListener
                (new View.OnSystemUiVisibilityChangeListener() {
                    @Override
                    public void onSystemUiVisibilityChange(int visibility) {
                        setImmersiveSticky();
                    }
                });
    }
    super.onCreate(savedInstanceState);
}

@Override
protected void onResume() {
    //Hide toolbar
    int SDK_INT = android.os.Build.VERSION.SDK_INT;
    if (SDK_INT >= 11 && SDK_INT < 14) {
        getWindow().getDecorView().setSystemUiVisibility(View.STATUS_BAR_HIDDEN);
    } else if (SDK_INT >= 14 && SDK_INT < 19) {
        getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LOW_PROFILE);
    } else if (SDK_INT >= 19) {
        setImmersiveSticky();
    }
    super.onResume();
}

}

The pure c++ android development still uses java, it gets it from the source inside the android SDK directory. What you can do is extend the NativeActivity with a few additional tweaks. Inside the manifest all you have to do is:

    android:hasCode="true"

and then the most importan part is to change the activity name from

        android:name="android.app.NativeActivity"

to

        android:name="com.example.package.NameOfActivity"

It will still call the android main and set it up just like a regular native activity, but now it gives you a completely full-screen. I hope this helps someone out there. It took me a days of searching for answers, and this is what I could come up with!

GOOD LUCK!

Persevere answered 10/12, 2016 at 11:47 Comment(4)
I've found this from sfml, its full c++ and takes account of older api versions : github.com/SFML/SFML/blob/…Decimalize
Thank you very much, I really hopes this works for me too :)Moue
Yes, extending the NativeActivity is the way to go about this. That's what Google are doing there too: github.com/googlesamples/android-ndk/tree/master/teapots/…Candlemaker
How is this the accepted answer? It uses Java, when the request was to not use Java!Cornea
M
7

I found this piece of code which works (requiring API level > 19). Just call the function at the beginning of main().

void AutoHideNavBar(struct android_app* state)
{
    JNIEnv* env{};
    state->activity->vm->AttachCurrentThread(&env, NULL);

    jclass activityClass = env->FindClass("android/app/NativeActivity");
    jmethodID getWindow = env->GetMethodID(activityClass, "getWindow", "()Landroid/view/Window;");

    jclass windowClass = env->FindClass("android/view/Window");
    jmethodID getDecorView = env->GetMethodID(windowClass, "getDecorView", "()Landroid/view/View;");

    jclass viewClass = env->FindClass("android/view/View");
    jmethodID setSystemUiVisibility = env->GetMethodID(viewClass, "setSystemUiVisibility", "(I)V");

    jobject window = env->CallObjectMethod(state->activity->clazz, getWindow);

    jobject decorView = env->CallObjectMethod(window, getDecorView);

    jfieldID flagFullscreenID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_FULLSCREEN", "I");
    jfieldID flagHideNavigationID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_HIDE_NAVIGATION", "I");
    jfieldID flagImmersiveStickyID = env->GetStaticFieldID(viewClass, "SYSTEM_UI_FLAG_IMMERSIVE_STICKY", "I");

    const int flagFullscreen = env->GetStaticIntField(viewClass, flagFullscreenID);
    const int flagHideNavigation = env->GetStaticIntField(viewClass, flagHideNavigationID);
    const int flagImmersiveSticky = env->GetStaticIntField(viewClass, flagImmersiveStickyID);
    const int flag = flagFullscreen | flagHideNavigation | flagImmersiveSticky;

    env->CallVoidMethod(decorView, setSystemUiVisibility, flag);

    state->activity->vm->DetachCurrentThread();
}
Moue answered 13/6, 2018 at 7:20 Comment(1)
This works great for me, and doesn't require adding JVM code. This should be the accepted answer!Cornea
P
5

So! If anyone is curious, I did come up with an answer from rummaging through one of Microsoft's teapot examples. And this is what I came up with:

public class NameOfActivity extends NativeActivity {

void setImmersiveSticky() {
    View decorView = getWindow().getDecorView();
    decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN
            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.activity_main);

    int SDK_INT = android.os.Build.VERSION.SDK_INT;
    if (SDK_INT >= 19) {
        setImmersiveSticky();

        View decorView = getWindow().getDecorView();
        decorView.setOnSystemUiVisibilityChangeListener
                (new View.OnSystemUiVisibilityChangeListener() {
                    @Override
                    public void onSystemUiVisibilityChange(int visibility) {
                        setImmersiveSticky();
                    }
                });
    }
    super.onCreate(savedInstanceState);
}

@Override
protected void onResume() {
    //Hide toolbar
    int SDK_INT = android.os.Build.VERSION.SDK_INT;
    if (SDK_INT >= 11 && SDK_INT < 14) {
        getWindow().getDecorView().setSystemUiVisibility(View.STATUS_BAR_HIDDEN);
    } else if (SDK_INT >= 14 && SDK_INT < 19) {
        getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LOW_PROFILE);
    } else if (SDK_INT >= 19) {
        setImmersiveSticky();
    }
    super.onResume();
}

}

The pure c++ android development still uses java, it gets it from the source inside the android SDK directory. What you can do is extend the NativeActivity with a few additional tweaks. Inside the manifest all you have to do is:

    android:hasCode="true"

and then the most importan part is to change the activity name from

        android:name="android.app.NativeActivity"

to

        android:name="com.example.package.NameOfActivity"

It will still call the android main and set it up just like a regular native activity, but now it gives you a completely full-screen. I hope this helps someone out there. It took me a days of searching for answers, and this is what I could come up with!

GOOD LUCK!

Persevere answered 10/12, 2016 at 11:47 Comment(4)
I've found this from sfml, its full c++ and takes account of older api versions : github.com/SFML/SFML/blob/…Decimalize
Thank you very much, I really hopes this works for me too :)Moue
Yes, extending the NativeActivity is the way to go about this. That's what Google are doing there too: github.com/googlesamples/android-ndk/tree/master/teapots/…Candlemaker
How is this the accepted answer? It uses Java, when the request was to not use Java!Cornea

© 2022 - 2024 — McMap. All rights reserved.