Скрытие панели навигации в чистом андроиде

Я видел статьи и статьи о том, как скрыть панель навигации для приложения Android через java. Тем не менее, что я хотел бы знать, так это как удалить панель навигации через чистое приложение Android C++ с собственной активностью для полноэкранного приложения (игры) (ВООБЩЕ НЕТ JAVA!). Полноэкранный режим из манифеста Android работает при скрытии верхней панели, но панель навигации остается видимой.

Это панель навигации, которую я хочу удалить.

Я безуспешно просматривал книги, фактической документации по нативной активности нет, а поиск в Google ничего не дает. В некоторых файлах заголовков есть только комментарии, которые представляют собой крошечные комментарии, которые даже не помогают. Кажется, что тема приложений для Android на чистом С++ - это черное пятно, но многие игры, выходящие на рынок, написаны на С++.

Я также пытался установить:

AConfiguration_setNavHidden(m_app->config, ACONFIGURATION_NAVHIDDEN_YES);

Но кажется, что это ничего не делает, на самом деле все AConfiguratin_setXXX ничего не делают. Может быть, я называю это не в том месте? Я вызывал его во время APP_CMD_INIT_WINDOW после создания окна. Где я должен вызывать эту функцию?


person MightyMoo    schedule 09.12.2016    source источник
comment
Насколько я знаю, вы не можете сделать это без вызова Java API. Возможно, вам придется вызывать методы Java через JNI из чистого кода C++, используя GetMethodID и связанные функции. Конфигурация, вероятно, не то, что вам нужно — судя по беглому просмотру документов, она предназначена для редактирования объекта Java Configuration. Вам нужно получить jobject для вашего Activity, получить JNIEnv и использовать его для вызова методов Java, необходимых для вашей задачи.   -  person user1643723    schedule 09.12.2016
comment
У меня только что было собеседование сегодня, и я упомянул об этой проблеме, и, по-видимому, у них была такая же проблема, но она была решена с помощью чистого С++. Я забыл спросить их, как они это сделали перед отъездом, но похоже, что это возможно. В крайнем случае, если я не могу найти ответ, я частично использую Java, как обычный человек. Спасибо за ваш вклад!   -  person MightyMoo    schedule 09.12.2016
comment
Использование C++ для вызова методов Java с помощью JNI является чистым C++, поскольку вы не пишете никакого кода Java — просто используете JVM C++ API для вызова методов Java.   -  person user1643723    schedule 09.12.2016
comment
Да, я понимаю, что чистый С++ все еще использует вызовы Java. Мне просто нужен секретный ингредиент, чтобы скрыть навигацию. Я знаю, что есть один, должен быть! Что я имел в виду под частичным использованием java в качестве последнего средства, так это скрыть навигацию в файле java.   -  person MightyMoo    schedule 09.12.2016


Ответы (2)


Так! Если кому-то интересно, я нашел ответ, покопавшись в одном из примеров чайника Microsoft. И вот что я придумал:

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();
}

}

Чистая разработка Android на С++ по-прежнему использует java, она получает ее из источника внутри каталога Android SDK. Что вы можете сделать, так это расширить NativeActivity несколькими дополнительными настройками. Внутри манифеста все, что вам нужно сделать, это:

    android:hasCode="true"

а затем самая важная часть - изменить имя действия с

        android:name="android.app.NativeActivity"

to

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

Он по-прежнему будет вызывать основной Android и настраивать его так же, как обычную нативную активность, но теперь он дает вам полностью полноэкранный режим. Я надеюсь, что это поможет кому-то там. Мне потребовались дни поиска ответов, и вот что я смог придумать!

УДАЧИ!

person MightyMoo    schedule 10.12.2016
comment
Я нашел это в sfml, его полный С++ и учитывает более старые версии API: L139" rel="nofollow noreferrer">github.com/SFML/SFML/blob/ - person user2591935; 03.01.2017
comment
Большое спасибо, я очень надеюсь, что это сработает и для меня :) - person Viktor Sehr; 10.06.2018
comment
Да, расширение NativeActivity — это способ сделать это. То же самое делает и Google: github.com/googlesamples/ android-ndk/дерево/мастер/чайники/ - person Slion; 31.07.2018
comment
Как это принятый ответ? Он использует Java, когда просили не использовать Java! - person Jon Watte; 04.11.2020

Я нашел этот фрагмент кода, который работает (требуется уровень API> 19). Просто вызовите функцию в начале 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();
}
person Viktor Sehr    schedule 13.06.2018
comment
Это отлично работает для меня и не требует добавления кода JVM. Это должен быть принятый ответ! - person Jon Watte; 04.11.2020