Workaround for Unable to load native library: libnative-activity.so
So, another bug I had to deal with NativeActivity and for which I have no clear solution but a workaround for.
The problem
I compiled a version of libnative-activity.so that depends on my own library, libmyy.so, in order to add more flexibility during the testing process.
However, when trying to load the app, the app crashed with the following error :
05-23 22:59:00.650: E/AndroidRuntime(4758): Caused by: java.lang.IllegalArgumentException: Unable to load native library: /data/app-lib/my.pack.name-2/libnative-activity.so
The workaround
- Create a java class that subclasses
android.app.NativeActivity
and load the libnative-activity.so library withSystem.loadLibrary
, in a static initialiser. - Edit AndroidManifest.xml to use this library, and remember to set
android:hasCode
totrue
in thetag.
Example
Here the java class will be called NativeDebug
app/src/main/java/my/pack/name/NativeDebug.java
package my.pack.name;
import android.app.NativeActivity;
public class NativeDebug extends NativeActivity {
static { System.loadLibrary("native-activity"); }
}
app/src/main/AndroidManifest.xml
<!-- The package name is generally set up by gradle. It is not very important here-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="my.pack.name">
<!-- Actually this .apk Java has code ! Set hasCode to true. Else your NativeDebug
class will not be inserted in the final apk and your app will crash failing to find it. -->
<application
android:allowBackup="false"
android:fullBackupContent="false"
android:icon="@mipmap/ic_launcher"
android:label="AppName"
android:hasCode="true">
<!-- Our activity is the built-in NativeActivity framework class.
This will take care of integrating with our NDK code. -->
<activity android:name=".NativeDebug"
android:configChanges="orientation|keyboardHidden">
<!-- Tell NativeActivity the name of or .so -->
<meta-data android:name="android.app.lib_name"
android:value="native-activity" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Note that this AndroidManifest.xml is based on the one provided with the NDK sample named native-activity.
Then install the new app (./gradlew installDebug
or Android Studio ▶ button) and try your application.
In my case, it worked ! The library was loaded, my library was loaded too in the process, and the native code in my library was executed !
I still do not understand why NativeActivity.java tries to load libraries with a native C++ method named loadNativeCode
. However, I do understand that loadNativeCode
returns 0 when trying to load my libnative-activity.so file and NativeActivity
in return throws an exception, with no hint about the problem whatsoever. A slightly more useful exception message seems to have been added now, though…
In the case that System.loadLibrary
fails to load the library, your app will still crash but with a nice and helpful error message that you can use to solve the problem, this time.