We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 2614 - SDLActivity.java can be silently out of date
Summary: SDLActivity.java can be silently out of date
Status: ASSIGNED
Alias: None
Product: SDL
Classification: Unclassified
Component: *don't know* (show other bugs)
Version: HG 2.0
Hardware: All Android (All)
: P2 normal
Assignee: Gabriel Jacobo
QA Contact: Sam Lantinga
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-06-28 18:46 UTC by Sam Lantinga
Modified: 2019-05-13 19:46 UTC (History)
4 users (show)

See Also:


Attachments
patch for Android interface version (4.10 KB, patch)
2014-10-19 21:23 UTC, Philipp Wiesemann
Details | Diff
patch for SDL JNI versioning on Android (3.64 KB, patch)
2014-10-23 21:48 UTC, Philipp Wiesemann
Details | Diff
android-project/installNewSdlLibVersion.sh (3.23 KB, text/x-sh)
2019-05-09 20:43 UTC, qufighter
Details
android-project/installNewSdlLibVersion.sh (3.40 KB, text/plain)
2019-05-09 23:12 UTC, qufighter
Details
android-project/installNewSdlLibVersion.sh (4.48 KB, text/plain)
2019-05-13 19:46 UTC, qufighter
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Sam Lantinga 2014-06-28 18:46:41 UTC
We need to implement some sort of version protection to make sure that SDLActivity.java and the SDL code are in sync. If people upgrade SDL and don't pull the latest changes to SDLActivity.java, they can crash or have other weird behavior.
Comment 1 Philipp Wiesemann 2014-10-19 21:23:36 UTC
Created attachment 1908 [details]
patch for Android interface version

Here is a patch for a possible solution.

It adds an "interface version" in SDLActivity.java and SDL_android.c which needs to be edited manually for every change and is compared when initializing SDL. If the values from both parts are not equal a warning will be logged. From this it should be clear that a file was not updated. No message box is shown and execution continues because it is only a warning. The value is passed around to prevent querying it using JNI.

The advantage of this solution is that nothing changes for the users. They neither need additional programs or scripts nor change their way to update SDL.

The disadvantage of this solution is that it means more work for the maintainers. They need to remember editing the values or set up a Mercurial hook locally to warn them. It is no automatic solution.
Comment 2 Sam Lantinga 2014-10-20 00:51:56 UTC
That sounds good. We should have big comments at the top of both files that describe the interface version and its purpose. Since it should reflect incompatibilities between different versions of the Java and the C code, it should show a message box and exit if they don't match.
Comment 3 Gabriel Jacobo 2014-10-20 12:21:37 UTC
Looks ok to me, one nitpick would be calling the define "SDL_JNI_VERSION"
Comment 4 Philipp Wiesemann 2014-10-23 21:48:44 UTC
Created attachment 1914 [details]
patch for SDL JNI versioning on Android

Here is a new patch with message box, exit and the more descriptive constant name.

The check now in Java because the exit and the message box are there. An exit from Java is more useful because of the more documented clean up. Also doing the check in C and then messaging back to Java (because the exit is there) would have needed an additional message channel. The return value of nativeInit() was not used for this because it is the return value of main() and may therefore already be in use by some applications. But the recently added message box for not loaded libraries is used. Having everything in Java also means that the version does not need to be passed around and one file less needs to be modified.

A new disadvantage is that the actual version check will not work until the Java file was updated at least once (because the check is inside).
Comment 5 Sylvain 2014-10-24 08:27:01 UTC
Hi, 

What about a more simple solution in SDL/Android.mk, that would just prevent the build:


SDL_JNI_VERSION_C_SIDE=$(shell cat $(LOCAL_PATH)/src/core/android/SDL_android.c | grep JNI_VERSION )
SDL_JAVA_FILE=$(shell find src | grep SDLActivity.java)
SDL_JNI_VERSION_JAVA_SIDE=$(shell cat $(SDL_JAVA_FILE) | grep JNI_VERSION)

ifeq ($(SDL_JNI_VERSION_JAVA_SIDE),$(SDL_JNI_VERSION_C_SIDE))
  $(info Ok: JNI Version API)
else
  $(error Error: JNI Version API mismatch. Update your Java file: $(SDL_JAVA_FILE))
endif

