Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial build for Android Studio #5991

Merged
merged 7 commits into from
Oct 20, 2022
Merged

Add initial build for Android Studio #5991

merged 7 commits into from
Oct 20, 2022

Conversation

ihhub
Copy link
Owner

@ihhub ihhub commented Oct 17, 2022

This is a very basic setup of Android Studio build with many unsolved issues such as:

  • release build requires signing
  • the path in internal storage is org.libsdl.app
  • source code of SDL2 and SDL2 mixer must be put under android/app/jni directory
  • source code of fheroes2 directory subfolders must be put under android/app/jni/src (we shouldn't do this but for POC it is that this way)
  • settings for the application are not set
  • midi music does not work and etc and etc

However, you can build a debug version and run it on an Android device. I do not have one so I tested on an emulator using Android Studio on Windows.

All comments and recommendations are welcome as I have limited knowledge in Android development but we need to make such step to move forward.

Thing to be done in this PR:

  • fix SonarQube analysis
  • fix path for compilation of fheroes2 source code

This is a very basic setup of Android Studio build with many unsolved issues such as:
- release build requires signing
- the path in internal storage is org.libsdl.app
- source code of SDL2 and SDL2 mixer must be put under `android/app/jni` directory
- source code of fheroes2 directory subfolders must be put under `android/app/jni/src` and we shouldn't do this
- settings for the application are not set
- midi music does not work
 and etc and etc

However, you can build a debug version and run it on an Android device. I do not have one so I tested on an emulator.

All comments and recommendations are welcome as I have limited knowledge in Android development but we need to make such step to move forward.
@ihhub ihhub added improvement New feature, request or improvement script Things related to various scripts (utility scripts, CI scripts, etc) Android Android version of the engine labels Oct 17, 2022
@ihhub ihhub added this to the 0.9.21 milestone Oct 17, 2022
@ihhub ihhub self-assigned this Oct 17, 2022
@ihhub
Copy link
Owner Author

ihhub commented Oct 17, 2022

Hi @oleg-derevenetz , I would say that this is more work in progress pull request rather than a ready for production solution so I am asking your help in this pull request if you have expertise in this area.

@ihhub
Copy link
Owner Author

ihhub commented Oct 17, 2022

Hi @zenseii , could you please try this solution on your machine to see if you are able to compile it?

@ihhub ihhub marked this pull request as draft October 17, 2022 16:42
@zenseii
Copy link
Collaborator

zenseii commented Oct 17, 2022

source code of SDL2 and SDL2 mixer must be put under android/app/jni directory
source code of fheroes2 directory subfolders must be put under android/app/jni/src (we shouldn't do this but for POC it is that this way)

Hi, @ihhub!

What should the name of the SDL2, SDL_mixer and fheroes2 folders be?

EDIT:
I can see from the android.mk file that they should be engine, fheroes2 and third-party for fheroes2.
For SDL I'm not sure.

@zenseii
Copy link
Collaborator

zenseii commented Oct 17, 2022

Hi @ihhub.
I still get this compile error in Android studio:
make (e=87): Wrong parameter.
I will have to look closer into why I get it, but it's probably something basic I'm misunderstanding here.
I named the SDL folders SDL2 and SDL2_mixer and put the latest SDL2 and SDL2-mixer source files in them.

EDIT:
The error might be related to this:
https://stackoverflow.com/questions/12598933/ndk-build-createprocess-make-e-87-the-parameter-is-incorrect

I am indeed building on Windows but I believe you were too, @ihhub?

@oleg-derevenetz
Copy link
Collaborator

I would say that this is more work in progress pull request rather than a ready for production solution so I am asking your help in this pull request if you have expertise in this area

I'm afraid I don't have much expertise in this area, because I developed only small apps for Android just for fun about two years ago (without using SDL), and I can't say that it gave me a lot of fun :) But of course, if I can help in any way, I will try to help.

@oleg-derevenetz
Copy link
Collaborator

oleg-derevenetz commented Oct 17, 2022

Hi @ihhub

the path in internal storage is org.libsdl.app

What you really need is to make your own app package with name, say, org.fheroes2 and your own Activity class, say, Fheroes2Activity or MainActivity, inherited from the SDLActivitywith minimal code (maybe without any fields and methods at all) and specify it in the app manifest and Gradle scripts. There is no need to include the SDL-related files (such as Java classes, SDL-specific Gradle scripts, etc) in the fheroes2 repo, they should be taken/included from the source tree of the particular SDL distribution, with which the app is being built, during the build process.

@ihhub
Copy link
Owner Author

ihhub commented Oct 18, 2022

Hi @zenseii , to solve this issue please try to put the project under a short path directory like D:\1 and then compile it.

@oleg-derevenetz , this is a good idea and I will try to do it.

@oleg-derevenetz
Copy link
Collaborator

oleg-derevenetz commented Oct 18, 2022

this is a good idea and I will try to do it.

This can be done by, say, copying the contents of SDL archive to, say, android/thirdparty/sdlduring build and adding the include ':thirdparty:sdl:android-project' to the settings.gradle. In theory after that Gradle should pick up all necessary files, including SDL Java classes, Gradle scripts and so on. Something like this.

@oleg-derevenetz
Copy link
Collaborator

oleg-derevenetz commented Oct 19, 2022

Hi @ihhub you can try to use pre-built Android package from this PR's artifacts:

fheroes2/fheroes2-prebuilt-deps#17

Remove all extra files, download the android.zip and extract it to the android/app subdirectory. This archive contains the pre-built SDL2 and SDL2_mixer JNI packages (SDL_mixer is built with Timidity BTW to support MIDI playback) as well as thirdparty dir with sdl2 library which can be linked by adding include ':thirdparty:sdl2' to the settings.gradle. Then you should be able to make your own package with an empty Activity inherited from the SDLActivity. Please let me know in case of any issues (there are can be layout issues for example).

@ihhub
Copy link
Owner Author

ihhub commented Oct 19, 2022

Hi @oleg-derevenetz , sure. I will do it within today.

@oleg-derevenetz
Copy link
Collaborator

Hi @ihhub

sure. I will do it within today.

I changed the layout to make it more "canonical":

./app
./app/jni
./app/jni/SDL2_mixer
./app/jni/SDL2_mixer/include
./app/jni/SDL2_mixer/libs
./app/jni/SDL2_mixer/libs/armeabi-v7a
./app/jni/SDL2_mixer/libs/x86
./app/jni/SDL2_mixer/libs/arm64-v8a
./app/jni/SDL2_mixer/libs/x86_64
./app/jni/SDL2
./app/jni/SDL2/include
./app/jni/SDL2/libs
./app/jni/SDL2/libs/armeabi-v7a
./app/jni/SDL2/libs/x86
./app/jni/SDL2/libs/arm64-v8a
./app/jni/SDL2/libs/x86_64
./sdl2
./sdl2/src
./sdl2/src/main
./sdl2/src/main/java
./sdl2/src/main/java/org
./sdl2/src/main/java/org/libsdl
./sdl2/src/main/java/org/libsdl/app

So now this archive should be extracted to /android and settings.gradle should contain

include ':sdl2'

It would be good to move these JNI deps from app to sdl2 as well, but I have no idea yet whether it will work or not.

@ihhub
Copy link
Owner Author

ihhub commented Oct 19, 2022

Hi @oleg-derevenetz , so far no luck. What I did:

  • extracted the content of PR's artifact into a separate directory
  • copied all content from android directory
  • changed the content of settings.gradle into include ':sdl2'
  • removed app/src/main/java directory

What I got:
image
image

@ihhub
Copy link
Owner Author

ihhub commented Oct 19, 2022

After some woodoo magic I fixed that error by changing the content settings.gradle into include ':app', ':sdl2'. I am trying to build but I already see some SDL2 related errors:
image

@ihhub
Copy link
Owner Author

ihhub commented Oct 19, 2022

@oleg-derevenetz , after lengthy compilation I still receive the same errors. Looks like we need to add these files:
image

@oleg-derevenetz
Copy link
Collaborator

Hi @ihhub OMG, the manifest file. Try to add some minimal manifest file to the sdl2 library directory, just like it's done for app.

@oleg-derevenetz
Copy link
Collaborator

oleg-derevenetz commented Oct 19, 2022

changed the content of settings.gradle into include ':sdl2'

It should contain BOTH include ':app' and include ':sdl2', because now there are two modules :)

@ihhub
Copy link
Owner Author

ihhub commented Oct 19, 2022

changed the content of settings.gradle into include ':sdl2'

It should contain BOTH include :app and include :sdl2, because now there are two modules :)

