adventuregamestudio / ags

AGS editor and engine source code
Other
697 stars 159 forks source link

Editor: Android build target #1337

Closed ivan-mogilko closed 2 years ago

ivan-mogilko commented 3 years ago

The suggestion is to implement game building and packaging for Android into the AGS Editor.

I do not have full knowledge of how properly packaged Android APK for single game is done, so give a general task overview, with intent to fill the gaps later as necessary.

Part 1: ensuring building by hand

  1. The required output is a signed APK containing single game.
  2. We have a single game APK template in the repository now, unless I'm mistaken it's here: https://github.com/adventuregamestudio/ags/tree/master/Android/mygame
  3. We should be assuming prebuilt native engine libraries for this, so that users don't have to build them themselves.
  4. Gather information of what steps are required in order to get from the compiled game data to the complete APK.
  5. As these steps would require tools (Android SDK and more), make list of what we may have to write ourselves, distribute with the Editor, and what we do not distribute and leave for users to download themselves.

NOTE: Ideally this feature should rely on as less downloaded utilities as possible. I.e. if it's possible to not download full Android Studio, but only its command line tools.

Part 2: integrating with IDE

After we have a list of things which make it possible to do by hand, we move to integrating with IDE.

  1. Building for Android may require setting additional things up. For these we may need a separate property list editor/panel. There was an Editor plugin created by monkey0506 several years ago, it is already in C#. If license allows we may use it directly, or use it as a reference to write our own (as plugin or as a part of the editor itself).
  2. Make a BuildTarget class for Android and make sure it appears in the list of possible targets in the project settings.
  3. Configure installer to have "Android build package" as an optional component, similar to the "Linux package". This package will include prebuilt native engine libraries and any extra tools we had to write.
  4. Adjust CI to let us package installer with this new component.
ericoporto commented 3 years ago

Godot docs for reference: https://docs.godotengine.org/en/stable/getting_started/workflow/export/exporting_for_android.html

The current gradle project is configured so it can leverage existing pre-built libraries of the engine and build without needing to rebuild the C/C++ files.

ivan-mogilko commented 3 years ago

The current gradle project is configured so it can leverage existing pre-built libraries of the engine and build without needing to rebuild the C/C++ files.

Right, I forgot to add, this building should be using prebuilt native engine libraries of course, similar to Linux target. We already have them uploaded for release.

ericoporto commented 3 years ago

There's an additional thing, I couldn't understand much yet, but the Android port has historically used obb files as the way to package the game files (mygame.ags, audio.vox, ...) in the APK or externally, but this was made due to the way Google Play worked it's limitation of 100MB maximum for an apk that required the files to be packaged separately.

If I understood their docs correctly by using the new way assets work there, I think this obb is not needed anymore. You either will be shipping a .aab, an Android App Bundle (APKs are no longer supported in Google Play), or you will be using a different store that doesn't have the apk size limits (the Amazon store).

So the obb packaging may not be relevant - just place the game files directly inside the asset directory when building. This requires some changes in the code.

ivan-mogilko commented 3 years ago

Are there any restrictions by Android system itself? Like, older versions of os can use only obb files, or something like that?

ericoporto commented 3 years ago

I don't think so, it doesn't seem to be connected to android itself, it's part of Play Core API, a library that comes with the sdk. I think previous OBB embedding was just done that way to easily test the behavior of mounting it without the need to send the OBB to Play Store. (the new way is theoretically simpler and reduce build steps, the catch is one needs to sit down with time to read the docs, delete the old code, and write the new code... )

Just to clarify, your phone will still download APKs, but now the one that builds this IS the Play Store. So it can generate a proper APK for your phone - like, it will figure your architecture and only download the binaries you need and remove the ones you don't, lowering download size. If you are using play asset delivery it will pull things from there too but the download of this piece may happen inside your app.

Edit: It appears that it's simply configuring PAD to use install-time asset pack and in this way it actually produces APK bigger than the limit that are accepted by the play store. I need to play with the bundletool a bit more, but if it's the case, it may be just building to AAB, which is already there in gradle, and simplify so it can load ags data files directly.

Edit2: we already implemented all the aab bundle and play core aasset stuff, so that part is done, now it's just placing the files in the proper place and calling gradle. Also some automation to install Android Studio would be nice.

ericoporto commented 2 years ago

I think first thing we need to do is to provide a source release of the Android mygame project including the runtime, and the libraries maybe already in place. This would unpack in an Android/ dir like the current Linux/ dir, containing the required files.

The file for the Editor dir would be this: Android.zip

We need a place to store the Android SDK configs (like, in which directory it is). We can just tell users how to install and later if we can provide it installable through our installer, but I don't think we need to do this right now.

Once we know where the SDK is, and we have the files, we need to

Once we have these mechanisms we can then make this better, like defaulting to .aab and have a togle for apk, and also selecting between game in the app itself or the asset pack - these will be fairly trivial since they are done by command line gradle commands.

Edit: I hid my previous comments since they were about things we already solved and are now outdated.

Edit2: It's like a gazillion files, does "GetRequiredLibraryPaths" in BuildTarget must return each individual filename?

Edit3: It will take a while, but I will be working here: https://github.com/ericoporto/ags/tree/feature-android-build

Edit4: I am going to put options in General Settings because we always add things there. :/

image

ivan-mogilko commented 2 years ago

Edit4: I am going to put options in General Settings because we always add things there. :/

About that, I was going to suggest to use a separate page, similar to how Default Setup is made: it is a separate class with properties, but based on the same parent class as the General Settings. Having Android settings on a distinct tab will hide it from people who do not need this, and keep General Settings actually "general". E: Also you won't have to prepend every property name with "Android", so it will be simply "Package Name" instead of "Android Package Name" and so on.

Furthermore, we may set a future rule to have separate pages per build target setup.

I never tried that before, but maybe it will be possible, and convenient, to have a folder in the project tree, called for example, "Build Setup" - on the place where "Default Setup" is found currently; and inside that folder there will be:

We may even move Windows-specific properties to its own page: there's this "Windows Game Explorer" category (on the other hand, maybe it's not needed anymore, as I heard that Microsoft does not support Game Explorer anymore? - in which case these could be deprecated).

ericoporto commented 2 years ago

I never tried that before, but maybe it will be possible, and convenient, to have a folder in the project tree

That would be perfect because then each system has its own properties that can be edited easily. And we can give obvious icons to each system under the tree :P

About the Android stuff I actually concluded that there's only package name as extra property. The build environment stuff I put in preferences - like, I don't want to config this once per game.

Hey, curious about one thing, currently when we build, we build every system. But like, the Android build process it... Takes a little longer - not that much after first run, but still. I was thinking if I need to do something to lead people to only turn on sometimes, or not. Like with Windows and Linux I usually tick both from the start of a game project and forget.

Also I am temporarily adding a new console pane to print Gradle build stuff. I don't trust it yet to live a life without log output. :O and I needed a place to put a button to call gradle stop in case something goes wrong.

ivan-mogilko commented 2 years ago

Hey, curious about one thing, currently when we build, we build every system. But like, the Android build process it... Takes a little longer - not that much after first run, but still. I was thinking if I need to do something to lead people to only turn on sometimes, or not. Like with Windows and Linux I usually tick both from the start of a game project and forget.

Ugh, yes, I am aware of this problem. This is something to think well about, perhaps separately when the build itself is implemented. But one thing I might mention, I was from the start not happy that this selection is located in the General Settings, as imo this is rather a "workspace" option, not a part of the project itself. And while people are testing the game, they normally need only the build for their os. Perhaps we may think in the direction of reimplementing this build selection differently, outside of General Settings. The dumbest idea is to have it in the Build menu; i.e. Build -> for X, for Y, for Z, or being able to configure a list of targets to build in a batch. But this is just thinking out loud for now.