How to get the Package Name from an Android app in a C library?

Asked

Viewed 679 times

1

I would like to know how I can get the Package Name of my Android APP through a library written in C.

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

With the package name obtained I would like to use it in the function int runcmd(void) printing on __android_log_print.

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

I have a simple function, which may help if 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 don’t intend to pass that figure off as a "string", I mean, it wouldn’t be good to get this with a Stacktraceelement and pass it through the hello(), I would like to get it directly in the C library.

Better understand...

An easy way to solve this would be to get Package Name on APP/java and move to the library via String, but this value could be set/modified and not obtained from the APP, the idea is to prevent anyone using the library that chose the package as it would be obtained only on library.

1 answer

1


How to get the Android APP Package Name on JNI?
Below, I show you a full example of how to get it into a library.

We get the context through the 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, it is possible to obtain the com.meu_app.mainframe. Simple modifications, but not found anywhere.

  • Code improvements are accepted, as are alternative options. It was difficult, but it’s there. =)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.