
This directory contains the Android-specific code for building xscreensaver.

It is very much a work in progress.  If you're messing with this, please let
us know:

        dennis@panaceasupplies.com
        jwz@jwz.org


############################################################################
#
#   To set up your Android development environment:
#
############################################################################

    Install JDK: https://www.oracle.com/java/technologies/downloads/
      You might need to nuke the old ones first:
      rm -r /Library/Java/JavaVirtualMachines/*
    Install Android Studio: http://developer.android.com/sdk/
    Install Android NDK: http://developer.android.com/ndk/downloads
      Rename or link the "android-ndk-*" directory to "ndk" inside your
      $ANDROID_HOME (the "sdk/" directory that is the parent of
      "build-tools/", etc.)  That is, it should be "sdk/ndk/".

      Update 2023: these seem to be DMGs now?  Sigh.  Mount it and then do:
      cp -pr /Volumes/Android\ NDK\ r25c/AndroidNDK*.app/Contents/NDK \
        ~/Library/Android/sdk/android-ndk-r25c

    ln -sf sdk/ndk/ndk-build .
    cd sdk ; ln -sf android-ndk-r* ndk
    Delete any old NDKs or they get used anyway.

    Set $ANDROID_HOME to where your SDK is installed, or
    set "sdk.dir" in the file local.properties.
    On MacOS, the value you want is probably ~/Library/Android/sdk/
    Also set "ndk.dir" in local.properties.

    Install ImageMagick ("convert").

    On an M1 Mac, you might also need to do this to make the emulator work:
    ln -s darwin-aarch64 ~/Library/Android/sdk/emulator/qemu/darwin-x86_64


############################################################################
#
#   To build:
#
############################################################################

    ./configure
    cd android
    make

    Hopefully an "xscreensaver-debug.apk" file will appear in
    android/xscreensaver/build/outputs/apk/.

    Load that onto your device and go to:
      Settings / Display / Daydream
    or maybe it's now called
      Settings / Display / Advanced / Screen saver
    or just click on the XScreenSaver icon, which is a shortcut to that.

    To create and configure an emulator image, use the GUI tool and and
    give the emulator a name (say, "Nexus_5").

      View / Tool Windows / Device Manager

      E.g.: Nexus 5, Android 5, Intel Atom x86_64, RAM 2048 VM 64,
      storage 200, use host GPU.

      This used to work but no longer does:
      $ANDROID_HOME/sdk/tools/android avd

    Configuration options are in $HOME/.android/avd/*.avd/config.ini

    To launch it:

      $ANDROID_HOME/sdk/emulator/emulator -avd Nexus_5

    To load xscreensaver into the currently-running emulator or device:
      $ANDROID_HOME/platform-tools/adb install -r \
        xscreensaver/build/outputs/apk/xscreensaver-debug.apk

    Extremely verbose log output, including stack traces:
        $ANDROID_HOME/platform-tools/adb logcat

    Non-fatal log output for only this app:
        $ANDROID_HOME/platform-tools/adb logcat \
          -s xscreensaver:d AndroidRuntime:d libEGL:d

    Note that sometimes "logcat" will just sit there forever saying
    "waiting for device".  This is because the emulator is a piece of
    shit and sometimes decides to just randomly not service connections.
    If you restart the emulator, and wait minutes for the whole damned
    thing to boot up again, it will probably work next time.  Probably.


    WTF is Gradle?

    "gradle" is a yet another re-invention of "make" that is written
    in Java, because we needed that like another hole in the head.
    The actual gradle app is bundled here, in a .jar file.

    "gradlew" is an sh script that tries to figure out how to invoke
    Java to run gradle properly.

    There are identical copies of gradle and gradlew in both
    "android/" and in "android/xscreensaver/".  I don't know why.

    The latest Gradle requires Java 11.  Because why wouldn't it, a
    build system needs the bleeding edge, right? That's totally normal.
    To download Java from Oracle, they want you to make an account and
    verify your email address, but if you don't want to go through that
    nonsense (because fuck those guys) you can find a mirror of it at
    https://www.techspot.com/downloads/5553-java-jdk.html -- but make
    sure that you verify that download with "shasum -a 256" against
    https://www.oracle.com/webfolder/s/digest/11-0-10-checksum.html so
    that you don't get a trojan.

    Not all versions of Gradle work with all versions of Java because of
    course they don't.  Here's a table listing compatible versions:
    https://docs.gradle.org/current/userguide/compatibility.html


############################################################################
#
#   Directory structure:
#
############################################################################

    Boilerplate for the Java version of "make":
        *gradle*
        *.properties
        xscreensaver/*gradle*
        xscreensaver/build.*
        xscreensaver/*.properties

    The other half of the Makefile:
        xscreensaver/jni/*.mk

    Source code:
        xscreensaver/src/org/jwz/xscreensaver/*.java
        xscreensaver/res/layout/*.xml

    Other relevant source code is in ../jwxyz/ and ../hacks/.

    Icons:
        xscreensaver/res/drawable-ldpi/
        xscreensaver/res/drawable-mdpi/
        xscreensaver/res/drawable/

    Fonts:
        xscreensaver/assets/fonts/

    Files that we generate:

        Most of the XML is generated by ../hacks/check-configs.pl

        gen/function-table.h
        xscreensaver/AndroidManifest.xml
        xscreensaver/res/drawable/*.png (except for thumbnail.png)
        xscreensaver/res/values/settings.xml
        xscreensaver/res/values/strings.xml
        xscreensaver/res/xml/*.xml
        xscreensaver/src/org/jwz/xscreensaver/gen/*.java

    Other files generated as a part of the build process:

        build/
        gen/
        .gradle/
        xscreensaver/build/
        xscreensaver/build/outputs/apk/  -- app appears here
        xscreensaver/jni/
        xscreensaver/libs/
        xscreensaver/obj/
        xscreensaver/res/
        xscreensaver/res/drawable/
        xscreensaver/res/values/
        xscreensaver/res/xml/
        xscreensaver/src/org/jwz/xscreensaver/gen/

When adding a new hack, edit android/Makefile, then "make clean" and "make".


############################################################################
#
#   TODO list -- known bugs
#
#   We could really use some help with these!
#
############################################################################

  - Rotation is wonky (on some devices?)

  - When a saver exits abnormally, we catch the exception and attempt to 
    display the error message in a dialog.  The catch works, but the dialog
    box does not.

  - There are lots of deprecation warnings about these, and I don't know what
    to do about it:

      - android.preference.*
      - MediaColumns.DATA
      - MediaStore.Images.Media.getBitmap

  - Rendering text into pixmaps doesn't work.  Affects:

      - apple2
      - bsod
      - fontglide
      - phosphor

 - Rendering text into textures doesn't work.  Possible causes include:
   the pixmap problem, above; and that retrieving the GL_TEXTURE_MATRIX
   seems to not work.  Affects:

      Any hack that uses print_texture_label:

      - FPS displays on every OpenGL hack
      - engine (engine names)
      - geodesicgears (number of teeth)
      - glslideshow (file names)
      - glsnake (shape names)
      - juggler3d (pattern names)
      - molecule (descriptions)
      - pinion (number of teeth)
      - polyhedra (object descriptions)
      - spheremonics (object descriptions)
      - tangram (object descriptions)
      - unicrud (character descriptions)

      Any hack that uses print_texture_string:

      - carousel (file names)
      - circuit (labels on components)
      - esper (coordinates and file names)
      - fliptext (the whole thing)
      - geodesicgears (gear numbers)
      - gibson (text on the towers)
      - jigsaw (loading message)
      - molecule (atom names)
      - photopile (file names)
      - sonar (everything)
      - starwars (everything)
      - unicrud (everything)
      - winduprobot (word bubbles)

      Interestingly, splitflap uses print_texture_string successfully,
      so that bears investigation.

  - Retrieving GL_MODELVIEW_MATRIX doesn't seem to work.  Affects:

      - discoball (back faces not masked out, billboarded lights)
      - energystream -- blank in emulator, works on real devices?
      - glsnake -- blank in emulator, works on real devices?
      - molecule (billboarded atom labels)
      - raverhoop -- blank in emulator, works on real devices?
      - starwars (blank)
      - winduprobot (billboarded word bubbles)

 - Pixmap masks don't work.  Affects:

      - barcode -- fails in emulator, works on real devices?
      - bsod (logos and such)
      - noseguy (character display as rectangle)
      - pacman (characters display as rectangles)
      - polyominoes (can't texture the objects)
      - spotlight (everything)

      Dave says:
      jwxyz_blit() just needs a GCFunction parameter that swaps out that
      memmove() when it's not GXcopy. I think xscreensaver_logo() is the only
      thing that needs GC functions under jwxyz-image.c, and that doesn't need
      fancy blending like jwxyz.m provides, so for instance GXxor could be
      implemented as `a ^ b` instead of `abs(a - b)`.

 - Complex polygon fills (XFillPolygon) are not implemented.  Affects:

      - pedal
      - qix
      - speedmine
      - starfish

  - The code that attempts to grab a screen shot before the Daydream begins
    doesn't work.  Affects every image-loading hack that wants to manipulate
    the "desktop".

  - Alpha blending of GL objects doesn't seem to work.  Affects:

      - beats (blur isn't transparent)
      - molecule (shells are not transparent)
      - winduprobot (dome is not transparent)

  - Weird outliers:

    - kumppa and slip are special-cased to use jwxyz-gl instead of jwxyz-image
      because otherwise they are too slow, as they do tons of XCopyArea. and
      OpenGL ES 1.1 doesn't have glCopyPixels or glBlitFramebuffer.

    - petri is similar, except with tons of XFillRectangle, which, at two
      triangles each, is a lot of geometry.

  - Undiagnosed problems:

      - antinspect has some kind of masking problem. Maybe only in emulator?
      - cityflow colors and shading are all wrong.
      - discoball doesn't draw rays.
      - endgame is insanely slow.
      - esper images display as black.
      - glblur is grayscale instead of color.  Endian or packing problem?
      - queens is insanely slow.
      - sonar doesn't display properly, but once it does, test icmp.
      - xmatrix is pretty slow.

############################################################################
#
#   Releasing (this is for my benefit)
#
############################################################################

  Everything moves around every 6 months, so listing URLs here would be
  foolish.

  - Search for "Google play developer console".
  - When that doesn't work search for "play console" "create a release".
  - The button is in the upper right, lately.
  - You might need to use Chrome instead of Safari.
  - Drag and drop the APK.

  - Next Google will complain that "Your app currently targets API level N".
    - Android Studio / Tools / SDK Mananger
    - SDK Platforms - install the latest released ("R"), note API Level, Rev.
    - SDK Tools - Show Details, install latest "SDK Build Tools", note version.
    - Edit xscreensaver/build.gradle, change "compileSdkVersion" and
      "buildToolsVersion" and "targetSdkVersion"
    - Also install latest "NDK Side by Side"

  - Next Android Studio will complain that Gradle is too old. Update it.
    - "make clean" and note the error that says something like:
      "Minimum supported Gradle version [...] to gradle-N.N.N-WHAT.zip"
    - Edit gradle/wrapper/gradle-wrapper.properties and change
      "distributionUrl" to end with that.

  - Might need to re-download the NDK and re-create the symlink
    ~/Library/Android/sdk/ndk
    Are there now multiple copies of the same version installed? I can't tell.

  - Delete any old NDKs in ~/Library/Android/sdk/ or they might get picked
    instead of the newer ones.

