How to get the Package Name of an Android application in a C library?

1

I'd like to know how I can get the Package Name from my Android APP via a library written in C .

What I want to get is the following com/meu_app/mainframe/MainActivity or com.meu_app.mainframe.MainActivity of the class that is loading the com/meu_app/mainframe/MainActivity.java library or where the public native String hello(); function is used with System.loadLibrary("getpackagename");

With the package name I'd like to use it in the function int runcmd(void) printing in __android_log_print .

There are many examples, but they are not very clear to me because they do not demonstrate how to use the function, or how to implement them from start to finish.

I have a simple function, which might help if it is modified to get the package name, is below.

JNIEXPORT jstring JNICALL Java_com_simple_example_MainActivity_Native_Hello(JNIEnv *env, jclass clazz)
{
    runcmd();
    return (*env)->NewStringUTF(env, "-------------hello world runcmd().-------------");
}


int runcmd(void)
{
    __android_log_print(ANDROID_LOG_INFO, "-----from--jni-------", "Enter RUN CMD function!");

//__android_log_print(ANDROID_LOG_INFO, "-----from--jni-------", "Imprime o a string PackageName %s\n", pkg_name);

}


static JNINativeMethod gMethods[] = {
        { "hello", "()Ljava/lang/String;", (void*)Java_com_simple_example_MainActivity_Native_Hello },
        }; /* * Register several native methods for one class. */

static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods)
{
    jclass clazz;
    clazz = (*env)->FindClass(env, className);
    if (clazz == NULL)
    {
        return JNI_FALSE;
    }
    if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0)
    {
        return JNI_FALSE;
    }

    return JNI_TRUE; }

/* * Register native methods for all classes we know about. */
static int registerNatives(JNIEnv* env)
{
    if (!registerNativeMethods(env, JNIREG_CLASS, gMethods, sizeof(gMethods) / sizeof(gMethods[0])))
    {
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
{
    JNIEnv* env = NULL;
    jint result = -1;
    if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK)
    {
        return -1;
    }
    assert(env != NULL);
    if (!registerNatives(env))//??
    {
        return -1;
    }
    /* success -- return valid version number */
    result = JNI_VERSION_1_4;
    return result;
}

In Android Studio we can call the hello () function as follows:

public class MainActivity ...
public native String hello();

static{
    System.loadLibrary("getpackagename");
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
    //Log.d("StackTraceElement", String.valueOf(stackTraceElements[2]));
    hello();
}
  

I do not intend to pass this value as a "string" , I mean, it would not   good get this with a StackTraceElement and pass it through hello (),   I would like to get it directly from the C library.

Understand better ...

  

One easy way to resolve this would be to get the Package Name in the   APP / java and pass to the library via String, but this value could be   set up / modified and not obtained from APP, the idea is to prevent anyone using the   library to choose the package, since it would only be obtained in the   library.

    
asked by anonymous 07.08.2016 / 04:36

1 answer

1

How to get the Android Package Name APP in the JNI?
Below, I show a complete implementation example, how to get it if simple form in a library.

We get context through jstring context in the library.

JNIEXPORT jstring JNICALL Java_com_simple_example_MainActivity_Native_Hello(JNIEnv *env, jclass clazz, jstring context)
{

    jclass cls = (*env)->FindClass(env, "android/content/ContextWrapper");
    jmethodID mid = (*env)->GetMethodID(env, cls, "getPackageName", "()Ljava/lang/String;");
    jstring packageName = (jstring)(*env)->CallObjectMethod(env, context, mid);

    //Faz a conversão do jstring para o char *, para que possa ser usado no __android_log_print
    const char *nativeString = (*env)->GetStringUTFChars(env, packageName, 0);
    __android_log_print(ANDROID_LOG_INFO, "--packageName--jni--", "%s", nativeString);

    runcmd();
    return (*env)->NewStringUTF(env, "-------------hello world runcmd().-------------");
}


int runcmd(void)
{
    __android_log_print(ANDROID_LOG_INFO, "-----from--jni-------", "Enter RUN CMD function!");

//__android_log_print(ANDROID_LOG_INFO, "-----from--jni-------", "Imprime o a string PackageName %s\n", pkg_name);

}

#define JNIREG_CLASS "com/simple/example/MainActivity"

/** * Table of methods associated with a single class. */
static JNINativeMethod gMethods[] = {
        { "hello", "()Ljava/lang/String;", (void*)Java_com_simple_example_MainActivity_Native_Hello },
        }; /* * Register several native methods for one class. */

static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods)
{
    jclass clazz;
    clazz = (*env)->FindClass(env, className);
    if (clazz == NULL)
    {
        return JNI_FALSE;
    }
    if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0)
    {
        return JNI_FALSE;
    }

    return JNI_TRUE; }

/* * Register native methods for all classes we know about. */
static int registerNatives(JNIEnv* env)
{
    if (!registerNativeMethods(env, JNIREG_CLASS, gMethods, sizeof(gMethods) / sizeof(gMethods[0])))
    {
        return JNI_FALSE;
    }
    return JNI_TRUE;
}

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
{
    JNIEnv* env = NULL;
    jint result = -1;
    if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK)
    {
        return -1;
    }
    assert(env != NULL);
    if (!registerNatives(env))//??
    {
        return -1;
    }
    /* success -- return valid version number */
    result = JNI_VERSION_1_4;
    return result;
}

In Android Studio, we can use the following.

@SuppressWarnings("JniMissingFunction")
public native String hello(Context context);
hello(this);

With these few modifications, you can get com.meu_app.mainframe . Modifications simple, but that I found nowhere.

    
09.08.2016 / 00:30