android: Fix assorted compatibility issues with plyer/pyjnius
pyjnius needs to do env->FindClass in the app thread, which only works if the app thread was created by Java, so I changed android_native_app_glue to do that instead of via pthreads
This commit is contained in:
parent
ba6b66fbb6
commit
ea55924e59
|
|
@ -4948,6 +4948,7 @@ if GetTarget() == 'android':
|
|||
TargetAdd('org/panda3d/android/PandaActivity$1.class', opts=OPTS+['DEPENDENCYONLY'], input='PandaActivity.java')
|
||||
TargetAdd('org/panda3d/android/PandaActivity$2.class', opts=OPTS+['DEPENDENCYONLY'], input='PandaActivity.java')
|
||||
TargetAdd('org/panda3d/android/PythonActivity.class', opts=OPTS, input='PythonActivity.java')
|
||||
TargetAdd('org/panda3d/android/PythonActivity$ActivityResultListener.class', opts=OPTS+['DEPENDENCYONLY'], input='PythonActivity.java')
|
||||
|
||||
TargetAdd('classes.dex', input='org/panda3d/android/NativeIStream.class')
|
||||
TargetAdd('classes.dex', input='org/panda3d/android/NativeOStream.class')
|
||||
|
|
@ -4955,6 +4956,7 @@ if GetTarget() == 'android':
|
|||
TargetAdd('classes.dex', input='org/panda3d/android/PandaActivity$1.class')
|
||||
TargetAdd('classes.dex', input='org/panda3d/android/PandaActivity$2.class')
|
||||
TargetAdd('classes.dex', input='org/panda3d/android/PythonActivity.class')
|
||||
TargetAdd('classes.dex', input='org/panda3d/android/PythonActivity$ActivityResultListener.class')
|
||||
|
||||
TargetAdd('p3android_composite1.obj', opts=OPTS, input='p3android_composite1.cxx')
|
||||
TargetAdd('libp3android.dll', input='p3android_composite1.obj')
|
||||
|
|
|
|||
|
|
@ -81,6 +81,16 @@ public class PandaActivity extends NativeActivity {
|
|||
return Thread.currentThread().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by android_native_app_glue to spawn the application thread.
|
||||
* Gets passed a function pointer and a data pointer to pass to it.
|
||||
*/
|
||||
protected void spawnAppThread(long ptr, long data) {
|
||||
new Thread(() -> {
|
||||
nativeThreadEntry(ptr, data);
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the blob to memory and returns the pointer.
|
||||
*/
|
||||
|
|
@ -193,4 +203,5 @@ public class PandaActivity extends NativeActivity {
|
|||
}
|
||||
|
||||
private static native long nativeMmap(int fd, long off, long len);
|
||||
private static native void nativeThreadEntry(long ptr, long data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,12 @@ package org.panda3d.android;
|
|||
|
||||
import org.panda3d.android.PandaActivity;
|
||||
|
||||
import android.content.Intent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Extends PandaActivity with some things that are useful in a Python
|
||||
* application.
|
||||
|
|
@ -26,4 +32,39 @@ public class PythonActivity extends PandaActivity {
|
|||
public PythonActivity() {
|
||||
mActivity = this;
|
||||
}
|
||||
|
||||
// Helper code to further support plyer.
|
||||
public interface ActivityResultListener {
|
||||
void onActivityResult(int requestCode, int resultCode, Intent data);
|
||||
}
|
||||
|
||||
private List<ActivityResultListener> activityResultListeners = null;
|
||||
|
||||
public void registerActivityResultListener(ActivityResultListener listener) {
|
||||
if (this.activityResultListeners == null) {
|
||||
this.activityResultListeners = Collections.synchronizedList(new ArrayList<ActivityResultListener>());
|
||||
}
|
||||
this.activityResultListeners.add(listener);
|
||||
}
|
||||
|
||||
public void unregisterActivityResultListener(ActivityResultListener listener) {
|
||||
if (this.activityResultListeners == null) {
|
||||
return;
|
||||
}
|
||||
this.activityResultListeners.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
|
||||
if (this.activityResultListeners == null) {
|
||||
return;
|
||||
}
|
||||
this.onResume();
|
||||
synchronized (this.activityResultListeners) {
|
||||
Iterator<ActivityResultListener> iterator = this.activityResultListeners.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
iterator.next().onActivityResult(requestCode, resultCode, intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -255,10 +255,19 @@ static struct android_app* android_app_create(ANativeActivity* activity,
|
|||
android_app->msgread = msgpipe[0];
|
||||
android_app->msgwrite = msgpipe[1];
|
||||
|
||||
// Spawn the app thread in Java so it gets a valid class loader.
|
||||
JNIEnv *env = activity->env;
|
||||
jclass activity_class = (*env)->GetObjectClass(env, activity->clazz);
|
||||
jmethodID method = (*env)->GetMethodID(env, activity_class, "spawnAppThread", "(JJ)V");
|
||||
LOGE("got function pointer: %ld, data: %ld, env: %ld", (jlong)(void *)android_app_entry, (jlong)(void *)android_app, (jlong)(void *)env);
|
||||
(*env)->CallVoidMethod(env, activity->clazz, method, (void *)android_app_entry, (void *)android_app);
|
||||
|
||||
/*
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
pthread_create(&android_app->thread, &attr, android_app_entry, android_app);
|
||||
*/
|
||||
|
||||
// Wait for thread to start.
|
||||
pthread_mutex_lock(&android_app->mutex);
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ struct android_app {
|
|||
int msgread;
|
||||
int msgwrite;
|
||||
|
||||
pthread_t thread;
|
||||
//pthread_t thread;
|
||||
|
||||
struct android_poll_source cmdPollSource;
|
||||
struct android_poll_source inputPollSource;
|
||||
|
|
|
|||
|
|
@ -193,3 +193,10 @@ void android_show_toast(ANativeActivity *activity, const std::string &message, i
|
|||
env->CallVoidMethod(activity->clazz, jni_PandaActivity_showToast, jmsg, (jint)duration);
|
||||
env->DeleteLocalRef(jmsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the JNIEnv pointer corresponding to the current thread.
|
||||
*/
|
||||
void *SDL_AndroidGetJNIEnv() {
|
||||
return Thread::get_current_thread()->get_jni_env();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,4 +44,9 @@ EXPORT_CLASS Filename android_find_library(ANativeActivity *activity, const std:
|
|||
EXPORT_CLASS void android_set_title(ANativeActivity *activity, const std::string &title);
|
||||
EXPORT_CLASS void android_show_toast(ANativeActivity *activity, const std::string &message, int duration);
|
||||
|
||||
// Used to support pyjnius
|
||||
extern "C" {
|
||||
EXPORT_CLASS void *SDL_AndroidGetJNIEnv(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -38,3 +38,11 @@ Java_org_panda3d_android_PandaActivity_nativeMmap(JNIEnv* env, jclass, jint fd,
|
|||
return (jlong)0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the given function pointer, passing the given data pointer.
|
||||
*/
|
||||
EXPORT_JNI void
|
||||
Java_org_panda3d_android_PandaActivity_nativeThreadEntry(JNIEnv* env, jobject self, jlong func, jlong data) {
|
||||
((void (*)(void *))(void *)func)((void *)data);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue