Android Studio如何同NDK集成

原文: http://ph0b.com/android-studio-gradle-and-ndk-integration/

将native库(.so文件)集成到你的APK包

以前的方法是把.so放到.jar包里, 现在很简单了

在 src/main/ 目录下(该目录下有 java和res两个子目录), 创建一个 jniLibs 目录
再创建相应ABI子目录(如 x86, mips, armeabi-v7a, armeabi)
最后,把相应的so文件放入对应的目录即可
build时,所有的.so文件都会被集成到你的apk里


如果jniLibs这个目录不适合你(你可能生成你的.so文件放在其他地方), 你可以在build.gradle里指定位置

android {
    ...
    sourceSets.main {
        jniLibs.srcDir 'src/main/libs'
    }
}

是在 模块目录下的 build.gradle里, 工程目录下的build.gradle里没有android {] 这个条目


有洁癖的人,喜欢为每个架构单独生成一个APK,这样, APK的体积会比较小

那就可以使用abiFilter这个属性, 这个属性默认是设置为 all, 将所有平台的.so都打包进apk

也是在build.gradle的android条目下添加一些东西

android{
  ...
  productFlavors {
        x86 {
            ndk {
                abiFilter "x86"
            }
        }
        mips {
            ndk {
                abiFilter "mips"
            }
        }
        armv7 {
            ndk {
                abiFilter "armeabi-v7a"
            }
        }
        arm {
            ndk {
                abiFilter "armeabi"
            }
        }
        fat
    }
}

为不同的架构设置不同的版本号(方便google play store上架)

import java.util.regex.Pattern
 
android {
    ...
    defaultConfig{
        versionCode getVersionCodeFromManifest()
    }
    ...
    productFlavors {
        x86 {
            versionCode Integer.parseInt("6" + defaultConfig.versionCode)
            ndk {
                abiFilter "x86"
            }
        }
        mips {
            versionCode Integer.parseInt("4" + defaultConfig.versionCode)
            ndk {
                abiFilter "mips"
            }
        }
        armv7 {
            versionCode Integer.parseInt("2" + defaultConfig.versionCode)
            ndk {
                abiFilter "armeabi-v7a"
            }
        }
        arm {
            versionCode Integer.parseInt("1" + defaultConfig.versionCode)
            ndk {
                abiFilter "armeabi"
            }
        }
        fat
    }


}
 
def getVersionCodeFromManifest() {
    def manifestFile = file(android.sourceSets.main.manifest.srcFile)
    def pattern = Pattern.compile("versionCode=\"(\\d+)\"")
    def matcher = pattern.matcher(manifestFile.getText())
    matcher.find()
    return Integer.parseInt(matcher.group(1))
}


决定是否调用ndk-build
如果在你的工程目录下面有jni/目录, 那么build系统将会试图 调用 ndk-build来自动生成.so文件
当前的实现是: 忽略你jni目录下的Android.mk这个makefile,然后自动创建一个新的
对于简单的工程来说,这真是太方便了(你根本就不需要自己创建*mk文件)
但是对于大工程来说,这就有点令人烦恼了, 因为你需要Makefile提供的所有功能. 你可以在build.gradle文件里禁止

android{
    ...
    sourceSets.main.jni.srcDirs = [] //disable automatic ndk-build call
}

参考资料

http://www.flakor.cn/2014-02-07-198.html

http://www.nsdev.org/blog/2014/01/01/including-native-libraries-in-your-apk

http://stackoverflow.com/questions/21096819/jni-and-gradle-in-android-studio

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s