opening URLs in external browser

Does cocos2dx have a cross-platform solution to open a link in browser?
(open the link in external browser on win32, use [[UIApplication sharedApplication] openURL:url]; on iOS etc.)
Thank you,
vws02

2 Likes

Tamas V wrote:

Does cocos2dx have a cross-platform solution to open a link in browser?
(open the link in external browser on win32, use [[UIApplication sharedApplication] openURL:url]; on iOS etc.)
Thank you,
vws02

i’ve add some code, cross-platform like!
and i hope they adopt this in next cocos2dx version.
(i’m using cocos2dx 2.0.1)
simply call this,

CCApplication::sharedApplication().openURL("http://www.google.com");

and added codes are :

  1. cocos2dx/platform/win32

CCApplication.h

void openURL(const char* pszUrl);

CCApplication.cpp

void CCApplication::openURL(const char* pszUrl)
{
    ShellExecuteA(NULL, "open", pszUrl, NULL, NULL, SW_SHOWNORMAL);
}
  1. cocos2dx/platform/android
    (see also http://digitalsynapsesblog.blogspot.kr/2011/09/cocos2d-x-launching-url-on-android.html)

CCApplication.h

void openURL(const char* pszUrl);

CCApplication.cpp

void CCApplication::openURL(const char* pszUrl)
{
    JniMethodInfo minfo;

    if(JniHelper::getStaticMethodInfo(minfo, 
        "org/cocos2dx/application/ApplicationDemo", 
        "openURL", 
        "(Ljava/lang/String;)V"))
    {
        jstring StringArg1 = minfo.env->NewStringUTF(pszUrl);
        minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID, StringArg1);
        minfo.env->DeleteLocalRef(StringArg1);
        minfo.env->DeleteLocalRef(minfo.classID);
    }
}

and, cocos2dx/application/ApplicationDemo.java

    *import android.app.Activity;*
    *private static Activity me = null;*

    protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
        *me = this;*   // => added!
    }
    // this is new method
*    public static void openURL(String url) { 
        Intent i = new Intent(Intent.ACTION_VIEW);  
        i.setData(Uri.parse(url));
        me.startActivity(i);
    }*
  1. cocos2dx/platform/ios
    (NOTE : i didn’t tested on ios, but i think it will also works)

CCApplication.h

void openURL(const char* pszUrl);

CCApplication.cpp

void CCApplication::openURL(const char* pszUrl)
{
    [[UIApplication sharedApplication] openURL:pszUrl];
}
1 Like

i’m beginner in ios, today fixed compile errors,

void CCApplication::openURL(const char* pszUrl)
{
    NSString *msg = [NSString stringWithCString:pszUrl encoding:NSASCIIStringEncodeing];
    NSURL *nsUrl = [NSURL URLWithString:msg];
    [[UIApplication sharedApplication] openURL:nsUrl];
}

and in android, it will better to put code into Cocos2dxActivity.java

    import android.app.Activity;
    private static Activity me = null;

    protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
        me = this;   // => added!
    }
    // this is new method
    public static void openURL(String url) { 
        Intent i = new Intent(Intent.ACTION_VIEW);  
        i.setData(Uri.parse(url));
        me.startActivity(i);
    }

and call like this,

void CCApplication::openURL(const char* pszUrl)
{
    JniMethodInfo minfo;

    if(JniHelper::getStaticMethodInfo(minfo, 
        "org/cocos2dx/lib/Cocos2dxActivity", 
        "openURL", 
        "(Ljava/lang/String;)V"))
    {
        jstring StringArg1 = minfo.env->NewStringUTF(pszUrl);
        minfo.env->CallStaticVoidMethod(minfo.classID, minfo.methodID, StringArg1);
        minfo.env->DeleteLocalRef(StringArg1);
        minfo.env->DeleteLocalRef(minfo.classID);
    }
}

because, such like playBackgroundMusic() are also in Cocos2dxActivity.

thanks.

1 Like

Thanks for sharing Seung-Hyun Lee; this is very useful code.

Ben

Hi

I have tested this methods on iOS but nothing happens, I have copied the methods you gave us and I called using CCApplication::sharedApplication()->openURL(“www.google.com”); The execution did enter in CCApplication::openURL but nothing happens. Did I miss something in the execution?

Thanks in advance.

plz verify your codes in cocos2dx/platform/ios/CCApplication.cpp.
i tested this only ios emulator, so don’t know if it fails on iphone.

but another sample codes both used is as below, wish you refer this.

-(void) onBtnBuy: (id) sender
{   
    [[SimpleAudioEngine sharedEngine] playEffect:@"bt_language.mp3"];

    DKgamedata* p = [DKgamedata sharedGamedata ];
    NSString* urlstr = [ p getvisitURL:UI_STR_BUY_FULL_VER ];
    NSLog(@"Open:Store:%@", urlstr );

    NSURL *_url = nil;

    _url = [NSURL URLWithString:urlstr];
    [[UIApplication sharedApplication] openURL:_url];

}

thanks.

