I've spent the last few days struggling with getting a system up and running for building multiple configurations of our Android NDK App. I am able to build the libraries fine; the issues I run into usually stem from keeping those libraries up to date when changing build configurations.
I need a system that is for the most part fully automated: the user should just change build configurations and everything just works!
How have you addressed build configurations and the issues with libraries not being properly rebuilt?
I've tried a bunch of different approaches to this, but they all seem to end up with issues that are out of my hands.
Initially we just outputted a Shared Object file with the same name regardless of Build Configuration (eg. game.so). The problem is, changing build configurations doesn't trigger the library to be rebuilt; you have to make a change to the source or build scripts. So people change from Debug to Release, run the app, and are unknowingly actually linking to the Debug version still.
So then we tried outputting the library to a unique Shared Object based on the build configuration. For example, the debug version is gamed.so. The release version is gamer.so. The problem is, the Java code has no concept of build configuration, so how do we know which version of the library to load (which is done from Java)?
Well to get around that we do a try/catch looping through all the possible versions of the library attempting to load them. When we find the one that exists, load it! Problem being that the old versions of the library do not get removed when deploying a new configuration to the phone. So if you have built and run both Debug and Release, both of those libraries are now on the phone! Which ever one you ask for first, it will find and load.
So anyway, this seems like something that must have been solved already, but I have found very little information online. Nothing that has met my needs.
My question is: how have you addressed build configurations and the issues with libraries not being properly rebuilt?
This is actually strange. I have always seen that install -r refreshes the /data/data/app.pack.age/lib directory. Which device do you use for development?
Related
I have created a location-based game using the Mapbox SDK in Unity 2018.2.1f1, and it has been able to build just fine. My goal was to add database functionality to my project by using Firebase, to store GPS coordinates online.
I followed the official tutorial for setting up Firebase in a Unity project. When this was completed, a window popped up saying "Resolving Android Dependencies", which took about half an hour.
Since then, I have been unable to build to my Android device. I receive 96 gradle build error, and the one at the top is:
> No toolchains found in the NDK toolchains folder for ABI with prefix:
mips64el-linux-android"
I reverted the project to its pre-Firebase version, and it was still unable to build, as if something in the Android build tools had been changed.
Next, I tried an entirely different version of Unity, and installed a fresh install of Unity 2019.2.9f1. I opted to use this version of Unity's in-build Android SDK and NDK. I reverted my project back to the last known working version (pre-Firebase), ported it to the new version of Unity, and completed a successful build to my device before moving on.
Then I followed the appropriate steps to add Firebase to my project again, and the same exact pop-up windows appeared in Unity, claiming that it detected "obsolete files" that it wished to delete (this time I said no), and then it performed the same "Resolving Android Dependencies" process.
Once this process was complete, I made no other changes, and tried to build again. It failed, and I received the same 96 gradle build errors. This confirms this error as repeatable on two different versions of Unity.
I believe this has something to do with conflicting dependencies between Mapbox and Firebase. Has anyone encountered this issue, or successfully been able to use these two things together in a project?
So, the baseline problem is that something is telling the Android build process to generate project files for the MIPS architecture. This architecture was removed from the official NDK in r17 (see this link for supported architectures). I'm not sure if Unity ever supported it, but it's not in the current version:
I do not know how MapBox is packaged and shipped, so I don't exactly know what postprocessing hooks might be conflicting between that and Firebase. I'll try to give you some steps forward though.
First, make sure you have the latest SDK from Firebase and MapBox. Also, when it asks to delete obsolete files, say yes. The Play Services Resolver should only prompt this for files that it tracks (and the Firebase plugin ships in a state where this is expected).
If that doesn't help, look for a mips folder included in your Unity project (probably something like libs/mips or jnilibs/mips). Hopefully deleting these will fix the issue.
If the above doesn't work or is non-actionable, try using a mainTemplate.gradle file:
If you follow the instructions I wrote up here to instruct the Play Services Resolver to patch your mainTemplate.gradle file:
You can double check your ABI filters directly in the file. By default it shows:
ndk {
abiFilters **ABIFILTERS**
}
to match what you've selected in Unity. But you can use this to double check that mips64 isn't included via some other process.
Unfortunately I don't know what else to suggest if neither of the above options work. In that case I'd suggest posting a bit more of the error you're getting. If you can reproduce the error you're having with one of the Firebase sample projects, you can file an issue on that issue tracker directly. Finally, if you don't get an answer here and you do think that it's Firebase related, you can contact the Firebase support as well.
I hope something in my post helps!
--Patrick
I'm working on a Xamarin Forms app for Android and iOS. We use a third-party SDK that comes as an .aar package, build action set to LibraryProjectZip. Then, we have calls from the forms, the iOS, and the Android parts of the code. Linking works just fine in debug mode if I remember correctly.
I'm failing to get the Linker+ProGuard work together. I've read for days and experimented with numerous solutions. I was having java codes 1 and 2 - so I updated ProGuard and it started working. Then Linking was producing errors - UnauthorizedAccessException so I had to go to the respective folder and remove the ReadOnly permission. Then the project is built successfully but the app functionality is lost even though it runs and in Device Log I can see that some classes are missing.
To fix that, I created a ProGuard.cfg and added most of the assemblies that were crashing with the "-keep" command. However, I can't seem to find a way to preserve the functionality from this .aar package
Any suggestions?
I'm using VS 2017 and Xamarin 7.4 on Windows 10 with JDK 1.8, running as Administrator. Tried linking Sdk Assemblies / User&Sdk Assemblies. Multidex is on. I've tried putting the names of the assemblies of all the projects in the Skip Linking Assemblies field, no results. In the device log, I get a package name for the call that is failing so I tried adding this to ProGuard too but it didn't help. (it looked like "-keep class com.something.something")
I can't comment, but this blog post may be of use.
"The Linker Analyzer is a command line tool that analyzes dependencies which are recorded during the LinkAssemblies step. It will show you what items were marked and resulted in the linked assembly."
https://www.jon-douglas.com/2017/09/22/linker-analyzer/
I'm not too familiar with the Android build process, so I'm sorry if this comes off as a really stupid question.
Anyway, I'm writing testing code utilizing ActivityInstrumentationTestCase2 and Robotium for an Android application by the company I work for.
The company is rather large, so the transition to Gradle is going very slow. I would like to use Gradle for my testing project for ease and future maintainability, but right now the application I'm testing is built using a combination of ANT scripts and manual intervention with all dependencies checked in as jars in the repository. I'm not at all involved in that process, but I know it's pretty hacked together.
From what I understand, Gradle cannot simply depend on and trigger the building of another existing Android project unless that project also utilizes Gradle. So unless I want to really get my hands dirty with the build process of our application (we have people who are literally hired to only deal with that), I'm out of luck.
What I do have access to, however, are debug builds of our application.
So my question is, is there some way that I can have Gradle use the compiled debug APK as a local file dependency, or can APKs not work like that?
APKs don't work like that; you can't depend on them, for a variety of reasons. The most important reason is that the code and resources are processed and compressed and much of the original information needed to build them is lost at that point.
You'll have a tough time getting it to work properly. If things that you depend on are pure Java libraries, then if you could get them in JAR format you could depend on them from a Gradle project pretty easily. But if they're Android projects containing resources and manifest entries and such, then there isn't a compiled file format you could obtain those libraries in that would be compatible with Gradle. Gradle supports the AAR format for Android libraries, but that format is generated by Gradle and nothing else.
I'm slowly starting to port my existing apps to Android Studio and Gradle. I have a few questions about it though before I get too far.
Is it possible to build a signed apk outside of Android Studio, from a command line, like you can with ant.
Is it possible to build a signed apk for every variant all in one go, again outside of the UI.
Finally, this is a situation that won't affect many people, but is there a limit on the number of variants you can realistically have. I am probably looking at having between 2000-4000 separate variants. Is this going to be a complete no go?
yes
yes
hmm that's quite a lot. I think there are going to be issues. For instance right now Gradle doesn't let us parallelise the compilation of the variants, so it's going to take forever to build. Also, you might run out of RAM when setting up the internal model that represent all the variants and their associated properties and tasks.
I guess you should just try it and see. Using simple groovy code you should be able to dynamically create 2000 flavors in an empty projects and then see if you can compile without problem.
I'm currently working on a large Android app using a massive amount of C++ code.
It compiles and runs, so far so good.
Unfortunately, every time I modify something in the structure of my native source (add/delete/rename/move a file), which happens pretty often, ndk-build rebuilds the whole source, even the untouched files.
Does anyone know how I can set up the Android NDK to build incrementally somehow?
Thanks in advance
I got fed up with the NDK build system, studied it for a bit, and wrote my own makefiles. This was not hard.
However, it was then pointed out to me that by doing this, I would have to take responsibility for tracking future changes to the platform, for example if it becomes necessary to ship binaries for additional processor types, I'd have to modify my homegrown build solution to do that too.
In other contexts, I've sometimes had projects with two build systems - one for quick experiments, another for deployable builds. The time spent updating both now and then was saved many times in the speed gain for daily work. Provided I had to do a real build at least every week or two, things never got very far out of consistency (and both build scripts were in the revision control system, so there was history to examine). Something like this could be done with a custom makefile for debug builds and still using the NDK build system for deployable packages.
(In one case of doing a lot of experiments at the edge of what the platform permits, I actually had my makefile pushing the updated .so onto the device and gave my application one of the discouraged hard-quit buttons, so I could restart it using an updated native library without even having to rebuild and reinstall the apk)