Call Android Activity Mtehod in C++ using JNI qt

5,155 views
Skip to first unread message

user1618

unread,
Mar 10, 2014, 10:58:44 AM3/10/14
to andro...@googlegroups.com
I am accessing a Method from Java class which has to show a Toast on Screen. But the method is in other class which is not an Activity.  I have two scenario, lets me explain them one by one..

Common idea
I can access the methods in both Acitivity and normal Java class from C++ through JNI but both have issues

Issue on Calling a method from Activty

I can access method from Activity and also have the activity context to show anything on UI. But in this case I am getting crash with this error
 

     java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

I have tried all general stuff like using AsyncTask, Handler, runOnUI etc but same I guess It is issue with some JNI call which also runs mainly in Threads

Issue on Calling a Method from Normal Java Class

I can access method here too, but I do not have the context of Activity in this class to show Toast on UI, so Issue here is to get the Activity context which I can not figured out how to pass it in JNI and all. I tried with passing through constructor but question is how to get it once in JNI to that It could be passed to this class. Error here is

     java.lang.NullPointerException
     E/AndroidRuntime( 4594):     at android.widget.Toast.<init>(Toast.java:92)
     E/AndroidRuntime( 4594):     at android.widget.Toast.makeText(Toast.java:238)

I have searched alot and tried many things but could not able to make it work, and also did not find good help, tutorials on JNI andorid. 
So I do know if there is any workaround availble to achive it

here is my JNI call code
[JNI Code][1]

here is my method in Activity

        public void ShowMessage(String message){   
        messageData = message;
       

        if(MainActivity.this == null){
            Log.d("Acitivtry", "issue");
            }    
       
            MainActivity.this.runOnUiThread(new Runnable() {
           
            public void run() {
                Log.d("in RunUIThread", "hmmm");
                Toast.makeText(MainActivity.this, "messageData", Toast.LENGTH_SHORT).show();
            }
                });
            }


  [1]: http://pastebin.kde.org/pmnrvwb22

J Decker

unread,
Mar 10, 2014, 6:55:00 PM3/10/14
to andro...@googlegroups.com
I assume 'MainActivity.this' is a static member; are you sure you set that?


--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to android-ndk...@googlegroups.com.
To post to this group, send email to andro...@googlegroups.com.
Visit this group at http://groups.google.com/group/android-ndk.
For more options, visit https://groups.google.com/d/optout.

inderjeet

unread,
Mar 11, 2014, 2:32:33 AM3/11/14
to andro...@googlegroups.com
MainActivity is current activity don't think being static would make any difference but I tried both ways still same issue. For me it looks like it is about accessing the android native activity object instead of using findclass for created MainActivity. But I am not sure how to do it. 
--
--
Best

INDERJEET SINGH

Please consider the environment before printing this mail

J Decker

unread,
Mar 11, 2014, 5:34:19 AM3/11/14
to andro...@googlegroups.com
I found an example a long time ago to show/hide the input keyboard; I modified that to just call the class in MyNativeActivity extends NativeActivity ... the original was more complex than this.... this way simplifies it kinda

{
    public void setSuspendSleep() {
        this.runOnUiThread( new Runnable() {
    public void run() 
                {
        getWindow().addFlags( WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON );
                }        
        } );
    }
    
    public void setAllowSleep() {
        this.runOnUiThread( new Runnable() {
    public void run() {
       getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
                }
        } );
    }
}



------- and then in C++ ------

// getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
// getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
extern "C" void SuspendSleep( int bStopSleep )
{
static int init;
static jobject  WindowManager_LayoutParams_FLAG_KEEP_SCREEN_ON;

    // Attaches the current thread to the JVM. 
    jint lResult; 
    jint lFlags = 0; 

    JavaVM* lJavaVM = engine.app->activity->vm; 
    JNIEnv* lJNIEnv = engine.app->activity->env; 

    JavaVMAttachArgs lJavaVMAttachArgs; 
    lJavaVMAttachArgs.version = JNI_VERSION_1_6; 
    lJavaVMAttachArgs.name = "NativeThread"; 
    lJavaVMAttachArgs.group = NULL; 

    lResult=lJavaVM->AttachCurrentThread(&lJNIEnv, &lJavaVMAttachArgs);
    if (lResult == JNI_ERR) { 
        return; 
    } 

    // Retrieves NativeActivity. 
    jobject lNativeActivity = engine.app->activity->clazz; 
jclass ClassNativeActivity = lJNIEnv->GetObjectClass(lNativeActivity);

if( bStopSleep )
{
jmethodID MethodSetFlags = lJNIEnv->GetMethodID(      ClassNativeActivity, "setSuspendSleep", "()V");
if( MethodSetFlags )
lJNIEnv->CallVoidMethod( lNativeActivity,  MethodSetFlags );
}
else
{
jmethodID MethodSetFlags = lJNIEnv->GetMethodID(      ClassNativeActivity, "setAllowSleep", "()V");
if( MethodSetFlags )
lJNIEnv->CallVoidMethod( lNativeActivity,  MethodSetFlags );
}



// Finished with the JVM. 
lJavaVM->DetachCurrentThread();
}

