Kaynağa Gözat

launchUrl to open URLs in external browser added to Game, run through static delegate to Platform implementation

pooerh 13 yıl önce
ebeveyn
işleme
c2a37f2d28

+ 9 - 0
gameplay/src/Game.h

@@ -517,6 +517,15 @@ public:
      */
     void schedule(float timeOffset, const char* function);
 
+    /**
+     * Opens an URL in an external browser, if available.
+     *
+     * @param url URL to be opened.
+     *
+     * @return True if URL was opened successfully, false otherwise.
+     */
+    bool launchUrl(const char *url) const;
+
 protected:
 
     /**

+ 6 - 0
gameplay/src/Game.inl

@@ -140,4 +140,10 @@ inline Gamepad* Game::getGamepad(unsigned int index) const
     else
         return NULL;
 }
+
+inline bool Game::launchUrl(const char* url) const
+{
+    return Platform::launchUrl(url);
+}
+
 }

+ 9 - 0
gameplay/src/Platform.h

@@ -361,6 +361,15 @@ public:
      * @see Mouse::MouseEvent
      */
     static bool mouseEventInternal(Mouse::MouseEvent evt, int x, int y, int wheelDelta);
+
+    /**
+     * Opens an URL in an external browser, if available.
+     *
+     * @param url URL to be opened.
+     *
+     * @return True if URL was opened successfully, false otherwise.
+     */
+    static bool launchUrl(const char *url);
     
 private:
 

+ 82 - 0
gameplay/src/PlatformAndroid.cpp

@@ -1307,6 +1307,88 @@ float Platform::getGamepadTriggerValue(unsigned int gamepadHandle, unsigned int
     return 0.0f;
 }
 
+bool Platform::launchUrl(const char *url)
+{
+    if (url == NULL || *url == '\0')
+        return false;
+
+    bool result = true;
+
+    android_app* state = __state;
+    GP_ASSERT(state && state->activity && state->activity->vm);
+    JavaVM* jvm = state->activity->vm;
+    JNIEnv* env = NULL;
+    jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
+    jint r = jvm->AttachCurrentThread(&env, NULL);
+    if (r == JNI_ERR)
+    {
+        GP_ERROR("Failed to retrieve JVM environment to display keyboard.");
+        return false;
+    }
+    GP_ASSERT(env);
+
+    jclass classActivity = env->FindClass("android/app/NativeActivity");
+    jclass classIntent = env->FindClass("android/content/Intent");
+    jclass classUri = env->FindClass("android/net/Uri");
+
+    GP_ASSERT(classActivity && classIntent && classUri);
+
+    // Get static field ID Intent.ACTION_VIEW
+    jfieldID fieldActionView = env->GetStaticFieldID(classIntent, "ACTION_VIEW", "Ljava/lang/String;");
+    GP_ASSERT(fieldActionView);
+
+    // Get string value of Intent.ACTION_VIEW, we'll need that to pass to Intent's constructor later on
+    jstring paramActionView = (jstring)env->GetStaticObjectField(classIntent, fieldActionView);
+    GP_ASSERT(paramActionView);
+
+    // Get method ID Uri.parse, will be needed to parse the url given into Uri object
+    jmethodID methodUriParse = env->GetStaticMethodID(classUri, "parse","(Ljava/lang/String;)Landroid/net/Uri;");
+    GP_ASSERT(methodUriParse);
+
+    // Get method ID Activity.startActivity, so we can start the appropriate activity for the View action of our Uri
+    jmethodID methodActivityStartActivity = env->GetMethodID(classActivity, "startActivity","(Landroid/content/Intent;)V");
+    GP_ASSERT(methodActivityStartActivity);
+
+    // Get method ID Intent constructor, the one that takes action and uri (String;Uri)
+    jmethodID methodIntentInit = env->GetMethodID(classIntent, "<init>","(Ljava/lang/String;Landroid/net/Uri;)V");
+    GP_ASSERT(methodIntentInit);
+
+    // Convert our url to Java's string and parse it to Uri
+    jstring paramUrlString = env->NewStringUTF(url);
+    jobject paramUri = env->CallStaticObjectMethod(classUri, methodUriParse, paramUrlString);
+    GP_ASSERT(paramUri);
+
+    // Create Intent with Intent.ACTION_VIEW and parsed Uri arguments
+    jobject paramIntent = env->NewObject(classIntent, methodIntentInit, paramActionView, paramUri);
+    GP_ASSERT(paramIntent);
+
+    // Launch NativeActivity.startActivity with our intent to view the url! state->activity->clazz holds
+    // our NativeActivity object
+    env->CallVoidMethod(state->activity->clazz, methodActivityStartActivity, paramIntent);
+
+    /* startActivity may throw a ActivitNotFoundException if, well, activity is not found.
+       Example: http://<url> is passed to the intent but there is no browser installed in the system
+       we need to handle it. */
+    jobject exception = env->ExceptionOccurred();
+
+    // We're not lucky here
+    if (exception)
+    {
+        // Print out the exception data to logcat
+        env->ExceptionDescribe();
+
+        // Exception needs to be cleared
+        env->ExceptionClear();
+
+        // Launching the url failed
+        result = false;
+    }
+
+    // See you Space Cowboy
+    jvm->DetachCurrentThread();
+    return result;
+}
+
 }
 
 #endif

