2

I would like to know how to build my APK so that my libraries are installed/copied under /data/data/<package name>/lib when installing the APK.

  • I am using Android Studio 4.0.1

  • I build an APK and confirm when I extract it that I have a lib/arm64-v8a folder that contains my jni libs.

  • I want that after I install my APK, some other applications on the same device can access the libs that I have in the lib/arm64-v8a. The /data/data/<package name> folder seems to be the right place for this, hence my question; if there is another approach for making my libraries accessible on device, I am open to it.

  • I set android.bundle.enableUncompressedNativeLibs=false in my gradle.properties file based on this discussion even though I didn't see any effect using it with true or false.

  • I set android:extractNativeLibs="true" in my Manifest

However, when I adb install my apk, the /data/data/<package name>/ folder on my device only contains a cache and code_cache folder, both of which are empty.

I do see under /data/app/ a folder with my libraries but they include strings that are randomly set each time I install the APK:

/data/app/~~sFE8-eNknFAkhKJ-1S03lg==/<package name>-rsDLNgpi4vult7yVBrPNOQ==/
   base.apk
   lib/arm64/
       <my .so in there>

These random strings prevent me from accessing reliably my libraries from any other application. (If there is a way to not have these random strings as part of the name and /data/app is the recommended location for my libraries to be shared with other applications, I am interested in that alternate approach.)

I have also installed other prebuilt APK and with these, I do see the libraries under /data/data/<package name>/lib like I want. This to me indicates that my issue is related to how I build my APK with AS 4.0.1, not to my device, its Android version, or how I install the APK.

Here is my gradle file:

import java.util.regex.Matcher
import java.util.regex.Pattern

apply plugin: 'com.android.application'

android {


    compileSdkVersion 30
    buildToolsVersion "30.0.2"

    lintOptions {
        checkReleaseBuilds false
        abortOnError false
    }

    sourceSets.main {
        jniLibs.srcDirs = ['libs']
        jni.srcDirs = []
    }

    defaultConfig {
        applicationId "com.example.myexample"
        minSdkVersion 16
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                version "3.17.0"
                cppFlags ""
                arguments "-DANDROID_STL=c++_shared"
            }
        }
        ndk {
            moduleName "myexample"
            abiFilter "arm64-v8a"
            ldLibs "log"
        }
        packagingOptions {
            exclude "lib/arm64-v8a/libassets.so"
        }

    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            version "3.17.0"
            path "src/main/cpp/CMakeLists.txt"
            // There can be only one CMAKE per project: https://developer.android.com/studio/projects/gradle-external-native-builds
        }
    }
}


task copyFiles(type: Copy) {
    description = 'Testing a manual copy operation (confirmed it works)...'
    from file("../dsp/external/ship/libmyexample_skel.so")
    into file("$buildDir/res/raw/")
}

project.afterEvaluate {
    preBuild.dependsOn copyFiles
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

}

Something else I tried: I created manually a src/main/jniLibs.arm64-v8a folder in which I place a .so. That .so appears in the my apk when I extract it, but my /data/data/<package name>/ folder doesn't have a lib nevertheless.

Lolo
  • 3,935
  • 5
  • 40
  • 50
  • do you want to copy the lib into your app or you just want to call functions from this lib? – Priyanka Dec 29 '20 at 12:32
  • @Priyankagb I need to know where the lib is on the file system. As part of the JNI code I use in my app, I need to dlopen my library and for this I need to know its path on the device. – Lolo Dec 30 '20 at 10:00

1 Answers1

1

I think you need to add this code to add libs in the appropriate folder like /data/data/<package name>/lib

add this to app's build.gradle file into android{} tag

sourceSets.main {
    jniLibs.srcDirs = ['libs']
    jni.srcDirs = []
}

this to CMakeList.txt file

cmake_minimum_required(VERSION 3.4.1)


find_library( # Sets the name of the path variable.
        log-lib
        log)

set(distribution_DIR ${CMAKE_SOURCE_DIR}/libs)


add_library(yourLibName
        SHARED
        ...//list of your c/c++ files here from jni folder
)

target_link_libraries(yourLibName ${log-lib})

as per developer.android.com

Note: When making changes to the Gradle configuration, make sure to apply your changes by clicking Sync Project in the toolbar. Additionally, when making changes to your CMake or ndk-build script file after you have already linked it to Gradle, you should sync Android Studio with your changes by selecting Build > Refresh Linked C++ Projects from the menu bar.

Priyanka
  • 3,369
  • 1
  • 10
  • 33
  • I added the sourceSets to build.gradle, which I didn't have. And I added the set of distribution_DIR I was missing from CMakeList.txt. The rest I had already. Still no lib folder under /data/data/ – Lolo Dec 30 '20 at 16:15
  • please post your build.gradle file – Priyanka Dec 31 '20 at 04:04
  • I added the build.gradle file and some more info. – Lolo Jan 05 '21 at 12:10
  • remove ndk {} if you are using cmake – Priyanka Jan 05 '21 at 12:23
  • This causes some linking errors for symbols needed in my jni code, but more importantly why would this be relevant to my current issue? All my code builds correctly and the APK does include a lib folder with all the .so I would like exposed. It's really the last step of APK install that doesn't behave as I expect. – Lolo Jan 06 '21 at 10:52
  • ohk, than let it be – Priyanka Jan 06 '21 at 10:58
  • Any other thoughts/suggestions? – Lolo Jan 08 '21 at 13:28
  • no, can't say where is the exact issue :( – Priyanka Jan 10 '21 at 07:03
  • Can we perhaps approach this differently? Is it easy enough for you to list the minimum number of steps you follow to start an AS C++ native project from scratch so that when you adb install the apk, a lib folder containing the .so is present under /data/data/? I just tried with a 'com.example.test' project and still only see a cache and code_cache folder under /data/data/com.example.test. Same with all the settings documented in this SO question. – Lolo Jan 12 '21 at 10:49
  • see this demo I have created https://github.com/priyankagb/NDKCrashlyticsDemo. run this demo and you will find .so files under /data/data/pkgname/lib folder. if you get error while running update firebase libs – Priyanka Jan 12 '21 at 12:28
  • wait, I got the same result in iBall device. the so files are stored in data/app/ folder. But in the emulator, it is working fine – Priyanka Jan 12 '21 at 12:39
  • but in vivo, the lib folder is nither located in /data/app/ nor in /data/data/ – Priyanka Jan 12 '21 at 12:44
  • So what you observe is that my issue is device-specific. What is strange is that I do have some APKs that I install on the same device and that have a lib folder under /data/data/ folder. I do not know why the name of the folders under /data/app are mangled. If they weren't, that would resolve my issue... – Lolo Jan 12 '21 at 13:29
  • I can't found any solution on this issue but i found this https://stackoverflow.com/a/47351428/10989990. here you can get native lib path – Priyanka Jan 13 '21 at 07:17
  • 1
    Yes, this is also the solution I arrived at after interacting on this question: https://stackoverflow.com/questions/65683441/missing-step-to-create-a-new-as-project-and-get-a-lib-folder-populated-on-my-dev This works for me. It seems that why an APK may on some occasions install the lib folder under /data/data/ and not on others will remain a mystery. It might have to do with the version of AS being used because I really tried many other things. – Lolo Jan 13 '21 at 15:06