start webview only branch
This commit is contained in:
parent
9a0919771d
commit
113b4641d4
3 changed files with 511 additions and 179 deletions
|
|
@ -1,10 +1,7 @@
|
||||||
# Android App Written in C (build via docker/podman)
|
# Native (non java written) Android App Written in C (build via docker/podman)
|
||||||
|
|
||||||
This repo provides its user with the ability to setup and compile a Android-App that is
|
branch `webview` to only setup a webview
|
||||||
based on `android.app.NativeActiviy` and thus can be completely compiled C source-code.
|
|
||||||
|
|
||||||
It is an adoptation (and hopefully somehow simplification of this repo [`rawdrawandroid`](https://github.com/cnlohr/rawdrawandroid)
|
|
||||||
and this many thanks and credits to most of the c-code goes to CNLohr.
|
|
||||||
|
|
||||||
## usage
|
## usage
|
||||||
|
|
||||||
|
|
@ -23,6 +20,7 @@ adb install -r app/result/app.apk
|
||||||
|
|
||||||
## basic ideas
|
## basic ideas
|
||||||
|
|
||||||
|
* "native app" to remove need to work with JAVA/KOTLIN madness
|
||||||
* work within container (debian based image)
|
* work within container (debian based image)
|
||||||
* use Makefile as a build tool
|
* use Makefile as a build tool
|
||||||
* avoid the "unhappiness" of having to deal with neither KOTLIN nor JAVA
|
* avoid the "unhappiness" of having to deal with neither KOTLIN nor JAVA
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,20 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
//why this (related to this OG_* functions)#include "os_generic.h"
|
//why this (related to this OG_* functions)#include "os_generic.h"
|
||||||
|
//#include "os_generic.h"
|
||||||
//#include <GLES3/gl3.h>
|
//#include <GLES3/gl3.h>
|
||||||
//A-s-s-e-t-s #include <android/asset_manager.h>
|
//#include <android/asset_manager.h>
|
||||||
//A-s-s-e-t-s #include <android/asset_manager_jni.h>
|
//#include <android/asset_manager_jni.h>
|
||||||
#include <android_native_app_glue.h>
|
#include <android_native_app_glue.h>
|
||||||
//SENSORSTURFF #include <android/sensor.h>
|
#include <android/log.h>
|
||||||
|
#define APPNAME "MyApp"
|
||||||
|
|
||||||
|
//#include <android/sensor.h>
|
||||||
#include <byteswap.h>
|
#include <byteswap.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include "CNFGAndroid.h"
|
#include "CNFGAndroid.h"
|
||||||
|
#define true 1
|
||||||
//#define CNFA_IMPLEMENTATION
|
//#define CNFA_IMPLEMENTATION
|
||||||
#define CNFG_IMPLEMENTATION
|
#define CNFG_IMPLEMENTATION
|
||||||
#define CNFG3D
|
#define CNFG3D
|
||||||
|
|
@ -23,8 +27,8 @@
|
||||||
//AUDIO //#include "cnfa/CNFA.h"
|
//AUDIO //#include "cnfa/CNFA.h"
|
||||||
#include "CNFG.h"
|
#include "CNFG.h"
|
||||||
|
|
||||||
//webview//#define WEBVIEW_NATIVE_ACTIVITY_IMPLEMENTATION
|
#define WEBVIEW_NATIVE_ACTIVITY_IMPLEMENTATION
|
||||||
//webview//#include "webview_native_activity.h"
|
#include "webview_native_activity.h"
|
||||||
|
|
||||||
//SENSORSTURFF //Heightmap float mountainangle;
|
//SENSORSTURFF //Heightmap float mountainangle;
|
||||||
//SENSORSTURFF //Heightmap float mountainoffsetx;
|
//SENSORSTURFF //Heightmap float mountainoffsetx;
|
||||||
|
|
@ -36,7 +40,7 @@
|
||||||
//SENSORSTURFF ASensorEventQueue* aeq;
|
//SENSORSTURFF ASensorEventQueue* aeq;
|
||||||
//SENSORSTURFF ALooper * l;
|
//SENSORSTURFF ALooper * l;
|
||||||
|
|
||||||
//webview//WebViewNativeActivityObject MyWebView;
|
WebViewNativeActivityObject MyWebView;
|
||||||
|
|
||||||
//AUDIO const uint32_t SAMPLE_RATE = 44100;
|
//AUDIO const uint32_t SAMPLE_RATE = 44100;
|
||||||
//AUDIO const uint16_t SAMPLE_COUNT = 512;
|
//AUDIO const uint16_t SAMPLE_COUNT = 512;
|
||||||
|
|
@ -355,175 +359,193 @@ void HandleThisWindowTermination()
|
||||||
|
|
||||||
|
|
||||||
//graphic-random-texture uint32_t randomtexturedata[256*256];
|
//graphic-random-texture uint32_t randomtexturedata[256*256];
|
||||||
//webview //uint32_t webviewdata[500*500];
|
|
||||||
//webview //char fromJSBuffer[128];
|
|
||||||
//webview
|
|
||||||
//webview //void CheckWebView( void * v )
|
|
||||||
//webview //{
|
|
||||||
//webview // static int runno = 0;
|
|
||||||
//webview // WebViewNativeActivityObject * wvn = (WebViewNativeActivityObject*)v;
|
|
||||||
//webview // if( WebViewGetProgress( wvn ) != 100 ) return;
|
|
||||||
//webview //
|
|
||||||
//webview // runno++;
|
|
||||||
//webview // if( runno == 1 )
|
|
||||||
//webview // {
|
|
||||||
//webview // // The attach (initial) message payload has no meaning.
|
|
||||||
//webview // WebViewPostMessage( wvn, "", 1 );
|
|
||||||
//webview // }
|
|
||||||
//webview // else
|
|
||||||
//webview // {
|
|
||||||
//webview // // Invoke JavaScript, which calls a function to send a webmessage
|
|
||||||
//webview // // back into C land.
|
|
||||||
//webview // WebViewExecuteJavascript( wvn, "SendMessageToC();" );
|
|
||||||
//webview //
|
|
||||||
//webview // // Send a WebMessage into the JavaScript code.
|
|
||||||
//webview // char st[128];
|
|
||||||
//webview // sprintf( st, "Into JavaScript %d\n", runno );
|
|
||||||
//webview // WebViewPostMessage( wvn, st, 0 );
|
|
||||||
//webview // }
|
|
||||||
//webview //}
|
|
||||||
|
|
||||||
//webview//jobject g_attachLooper;
|
uint32_t * webviewdata;//[500*500];
|
||||||
|
//uint32_t webviewdata[3000*2000];
|
||||||
|
char fromJSBuffer[128];
|
||||||
|
|
||||||
//webview //void SetupWebView( void * v )
|
void CheckWebView( void * v )
|
||||||
//webview //{
|
{
|
||||||
//webview // WebViewNativeActivityObject * wvn = (WebViewNativeActivityObject*)v;
|
static int runno = 0;
|
||||||
//webview //
|
WebViewNativeActivityObject * wvn = (WebViewNativeActivityObject*)v;
|
||||||
//webview //
|
if( WebViewGetProgress( wvn ) != 100 ) return;
|
||||||
//webview // const struct JNINativeInterface * env = 0;
|
|
||||||
//webview // const struct JNINativeInterface ** envptr = &env;
|
runno++;
|
||||||
//webview // const struct JNIInvokeInterface ** jniiptr = gapp->activity->vm;
|
if( runno == 1 )
|
||||||
//webview // const struct JNIInvokeInterface * jnii = *jniiptr;
|
{
|
||||||
//webview //
|
// The attach (initial) message payload has no meaning.
|
||||||
//webview // jnii->AttachCurrentThread( jniiptr, &envptr, NULL);
|
WebViewPostMessage( wvn, "", 1 );
|
||||||
//webview // env = (*envptr);
|
}
|
||||||
//webview //
|
else
|
||||||
//webview // while( g_attachLooper == 0 ) usleep(1);
|
{
|
||||||
//webview // WebViewCreate( wvn, "file:///android_asset/index.html", g_attachLooper, 500, 500 );
|
// Invoke JavaScript, which calls a function to send a webmessage
|
||||||
//webview // //WebViewCreate( wvn, "about:blank", g_attachLooper, 500, 500 );
|
// back into C land.
|
||||||
//webview //}
|
WebViewExecuteJavascript( wvn, "SendMessageToC();" );
|
||||||
|
|
||||||
|
// Send a WebMessage into the JavaScript code.
|
||||||
|
char st[128];
|
||||||
|
sprintf( st, "Into JavaScript %d\n", runno );
|
||||||
|
WebViewPostMessage( wvn, st, 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jobject g_attachLooper;
|
||||||
|
|
||||||
|
void SetupWebView( void * v )
|
||||||
|
{
|
||||||
|
WebViewNativeActivityObject * wvn = (WebViewNativeActivityObject*)v;
|
||||||
|
|
||||||
|
|
||||||
//webview //pthread_t jsthread;
|
const struct JNINativeInterface * env = 0;
|
||||||
//webview //
|
const struct JNINativeInterface ** envptr = &env;
|
||||||
//webview //void * JavscriptThread( void * v )
|
const struct JNIInvokeInterface ** jniiptr = gapp->activity->vm;
|
||||||
//webview //{
|
const struct JNIInvokeInterface * jnii = *jniiptr;
|
||||||
//webview // const struct JNINativeInterface * env = 0;
|
|
||||||
//webview // const struct JNINativeInterface ** envptr = &env;
|
jnii->AttachCurrentThread( jniiptr, &envptr, NULL);
|
||||||
//webview // const struct JNIInvokeInterface ** jniiptr = gapp->activity->vm;
|
env = (*envptr);
|
||||||
//webview // const struct JNIInvokeInterface * jnii = *jniiptr;
|
|
||||||
//webview //
|
while( g_attachLooper == 0 ) usleep(1);
|
||||||
//webview // jnii->AttachCurrentThread( jniiptr, &envptr, NULL);
|
if(screenx<1000){
|
||||||
//webview // env = (*envptr);
|
screenx=1000;
|
||||||
//webview //
|
}
|
||||||
//webview // // Create a looper on this thread...
|
if(screeny<1000){
|
||||||
//webview // jclass LooperClass = env->FindClass(envptr, "android/os/Looper");
|
screeny=1000;
|
||||||
//webview // jmethodID myLooperMethod = env->GetStaticMethodID(envptr, LooperClass, "myLooper", "()Landroid/os/Looper;");
|
}
|
||||||
//webview // jobject thisLooper = env->CallStaticObjectMethod( envptr, LooperClass, myLooperMethod );
|
//WebViewCreate( wvn, "https://server.alexmahr.de/browser.html"file:///android_asset/index.html", g_attachLooper, screenx, screeny); //500, 500 );
|
||||||
//webview // if( !thisLooper )
|
WebViewCreate( wvn, "https://server.alexmahr.de/browser.html", g_attachLooper, screenx, screeny); //500, 500 );
|
||||||
//webview // {
|
//WebViewCreate( wvn, "about:blank", g_attachLooper, 500, 500 );
|
||||||
//webview // jmethodID prepareMethod = env->GetStaticMethodID(envptr, LooperClass, "prepare", "()V");
|
}
|
||||||
//webview // env->CallStaticVoidMethod( envptr, LooperClass, prepareMethod );
|
|
||||||
//webview // thisLooper = env->CallStaticObjectMethod( envptr, LooperClass, myLooperMethod );
|
|
||||||
//webview // g_attachLooper = env->NewGlobalRef(envptr, thisLooper);
|
pthread_t jsthread;
|
||||||
//webview // }
|
|
||||||
//webview //
|
void * JavscriptThread( void * v )
|
||||||
//webview // jmethodID getQueueMethod = env->GetMethodID( envptr, LooperClass, "getQueue", "()Landroid/os/MessageQueue;" );
|
{
|
||||||
//webview // jobject lque = env->CallObjectMethod( envptr, g_attachLooper, getQueueMethod );
|
const struct JNINativeInterface * env = 0;
|
||||||
//webview //
|
const struct JNINativeInterface ** envptr = &env;
|
||||||
//webview // jclass MessageQueueClass = env->FindClass(envptr, "android/os/MessageQueue");
|
const struct JNIInvokeInterface ** jniiptr = gapp->activity->vm;
|
||||||
//webview // jmethodID nextMethod = env->GetMethodID( envptr, MessageQueueClass, "next", "()Landroid/os/Message;" );
|
const struct JNIInvokeInterface * jnii = *jniiptr;
|
||||||
//webview //
|
|
||||||
//webview // jclass MessageClass = env->FindClass(envptr, "android/os/Message");
|
jnii->AttachCurrentThread( jniiptr, &envptr, NULL);
|
||||||
//webview // jfieldID objid = env->GetFieldID( envptr, MessageClass, "obj", "Ljava/lang/Object;" );
|
env = (*envptr);
|
||||||
//webview // jclass PairClass = env->FindClass(envptr, "android/util/Pair");
|
|
||||||
//webview // jfieldID pairfirst = env->GetFieldID( envptr, PairClass, "first", "Ljava/lang/Object;" );
|
// Create a looper on this thread...
|
||||||
//webview //
|
jclass LooperClass = env->FindClass(envptr, "android/os/Looper");
|
||||||
//webview // while(1)
|
jmethodID myLooperMethod = env->GetStaticMethodID(envptr, LooperClass, "myLooper", "()Landroid/os/Looper;");
|
||||||
//webview // {
|
jobject thisLooper = env->CallStaticObjectMethod( envptr, LooperClass, myLooperMethod );
|
||||||
//webview // // Instead of using Looper::loop(), we just call next on the looper object.
|
if( !thisLooper )
|
||||||
//webview // jobject msg = env->CallObjectMethod( envptr, lque, nextMethod );
|
{
|
||||||
//webview // jobject innerObj = env->GetObjectField( envptr, msg, objid );
|
jmethodID prepareMethod = env->GetStaticMethodID(envptr, LooperClass, "prepare", "()V");
|
||||||
//webview // const char * name;
|
env->CallStaticVoidMethod( envptr, LooperClass, prepareMethod );
|
||||||
//webview // jstring strObj;
|
thisLooper = env->CallStaticObjectMethod( envptr, LooperClass, myLooperMethod );
|
||||||
//webview // jclass innerClass;
|
g_attachLooper = env->NewGlobalRef(envptr, thisLooper);
|
||||||
//webview //
|
}
|
||||||
//webview // // Check Object Type
|
|
||||||
//webview // {
|
jmethodID getQueueMethod = env->GetMethodID( envptr, LooperClass, "getQueue", "()Landroid/os/MessageQueue;" );
|
||||||
//webview // innerClass = env->GetObjectClass( envptr, innerObj );
|
jobject lque = env->CallObjectMethod( envptr, g_attachLooper, getQueueMethod );
|
||||||
//webview // jmethodID mid = env->GetMethodID( envptr, innerClass, "getClass", "()Ljava/lang/Class;");
|
|
||||||
//webview // jobject clsObj = env->CallObjectMethod( envptr, innerObj, mid );
|
jclass MessageQueueClass = env->FindClass(envptr, "android/os/MessageQueue");
|
||||||
//webview // jclass clazzz = env->GetObjectClass( envptr, clsObj );
|
jmethodID nextMethod = env->GetMethodID( envptr, MessageQueueClass, "next", "()Landroid/os/Message;" );
|
||||||
//webview // mid = env->GetMethodID(envptr, clazzz, "getName", "()Ljava/lang/String;");
|
|
||||||
//webview // strObj = (jstring)env->CallObjectMethod( envptr, clsObj, mid);
|
jclass MessageClass = env->FindClass(envptr, "android/os/Message");
|
||||||
//webview // name = env->GetStringUTFChars( envptr, strObj, 0);
|
jfieldID objid = env->GetFieldID( envptr, MessageClass, "obj", "Ljava/lang/Object;" );
|
||||||
//webview // env->DeleteLocalRef( envptr, clsObj );
|
jclass PairClass = env->FindClass(envptr, "android/util/Pair");
|
||||||
//webview // env->DeleteLocalRef( envptr, clazzz );
|
jfieldID pairfirst = env->GetFieldID( envptr, PairClass, "first", "Ljava/lang/Object;" );
|
||||||
//webview // }
|
|
||||||
//webview //
|
while(1)
|
||||||
//webview // if( strcmp( name, "z5" ) == 0 )
|
{
|
||||||
//webview // {
|
// Instead of using Looper::loop(), we just call next on the looper object.
|
||||||
//webview // // Special, Some Androids (notably Meta Quest) use a different private message type.
|
jobject msg = env->CallObjectMethod( envptr, lque, nextMethod );
|
||||||
//webview // jfieldID mstrf = env->GetFieldID( envptr, innerClass, "a", "[B" );
|
jobject innerObj = env->GetObjectField( envptr, msg, objid );
|
||||||
//webview // jbyteArray jba = (jstring)env->GetObjectField(envptr, innerObj, mstrf );
|
const char * name;
|
||||||
//webview // int len = env->GetArrayLength( envptr, jba );
|
jstring strObj;
|
||||||
//webview // jboolean isCopy = 0;
|
jclass innerClass;
|
||||||
//webview // jbyte * bufferPtr = env->GetByteArrayElements(envptr, jba, &isCopy);
|
|
||||||
//webview //
|
// Check Object Type
|
||||||
//webview // if( len >= 6 )
|
{
|
||||||
//webview // {
|
innerClass = env->GetObjectClass( envptr, innerObj );
|
||||||
//webview // const char *descr = (const char*)bufferPtr + 6;
|
jmethodID mid = env->GetMethodID( envptr, innerClass, "getClass", "()Ljava/lang/Class;");
|
||||||
//webview // char tcpy[len-5];
|
jobject clsObj = env->CallObjectMethod( envptr, innerObj, mid );
|
||||||
//webview // memcpy( tcpy, descr, len-6 );
|
jclass clazzz = env->GetObjectClass( envptr, clsObj );
|
||||||
//webview // tcpy[len-6] = 0;
|
mid = env->GetMethodID(envptr, clazzz, "getName", "()Ljava/lang/String;");
|
||||||
//webview // snprintf( fromJSBuffer, sizeof( fromJSBuffer)-1, "WebMessage: %s\n", tcpy );
|
strObj = (jstring)env->CallObjectMethod( envptr, clsObj, mid);
|
||||||
//webview //
|
name = env->GetStringUTFChars( envptr, strObj, 0);
|
||||||
//webview // env->DeleteLocalRef( envptr, jba );
|
env->DeleteLocalRef( envptr, clsObj );
|
||||||
//webview // }
|
env->DeleteLocalRef( envptr, clazzz );
|
||||||
//webview // }
|
}
|
||||||
//webview // else
|
|
||||||
//webview // {
|
if( strcmp( name, "z5" ) == 0 )
|
||||||
//webview // jobject MessagePayload = env->GetObjectField( envptr, innerObj, pairfirst );
|
{
|
||||||
//webview // // MessagePayload is a org.chromium.content_public.browser.MessagePayload
|
// Special, Some Androids (notably Meta Quest) use a different private message type.
|
||||||
//webview //
|
jfieldID mstrf = env->GetFieldID( envptr, innerClass, "a", "[B" );
|
||||||
//webview // jclass mpclass = env->GetObjectClass( envptr, MessagePayload );
|
jbyteArray jba = (jstring)env->GetObjectField(envptr, innerObj, mstrf );
|
||||||
//webview //
|
int len = env->GetArrayLength( envptr, jba );
|
||||||
//webview // // Get field "b" which is the web message payload.
|
jboolean isCopy = 0;
|
||||||
//webview // // If you are using binary sockets, it will be in `c` and be a byte array.
|
jbyte * bufferPtr = env->GetByteArrayElements(envptr, jba, &isCopy);
|
||||||
//webview // jfieldID mstrf = env->GetFieldID( envptr, mpclass, "b", "Ljava/lang/String;" );
|
|
||||||
//webview // jstring strObjDescr = (jstring)env->GetObjectField(envptr, MessagePayload, mstrf );
|
if( len >= 6 )
|
||||||
//webview //
|
{
|
||||||
//webview // const char *descr = env->GetStringUTFChars( envptr, strObjDescr, 0);
|
const char *descr = (const char*)bufferPtr + 6;
|
||||||
//webview // snprintf( fromJSBuffer, sizeof( fromJSBuffer)-1, "WebMessage: %s\n", descr );
|
char tcpy[len-5];
|
||||||
//webview //
|
memcpy( tcpy, descr, len-6 );
|
||||||
//webview // env->ReleaseStringUTFChars(envptr, strObjDescr, descr);
|
tcpy[len-6] = 0;
|
||||||
//webview // env->DeleteLocalRef( envptr, strObjDescr );
|
snprintf( fromJSBuffer, sizeof( fromJSBuffer)-1, "WebMessage: %s\n", tcpy );
|
||||||
//webview // env->DeleteLocalRef( envptr, MessagePayload );
|
|
||||||
//webview // env->DeleteLocalRef( envptr, mpclass );
|
env->DeleteLocalRef( envptr, jba );
|
||||||
//webview // }
|
}
|
||||||
//webview // env->ReleaseStringUTFChars(envptr, strObj, name);
|
}
|
||||||
//webview // env->DeleteLocalRef( envptr, strObj );
|
else
|
||||||
//webview // env->DeleteLocalRef( envptr, msg );
|
{
|
||||||
//webview // env->DeleteLocalRef( envptr, innerObj );
|
jobject MessagePayload = env->GetObjectField( envptr, innerObj, pairfirst );
|
||||||
//webview // env->DeleteLocalRef( envptr, innerClass );
|
// MessagePayload is a org.chromium.content_public.browser.MessagePayload
|
||||||
//webview // }
|
|
||||||
//webview //}
|
jclass mpclass = env->GetObjectClass( envptr, MessagePayload );
|
||||||
//webview //
|
|
||||||
//webview //void SetupJSThread()
|
// Get field "b" which is the web message payload.
|
||||||
//webview //{
|
// If you are using binary sockets, it will be in `c` and be a byte array.
|
||||||
//webview // pthread_create( &jsthread, 0, JavscriptThread, 0 );
|
jfieldID mstrf = env->GetFieldID( envptr, mpclass, "b", "Ljava/lang/String;" );
|
||||||
//webview //}
|
jstring strObjDescr = (jstring)env->GetObjectField(envptr, MessagePayload, mstrf );
|
||||||
|
|
||||||
|
const char *descr = env->GetStringUTFChars( envptr, strObjDescr, 0);
|
||||||
|
snprintf( fromJSBuffer, sizeof( fromJSBuffer)-1, "WebMessage: %s\n", descr );
|
||||||
|
|
||||||
|
env->ReleaseStringUTFChars(envptr, strObjDescr, descr);
|
||||||
|
env->DeleteLocalRef( envptr, strObjDescr );
|
||||||
|
env->DeleteLocalRef( envptr, MessagePayload );
|
||||||
|
env->DeleteLocalRef( envptr, mpclass );
|
||||||
|
}
|
||||||
|
env->ReleaseStringUTFChars(envptr, strObj, name);
|
||||||
|
env->DeleteLocalRef( envptr, strObj );
|
||||||
|
env->DeleteLocalRef( envptr, msg );
|
||||||
|
env->DeleteLocalRef( envptr, innerObj );
|
||||||
|
env->DeleteLocalRef( envptr, innerClass );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetupJSThread()
|
||||||
|
{
|
||||||
|
pthread_create( &jsthread, 0, JavscriptThread, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
int main( int argc, char ** argv )
|
int main( int argc, char ** argv )
|
||||||
{
|
{
|
||||||
//Heightmap int x, y;
|
//Heightmap int x, y;
|
||||||
//why this? double ThisTime;
|
//why this? double ThisTime;
|
||||||
//why this? double LastFPSTime = OGGetAbsoluteTime();
|
//why this? double LastFPSTime = OGGetAbsoluteTime();
|
||||||
|
|
||||||
Log( "Starting Up" );
|
Log( "Starting Up" );
|
||||||
|
|
||||||
CNFGBGColor = 0x000040ff;
|
CNFGBGColor = 0x000040ff;
|
||||||
CNFGSetupFullscreen( "Test Bench", 0 );
|
CNFGSetupFullscreen( "Test Bench", 0 );
|
||||||
|
CNFGGetDimensions( &screenx, &screeny );
|
||||||
|
char mystring[900];
|
||||||
|
|
||||||
|
size_t webviewdatasize = sizeof(uint32_t) * screeny * screenx;
|
||||||
|
sprintf( mystring, "MYSTRING %dx%d,%ld",screenx, screeny,webviewdatasize);
|
||||||
|
__android_log_print(ANDROID_LOG_VERBOSE, APPNAME,"%s",mystring);
|
||||||
|
// Log(mystring );
|
||||||
|
|
||||||
|
webviewdata = malloc(webviewdatasize);
|
||||||
|
|
||||||
|
|
||||||
HandleWindowTermination = HandleThisWindowTermination;
|
HandleWindowTermination = HandleThisWindowTermination;
|
||||||
|
|
||||||
|
|
@ -550,11 +572,11 @@ int main( int argc, char ** argv )
|
||||||
//SOUND // Disabled, for now.
|
//SOUND // Disabled, for now.
|
||||||
//SOUND //InitCNFAAndroid( AudioCallback, "A Name", SAMPLE_RATE, 0, 1, 0, SAMPLE_COUNT, 0, 0, 0 );
|
//SOUND //InitCNFAAndroid( AudioCallback, "A Name", SAMPLE_RATE, 0, 1, 0, SAMPLE_COUNT, 0, 0, 0 );
|
||||||
|
|
||||||
//webview// SetupJSThread();
|
SetupJSThread();
|
||||||
|
|
||||||
//webview // Create webview and wait for its completion
|
// Create webview and wait for its completion
|
||||||
//webview // RunCallbackOnUIThread( SetupWebView, &MyWebView );
|
RunCallbackOnUIThread( SetupWebView, &MyWebView );
|
||||||
//webview // while( !MyWebView.WebViewObject ) usleep(1);
|
while( !MyWebView.WebViewObject ) usleep(1);
|
||||||
|
|
||||||
Log( "Startup Complete" );
|
Log( "Startup Complete" );
|
||||||
|
|
||||||
|
|
@ -573,8 +595,8 @@ int main( int argc, char ** argv )
|
||||||
|
|
||||||
if( suspended ) { usleep(1000000); continue; }
|
if( suspended ) { usleep(1000000); continue; }
|
||||||
|
|
||||||
//webview // RunCallbackOnUIThread( (void(*)(void*))WebViewRequestRenderToCanvas, &MyWebView );
|
RunCallbackOnUIThread( (void(*)(void*))WebViewRequestRenderToCanvas, &MyWebView );
|
||||||
//webview // RunCallbackOnUIThread( CheckWebView, &MyWebView );
|
RunCallbackOnUIThread( CheckWebView, &MyWebView );
|
||||||
|
|
||||||
CNFGClearFrame();
|
CNFGClearFrame();
|
||||||
CNFGColor( 0xFFFFFFFF );
|
CNFGColor( 0xFFFFFFFF );
|
||||||
|
|
@ -633,10 +655,10 @@ int main( int argc, char ** argv )
|
||||||
//graphic-triangles CNFGTackPoly( pp, 3 );
|
//graphic-triangles CNFGTackPoly( pp, 3 );
|
||||||
//graphic-triangles }
|
//graphic-triangles }
|
||||||
|
|
||||||
//webview // Last WebMessage
|
// Last WebMessage
|
||||||
//webview CNFGColor( 0xFFFFFFFF );
|
CNFGColor( 0xFFFFFFFF );
|
||||||
//webview CNFGPenX = 0; CNFGPenY = 100;
|
CNFGPenX = 0; CNFGPenY = 100;
|
||||||
//webview // CNFGDrawText( fromJSBuffer, 6 );
|
CNFGDrawText( fromJSBuffer, 6 );
|
||||||
|
|
||||||
//graphic-random-texture int x, y;
|
//graphic-random-texture int x, y;
|
||||||
//graphic-random-texture for( y = 0; y < 256; y++ )
|
//graphic-random-texture for( y = 0; y < 256; y++ )
|
||||||
|
|
@ -644,8 +666,8 @@ int main( int argc, char ** argv )
|
||||||
//graphic-random-texture randomtexturedata[x+y*256] = x | ((x*394543L+y*355+iframeno*3)<<8);
|
//graphic-random-texture randomtexturedata[x+y*256] = x | ((x*394543L+y*355+iframeno*3)<<8);
|
||||||
//graphic-random-texture CNFGBlitImage( randomtexturedata, 100, 600, 256, 256 );
|
//graphic-random-texture CNFGBlitImage( randomtexturedata, 100, 600, 256, 256 );
|
||||||
|
|
||||||
//webview //WebViewNativeGetPixels( &MyWebView, webviewdata, 500, 500 );
|
WebViewNativeGetPixels( &MyWebView, webviewdata,screenx,screeny);
|
||||||
//webview //CNFGBlitImage( webviewdata, 500, 640, 500, 500 );
|
CNFGBlitImage( webviewdata, 0, 0, screenx,screeny );
|
||||||
|
|
||||||
//why this? frames++;
|
//why this? frames++;
|
||||||
//On Android, CNFGSwapBuffers must be called, and CNFGUpdateScreenWithBitmap does not have an implied framebuffer swap.
|
//On Android, CNFGSwapBuffers must be called, and CNFGUpdateScreenWithBitmap does not have an implied framebuffer swap.
|
||||||
|
|
|
||||||
312
app/src/nativecode/webview_native_activity.h
Normal file
312
app/src/nativecode/webview_native_activity.h
Normal file
|
|
@ -0,0 +1,312 @@
|
||||||
|
#ifndef _WEBVIEW_NATIVE_ACTIVITY
|
||||||
|
#define _WEBVIEW_NATIVE_ACTIVITY
|
||||||
|
|
||||||
|
#include <android/native_activity.h>
|
||||||
|
|
||||||
|
extern volatile jobject g_objRootView;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
jobject WebViewObject;
|
||||||
|
jobjectArray MessageChannels;
|
||||||
|
jobject BackingBitmap;
|
||||||
|
jobject BackingCanvas;
|
||||||
|
int updated_canvas;
|
||||||
|
int w, h;
|
||||||
|
} WebViewNativeActivityObject;
|
||||||
|
|
||||||
|
// Must be called from main thread
|
||||||
|
|
||||||
|
// initial_url = "about:blank" for a java-script only page. Can also be file:///android_asset/test.html.
|
||||||
|
// Loading from "about:blank" will make the page ready almost immediately, otherwise it's about 50ms to load.
|
||||||
|
// useLooperForWebMessages is required, and must be a global jobject of your preferred looper to handle webmessages.
|
||||||
|
void WebViewCreate( WebViewNativeActivityObject * w, const char * initial_url, jobject useLooperForWebMessages, int pw, int ph );
|
||||||
|
void WebViewExecuteJavascript( WebViewNativeActivityObject * obj, const char * js );
|
||||||
|
|
||||||
|
// Note: Do not initialize until page reports as 100% loaded, with WebViewGetProgress.
|
||||||
|
void WebViewPostMessage( WebViewNativeActivityObject * obj, const char * mesg, int initial );
|
||||||
|
void WebViewRequestRenderToCanvas( WebViewNativeActivityObject * obj );
|
||||||
|
int WebViewGetProgress( WebViewNativeActivityObject * obj );
|
||||||
|
char * WebViewGetLastWindowTitle( WebViewNativeActivityObject * obj );
|
||||||
|
|
||||||
|
// Can be called from any thread.
|
||||||
|
void WebViewNativeGetPixels( WebViewNativeActivityObject * obj, uint32_t * pixel_data, int w, int h );
|
||||||
|
|
||||||
|
#ifdef WEBVIEW_NATIVE_ACTIVITY_IMPLEMENTATION
|
||||||
|
|
||||||
|
volatile jobject g_objRootView;
|
||||||
|
|
||||||
|
void WebViewCreate( WebViewNativeActivityObject * w, const char * initial_url, jobject useLooperForWebMessages, int pw, int ph )
|
||||||
|
{
|
||||||
|
const struct JNINativeInterface * env = 0;
|
||||||
|
const struct JNINativeInterface ** envptr = &env;
|
||||||
|
const struct JNIInvokeInterface ** jniiptr = gapp->activity->vm;
|
||||||
|
jobject clazz = gapp->activity->clazz;
|
||||||
|
const struct JNIInvokeInterface * jnii = *jniiptr;
|
||||||
|
|
||||||
|
jnii->AttachCurrentThread( jniiptr, &envptr, NULL);
|
||||||
|
env = (*envptr);
|
||||||
|
|
||||||
|
if( g_objRootView == 0 )
|
||||||
|
{
|
||||||
|
jclass ViewClass = env->FindClass(envptr, "android/widget/LinearLayout");
|
||||||
|
jmethodID ViewConstructor = env->GetMethodID(envptr, ViewClass, "<init>", "(Landroid/content/Context;)V");
|
||||||
|
jclass activityClass = env->FindClass(envptr, "android/app/Activity");
|
||||||
|
jmethodID activityGetContextMethod = env->GetMethodID(envptr, activityClass, "getApplicationContext", "()Landroid/content/Context;");
|
||||||
|
jobject contextObject = env->CallObjectMethod(envptr, clazz, activityGetContextMethod);
|
||||||
|
jobject jv = env->NewObject(envptr, ViewClass, ViewConstructor, contextObject );
|
||||||
|
g_objRootView = env->NewGlobalRef(envptr, jv);
|
||||||
|
|
||||||
|
jclass clszz = env->GetObjectClass(envptr,clazz);
|
||||||
|
jmethodID setContentViewMethod = env->GetMethodID(envptr, clszz, "setContentView", "(Landroid/view/View;)V");
|
||||||
|
env->CallVoidMethod(envptr,clazz, setContentViewMethod, g_objRootView );
|
||||||
|
}
|
||||||
|
|
||||||
|
jclass WebViewClass = env->FindClass(envptr, "android/webkit/WebView");
|
||||||
|
jclass activityClass = env->FindClass(envptr, "android/app/Activity");
|
||||||
|
jmethodID activityGetContextMethod = env->GetMethodID(envptr, activityClass, "getApplicationContext", "()Landroid/content/Context;");
|
||||||
|
jobject contextObject = env->CallObjectMethod(envptr, clazz, activityGetContextMethod);
|
||||||
|
|
||||||
|
jmethodID WebViewConstructor = env->GetMethodID(envptr, WebViewClass, "<init>", "(Landroid/content/Context;)V");
|
||||||
|
jobject wvObj = env->NewObject(envptr, WebViewClass, WebViewConstructor, contextObject );
|
||||||
|
|
||||||
|
// Unknown reason why - if you don't first load about:blank, it sometimes doesn't render right?
|
||||||
|
// Even more annoying - you can't pre-use loadUrl if you want to use message channels.
|
||||||
|
jmethodID WebViewLoadBaseURLMethod = env->GetMethodID(envptr, WebViewClass, "loadDataWithBaseURL", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
||||||
|
jstring strul = env->NewStringUTF( envptr, "http://example.com" );
|
||||||
|
jstring strdata = env->NewStringUTF( envptr, "not-yet-loaded" );
|
||||||
|
jstring strmime = env->NewStringUTF( envptr, "text/html" );
|
||||||
|
jstring strencoding = env->NewStringUTF( envptr, "utf8" );
|
||||||
|
jstring strhistoryurl = env->NewStringUTF( envptr, "" );
|
||||||
|
env->CallVoidMethod(envptr, wvObj, WebViewLoadBaseURLMethod, strul, strdata, strmime, strencoding, strhistoryurl );
|
||||||
|
env->DeleteLocalRef( envptr, strul );
|
||||||
|
env->DeleteLocalRef( envptr, strdata );
|
||||||
|
env->DeleteLocalRef( envptr, strmime );
|
||||||
|
env->DeleteLocalRef( envptr, strencoding );
|
||||||
|
env->DeleteLocalRef( envptr, strhistoryurl );
|
||||||
|
|
||||||
|
// You have to switch to this to be able to run javascript code.
|
||||||
|
jmethodID LoadURLMethod = env->GetMethodID(envptr, WebViewClass, "loadUrl", "(Ljava/lang/String;)V");
|
||||||
|
jstring strjs = env->NewStringUTF( envptr, initial_url );
|
||||||
|
env->CallVoidMethod(envptr, wvObj, LoadURLMethod, strjs );
|
||||||
|
env->DeleteLocalRef( envptr, strjs );
|
||||||
|
|
||||||
|
jmethodID WebViewGetSettingMethod = env->GetMethodID(envptr, WebViewClass, "getSettings", "()Landroid/webkit/WebSettings;");
|
||||||
|
jobject websettings = env->CallObjectMethod(envptr, wvObj, WebViewGetSettingMethod );
|
||||||
|
jclass WebSettingsClass = env->FindClass(envptr, "android/webkit/WebSettings");
|
||||||
|
jmethodID setJavaScriptEnabledMethod = env->GetMethodID(envptr, WebSettingsClass, "setJavaScriptEnabled", "(Z)V");
|
||||||
|
env->CallVoidMethod( envptr, websettings, setJavaScriptEnabledMethod, true );
|
||||||
|
env->DeleteLocalRef( envptr, websettings );
|
||||||
|
|
||||||
|
jmethodID setMeasuredDimensionMethodID = env->GetMethodID(envptr, WebViewClass, "setMeasuredDimension", "(II)V");
|
||||||
|
env->CallVoidMethod(envptr, wvObj, setMeasuredDimensionMethodID, pw, ph );
|
||||||
|
|
||||||
|
jclass ViewClass = env->FindClass(envptr, "android/widget/LinearLayout");
|
||||||
|
jmethodID addViewMethod = env->GetMethodID(envptr, ViewClass, "addView", "(Landroid/view/View;)V");
|
||||||
|
env->CallVoidMethod( envptr, g_objRootView, addViewMethod, wvObj );
|
||||||
|
|
||||||
|
jclass WebMessagePortClass = env->FindClass(envptr, "android/webkit/WebMessagePort" );
|
||||||
|
jmethodID createWebMessageChannelMethod = env->GetMethodID(envptr, WebViewClass, "createWebMessageChannel", "()[Landroid/webkit/WebMessagePort;");
|
||||||
|
jobjectArray messageChannels = env->CallObjectMethod( envptr, wvObj, createWebMessageChannelMethod );
|
||||||
|
jobject mc0 = env->GetObjectArrayElement(envptr, messageChannels, 0); // MC1 is handed over to javascript.
|
||||||
|
|
||||||
|
jclass HandlerClassType = env->FindClass(envptr, "android/os/Handler" );
|
||||||
|
jmethodID HandlerObjectConstructor = env->GetMethodID(envptr, HandlerClassType, "<init>", "(Landroid/os/Looper;)V");
|
||||||
|
jobject handlerObject = env->NewObject( envptr, HandlerClassType, HandlerObjectConstructor, useLooperForWebMessages );
|
||||||
|
handlerObject = env->NewGlobalRef(envptr, handlerObject);
|
||||||
|
jmethodID setWebMessageCallbackMethod = env->GetMethodID( envptr, WebMessagePortClass, "setWebMessageCallback", "(Landroid/webkit/WebMessagePort$WebMessageCallback;Landroid/os/Handler;)V" );
|
||||||
|
|
||||||
|
// Only can receive messages on MC0
|
||||||
|
env->CallVoidMethod( envptr, mc0, setWebMessageCallbackMethod, 0, handlerObject );
|
||||||
|
|
||||||
|
// Generate backing bitmap and canvas.
|
||||||
|
jclass CanvasClass = env->FindClass(envptr, "android/graphics/Canvas");
|
||||||
|
jclass BitmapClass = env->FindClass(envptr, "android/graphics/Bitmap");
|
||||||
|
jmethodID createBitmap = env->GetStaticMethodID(envptr, BitmapClass, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
|
||||||
|
jclass bmpCfgCls = env->FindClass(envptr, "android/graphics/Bitmap$Config");
|
||||||
|
jstring bitmap_mode = env->NewStringUTF(envptr, "ARGB_8888");
|
||||||
|
jmethodID bmpClsValueOfMid = env->GetStaticMethodID(envptr, bmpCfgCls, "valueOf", "(Ljava/lang/String;)Landroid/graphics/Bitmap$Config;");
|
||||||
|
jobject jBmpCfg = env->CallStaticObjectMethod(envptr, bmpCfgCls, bmpClsValueOfMid, bitmap_mode);
|
||||||
|
jobject bitmap = env->CallStaticObjectMethod( envptr, BitmapClass, createBitmap, pw, ph, jBmpCfg );
|
||||||
|
jmethodID canvasConstructor = env->GetMethodID(envptr, CanvasClass, "<init>", "(Landroid/graphics/Bitmap;)V");
|
||||||
|
jobject canvas = env->NewObject(envptr, CanvasClass, canvasConstructor, bitmap );
|
||||||
|
|
||||||
|
env->DeleteLocalRef( envptr, CanvasClass );
|
||||||
|
env->DeleteLocalRef( envptr, BitmapClass );
|
||||||
|
env->DeleteLocalRef( envptr, bmpCfgCls );
|
||||||
|
env->DeleteLocalRef( envptr, bitmap_mode );
|
||||||
|
|
||||||
|
w->BackingBitmap = env->NewGlobalRef(envptr, bitmap );
|
||||||
|
w->BackingCanvas = env->NewGlobalRef(envptr, canvas );
|
||||||
|
w->WebViewObject = env->NewGlobalRef(envptr, wvObj);
|
||||||
|
w->MessageChannels = env->NewGlobalRef(envptr, messageChannels);
|
||||||
|
w->w = pw;
|
||||||
|
w->h = ph;
|
||||||
|
|
||||||
|
env->DeleteLocalRef( envptr, WebViewClass );
|
||||||
|
env->DeleteLocalRef( envptr, activityClass );
|
||||||
|
env->DeleteLocalRef( envptr, WebSettingsClass );
|
||||||
|
env->DeleteLocalRef( envptr, ViewClass );
|
||||||
|
}
|
||||||
|
|
||||||
|
int WebViewGetProgress( WebViewNativeActivityObject * obj )
|
||||||
|
{
|
||||||
|
const struct JNINativeInterface * env = 0;
|
||||||
|
const struct JNINativeInterface ** envptr = &env;
|
||||||
|
const struct JNIInvokeInterface ** jniiptr = gapp->activity->vm;
|
||||||
|
const struct JNIInvokeInterface * jnii = *jniiptr;
|
||||||
|
|
||||||
|
jnii->AttachCurrentThread( jniiptr, &envptr, NULL);
|
||||||
|
env = (*envptr);
|
||||||
|
|
||||||
|
jclass WebViewClass = env->FindClass(envptr, "android/webkit/WebView");
|
||||||
|
jmethodID WebViewProgress = env->GetMethodID(envptr, WebViewClass, "getProgress", "()I");
|
||||||
|
int ret = env->CallIntMethod( envptr, obj->WebViewObject, WebViewProgress );
|
||||||
|
env->DeleteLocalRef( envptr, WebViewClass );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebViewPostMessage( WebViewNativeActivityObject * w, const char * mesg, int initial )
|
||||||
|
{
|
||||||
|
const struct JNINativeInterface * env = 0;
|
||||||
|
const struct JNINativeInterface ** envptr = &env;
|
||||||
|
const struct JNIInvokeInterface ** jniiptr = gapp->activity->vm;
|
||||||
|
const struct JNIInvokeInterface * jnii = *jniiptr;
|
||||||
|
|
||||||
|
jnii->AttachCurrentThread( jniiptr, &envptr, NULL);
|
||||||
|
env = (*envptr);
|
||||||
|
|
||||||
|
jclass WebMessagePortClass = env->FindClass(envptr, "android/webkit/WebMessagePort" );
|
||||||
|
jclass WebViewClass = env->FindClass(envptr, "android/webkit/WebView");
|
||||||
|
jclass WebMessageClass = env->FindClass(envptr, "android/webkit/WebMessage" );
|
||||||
|
|
||||||
|
jstring strjs = env->NewStringUTF( envptr, mesg );
|
||||||
|
|
||||||
|
if( initial )
|
||||||
|
{
|
||||||
|
jobject mc1 = env->GetObjectArrayElement(envptr, w->MessageChannels, 1);
|
||||||
|
jmethodID WebMessageConstructor = env->GetMethodID(envptr, WebMessageClass, "<init>", "(Ljava/lang/String;[Landroid/webkit/WebMessagePort;)V");
|
||||||
|
|
||||||
|
//https://stackoverflow.com/questions/41753104/how-do-you-use-webmessageport-as-an-alternative-to-addjavascriptinterface
|
||||||
|
// Only on initial hop do we want to post the root webmessage, which hooks up out webmessage port.
|
||||||
|
jmethodID postMessageMethod = env->GetMethodID(envptr, WebViewClass, "postWebMessage", "(Landroid/webkit/WebMessage;Landroid/net/Uri;)V");
|
||||||
|
|
||||||
|
// Need to generate a new message channel array.
|
||||||
|
jobjectArray jsUseWebPorts = env->NewObjectArray( envptr, 1, WebMessagePortClass, mc1);
|
||||||
|
|
||||||
|
// Need Uri.EMPTY
|
||||||
|
jclass UriClass = env->FindClass(envptr, "android/net/Uri" );
|
||||||
|
jfieldID EmptyField = env->GetStaticFieldID( envptr, UriClass, "EMPTY", "Landroid/net/Uri;" );
|
||||||
|
jobject EmptyURI = env->GetStaticObjectField( envptr, UriClass, EmptyField );
|
||||||
|
|
||||||
|
|
||||||
|
jobject newwm = env->NewObject(envptr, WebMessageClass, WebMessageConstructor, strjs, jsUseWebPorts );
|
||||||
|
env->CallVoidMethod( envptr, w->WebViewObject, postMessageMethod, newwm, EmptyURI );
|
||||||
|
|
||||||
|
env->DeleteLocalRef( envptr, jsUseWebPorts );
|
||||||
|
env->DeleteLocalRef( envptr, newwm );
|
||||||
|
env->DeleteLocalRef( envptr, EmptyURI );
|
||||||
|
env->DeleteLocalRef( envptr, UriClass );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
jobject mc0 = env->GetObjectArrayElement(envptr, w->MessageChannels, 0);
|
||||||
|
jmethodID postMessageMethod = env->GetMethodID(envptr, WebMessagePortClass, "postMessage", "(Landroid/webkit/WebMessage;)V");
|
||||||
|
jmethodID WebMessageConstructor = env->GetMethodID(envptr, WebMessageClass, "<init>", "(Ljava/lang/String;)V");
|
||||||
|
|
||||||
|
jobject newwm = env->NewObject(envptr, WebMessageClass, WebMessageConstructor, strjs );
|
||||||
|
env->CallVoidMethod( envptr, mc0, postMessageMethod, newwm );
|
||||||
|
|
||||||
|
env->DeleteLocalRef( envptr, newwm );
|
||||||
|
env->DeleteLocalRef( envptr, mc0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
env->DeleteLocalRef( envptr, strjs );
|
||||||
|
env->DeleteLocalRef( envptr, WebViewClass );
|
||||||
|
env->DeleteLocalRef( envptr, WebMessageClass );
|
||||||
|
env->DeleteLocalRef( envptr, WebMessagePortClass );
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebViewRequestRenderToCanvas( WebViewNativeActivityObject * obj )
|
||||||
|
{
|
||||||
|
const struct JNINativeInterface * env = 0;
|
||||||
|
const struct JNINativeInterface ** envptr = &env;
|
||||||
|
const struct JNIInvokeInterface ** jniiptr = gapp->activity->vm;
|
||||||
|
const struct JNIInvokeInterface * jnii = *jniiptr;
|
||||||
|
|
||||||
|
jnii->AttachCurrentThread( jniiptr, &envptr, NULL);
|
||||||
|
env = (*envptr);
|
||||||
|
|
||||||
|
jclass WebViewClass = env->FindClass(envptr, "android/webkit/WebView");
|
||||||
|
jmethodID drawMethod = env->GetMethodID(envptr, WebViewClass, "draw", "(Landroid/graphics/Canvas;)V");
|
||||||
|
env->CallVoidMethod( envptr, obj->WebViewObject, drawMethod, obj->BackingCanvas );
|
||||||
|
env->DeleteLocalRef( envptr, WebViewClass );
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebViewNativeGetPixels( WebViewNativeActivityObject * obj, uint32_t * pixel_data, int w, int h )
|
||||||
|
{
|
||||||
|
const struct JNINativeInterface * env = 0;
|
||||||
|
const struct JNINativeInterface ** envptr = &env;
|
||||||
|
const struct JNIInvokeInterface ** jniiptr = gapp->activity->vm;
|
||||||
|
const struct JNIInvokeInterface * jnii = *jniiptr;
|
||||||
|
|
||||||
|
jnii->AttachCurrentThread( jniiptr, &envptr, NULL);
|
||||||
|
env = (*envptr);
|
||||||
|
|
||||||
|
jclass BitmapClass = env->FindClass(envptr, "android/graphics/Bitmap");
|
||||||
|
jobject buffer = env->NewDirectByteBuffer(envptr, pixel_data, obj->w*obj->h*4 );
|
||||||
|
jmethodID copyPixelsBufferID = env->GetMethodID( envptr, BitmapClass, "copyPixelsToBuffer", "(Ljava/nio/Buffer;)V" );
|
||||||
|
env->CallVoidMethod( envptr, obj->BackingBitmap, copyPixelsBufferID, buffer );
|
||||||
|
|
||||||
|
int i;
|
||||||
|
int num = obj->w * obj->h;
|
||||||
|
for( i = 0; i < num; i++ ) pixel_data[i] = bswap_32( pixel_data[i] );
|
||||||
|
|
||||||
|
env->DeleteLocalRef( envptr, BitmapClass );
|
||||||
|
env->DeleteLocalRef( envptr, buffer );
|
||||||
|
|
||||||
|
jnii->DetachCurrentThread( jniiptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebViewExecuteJavascript( WebViewNativeActivityObject * obj, const char * js )
|
||||||
|
{
|
||||||
|
const struct JNINativeInterface * env = 0;
|
||||||
|
const struct JNINativeInterface ** envptr = &env;
|
||||||
|
const struct JNIInvokeInterface ** jniiptr = gapp->activity->vm;
|
||||||
|
const struct JNIInvokeInterface * jnii = *jniiptr;
|
||||||
|
jnii->AttachCurrentThread( jniiptr, &envptr, NULL);
|
||||||
|
env = (*envptr);
|
||||||
|
|
||||||
|
jclass WebViewClass = env->FindClass(envptr, "android/webkit/WebView");
|
||||||
|
jmethodID WebViewEvalJSMethod = env->GetMethodID(envptr, WebViewClass, "evaluateJavascript", "(Ljava/lang/String;Landroid/webkit/ValueCallback;)V");
|
||||||
|
|
||||||
|
//WebView.evaluateJavascript(String script, ValueCallback<String> resultCallback)
|
||||||
|
jstring strjs = env->NewStringUTF( envptr, js );
|
||||||
|
env->CallVoidMethod( envptr, obj->WebViewObject, WebViewEvalJSMethod, strjs, 0 ); // Tricky: resultCallback = 0, if you try running looper.loop() it will crash - only manually process messages.
|
||||||
|
env->DeleteLocalRef( envptr, WebViewClass );
|
||||||
|
env->DeleteLocalRef( envptr, strjs );
|
||||||
|
}
|
||||||
|
|
||||||
|
char * WebViewGetLastWindowTitle( WebViewNativeActivityObject * obj )
|
||||||
|
{
|
||||||
|
const struct JNINativeInterface * env = 0;
|
||||||
|
const struct JNINativeInterface ** envptr = &env;
|
||||||
|
const struct JNIInvokeInterface ** jniiptr = gapp->activity->vm;
|
||||||
|
const struct JNIInvokeInterface * jnii = *jniiptr;
|
||||||
|
jnii->AttachCurrentThread( jniiptr, &envptr, NULL);
|
||||||
|
env = (*envptr);
|
||||||
|
|
||||||
|
jclass WebViewClass = env->FindClass(envptr, "android/webkit/WebView");
|
||||||
|
jmethodID getTitle = env->GetMethodID(envptr, WebViewClass, "getTitle", "()Ljava/lang/String;");
|
||||||
|
jobject titleObject = env->CallObjectMethod( envptr, obj->WebViewObject, getTitle );
|
||||||
|
char *nativeString = strdup( env->GetStringUTFChars(envptr, titleObject, 0) );
|
||||||
|
env->DeleteLocalRef( envptr, titleObject );
|
||||||
|
env->DeleteLocalRef( envptr, WebViewClass );
|
||||||
|
|
||||||
|
return nativeString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
Loading…
Add table
Reference in a new issue