Android JNI: Cannot call functions in non-Activity class - android

I am using jni and I can call java functions in regular activity from c++ class but when I try to call java functions in non activity class, my code does not work.
I mean
jclass activityclass = env->FindClass("com/example/test/MyActivity);
jmethodID methodID = env->GetMethodID(activityclass,"FunctionName","()V");
env ->CallVoidMethod(obj,methodID);
This works.
When I try to call same function(with same name) from non activity regular java class, it doesnt work.
jclass regularclass = env->FindClass("com/example/test/MyRegularClass);
jmethodID methodID = env->GetMethodID(regularclass ,"FunctionName","()V");
env ->CallVoidMethod(obj,methodID);
Why I cannot call function in non activity class? What is my mistake?
My MyRegularClass
public class MyRegularClass{
public static void FunctionName(){
Log.i("Java Worked","Java Worked");
}
}
My Activity classs
public class MyActivity{
system.load.library("mylib");
#Override
public void onCreate(Bundle savedInstanceState){
....
....
testJNI();
}
public static void FunctionName(){
Log.i("Activity Worked","Activity Worked");
}
public native void testJNI();
}

You need to use GetStaticMethodID() and CallStaticVoidMethod() for static methods. This has nothing to do with the methods being in activities or not.

Related

Android calling Java function from another activity class in C++ JNI code

As the title suggested, How can I call Java function from C++ if the function is from a different java activity class?
All of the sample and tutorials calls C++ function and java back and forth but the caller is the class and the JNIEnv and jobject are passed from java thru JNI. But what if the function that needed to be called is from a different java activity class? How to do this? passing the "this" of the activity did not work
Here is sample layout of classes
Activity class
public class MainActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
JNIAdapter.launch();
}
private void DisplayLoginDialog()
{
//...
}
}
JNIAdapter.class
public class JNIAdapter {
static {
System.loadLibrary("jnisample-lib");
}
public static native void launch();
}
jnisample.cpp
extern "C"
JNIEXPORT void JNICALL
Java_com_JNIAdapter_launch(JNIEnv *env,jobject object)
{
jclass dataClass = env->FindClass("com/game/ramo/MainActivity");
jmethodID javaMethodRef = env->GetMethodID(dataClass, "DisplayLoginDialog", "()V");
env->CallVoidMethod(object, javaMethodRef);
}
In the above code, using the jobject, refers to the JNIAdapter class and not the Activity hence the DisplayLoginDialog() is not called.
How to do this?
Your small example (I understand that you reduced all details not relevant to the specific problem, that's very nice!) could run without native method. JNIAdaptor.launch() could be pure Java. So, to begin with, rewrite it in Java and make sure it works.
The issues could be that MainActivity.DisplayLoginDialog() may expect its parent activity to be in the foreground, or in some specific state. This is easier to fix in pure Java.
After that, the JNI code you wrote should run without problems.

Call public void function from different activity android

How can I call public void function from FirstActivity in SecondActivity?
// FirstActivity
public void thisFunction(){
// do something
// do something
}
in Second Activity
if(x){
FirstActivity.thisFunction();
}
but returns error:
Non-static method 'thisFunction()' cannot be reference from a static context
Static functions are functions of class and don't depend on any objects of that class
Class.staticFunction() (no need to instantiate), you can call it everywhere
public static void thisFunction(){
// do something
// do something
}
Then in SecondActivity:
FirstActivity.thisFunctions();

Unable to call instance method from SensorEventListener native JNI method

I am implementing SensorEventListener in native method as follows (to make calculations faster):
public class GPSLogger extends Service
implements SensorEventListener {
public native void onSensorChanged(SensorEvent event);
public void startLocationUpdates() { // some code }
}
The corresponding JNI implementation gets called. But I am trying to call startLocationUpdates() from the native C code as follows:
jclass objcls = (*env).GetObjectClass(obj);
jmethodID methid = (*env).GetMethodID(objcls, "startLocationUpdates", "()V");
if (methid == NULL)
__android_log_write(ANDROID_LOG_ERROR, "[IFL]", "startLocationUpdates not found");
else
(*env).CallVoidMethod(obj, methid);
In this case methid is NULL. and there is an exception in ADB log saying
java.lang.NoSuchMethodError: no non-static method "Lmy/package/GPSLogger;.startLocationUpdates()V"
What could be wrong? I even tried geting objcls as
jclass objcls = (*env).FindClass("my/package/GPSLogger");
but same problem.
Problem solved after adding proguard rule (to prevent obfuscation of method name):
-keep class my.package.GPSLogger { void startLocationUpdates(); }

Qt/QML Android best practice to send a custom Intent (share URL)

I was wondering if there are any best practice tips for sending custom android intents from QML (or c++ for that matter).
should I create a custom android activity and use the QAndroidJniObject class to call it or are there any better ways?
My intention is to create a simple share URL function from QML to other android apps.
thanks
Extend QtActivity with additional static method:
package org.whatever
public class YourActivity extends org.qtproject.qt5.android.bindings.QtActivity
{
private static YourActivity instance;
YourActivity() {
instance = this;
}
public static void shareUrl(QString url) {
//create intent here
//can use instance object
}
}
On c++ side call shareUrl method using QAndroidJniObject
class QmlInterface : public QObject
{
Q_OBJECT
public:
QmlInterface();
Q_INVOKABLE void shareUrl( QString url );
};
and implementation:
void QmlInterface:: shareUrl( QString url )
{
#ifdef Q_OS_ANDROID
QAndroidJniObject::callStaticMethod( "org/whatever/YourActivity",
"shareUrl",
"(Ljava/lang/String;)V",
QAndroidJniObject::fromString( url ));
#endif
}
Using static method on java side simplifies jni call significantly because you don't have to get Activity instance. Because Activity context is needed to send Intent static instance member object is used on java side.

How to call a non static method of an Activity from a C file

I have one activity that has one void method say receiveSMS(), this is a void method, because of some reason i can not make it static function.
my question is how to call a void method of activity from a c file.
as calling a non- static method we need the instance of the class. how can i get the instance of a Activity in my c file.
Thanks In advance.
you need the Following Signature for Void Type
JNIEXPORT void JNICALL
after that add the method name with its package and its attribute
as an example following can be use as reference
Java_com_putitout_buck_talkinganimals_VideoPlayback_setActivityPortraitMode(JNIEnv *, jobject, jboolean isPortrait)
{
isActivityInPortraitMode = isPortrait;
}
in Java Method Signature will be like this
private native void setActivityPortraitMode(boolean isPortrait);
for further underStanding take look at JNI

Categories

Resources