This I did :)

@oleg-derevenetz
Copy link
Collaborator

oleg-derevenetz commented Oct 19, 2022

@ihhub Try to add the following AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest package="org.libsdl.app"
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:versionCode="1"
          android:versionName="1.0">
</manifest>

or maybe even

<?xml version="1.0" encoding="utf-8"?>
<manifest package="org.libsdl.app"
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:versionCode="1"
          android:versionName="1.0"/>

@ihhub
Copy link
Owner Author

ihhub commented Oct 19, 2022

<?xml version="1.0" encoding="utf-8"?>
<!-- Replace com.test.game with the identifier of your game below, e.g.
     com.gamemaker.game
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.libsdl.app"
    android:versionCode="1"
    android:versionName="1.0"
    android:installLocation="auto">
</manifest>

did the magic.

@oleg-derevenetz
Copy link
Collaborator

@ihhub Yeah, I forgot that even a library still requires the some minimal manifest. I'll add something to the prebuilt package.

@oleg-derevenetz
Copy link
Collaborator

@ihhub Does the sound work now?

@ihhub
Copy link
Owner Author

ihhub commented Oct 19, 2022

Despite of fact to have a successful build the application fails to startup:

10/19 20:32:08: Launching 'app' on Pixel 3a API 33.
Install successfully finished in 348 ms.
$ adb shell am start -n "org.libsdl.app/org.libsdl.app.SDLActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Connected to process 3089 on device 'Pixel_3a_API_33 [emulator-5554]'.
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
I/org.libsdl.app: Late-enabling -Xcheck:jni
W/org.libsdl.app: Unexpected CPU variant for x86: x86_64.
    Known variants: atom, sandybridge, silvermont, kabylake, default
