How to launch another Android app with native C++ code?


#1

Hi all, I’m making a game with cocos2d-x for Android using C++. Now I’m looking for a way to open another Android App (likes YouTube, Google Play Store, …) using their package name from inside my game through a button . I have searched around and found that it could be done in Java code with something like this:

Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.package.address");
if (launchIntent != null) { 
    startActivity(launchIntent);//null pointer check in case package name was not found
}

My question is: Is it possible to open another Android App in my native code (.cpp files) or I have to put them in java side (.java files)? If I have to do it in .java files, where should I put it? I always work with .cpp files in Visual Studio, compile with cmd and run with emulator on Android Studio, I have never worked with .java files that generated by cocos2d-x in Android Studio, the engine just makes everything ready for me so I got a little confused here.
Your attention and help is very much appreciated.


#2

Yes you can. Use JNI.
See this blog. http://stnguyen.com/cocos2d-x/call-java-functions-from-cpp.html


#3

You can use

Application::getInstance()->openURL(“http://www.cocos2d-x.org/”);

and the Url you pass in can be a system url if you google Android URL schemes it should put you in the right direction


#4

Hi
you can use JNI for this …
if you are using android-studio add this to AppActivity.java in
proj.android-studio/app/src/org/cocos2dx/cpp/AppActivity.java
and if you’re using eclipse add this to
/proj.android/src/org/cocos2dx/cpp/AppActivity.java

Your new AppActivity.java :

package org.cocos2dx.cpp;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;

public class AppActivity extends Cocos2dxActivity {

    public static Activity _activity;

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        _activity = this;
	
    }
    public static void openAnotherApp(){
    	Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.package.address");
	if (launchIntent != null) { 
	    startActivity(launchIntent);//null pointer check in case package name was not found
	}
    }
}

and then in your Scene or another class just call this java method like this :
Cpp class :

// C and C++ headers

// cocos2d-x headers
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "platform/android/jni/JniHelper.h"
#endif



USING_NS_CC;

Scene* GameScene::createScene()
{
    // 'scene' is an autorelease object
    auto scene = Scene::create();
    
    // 'layer' is an autorelease object
    auto layer = GameScene::create();

    // add layer as a child to scene
    scene->addChild(layer);

    // return the scene
    return scene;
}

// implementation of GameScene
GameScene::GameScene()
{
    
}

GameScene::~GameScene()
{

    
}

GameScene* GameScene::create()
{
    GameScene* ret = new (std::nothrow) GameScene();
    if (ret && ret->init())
    {
        ret->autorelease();
    }
    else
    {
        CC_SAFE_DELETE(ret);
    }
    
    return ret;
}

// on "init" you need to initialize your instance
bool GameScene::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }   
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)

    cocos2d::JniMethodInfo methodInfo;
    if(!cocos2d::JniHelper::getStaticMethodInfo(methodInfo , "org/cocos2dx/cpp/AppActivity" , "openAnotherApp" , "()V")){

    }
    methodInfo.env->CallStaticVoidMethod(methodInfo.classID , methodInfo.methodID);
    methodInfo.env->DeleteLocalRef(methodInfo.classID);

#endif
    return true;
}

i hope this can help you with your problem.


#5

Hi @michio, thanks for your help, it works like a charm. However, I’m running into another problem that my Game crashed.

My expect: Press the button => pause my game and open You Tube on Android => Press Back Button => pause You Tube and resume my game.
What happens: I could open You Tube but my App crashed when I press back button. I got the following error code from Android Studio:

A/libc: Fatal signal 11 (SIGSEGV) at 0x0004fb18 (code=1), thread 1975 (Thread-55)

I’m trying to performs some actions before opening others app and they might cause the crash because my Game runs without any problem if I remove those actions and leave openApp function alone.

My code :

   auto imageOpeningAction = CallFunc::create([&]() {
	mOpeningImage->setEnabled(true);
	mOpeningImage->setOpacity(255);
	mOpeningImage->setPosition(menuItem->getPosition());
	mOpeningImage->runAction(fullScale);
});
   auto imageClosingAction = CallFunc::create([&]() {
	mOpeningImage->runAction(reverseScale);
	mOpeningImage->setOpacity(0);
	mOpeningImage->setEnabled(false);
});
   auto openAnotherApp = CallFunc::create([&]() {  // Open YouTube App
	HelloWorld::openApp(packageName);
});
runAction(Sequence::create(imageOpeningAction->clone(), DelayTime::create(0.5f), openAnotherApp->clone(), nullptr));

Any idea how to fix it?


#6

Hi @sinhviencodon , your welcome buddy.
your code seems fine , but if i recall correctly there is a problem with Sequence in android platform. i’m not sure about that though. check it out. and what is your cocos2dx version and android studio version?


#7

@michio, I’m using cocos2d-x 3.14.1 downloaded from the home page and Android Studio 2.2.3. You have any idea how should I workaround this ?