NDK support with different Product Flavour
Asked Answered
R

2

9

I want different string value from ndk library. as i have two flavor demo and live I want value "hello I am from demo " for demo flavor and for live flavor i want "hello I am from live "

Here is my java file code

public class MainActivity extends AppCompatActivity {
    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Example of a call to a native method
    TextView tv = (TextView) findViewById(R.id.sample_text);
    tv.setText(stringFromJNI());
}

/**
 * A native method that is implemented by the 'native-lib' native library,
 * which is packaged with this application.
 */
public native String stringFromJNI();

}

Here is my cpp file code

#include <jni.h>
#include <string>

extern "C"
JNIEXPORT jstring JNICALL
Java_com_de_demo_ndk2_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "hello I am from  demo";
    return env->NewStringUTF(hello.c_str());
}

this is my build.gradle file

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.de.demo.ndk2"
        minSdkVersion 15
        targetSdkVersion 26
        versionCode 1
        flavorDimensions "default"
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags ""
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    productFlavors {

        demo
                {
                    // applicationId "com.readwhere.whitelabel.test"
                    //applicationId "com.android.rwstaging"
                    applicationId "com.android.demo"
                    versionName "2.1"
                    dimension "default"

                    externalNativeBuild {
                        cmake {

                            targets "native-lib-demo","my-executible-                   demo"

                        }}


                }
        live
                {
                    // applicationId "com.readwhere.whitelabel.test"
                    //applicationId "com.android.rwstaging"
                    applicationId "com.android.live"
                    versionName "2.1"
                    dimension "default"



                }}
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}

I have paste same cpp file in demo folder as well as in main folder but could achieve my task. Any help would be appreciate this are some refrence links

https://developer.android.com/studio/projects/gradle-external-native-builds.html

How to set CmakeLists path in product flavor for each Android ABI?

Rigidify answered 17/11, 2017 at 12:3 Comment(3)
Possible duplicate of Read build arguments from NDK codeDarsey
no it is different then my question..Rigidify
It's one way of achieving the same end result (having different values in your native code for different product flavors). If you want to use some other method then you need to explain in detail exactly what you're having trouble with right now with your current solution.Darsey
R
1

Finally I a solution. Here is my cpp file code

Java_com_de_demo_ndk2_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject jobject1, jstring jstring1) {

    std::string hello;
    const char *nativeString1 = env->GetStringUTFChars( jstring1, 0);
    if (strcmp(nativeString1, "demo") == 0) {
        hello = "Hello from demo C++";
    } else if (strcmp(nativeString1, "live") == 0) {
        hello = "Hello from live C++";
    }

    return env->NewStringUTF(hello.c_str());
}

I am passing flavor value from java code here is my code for java file.

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        TextView tv = (TextView) findViewById(R.id.sample_text);
        String value = BuildConfig.FLAVOR;
        String ndkValue = stringFromJNI(value);
        tv.setText(ndkValue);
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     * @param value
     */
    public native String stringFromJNI(String value);
}

Now i can get whatever text i want according to selected flavor.

Rigidify answered 18/11, 2017 at 5:47 Comment(1)
Your solution is better, you don't need separate native lib for each flavor. But other scenarios involve compile-time flavoring, like in my answer.Capsulize
C
16

Probably, the minimal code to achieve your goal at compile time is to set cppFLags per flavor:

productFlavors {
  demo {
    applicationId "com.android.demo"
    versionName "2.1"
    dimension "default"

    externalNativeBuild.cmake {
      cppFlags '-DDEMO'
    }
  }
  live {
     applicationId "com.android.live"
     versionName "2.1"
     dimension "default"
    externalNativeBuild.cmake {
      cppFlags '-DLIVE'
    }
  }
}

and in your cpp file

#ifdef DEMO
  std::string hello = "hello I am from demo";
#endif
#ifdef LIVE
  std::string hello = "hello I am from live";
#endif

Or you can use stingify pattern as in this answer.

Naturally, your conditional compilation is not limited to string variation.

Capsulize answered 18/11, 2017 at 0:35 Comment(4)
thanks for reply . I already found a solution by passing build flavor in my native method. I have not tried your solution but the concept is similar to me. I am checking flavor value for your solution I have to add another value that is cppflags in gradle Giving thumbs up to your solution and posting my solution as answer.Rigidify
Could you please take a look at my question #61190587 interesting to know what do you thinkAmazing
how can I do for ndkBuild?Blunt
@AbhayKoradiya externalNativeBuild.ndkBuild accepts cppFlags, too, with the same syntax.Capsulize
R
1

Finally I a solution. Here is my cpp file code

Java_com_de_demo_ndk2_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject jobject1, jstring jstring1) {

    std::string hello;
    const char *nativeString1 = env->GetStringUTFChars( jstring1, 0);
    if (strcmp(nativeString1, "demo") == 0) {
        hello = "Hello from demo C++";
    } else if (strcmp(nativeString1, "live") == 0) {
        hello = "Hello from live C++";
    }

    return env->NewStringUTF(hello.c_str());
}

I am passing flavor value from java code here is my code for java file.

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        TextView tv = (TextView) findViewById(R.id.sample_text);
        String value = BuildConfig.FLAVOR;
        String ndkValue = stringFromJNI(value);
        tv.setText(ndkValue);
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     * @param value
     */
    public native String stringFromJNI(String value);
}

Now i can get whatever text i want according to selected flavor.

Rigidify answered 18/11, 2017 at 5:47 Comment(1)
Your solution is better, you don't need separate native lib for each flavor. But other scenarios involve compile-time flavoring, like in my answer.Capsulize

© 2022 - 2024 — McMap. All rights reserved.