james Lee

unread,
Mar 22, 2014, 12:06:01 PM3/22/14
to andro...@googlegroups.com
Hi~
 
What is the engine.app->activity ?
Build error is generated..
 
Yorr code seem to helpful for me..
I can't access an android activity dialog by using Qt-C++.
 
 
 
 
 JavaVM* lJavaVM = engine.app->activity->vm; 
 JNIEnv* lJNIEnv = engine.app->activity->env; 
 
 

2014년 3월 11일 화요일 오후 6시 34분 19초 UTC+9, J Decker 님의 말:
To unsubscribe from this group and stop receiving emails from it, send an email to android-ndk+unsubscribe@googlegroups.com.

To post to this group, send email to andro...@googlegroups.com.
Visit this group at http://groups.google.com/group/android-ndk.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to android-ndk+unsubscribe@googlegroups.com.

To post to this group, send email to andro...@googlegroups.com.
Visit this group at http://groups.google.com/group/android-ndk.
For more options, visit https://groups.google.com/d/optout.

VS Hải Long

unread,
May 9, 2014, 12:09:14 PM5/9/14
to andro...@googlegroups.com
I call java method from jni native method. but it can't access any API UI.
now your code solved my problem. Thank J Decker very much

suresh kumar

unread,
Dec 31, 2014, 2:35:16 AM12/31/14
to andro...@googlegroups.com
I tried to use mentioned in the post. Iam getting build error.
Please let me know engine object means here ?

J Decker

unread,
Jan 4, 2015, 11:18:12 AM1/4/15
to andro...@googlegroups.com
Engine is a structure that's in a sample NDK thing... it contains a 
struct engine {
struct android_app* app;
}

which the app is what it really wants.


it's set from android_main 


/**
 * This is the main entry point of a native application that is using
 * android_native_app_glue.  It runs in its own thread, with its own
 * event loop for receiving input events and doing other things.
 */
void android_main(struct android_app* state) {
const char *data_path = engine.data_path;
   struct event_queue queue = engine.events;
// Make sure glue isn't stripped.
app_dummy();

memset(&engine, 0, sizeof(engine));

engine.data_path = data_path;
engine.events = queue;
if( !engine.events.msgpipe[0] )
if (pipe(engine.events.msgpipe)) {
LOGI("could not create pipe: %s", strerror(errno));
}


state->userData = &engine;
state->onAppCmd = engine_handle_cmd;
state->onInputEvent = engine_handle_input;
engine.app = state;

suresh kumar

unread,
Jan 5, 2015, 8:55:38 AM1/5/15
to andro...@googlegroups.com
Thanks for your reply. How come i can get engine object instance in my code when it is in defined in ndk native code glue code?
Please explain it

J Decker

unread,
Jan 5, 2015, 9:55:22 AM1/5/15
to andro...@googlegroups.com
On Mon, Jan 5, 2015 at 5:55 AM, suresh kumar <sureshk...@gmail.com> wrote:
Thanks for your reply. How come i can get engine object instance in my code when it is in defined in ndk native code glue code?
Please explain it

because GCC by default makes all non static or hidden symbols public ?
since engine is shared... it ended up having a public name you can link against?
I don't understand your question 

--

suresh kumar

unread,
Jan 6, 2015, 5:44:09 AM1/6/15
to andro...@googlegroups.com
iam unable to include engine structure in my native application.Getting compile error.
my implementation will be like this

J Decker

unread,
Jan 6, 2015, 8:43:26 AM1/6/15
to andro...@googlegroups.com
On Tue, Jan 6, 2015 at 2:44 AM, suresh kumar <sureshk...@gmail.com> wrote:
iam unable to include engine structure in my native application.Getting compile error.
my implementation will be like this

#include <android_native_app_glue.h>
but this is from NativeActivity which extends Activity...
inbetween the java... 

 private native int loadNativeCode(String pathString funcnameMessageQueue queue,
             String internalDataPathString obbPathString externalDataPathint sdkVersion,
             AssetManager assetMgrbyte[] savedState);

I haven't found the implementation of this function which creates a 

ANativeActivity* activity,
... defined here....

which has a JavaVM and JaveEnv  etc in it... which is used in all of my examples that work...

so how NativeActivity_loadNativeCode creates a ANativeActivity?  
Reply all
Reply to author
Forward
0 new messages