With a keyword JNI_VERSION more unique.
Comment 6 Philipp Wiesemann 2014-10-24 09:03:03 UTC
(In reply to Sylvain from comment #5)
> Hi, 
> 
> What about a more simple solution in SDL/Android.mk, that would just prevent
> the build:
> 
> 
> SDL_JNI_VERSION_C_SIDE=$(shell cat
> $(LOCAL_PATH)/src/core/android/SDL_android.c | grep JNI_VERSION )
> SDL_JAVA_FILE=$(shell find src | grep SDLActivity.java)
> SDL_JNI_VERSION_JAVA_SIDE=$(shell cat $(SDL_JAVA_FILE) | grep JNI_VERSION)
> 
> ifeq ($(SDL_JNI_VERSION_JAVA_SIDE),$(SDL_JNI_VERSION_C_SIDE))
>   $(info Ok: JNI Version API)
> else
>   $(error Error: JNI Version API mismatch. Update your Java file:
> $(SDL_JAVA_FILE))
> endif
> 
> With a keyword JNI_VERSION more unique.

This is a really a better idea. It also prevents overhead at runtime and confusing in the source files.

Does it work on Windows (if this is still a requirement)? There used to be no cat and grep (without Cygwin which is not required by NDK).

A disadvantage may be that it does not help if the compiled Java class files are outdated. The version is read from the source which may already be okay.
Comment 7 Gabriel Jacobo 2014-10-29 22:56:34 UTC
The NDK does seem to require Cygwin:

Required development tools

For all development platforms, GNU Make 3.81 or later is required. Earlier versions of GNU Make might work but have not been tested.
A recent version of awk (either GNU Awk or Nawk) is also required.
For Windows, Cygwin 1.7 or higher is required. The NDK will not work with Cygwin 1.5 installations.

Reference: http://developer.android.com/tools/sdk/ndk/index.html
Comment 8 Philipp Wiesemann 2014-10-30 09:01:32 UTC
(In reply to Gabriel Jacobo from comment #7)
> The NDK does seem to require Cygwin:
> 
> ...
> 
> Reference: http://developer.android.com/tools/sdk/ndk/index.html

You are right. Then using it on Windows at all should be no problem.

I did not read the requirements before my claim and just wrongly assumed it worked without Cygwin because it worked for me the last time I used it on Windows.

In the reference you linked under "Android NDK, Revision 7 (November 2011)" it says that building "on Windows without Cygwin" works but is still experimental. So that seems the reason why it worked for me.
Comment 9 Sam Lantinga 2017-08-14 06:25:14 UTC
One problem with this is that we're getting lots of patches for the Java file that won't automatically increment the interface version.

Maybe we should just write the major and minor version into the Java file, and check to make sure that matches SDL_version.h?

The other issue is that people aren't necessarily building SDL in-app, so we may not find the application Java file.
Comment 10 Olli Kallioinen 2017-09-12 15:48:31 UTC
In my opinion the best solution would be to remove the need to copy the java file to user projects. In normal use cases you should not need to modify the class anyway, so adding it to your own project only creates these out-of-sync issues. Also I think the class should be made abstract so that the users would be forced to extend it in their own class. 

Then the SDL base class would be referenced by the user projects either from a jar library or preferably SDL as a whole would be packaged to an android archive (AAR): https://developer.android.com/studio/projects/android-library.html

Users can still override the important stuff in their implementation class and if they really need to modify the SDL stuff they need to do it the old way and copy the class or edit it in SDL source.

The thing is that while you can include native libraries in the AAR already, it doesn't support including native header files properly yet, but it's in the works: https://issuetracker.google.com/issues/37086680

This way there would be a precompiled distribution for android that would use AAR instead of  making everybody compile from source. I thought about testing it out and doing a patch, but I'm waiting for the native library support issues to be solved first.

Another related issue is the outdated sample project that could then be then updated to just use gradle and the AAR: (https://bugzilla.libsdl.org/show_bug.cgi?id=3510)
Comment 11 qufighter 2019-05-09 20:43:41 UTC
Created attachment 3781 [details]
android-project/installNewSdlLibVersion.sh

+1 what Olli suggests

In the meantime I wrote a shell script that makes installing a new lib pretty easy (attached installNewSdlLibVersion.sh goes in android-project folder and should be run from there).

It does the following:
    verifies arguments
    clears app/build/intermediates to make sure your build uses new version
    updates the symlink to the SDL library code
    copies the src/main/java/org/libsdl/app/ java files replacing all
    displays a diff of AndroidManifest.xml (which needs to be manually merged)

It's suppose to be harmless to run with the current setting (when the args define current symlink).

./installNewSdlLibVersion.sh SDL /full/path/to/libs/SDL-2.0.9-12723

For me it works with or without trailing slash (only tested on osx).  Should work fine to upgrade other symlinks too.

I guess its worth pointing out keeping this manifest file up to date is also important when upgrading, which is arguably also part of this issue.
Comment 12 qufighter 2019-05-09 23:12:26 UTC
Created attachment 3782 [details]
android-project/installNewSdlLibVersion.sh
Comment 13 qufighter 2019-05-13 19:46:27 UTC
Created attachment 3783 [details]
android-project/installNewSdlLibVersion.sh

diff the build.gradle files too