+ 8 - 0
gameplay/src/PlatformBlackBerry.cpp

@@ -1419,6 +1419,14 @@ float Platform::getGamepadTriggerValue(unsigned int gamepadHandle, unsigned int
     return 0.0f;
 }
 
+bool Platform::launchURL(const char* url)
+{
+    if (url == NULL || *url == '\0')
+        return false;
+
+    return navigator_invoke(url, NULL) == BPS_SUCCESS;
+}
+
 }
 
 #endif

+ 15 - 0
gameplay/src/PlatformLinux.cpp

@@ -1002,6 +1002,21 @@ float Platform::getGamepadTriggerValue(unsigned int gamepadHandle, unsigned int
     return 0.0f;
 }
 
+bool Platform::launchUrl(const char* url)
+{
+    if (url == NULL || *url == '\0')
+        return false;
+
+    int len = strlen(url);
+    
+    char* cmd = new char[11 + len];
+    sprintf(cmd, "xdg-open %s", url);
+    int r = system(cmd);
+    SAFE_DELETE_ARRAY(cmd);
+    
+    return (r == 0);
+}
+
 }
 
 #endif

+ 17 - 0
gameplay/src/PlatformMacOSX.mm

@@ -1881,4 +1881,21 @@ static void hidDeviceValueAvailableCallback(void* inContext, IOReturn inResult,
         CFRelease(valueRef); // Don't forget to release our HID value reference
     } while (1);
 }
+
+bool Platform::launchUrl(const char *url)
+{
+    if (url == NULL || *url == '\0')
+        return false;
+
+    CFURLRef cfUrl = CFURLCreateWithString(0, CFSTR(url), 0);
+    if (cfUrl == 0)
+        return false;
+
+    const OSStatus err = LSOpenCFURLRef(cfUrl, 0);
+
+    return (err == noErr);
+}
+
+}
+
 #endif

+ 14 - 0
gameplay/src/PlatformWindows.cpp

@@ -1454,6 +1454,20 @@ bool Platform::mouseEventInternal(Mouse::MouseEvent evt, int x, int y, int wheel
     }
 }
 
+bool Platform::launchURL(const char* url)
+{
+    if (url == NULL || *url == '\0')
+        return false;
+ 
+    // Success when result code > 32
+    int len = MultiByteToWideChar(CP_ACP, 0, url, -1, NULL, 0);
+    wchar_t* wurl = new wchar_t[len];
+    MultiByteToWideChar(CP_ACP, 0, url, -1, wurl, len);
+    int r = (int)ShellExecute(NULL, NULL, wurl, NULL, NULL, SW_SHOWNORMAL);
+    SAFE_DELETE_ARRAY(wurl);
+    return (r > 32);
+}
+
 }
 
 #endif

+ 8 - 0
gameplay/src/PlatformiOS.mm

@@ -1319,6 +1319,14 @@ float Platform::getGamepadTriggerValue(unsigned int gamepadHandle, unsigned int
 {
     return 0.0f;
 }
+
+bool Platform::launchUrl(const char *url)
+{
+    if (url == NULL || *url == '\0')
+        return false;
+
+    return [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithUTF8String: url]]];
+}
     
 }