// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only

/*!

    \example demos/qtjennydemo
    \title QtJenny: Generating C++ proxy classes to access Android APIs
    \target QtJenny Demo
    \ingroup qtquickdemos
    \brief Demo showcasing the use of QtJenny.
    \meta {tag} {demo,qtjenny,generator,android}
    \examplecategory {Mobile}

    \borderedimage qtjennydemo_overview.webp

    \section1 Overview

    This demo showcases the use of \l {Maven Central: QtJenny}{QtJenny} and
    uses it to generate C++ proxy classes to access Android APIs from C++ code.
    The generated C++ classes are used in the UI application of this demo to
    perform actions such as adjusting the volume and brightness, activating
    and deactivating \l {Android: wake lock} {wake locks}, sending notifications
    and triggering vibrations. These actions are part of Android APIs that
    Qt doesn't implement.

    Generating C++ classes using QtJenny removes the need to write
    \l {Android: JNI} {JNI} code manually.

    \section1 How it works

    The demo contains two distinctive parts, one is the UI application
    i.e the Qt Quick project called \c qtjenny_consumer that uses the code
    generated by QtJenny, and the other one is a combination of three different Gradle
    projects called \c qtjenny_general, \c qtjenny_callback and \c qtjenny_baseclass
    that together handle the code generation using QtJenny.
    Each of the three gradle projects contain class annonations and \c Gradle
    configurations for QtJenny code generation.

    The QtJenny code generation is triggered automatically during the CMake
    configuration of \c qtjenny_consumer project by executing \c kaptReleaseKotlin
    gradle task in each of \c qtjenny_general, \c qtjenny_callback
    and \c qtjenny_baseclass gradle projects.

    \snippet CMakeLists.txt 0

    Running the \c qtjenny_consumer project launches the UI application.

    \section1 Generating the C++ headers

    Running the \c kaptReleaseKotlin task in the gradle projects triggers
    an annotation processor that processes the annotations declared in
    \c GenerateCppCode.kt.

    Code snippet from the \c GenerateCppCode.kt file of \c qtjenny_general :

    \snippet qtjenny_general/app/src/main/java/org/qtproject/qt/qtjenny_general/GenerateCppCode.kt 1

    In the case of \c qtjenny_general the annotation processor generates
    the C++ headers to \c qtjenny_output directory. Those C++ headers contain
    the needed JNI boilerplate code to access the Android APIs used in the \c qtjenny_consumer.

    The app level \c build.gradle script in \c qtjenny_general specifies the
    arguments for \l {Android: Kapt compiler plugin}{kapt} which QtJenny
    implements. These arguments are parsed in the QtJenny compiler and used
    in the generation process.

    \snippet qtjenny_general/app/build.gradle 2


    \section2 qtjenny_general

    The \c qtjenny_general takes care of generating wrappers for Java classes, to
    allow constructing Java objects and invoking methods on them. These wrappers
    wrap the usual method calls, and for callbacks, the qtjenny_baseclass and
    qtjenny_callback are used.

    \section2 qtjenny_baseclass

    The \c qtjenny_baseclass effectively allows extending the Java class
    ContentObserver in C++ code, using a combination of the baseclass generation
    and callback generation.

    \section2 qtjenny_callback

    The \c qtjenny_callback effectively allows implementing a Java interface in C++.
    The \c qtjenny_baseclass class extending also uses this mechanism.

    For implementing an interface, a Java Proxy class  is constructed, using an
    InvocationHandler that performs virtual function calls into the generated C++
    class hierachy.

    For extending a base class, the generated extended class performs virtual
    function calls into the generated C++ class hierarchy.

    \section1 Using the generated C++ headers in the Qt Quick application

    The \c qtjenny_consumer is the Qt Quick Application that uses the C++ headers
    generated by the \c qtjenny_general. We include the generated headers in
    \c backend.h file and use them in \c backend.cpp to access various Android
    APIs.

    The app's UI consists of one \c Main.qml file, which is connected to the
    \c BackEnd class using \l Q_INVOKABLE and \l Q_PROPERTY macros.

    The UI contains the following controls and actions.

    \section2 Wake locks

    You can activate and deactivate either full or partial wake locks, using
    \l {Switch} {Switches}. These switches trigger corresponding \c Q_INVOKABLE
    functions of \c Backend class, that activate the wake lock and set the wake
    lock status text that will be shown to user in the UI.

    \snippet Main.qml 3

    Setting partial wake lock uses the \c WakeLockProxy class that connects
    to \c PowerManager.WakeLock Android API. Setting full wake lock is done
    by using \c WindowProxy that connects to \c Window Android API.

    \section2 Vibrate

    You can trigger a vibration using the \c BackEnd::vibrate() function,
    that uses \c VibrationEffectProxy, \c VibratorManagerProxy and
    \c VibratorProxy classes to create the vibration.

    \section2 Notifications

    Sending a notification is handled in the \c BackEnd::notfy() function in
    \c Backend with use of the \c NotificationManagerProxy class.

    The notification is already created during the \c Backend class
    initialization in \c BackEnd::createNotification() function.

    \section2 Adjusting the brightness

    Adjusting brightness with the brightness slider in the UI triggers
    property change in \c Backend class that will be handled in \c BackEnd::setBrightness()
    function. There the system brightness is adjusted with the use of
    \c SettingsProxy, \c SystemProxy, \c ContextProxy, \c LayoutParamsProxy and
    \c WindowProxy classes.

    The brightness slider is dynamically synchronized with the system brightness,
    so if the system brightness is changed from outside the application the
    brightness slider adjusts to reflect the current system brightness.

    If the application does not have permission to write system settings, an
    \c Activity is started with the \c ACTION_MANAGE_WRITE_SETTINGS intent. After
    this \c Activity is started, user has to manually give permission for the application
    to write system settings.

    \section2 Adjusting the volume

    Adjusting volume with volume slider in the UI triggers property
    change in \c Backend class that will be handled in \c BackEnd::setVolume()
    function. There the system volume is adjusted with the use of
    \c AudioManagerProxy class.

    The volume slider is dynamically synchronized with the system music volume,
    so if the system music volume is changed from outside the application
    the volume slider adjusts to reflect the current system music volume.
*/