V/studio.deploy: Startup agent attached to VM
V/studio.deploy: No existing instrumentation found. Loading instrumentation from instruments-6b5afa68.jar
W/org.libsdl.app: DexFile /data/data/org.libsdl.app/code_cache/.studio/instruments-6b5afa68.jar is in boot class path but is not in a known location
V/studio.deploy: Applying transforms with cached classes
W/re-initialized>: type=1400 audit(0.0:20): avc: granted { execute } for path="/data/data/org.libsdl.app/code_cache/startup_agents/69880af5-agent.so" dev="dm-33" ino=132297 scontext=u:r:untrusted_app_30:s0:c157,c256,c512,c768 tcontext=u:object_r:app_data_file:s0:c157,c256,c512,c768 tclass=file app=org.libsdl.app
W/org.libsdl.app: Redefining intrinsic method java.lang.Thread java.lang.Thread.currentThread(). This may cause the unexpected use of the original definition of java.lang.Thread java.lang.Thread.currentThread()in methods that have already been compiled.
W/org.libsdl.app: Redefining intrinsic method boolean java.lang.Thread.interrupted(). This may cause the unexpected use of the original definition of boolean java.lang.Thread.interrupted()in methods that have already been compiled.
D/CompatibilityChangeReporter: Compat change id reported: 171979766; UID 10157; state: ENABLED
W/ziparchive: Unable to open '/data/app/~~7S4oy0F9k9RCC7RxdU88nw==/org.libsdl.app-JwaJsoEnzdNR73XJkiM59w==/base.dm': No such file or directory
W/ziparchive: Unable to open '/data/app/~~7S4oy0F9k9RCC7RxdU88nw==/org.libsdl.app-JwaJsoEnzdNR73XJkiM59w==/base.dm': No such file or directory
V/GraphicsEnvironment: ANGLE Developer option for 'org.libsdl.app' set to: 'default'
V/GraphicsEnvironment: ANGLE GameManagerService for org.libsdl.app: false
V/GraphicsEnvironment: Neither updatable production driver nor prerelease driver is supported.
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: org.libsdl.app, PID: 3089
    java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{org.libsdl.app/org.libsdl.app.SDLActivity}: java.lang.ClassNotFoundException: Didn't find class "org.libsdl.app.SDLActivity" on path: DexPathList[[zip file "/data/app/~~7S4oy0F9k9RCC7RxdU88nw==/org.libsdl.app-JwaJsoEnzdNR73XJkiM59w==/base.apk"],nativeLibraryDirectories=[/data/app/~~7S4oy0F9k9RCC7RxdU88nw==/org.libsdl.app-JwaJsoEnzdNR73XJkiM59w==/lib/x86_64, /data/app/~~7S4oy0F9k9RCC7RxdU88nw==/org.libsdl.app-JwaJsoEnzdNR73XJkiM59w==/base.apk!/lib/x86_64, /system/lib64, /system_ext/lib64]]
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3582)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3813)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2308)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.app.ActivityThread.main(ActivityThread.java:7898)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "org.libsdl.app.SDLActivity" on path: DexPathList[[zip file "/data/app/~~7S4oy0F9k9RCC7RxdU88nw==/org.libsdl.app-JwaJsoEnzdNR73XJkiM59w==/base.apk"],nativeLibraryDirectories=[/data/app/~~7S4oy0F9k9RCC7RxdU88nw==/org.libsdl.app-JwaJsoEnzdNR73XJkiM59w==/lib/x86_64, /data/app/~~7S4oy0F9k9RCC7RxdU88nw==/org.libsdl.app-JwaJsoEnzdNR73XJkiM59w==/base.apk!/lib/x86_64, /system/lib64, /system_ext/lib64]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:259)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:95)
        at android.app.Instrumentation.newActivity(Instrumentation.java:1328)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3569)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3813) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2308) 
        at android.os.Handler.dispatchMessage(Handler.java:106) 
        at android.os.Looper.loopOnce(Looper.java:201) 
        at android.os.Looper.loop(Looper.java:288) 
        at android.app.ActivityThread.main(ActivityThread.java:7898) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936) 
D/libEGL: loaded /vendor/lib64/egl/libEGL_emulation.so
D/libEGL: loaded /vendor/lib64/egl/libGLESv1_CM_emulation.so
D/libEGL: loaded /vendor/lib64/egl/libGLESv2_emulation.so
W/System: A resource failed to call close. 

I suspect that we still need to add a Java class which you mentioned before.

@oleg-derevenetz
Copy link
Collaborator

@ihhub

I suspect that we still need to add a Java class which you mentioned before.

Yes, it seems so :) Try to add app/src/main/java/org/fheroes2/MainActivity.java with something like this:

package fheroes2.org;

import org.libsdl.app.SDLActivity;

public class MainActivity extends SDLActivity
{
}

And replace org.libsdl.app with org.fheroes2 and SDLActivity by MainActivity in the appropriate places in the app module (especially in the manifest).

@ihhub
Copy link
Owner Author

ihhub commented Oct 19, 2022

package org.fheroes2;

import org.libsdl.app.SDLActivity;

public class MainActivity extends SDLActivity
{
}

with changes needed within app leads to D:\17\app\src\main\java\org\fheroes2\MainActivity.java:3: error: package org.libsdl.app does not exist.

@oleg-derevenetz
Copy link
Collaborator

oleg-derevenetz commented Oct 19, 2022

@ihhub Try to add the following to the app module's build.gradle file:

dependencies {
    [...]
    implementation project(':sdl2')
}

@ihhub
Copy link
Owner Author

ihhub commented Oct 19, 2022

@ihhub Try to add the following to the app module's build.gradle file:

dependencies {
    [...]
    implementation project(':sdl2')
}
Build file 'D:\17\build.gradle' line: 11

A problem occurred evaluating root project '17'.
> Could not find method implementation() for arguments [project ':sdl2'] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.

@oleg-derevenetz
Copy link
Collaborator

Hi @ihhub Did you add this dependency to the android/app/build.gradle, not to the android/build.gradle?

@ihhub
Copy link
Owner Author

ihhub commented Oct 19, 2022

Hi @ihhub Did you add this dependency to the android/app/build.gradle, not to the android/build.gradle?

Oops, no, I didn't. My apologies. After changing it this errors occurs:

D:\17\app\src\main\AndroidManifest.xml Error:
	uses-sdk:minSdkVersion 16 cannot be smaller than version 19 declared in library [:sdl2] D:\17\sdl2\build\intermediates\merged_manifest\debug\AndroidManifest.xml as the library might be using APIs not available in 16
	Suggestion: use a compatible library with a minSdk of at most 16,
		or increase this project's minSdk version to at least 19,
		or use tools:overrideLibrary="org.libsdl.app" to force usage (may lead to runtime failures)

So to fix this I changed minSdkVersion 19 and

            ndkBuild {
                arguments "APP_PLATFORM=android-19"
                abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
            }

I am not sure that the last change is necessary. And now it works!

@oleg-derevenetz
Copy link
Collaborator

@ihhub NDK on linux-latest doesn't support SDK 16, the minimum supported version is SDK 19, so there is nothing surprising. Please update this PR when you have time, there is still a lot of work to do - for example, I'm sure that build.gradle can be severely minimized.

Does the sound work?

@ihhub
Copy link
Owner Author

ihhub commented Oct 19, 2022

Hi @oleg-derevenetz , the sound works as well as external music but no MIDI. I will make changes into this pull request.

@oleg-derevenetz
Copy link
Collaborator

oleg-derevenetz commented Oct 19, 2022

@ihhub

the sound works as well as external music but no MIDI.

Interesting, because SDL_mixer is built with the Tmidity library. Maybe Timidity needs some additional files?

P.S. Try to comment out the Music::SetMidiSoundFonts() call in the AudioInitializer's constructor.

@oleg-derevenetz
Copy link
Collaborator

Ah, there are also additional files needed for Timidity:

https://github.com/libsdl-org/SDL_mixer/blob/main/README.txt

I have no idea where they should be placed on Android.

@ihhub
Copy link
Owner Author

ihhub commented Oct 19, 2022

Ah, there are also additional files needed for Timidity:

https://github.com/libsdl-org/SDL_mixer/blob/main/README.txt

I have no idea where they should be placed on Android.

Let's fix MIDI issue in a separate pull request. I found more issues with it and it's easier to track all of them separately.

@ihhub
Copy link
Owner Author

ihhub commented Oct 19, 2022

Hi @oleg-derevenetz , could you please add manifest file to artifacts?

@oleg-derevenetz
Copy link
Collaborator

Hi @ihhub

could you please add manifest file to artifacts?

Done.

@oleg-derevenetz
Copy link
Collaborator

Hi @ihhub I performed the minor cleanup, made the build parallel (-j4) and removed 32-bit architectures from build, because this only slows down the build without any real profit - the vast majority of currently working devices are 64-bit.

@felix642
Copy link
Contributor

Hi @ihhub, I have built this branch on my Linux machine and everything went well! :)

I wanted to upload this project on an android device to ensure that it was correctly working and the app managed to boot up without any issues!

The only thing left for me to do is upload the required files to start the game on my android device. I'm not sure to know where I should upload them so that the android app could see them.

I know that savefile and config are currently stored in: /data/data/org.fheroes2/files
But I can't figure out where to upload the data, anim and sounds folder.

@ihhub
Copy link
Owner Author

ihhub commented Oct 20, 2022

Hi @felix642 , we are solving this in Discord :)

@ihhub ihhub marked this pull request as ready for review October 20, 2022 00:51
@ihhub
Copy link
Owner Author

ihhub commented Oct 20, 2022

Hi @oleg-derevenetz , thank for the changes! Do you have anything else to update in this pull request? If not we can proceed with merging.

Copy link
Collaborator

@oleg-derevenetz oleg-derevenetz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ihhub I have no new ideas so far :)

@sonarcloud
Copy link

sonarcloud bot commented Oct 20, 2022

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot E 2 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

@ihhub ihhub merged commit 34a3494 into master Oct 20, 2022
@ihhub ihhub deleted the andoir_studio_support branch October 20, 2022 01:53
@ihhub
Copy link
Owner Author

ihhub commented Oct 20, 2022

@oleg-derevenetz , thanks a lot for helping me with this pull request!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Android Android version of the engine improvement New feature, request or improvement script Things related to various scripts (utility scripts, CI scripts, etc)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants