I've compiled ffmpeg library for usage in my Android apps, so now I have *.so files and I want to use them in other Android projects.
But I've compiled them in Linux and now I am going to work in Windows. Can I just put these compiled files to my project in Windows link them in mk file and use? Does difference between 32 and 64 bit OS play role?
Thanks!
As long as your target android platform is the same, it should work.
The .so file generated by Android NDK compiler is native code of the target android platform.
It is just packed into the APK intact, so the OS you use to pack the APK doesn't affect the outcome.
EDIT:
As a commenter suggested, by target platform I meant CPU architectures like ARM, x86 or MIPS
As to the API level, neither targetSdkVersion nor minSdkVersion doesn't directly affect the native code.
Rather, your code may fail at runtime, if you use higher level API than is available on the actual Android device.
To avoid this safely, you need to set your minSdkVersion according to the NDK API level which was assumed when compiling your .so file.
In other words, files under "<your-ndk-dir>/platforms/android-<NDK-API-level>/arch-<CPU type>/usr/..." should have been looked up by the NDK compiler when you compiled your native code. Identify which level was used, and make sure you have equal or greater number as minSdkVersion.
If you have NDK installed, it's documented in "<your-ndk-dir>/docs/STABLE-APIS.html".
Related
My Android app includes a set of executables that are extracted to app directory (/data/data/%package%/) on the first run. It worked just fine if targeted to Android 28 (targetSdkVersion). Since November 2, 2020 it not allowed in Google Play and all the apps must target to 29. So it stopped working with permission exception.
What directory should executables be put to now?
PS. Some similar apps have the same issue.
https://developer.android.com/about/versions/10/behavior-changes-10#execute-permission
When targeting API 29 (Android 10 / Q) or above, it is not possible anymore to have execute permission for files stored within the app's home directory (data), which is exactly what you are describing (/data/data/%package%/).
This Android 10 modification was introduced in commit: https://android-review.googlesource.com/c/platform/system/sepolicy/+/804149 and was then confirmed officially by Google here: https://issuetracker.google.com/issues/128554619
This significant change is being discussed by various projects, in termux/termux-app#1072 for instance. One recommended and (hopefully) future-proof way is to extract program binaries into the application's native lib directory (with android:extractNativeLibs=true), where files can still be executed but are stored read-only for improved security.
Here are examples showing how to handle this change, in Termux with commit f6c3b6f in the android-10 branch or in this other project showing how to run the Erlang runtime on Android by exctrating all the files from a .zip archive into the jniLibs/"abi" subdirectory ("abi" being arm64-v8a for 64-bit ARM, armeabi-v7a for 32-bit ARM, etc.) with the imposed lib___.so filename format expected by the Android platform. Executable files can simply be moved in the right project folder manually, the important part is to use the lib___.so format for the filenames.
In the Android Manifest file, setting the attribute android:extractNativeLibs="true" will get these lib___.so files extracted at installation time in the right native lib directory, with support for execute permission. Symlinks can finally be created if needed in the usual app directory to use the regular executable names, instead of the harder-to-manipulate lib___.so versions.
Thanks, Jérôme
According to the source and wiki, Titanium requires r9 of the Android NDK. But in the Android archives, the oldest version available is r10e (May 2015). The current version is r14b.
With r14b (and r13b) I get compilation failures from ndk-build involving a C++ type mismatch.
[ERROR] /Users/jdee/Library/Application Support/Titanium/mobilesdk/osx/6.1.0.GA/android/native/include/AndroidUtil.h:57:49: warning: format specifies type 'int' but the argument has type 'long' [-Wformat]
I can compile a module cleanly using r10e, r11c and r12b, but I'm hesitant to release something with an unsupported NDK version. It seems strange that Titanium requires a version of NDK from 2014 as well. I'm not sure which version to use.
As of today, the same wiki page speaks of NDK r12, which can be downloaded from the official archive. The drawbacks of using an older NDK are, outweighed by the risks of relying on tiny nuances of compiler compatibility. It would require exhaustive testing on a wide range of supported devices to prove that your build with NDK r16 is OK. And note that upgrading NDK requires some fixes, see https://github.com/appcelerator/titanium_mobile/pull/9926.
As long as you don't need the native APIs that are specific for Oreo and higher, you can use r12 without fear.
If your project involves other NDK components that cannot be built with NDK r12, please remember that you can mix shared libraries built separately (with different NDK versions) in one app, as long as they do not share C++ objects between them. Titanium v8 framework is safe is this sense.
One point of weakness here is the shared STL runtime libc++_shared.so. You cannot have two different versions of it in your app. Probably the safest solution for such situation is to change the Titanium Application.mk file to use
APP_STL := c++_static
Short question:
I'm trying to build an app that has a JNI dependency, using Eclipse ADT and NDK r10e (the current version). The JNI dependency (apparently) builds a binary to run on the build host, using build-host-executable.mk from the NDK. However, that script seems to have been removed in recent NDK versions. What do I do?
Long question:
The JNI dependency is platform/external/srec from AOSP, which comes with an Android.mk file (actually, several of them).
I have set up Eclipse to build the native parts according to the instructions here, and copied the JNI code tree into the jni directory of my app's source tree. Additionally, I had to edit jni/Android.mk, adding the following line:
export TARGET_BUILD_TYPE := debug
which, as I understand it, would be set by the AOSP toolchain but is not set when building from Eclipse.
However, I get the following error:
android-ndk-r10e/build/core/build-host-executable.mk: No such file or directory
This is caused by a line in one of my Android.mk files:
include $(BUILD_HOST_EXECUTABLE)
The NDK defines BUILD_HOST_EXECUTABLE in build/core/build-all.mk:
BUILD_HOST_EXECUTABLE := $(BUILD_SYSTEM)/build-host-executable.mk
However, build_host_executable.mk is absent from the build/core directory (and so are the other build-host-*.mk scripts declared in the surrounding lines).
Googling around a bit, I find that this script seems to have been present in earlier NDK versions (up to at least NDK r7 r7b) but seems to be absent from later versions (possibly since r10b). The JNI lib was used by the (now abandoned) Voice Dial app. It had its last commit in December 2014, though the last real code change might have been in June 2014. AOSP had stopped building it by June 2015. Comparing this with the NDK release history, it might never have been built against NDK versions later than r9d or maybe r10.
The NDK r7b I found appears to be a patched version to which host target support added, see also https://github.com/flyskywhy/android-ndk-host. Looks like support for this was planned in NDK and some stubs added, but it was never fully implemented. That gives me the choice of either building the host stuff with the local toolchain, or patching NDK r10e to add host target support.
On the other hand, this package has been part of AOSP for a while (Cyanogenmod included it until KitKat and dropped it in Lollipop), therefore the AOSP toolchain must have been capable of building it. Any pointers to that toolchain? Maybe it's possible to extract the relevant parts from the AOSP toolchain and add them to the package.
The JNI dependency in question is taken from the AOSP code tree. The toolchain used by AOSP is different from NDK, though both are built around a set of GNU make macros. The format for Android.mk (their makefile equivalent) is intentionally similar between both, so that in many cases a project can be built with either toolchain.
One case for which this will not work is host targets, i.e. building binaries (executables or libraries) intended to run on the build host rather than on the Android device. The AOSP toolchain has this kind of support but the NDK doesn't. Confusingly, the NDK does have some stubs for that functionality (including definitions for BUILD_HOST_EXECUTABLE and similar) but the implementation is missing.
There are three options. Be aware that the package you are building may depend on other packages from the AOSP source code, which you would need to build as well.
Build the native code (or the host targets) using the AOSP toolchain, as described in this answer. This approach is most likely to be successful, as this is the toolchain for which the package was designed. It requires at least the packages containing the build tools, which are several gigabytes in size. You can get the entire AOSP source code as described here, which should give you all the dependencies you need, but this will download some 50 gigabytes (!) of data.
There is a patched version of NDK which adds support for host targets here (or just the make macros here). However, it is based on the now-outdated NDK r7b and had its last commit sometime in 2012 – you'll be working with a toolchain that is somewhat exotic and no longer maintained. Also, you'll need to determine your dependencies manually by examining the package.
Ditch the Android.mk files that build the host targets and build these with a regular GNU toolchain. An introduction to that can be found here. You can amend a higher-level Android.mk to invoke the "other" toolchain for your host targets, so you can automate the whole build. All of this may be a lot of work if the Android.mk content is very complex, but it is a one-time effort, after which your code will build with standard toolchains. As with the previous approach, you'll need to determine your dependencies manually. Dependencies which are required for the host target may be easier, though, if they are standard libraries which were ported to Android, as there may be an upstream version designed to be built with the GNU toolchain.
I have some libraries that use native components, the libraries are built with NDK for 32 bit Arm architectures.
now we have 64-bit processors on modern devices, so I'm wondering if the libraries will work. In my situation, I don't have the source code files of the native library, just the SO files, I can't build them for 64-bits.
So will the 32-bits libraries run on 64-bits processors? or I have to re-build them?
**
EDIT
**
In my scenario I have the following:
1- I distribute the APK manually, didn't publish to Google Play yet.
2- The project has two native libraries, one with 64 & 32-bits support and the other with 32-bits only.
Is there a way to make the application work on 64-bits devices without having to publish to Google Play for now? can I remove the 64-bits libs to enforce the package manger to load the 32-bits ones?
The 32 bits libraries will work just fine on 64 bits processors.
As long as the libraries get installed the right/official way (i.e., not manually downloaded or extracted from some nonstandard part in the APK, but packaged properly in the APK), the package manager will detect that the process uses 32 bit libraries, and the process should be started in 32 bit mode. If not, the process will be started in 64 bit mode, and later will be unable to load 32 bit libraries. (If your APK would contain some .so files, but not all, in 64 bit mode, it would only install them, and the process would be launched in 64 bit mode. So unless all .so files are available for a specific ABI, don't include any of them).
So if you have a 64 bit version of one of the native libraries, just remove that and only ship the 32 bit version, until you have 64 bit versions of all of them.
I am currently in the process of updating our project OpenSSL to 1.0.1i using http://wiki.openssl.org/index.php/Android.
Looking in the config file I found that OpenSSL has 2 Android build options: android-armv7 and android-x86.
I have been able to build the armv7 configuration and it appears to be working correctly on a Nexus 5 and a Kindle Fire 1st Gen.
What I am wondering is would my current library work if it were in the armeabi directory instead of the armeabi-v7a directory? I was not able to find sufficient information as to whether it matters if the OpenSSL is built with armv7 but my project libraries are built with older arm in mind.
Note: My minimum API level is 8.
What I am wondering is would my current library work if it were in the armeabi directory instead of the armeabi-v7a directory?
I think there are a couple questions here. First, can you put libssl and libcrypto in armeabi/. That's an Android question (not an OpenSSL question). I seem to recall Brian talking about this on the NDK mailing list (but I can't find it at the moment). I believe the idea is armeabi/ is a fallback if a more specific library is not found in, for example, armeabi-v7a/.
Second is, can you run ARMv7a version of libssl and libcrypto on other platforms. I believe ARMv7a added a few hypervisor extensions over ARMv7, so you should be OK since OpenSSL does not use them. However, you might find yourself in trouble if running on an older device with ARMv6 or ARMv5.
In this case, you might want to download an older version of the Android NDK that builds for ARMv5, and then place ARMv5 version of libssl and libcrypto in armeabi/. You can find older versions of the NDK at Android NDK about a third of the way down the page.
To be more specific, Android 2.2 is API 8, and it was released around May 2010. So you might want to fetch and build with Android NDK Revision 3 from March 2010. NDK R3 only supported armeabi and targeted ARMv5TE (from the CPU-ARCH-ABIS.TXT file). The download is http://dl.google.com/android/ndk/android-ndk-r3-linux-x86.zip.
OpenSSL does not follow the instructions at Standalone Toolchain for ARMv7a. Its missing the -mfloat-abi=softfp flag. You might have trouble calling a function that passes a float to the library from Java. There are not many of them, but one is RAND_add. The entropy estimate is passed as a float and after the incompatibility, your estimate will likely be 0.0f. See Hard-float and JNI on the NDK mailing list and [Bug #3080]: Android NEON and CFLAGS options.
Here's a note from the README's that you should also be aware of:
III.3. Automatic extraction of native code at install time:
-----------------------------------------------------------
When installing an application, the package manager service will scan
the .apk and look for any shared library of the form:
lib/<abi>/lib<name>.so
If one is found, then it is copied under $APPDIR/lib/lib<name>.so,
where $APPDIR corresponds to the application's specific data directory.
If you update the APK and nothing changes, then be sure to delete anything under lib\ or delte the APK first (they have a tendency to become "sticky").
Another issue you will likely encounter is building and compiling against 1.0.1. Be sure you provide a wrapper shared object with a different name. Otherwise, you will likely link against 0.9.8 at runtime, and not the 1.0.1 gear in your APK. That's because Zygote loads Android's version of OpenSSL, and that version is 0.9.8. Later, when Zygote forks to create your process, the link-loader will not map-in your version of OpenSSL because its already present from Zygote.
OpenSSL has 2 Android build options: android-armv7 and android-x86
I added android-x86 to the script in June 2014. I was able to get through the build with one patch: [Bug #3398] PATCH: fix broken compile on android-x86 with no-comp configure option. I don't have an x86 Android device, so I was not able to run the self tests on a device. Feedback is welcomed.