Including OpenCV native library headers in Android Studio - opencv

I can't get my C code using native OpenCV to work in Android Studio. OpenCV through the Java wrappers work, but I have been banging my head against this for the last couple of days trying to get it to work with the native libraries. (I have some C code that depends on OpenCV that I need to use in my project)
To pin down the problem I'm trying to get the tutorial-2-mixedprocessing OpenCV sample project to build in AS.
OpenCV is in a separate module in the project, with the shared libraries (.so, .a files) in jniLibs, and the headers are in jni. The application module has a dependency on it. See the image below for the sample code and result when building.
Apparently the headers are not found?
I have tried adding the -I flag to CFlags in android.ndk in the gradle file with no success:
CFlags.add("-I${file("path/to/opencv-android-sdk/native/jni/include/")}".toString())
I have also tried placing the headers in the app module jni folder, as well as using different versions of Android Studio and Gradle.
I keep finding outdated solutions and conflicting information online, it seems like the build system in Android Studio is still changing a lot between versions. I'm also new to both Android development and NDK, so apologies if this is a stupid question. All I really need is a working sample that I can adapt to my project.
What am I missing?
Project structure:
Project gradle:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle-experimental:0.7.2'
}
}
allprojects {
repositories {
jcenter()
}
}
OpenCV library module gradle:
apply plugin: 'com.android.model.library'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
defaultConfig {
minSdkVersion.apiLevel = 21
targetSdkVersion.apiLevel = 23
}
buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file('proguard-rules.txt'))
}
}
}
}
Application module gradle:
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.2"
defaultConfig {
applicationId = "org.opencv.samples.tutorial2"
minSdkVersion.apiLevel = 21
targetSdkVersion.apiLevel = 23
}
ndk {
moduleName = "mixed_sample"
//CFlags.add("-I${file("path/to/opencv-android-sdk/native/jni/include/")}".toString())
}
buildTypes {
release {
minifyEnabled = false
proguardFiles.add(file('proguard-rules.txt'))
}
}
}
}
dependencies {
compile project(':openCVLibrary2411')
}

Related

Aar containing string resources aren't visible in a jetpack compose project

