Support web3d overlays in android

This commit is contained in:
Gabriel Calero 2018-06-25 16:37:03 -03:00
parent 4088035b3b
commit fedc0a9e61
9 changed files with 185 additions and 32 deletions

View file

@ -29,6 +29,7 @@
</intent-filter>
</activity>
<activity android:name="io.highfidelity.hifiinterface.WebViewActivity"
android:configChanges="orientation"
android:theme="@android:style/Theme.Material.Light.NoActionBar"/>
<!-- We don't want to show this on Daydream yet (we need to fix the turn-around problem on this screen)
<activity android:name="io.highfidelity.hifiinterface.GvrLoaderActivity">

View file

@ -153,10 +153,29 @@ JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeOnCrea
unpackAndroidAssets();
qInstallMessageHandler(oldMessageHandler);
QObject::connect(&AndroidHelper::instance(), &AndroidHelper::androidActivityRequested, [](const QString& a, const bool backToScene) {
JavaVM* jvm;
env->GetJavaVM(&jvm);
QObject::connect(&AndroidHelper::instance(), &AndroidHelper::androidActivityRequested, [jvm](const QString& a, const bool backToScene, QList<QString> args) {
JNIEnv* myNewEnv;
JavaVMAttachArgs jvmArgs;
jvmArgs.version = JNI_VERSION_1_6; // choose your JNI version
jvmArgs.name = NULL; // you might want to give the java thread a name
jvmArgs.group = NULL; // you might want to assign the java thread to a ThreadGroup
jvm->AttachCurrentThread(reinterpret_cast<JNIEnv **>(&myNewEnv), &jvmArgs);
QAndroidJniObject string = QAndroidJniObject::fromString(a);
jboolean jBackToScene = (jboolean) backToScene;
__interfaceActivity.callMethod<void>("openAndroidActivity", "(Ljava/lang/String;Z)V", string.object<jstring>(), jBackToScene);
jclass hashMapClass = myNewEnv->FindClass("java/util/HashMap");
jmethodID mapClassConstructor = myNewEnv->GetMethodID(hashMapClass, "<init>", "()V");
jobject hashmap = myNewEnv->NewObject(hashMapClass, mapClassConstructor);
jmethodID mapClassPut = myNewEnv->GetMethodID(hashMapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
for (const QString& arg: args) {
QAndroidJniObject jArg = QAndroidJniObject::fromString(arg);
myNewEnv->CallObjectMethod(hashmap, mapClassPut, QAndroidJniObject::fromString("url").object<jstring>(), jArg.object<jstring>());
}
__interfaceActivity.callMethod<void>("openAndroidActivity", "(Ljava/lang/String;ZLjava/util/HashMap;)V", string.object<jstring>(), jBackToScene, hashmap);
jvm->DetachCurrentThread();
});
QObject::connect(&AndroidHelper::instance(), &AndroidHelper::hapticFeedbackRequested, [](int duration) {
@ -295,4 +314,10 @@ Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeEnterForeground(JNIEn
AndroidHelper::instance().notifyEnterForeground();
}
JNIEXPORT void Java_io_highfidelity_hifiinterface_WebViewActivity_nativeProcessURL(JNIEnv* env, jobject obj, jstring url_str) {
const char *nativeString = env->GetStringUTFChars(url_str, 0);
AndroidHelper::instance().processURL(QString::fromUtf8(nativeString));
}
}

View file

@ -12,32 +12,31 @@
package io.highfidelity.hifiinterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.graphics.Point;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.view.HapticFeedbackConstants;
import android.view.WindowManager;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.FrameLayout;
import org.qtproject.qt5.android.QtLayout;
import org.qtproject.qt5.android.QtSurface;
import org.qtproject.qt5.android.bindings.QtActivity;
import java.lang.reflect.Field;
import java.util.HashMap;
/*import com.google.vr.cardboard.DisplaySynchronizer;
import com.google.vr.cardboard.DisplayUtils;
import com.google.vr.ndk.base.GvrApi;*/
import android.graphics.Point;
import android.content.res.Configuration;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.view.View;
import android.widget.FrameLayout;
import java.lang.reflect.Field;
public class InterfaceActivity extends QtActivity {
@ -244,6 +243,10 @@ public class InterfaceActivity extends QtActivity {
}
public void openAndroidActivity(String activityName, boolean backToScene) {
openAndroidActivity(activityName, backToScene, null);
}
public void openAndroidActivity(String activityName, boolean backToScene, HashMap args) {
switch (activityName) {
case "Home":
case "Privacy Policy":
@ -254,6 +257,13 @@ public class InterfaceActivity extends QtActivity {
startActivity(intent);
break;
}
case "WebView":
Intent intent = new Intent(this, WebViewActivity.class);
if (args != null && args.containsKey(WebViewActivity.WEB_VIEW_ACTIVITY_EXTRA_URL)) {
intent.putExtra(WebViewActivity.WEB_VIEW_ACTIVITY_EXTRA_URL, (String) args.get(WebViewActivity.WEB_VIEW_ACTIVITY_EXTRA_URL));
}
startActivity(intent);
break;
default: {
Log.w(TAG, "Could not open activity by name " + activityName);
break;

View file

@ -8,8 +8,6 @@
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
//package hifiinterface.highfidelity.io.mybrowserapplication;
package io.highfidelity.hifiinterface;
import android.app.ActionBar;
@ -36,9 +34,6 @@ import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.widget.Toast;
import android.widget.Toolbar;
import android.os.Looper;
import java.lang.Thread;
import java.lang.Runnable;
import java.net.MalformedURLException;
import java.net.URL;
@ -73,14 +68,13 @@ public class WebViewActivity extends Activity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_web_view);
setActionBar((Toolbar) findViewById(R.id.toolbar_actionbar));
setActionBar(findViewById(R.id.toolbar_actionbar));
mActionBar = getActionBar();
mActionBar.setDisplayHomeAsUpEnabled(true);
mProgressBar = (ProgressBar) findViewById(R.id.toolbarProgressBar);
mProgressBar = findViewById(R.id.toolbarProgressBar);
mUrl = getIntent().getStringExtra(WEB_VIEW_ACTIVITY_EXTRA_URL);
myWebView = (WebView) findViewById(R.id.web_view);
myWebView = findViewById(R.id.web_view);
myWebView.setWebViewClient(new HiFiWebViewClient());
myWebView.setWebChromeClient(new HiFiWebChromeClient());
WebSettings webSettings = myWebView.getSettings();
@ -203,11 +197,7 @@ public class WebViewActivity extends Activity {
// managing avatar selections
if (isFst(request)) {
final String url = request.getUrl().toString();
new Thread(new Runnable() {
public void run() {
nativeProcessURL(url);
}
}).start(); // Avoid deadlock in Qt dialog
new Thread(() -> nativeProcessURL(url)).start(); // Avoid deadlock in Qt dialog
WebViewActivity.this.finish();
return true;
}

View file

@ -0,0 +1,36 @@
//
// Web3DOverlay.qml
//
// Created by Gabriel Calero & Cristian Duarte on Jun 22, 2018
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
import QtQuick 2.5
Item {
property string url
Text {
id: webContentText
anchors.horizontalCenter : parent.horizontalCenter
text: "Web content\nClick to view"
font.family: "Helvetica"
font.pointSize: 24
color: "#0098CA"
}
Text {
id: urlText
text: url
anchors.horizontalCenter : parent.horizontalCenter
anchors.top : webContentText.bottom
font.family: "Helvetica"
font.pointSize: 18
color: "#0098CA"
}
}

View file

@ -11,6 +11,12 @@
#include "AndroidHelper.h"
#include <QDebug>
#include <AccountManager.h>
#include "Application.h"
#if defined(qApp)
#undef qApp
#endif
#define qApp (static_cast<Application*>(QCoreApplication::instance()))
AndroidHelper::AndroidHelper() {
}
@ -37,8 +43,8 @@ void AndroidHelper::init() {
_accountManager->moveToThread(&workerThread);
}
void AndroidHelper::requestActivity(const QString &activityName, const bool backToScene) {
emit androidActivityRequested(activityName, backToScene);
void AndroidHelper::requestActivity(const QString &activityName, const bool backToScene, QList<QString> args) {
emit androidActivityRequested(activityName, backToScene, args);
}
void AndroidHelper::notifyLoadComplete() {
@ -60,3 +66,9 @@ void AndroidHelper::performHapticFeedback(int duration) {
void AndroidHelper::showLoginDialog() {
emit androidActivityRequested("Login", true);
}
void AndroidHelper::processURL(const QString &url) {
if (qApp->canAcceptURL(url)) {
qApp->acceptURL(url);
}
}

View file

@ -24,12 +24,13 @@ public:
return instance;
}
void init();
void requestActivity(const QString &activityName, const bool backToScene);
void requestActivity(const QString &activityName, const bool backToScene, QList<QString> args = QList<QString>());
void notifyLoadComplete();
void notifyEnterForeground();
void notifyEnterBackground();
void performHapticFeedback(int duration);
void processURL(const QString &url);
QSharedPointer<AccountManager> getAccountManager() { return _accountManager; }
AndroidHelper(AndroidHelper const&) = delete;
@ -39,7 +40,7 @@ public slots:
void showLoginDialog();
signals:
void androidActivityRequested(const QString &activityName, const bool backToScene);
void androidActivityRequested(const QString &activityName, const bool backToScene, QList<QString> args = QList<QString>());
void qtAppLoadComplete();
void enterForeground();
void enterBackground();

View file

@ -137,8 +137,13 @@ void WindowScriptingInterface::openUrl(const QUrl& url) {
if (url.scheme() == URL_SCHEME_HIFI) {
DependencyManager::get<AddressManager>()->handleLookupString(url.toString());
} else {
#if defined(Q_OS_ANDROID)
QList<QString> args = { url.toString() };
AndroidHelper::instance().requestActivity("WebView", true, args);
#else
// address manager did not handle - ask QDesktopServices to handle
QDesktopServices::openUrl(url);
#endif
}
}
}

View file

@ -0,0 +1,73 @@
"use strict";
//
// clickOverlays.js
// scripts/system/+android
//
// Created by Gabriel Calero & Cristian Duarte on Jun 22, 2018
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
(function() { // BEGIN LOCAL_SCOPE
var logEnabled = false;
var touchOverlayID;
function printd(str) {
if (logEnabled)
print("[clickOverlays.js] " + str);
}
function touchBegin(event) {
var rayIntersection = Overlays.findRayIntersection(Camera.computePickRay(event.x, event.y));
if (rayIntersection && rayIntersection.intersects && rayIntersection.overlayID &&
Overlays.getOverlayType(rayIntersection.overlayID) == "web3d") {
touchOverlayID = rayIntersection.overlayID;
} else {
touchOverlayID = null;
}
}
function touchEnd(event) {
var rayIntersection = Overlays.findRayIntersection(Camera.computePickRay(event.x, event.y));
if (rayIntersection && rayIntersection.intersects && rayIntersection.overlayID &&
touchOverlayID == rayIntersection.overlayID) {
var propertiesToGet = {};
propertiesToGet[rayIntersection.overlayID] = ['url'];
var properties = Overlays.getOverlaysProperties(propertiesToGet);
if (properties[rayIntersection.overlayID].url) {
Window.openUrl(properties[rayIntersection.overlayID].url);
}
var overlayObj = Overlays.getOverlayObject(rayIntersection.overlayID);
Overlays.sendMousePressOnOverlay(rayIntersection.overlayID, {
type: "press",
id: 0,
pos2D: event
});
}
touchOverlayID = null;
}
function ending() {
Controller.touchBeginEvent.disconnect(touchBegin);
Controller.touchEndEvent.disconnect(touchEnd);
}
function init() {
Controller.touchBeginEvent.connect(touchBegin);
Controller.touchEndEvent.connect(touchEnd);
Script.scriptEnding.connect(function () {
ending();
});
}
module.exports = {
init: init,
ending: ending
}
}()); // END LOCAL_SCOPE