I try your code and not work too, and I change the URL “www.google.com” -> “http://www.google.com”, and it is fine!

This should be integrated in the official version !

It’s super useful !

1 Like

Sadly a pull request with this feature was not merged to the official version: https://github.com/cocos2d/cocos2d-x/pull/1940 :frowning:

I will discuss this issue with Minggo on Monday.
Issue #2239 is created.

@Zhe Wang : there was also other thread about opening urls on this forum, but for Android. It was solved via a JNI call that created an Intent on Java-side and launched the browser. Could you please also integrate urls fro Android?

Small note: bool openURL() is better than void openURL(): at first, iOS/Mac have message - (BOOL)canOpenURL:(NSURL *)url to check if app is able to open such URL; at second, on some platforms this method will be not implemented for some time.

So it can be said in documentation that it returns the result of canOpenURL on IOS and always “true” on other platforms.

Pawel Lopusinski wrote:

So it can be said in documentation that it returns the result of canOpenURL on IOS and always “true” on other platforms.

On win32 ShellExecuteA also can return error code if opening failed: http://msdn.microsoft.com/en-us/library/windows/desktop/bb762153(v=vs.85).aspx
On Linux cocos2d-x should use command-line utility xdg-open, but it can perform simple URL validation before launch it (with fork & execvp).
On Mac there are - (BOOL)openURL:(NSURL *)url in NSWorkspace, which also returns false on fail.
On platforms where launching URL will be not implemented at first time, method also will return false.

Hi,

I have been using this methods both in ios and android.It is working fine.

Now I found one problem :

my link was for a facebook page Eg: https://www.facebook.com/iTunes

if the device doesn’t have facebook app installed,the link opens in safari and everything is fine.
but if facebook app is installed but doesn’t redirect to the page.

How to correct this problem??

Thanks for any help.

I think it is better to add it into extension.

@Minggo : Whatever floats your boat, it would be nice to have such thing integreated into cocos, and not having to dug into it to achieve such “simple” functionality. Though it was quite educational having to explore jni caves of cocos.

And now, there has no a good method to check network status, if it should be add to extension too? Such as get the network connection type of 3G, wifi, or 2g ….

Minggo Zhang wrote:

I think it is better to add it into extension.

Working on that. Now I know how to implement Reachibility API for iOS and opening URL for iOS/OSX/win32/Linux/android. I’ll put code to extensions/network/NetworkAccess class, with following API:

enum class NetworkState
{
    Unavailable,    ///< Network is not available.
    Mobile,         ///< Slow and potentially expensive network available.
    Wifi,           ///< Nice network available.
    NotImplemented  ///< Checking state is not implemented for this platform.
};

class NetworkAccess
{
public:
    /// Opens URL in external application.
    /// @param URL Full URL with scheme, e.g "http://cocos2d-x.org/".
    /// @return False if URL is invalid, or scheme is not acceptable
    /// on this platform, or opening URL is not implemented for this platform.
    /// @note Not all platforms accept specific URL schemes like twitter//.
    static bool openURL(const std::string &URL);

    /// Checks current network reachibility.
    static NetworkState getNetworkState();
};
1 Like

SEUNG-HYUN LEE,

Very informative post. Thank you! I am running across a problem though, and that probably has more to do with the blog you linked than the code itself. There doesn’t appear to be a Cocos2dJni file to update in the latest version of Cocos2d-X, so I’ve placed it in Java_org_cocos2dx_lib_Cocos2dxHelper (h/cpp) instead. When I try to run the code, I get the following errors.

/Users/ME/Cocos2d-x/HelloWorld/proj.android/../../cocos2dx/platform/android/jni/Java_org_cocos2dx_lib_Cocos2dxHelper.cpp:343:5: error: 'TMethodJNI' was not declared in this scope
/Users/ME/Cocos2d-x/HelloWorld/proj.android/../../cocos2dx/platform/android/jni/Java_org_cocos2dx_lib_Cocos2dxHelper.cpp:343:16: error: expected ';' before 't'
/Users/ME/Cocos2d-x/HelloWorld/proj.android/../../cocos2dx/platform/android/jni/Java_org_cocos2dx_lib_Cocos2dxHelper.cpp:344:21: error: 't' was not declared in this scope
/Users/ME/Cocos2d-x/HelloWorld/proj.android/../../cocos2dx/platform/android/jni/Java_org_cocos2dx_lib_Cocos2dxHelper.cpp:347:46: error: 'getMethodID' was not declared in this scope
make: *** [obj/local/armeabi/objs-debug/cocos2dx_static/platform/android/jni/Java_org_cocos2dx_lib_Cocos2dxHelper.o] Error 1

Am I putting

void openURLJNI(const char* url)
{
    TMethodJNI t;
    if (getMethodID(t
                    , "org/cocos2dx/lib/Cocos2dxActivity"
                    , "openURL"
                    , "(Ljava/lang/String;)V"))
    {
        jstring StringArg1 = t.env->NewStringUTF(url);
        t.env->CallStaticVoidMethod(t.classID, t.methodID, StringArg1);
    }
}

In the right place, or should I go somewhere else?