I'm having an issue with an aar in a jetpack compose project.
I've created a library which contains all the string resources I'm using in multiple projects. In my old java/kotlin projects there is no issue and I can implement the library and reach the strings. But when I do this in my new jetpack compose project it loads the aar but when in code I do R.string. I don't see the specific strings.
Also when I add some kotlin classes with functions in the library, these functions can be accessed. This way I'm 100% sure the library is loaded.
Is there a way to solve this?
The android manifest for the library looks like:
<manifest package="com.test.library"/>
The build.gradle:
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdk 31
defaultConfig {
minSdk 21
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
android.libraryVariants.all { variant ->
def debug = ""
if (variant.name == "debug") {
debug = "-debug"
}
variant.outputs.all {
outputFileName = "TestLibrary" + debug + ".aar"
}
}
}
}
}
dependencies {
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.0'
implementation 'com.google.android.material:material:1.4.0'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
In my jetpack compose project I implement it with the following call:
implementation files('libs/TestLibrary.aar')
How can I solve this? Is there somebody with the same issue (and a solution)?
Kind regards,
Jeroen
I also have been struggling with this for a while and I believe I found what causes this issue.
Your jetpack compose project should have a new entry in its gradle.properties file. The entry should look like this:
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
If you change this value to false your project should be able to find the string resources declared in your library. As the description shows.
So your new entry will look like this:
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=false
Hope this helps!

TrustWalletCore/WalletCore pod in Kotlin Multiplatform - almost no classes

In our Kotlin Mobile Multiplatform project for iOS and Android, we're trying to access TrustWalletCore cocoapod from Kotlin.
// build.gradle.kts (:shared)
cocoapods {
version = "1.0"
podfile = project.file("../iosApp/Podfile")
pod("WalletCore")
}
And the Podfile is
target 'iosApp' do
pod 'TrustWalletCore'
end
This successfully enables import cocoapods.WalletCore.* in shared/iosMain - without the above cocoapods {...} the import is unavailable.
However, only a Crypto class is available from this package (and CryptoMeta which doesn't look too different).
By the looks of it, it's generated from the Pod/library by commonizer in 0_WalletCore.knm (about 15 expect functions in total - a couple here for illustration):
#kotlin.commonizer.ObjCCallable public open external expect fun base58Encode(data: platform.Foundation.NSData): kotlin.String { /* compiled code */ }
#kotlin.commonizer.ObjCCallable public open external expect fun generateMnemonicFromSeed(seed: platform.Foundation.NSData): kotlin.String { /* compiled code */ }
It has mnemonic-related functionality, as well as signHash/verifySignature but not much else.
I was hoping to see - available to import in Kotlin - classes like HDWallet, EthereumSigningInput etc.
I can use these library classes in Swift, via pod TrustWalletCore in Xcode (import WalletCore).
WHY can I not get a similar/full set of classes via native.cocoapods plugin?
Try to declare dependency with moduleName parameter:
kotlin {
cocoapods {
...
pod(name = "TrustWalletCore", version = "3.1.0", moduleName = "WalletCore")
}
}

Xcode shows swift compiler errors when importing cocoapods generated by gradle plugin

I am trying to use shared code in my iOS project from cocoapods that i created with cocoapods gradle plugin.
Podspec is created without problems.
My shared build.gradle:
plugins {
id("org.jetbrains.kotlin.multiplatform")
id("com.android.library")
id ("org.jetbrains.kotlin.native.cocoapods")
}
android {
compileSdkVersion 29
buildToolsVersion '30.0.0'
defaultConfig {
minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
version = "1.0"
kotlin {
ios()
android()
cocoapods {
// Configure fields required by CocoaPods.
summary = "Some description for a Kotlin/Native module"
homepage = "Link to a Kotlin/Native module homepage"
// The name of the produced framework can be changed.
// The name of the Gradle project is used here by default.
frameworkName = "toshlShared"
}
sourceSets {
commonMain.dependencies {
api 'org.jetbrains.kotlin:kotlin-stdlib-common'
}
androidMain.dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version"
}
iosMain.dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-common:$kotlin_version"
}
}
}
When i run pod install all looks good, but when i run ios app i see this error:
EDIT: Added my project folder structure with my single .kt file (it is accessible from android code)
As far as I can see, the problem here is caused by the project structure. In the Gradle script, there are three targets declared: an Android one, and iosX64+iosArm64 shortcut(see details here) providing the other two. For this layout, there would be two compilations per iOS target(iosX64Main, iosX64Test, iosArm64Main, iosArm64Test) and
a compilation per Android build variant, for Android targets;
according to the documentation.In this particular case, only source file SharedUtils.kt is being located in a directory located on an Android main compilation's source set. This means it does not get into any iOS compilation. To make this source file shared, it should be relocated to the common code. There are two default source sets for common code in Kotlin Multiplatform: commonMain and commonTest. Therefore, source code should be placed under src/<sourceSetName>/kotlin directory(commonMain for this case).

How to fix the Java Compiler error in Android Studio when using Apache POI

I'm developing an Android App in Android Studio with Java Coding. In this app when user clicks a button an excel file gets saved in external storage with some data.
For this I'm using Apache POI 4.1.0. I have added this in dependencies, but when I run the app error is coming as below
Error: MethodHandle.invoke and MethodHandle.invokeExact are only supported starting with Android O (--min-api 26)
android {
compileSdkVersion 27
defaultConfig {
applicationId "xxxxxxx"
minSdkVersion 23
targetSdkVersion 27
versionCode 4
versionName "1.0.3"
testInstrumentationRunner
"android.support.test.runner.AndroidJUnitRunner"
signingConfig signingConfigs.config
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}
dependencies {
implementation 'org.apache.poi:poi:4.1.0'
implementation 'org.apache.poi:poi-ooxml:4.1.0'
}
I was having the same problem, after reading this article I downloaded a previous version (specifically version poi-bin-4.0.1-20181203.zip ) from here and now it´s working. I hope this helps anyone having the same issue.
Finally I got the solution for my issue. Instead of using Apache POI, I used FileWriter for CSV format. Below is the reference for this.
https://stackabuse.com/reading-and-writing-csvs-in-java/

Can a Gluon Mobile project automatically download and include libCharm.a?

I have written a small sample that makes use of com.gluonhq.charm.down.common.ScanService. It works as expected on a real iOS device, if I manually include the native library libCharm.a in src/ios/jniLibs. This is explained in the Gluon documentation of their GoNative app. If I am not mistaken, the library is built in the build.gradle file of Charm Down IOS.
Here is the build.gradle of my sample. As I have said, this leads to a fully working app if I copy libCharm.a manually to src/ios/jniLibs.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.0.8'
}
}
apply plugin: 'org.javafxports.jfxmobile'
repositories {
jcenter()
maven {
url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
}
}
mainClassName = 'com.thomaskuenneth.scanservicedemo.ScanserviceDemo'
dependencies {
compile 'com.gluonhq:charm:3.0.0'
androidRuntime 'com.gluonhq:charm-android:3.0.0'
androidRuntime 'com.google.zxing:core:3.2.1'
iosRuntime 'com.gluonhq:charm-ios:3.0.0'
desktopRuntime 'com.gluonhq:charm-desktop:3.0.0'
}
jfxmobile {
apply plugin: 'idea'
idea.module.downloadJavadoc = true
android {
manifest = 'src/android/AndroidManifest.xml'
androidSdk = '/Users/thomas/Library/Android/sdk'
compileSdkVersion = 23
}
ios {
infoPList = file('src/ios/Default-Info.plist')
forceLinkClasses = [
'com.google.zxing.**.*',
'com.gluonhq.**.*',
'io.datafx.**.*',
'javax.annotations.**.*',
'javax.inject.**.*',
'javax.json.**.*',
'org.glassfish.json.**.*'
]
}
}
I tried to add a iosRuntime dependency to the latest version of charm-down-ios, but this seemed to have no effect. So, the question: is there a way to automatically get a libCharm.a that matches my specified dependencies or is the manual way (which, again, does work) the only one possible? Thank you very much in advance.
As of now there is no automatic tool for this included in the plugin that manages the proper installation of the native library, extracting it from the charm-down-ios.jar and moving it to the jniLibs library of the project. But it should be available in a future version of the plugin.
For now, you have to do it manually, as you mentioned, extracting the libCharm.a file from the charm-ios-3.0.0.jar that will be located on your local .m2 repository, and copying it into your project under src/ios/jniLibs.
I've come up with this task that will help you do it:
task extractNativeLib(type: Sync) {
def iosNativeDir = project.file(project.jfxmobile.ios.nativeDirectory)
if (!iosNativeDir.exists()) {
iosNativeDir.mkdirs()
}
setIncludeEmptyDirs(false)
from {
configurations.iosRuntime.collect { zipTree(it).matching { include 'native/**' } }
}
into iosNativeDir
eachFile {details -> details.path = details.name }
}
Run this task before calling launchIOSDevice, and it will extract the library and copy it into your native folder.
EDIT
Since the release of the javafxmobile plugin 1.1.0 (October 2016) there is no need for using this task, as the plugin will manage it.
For the Charm Down 3.0.0+ plugins included in the project, their native libraries will be automatically added to the build, as well as any other third party native library included in src/ios/jniLibs.

Resources