cocos2dx-3.2調用java(jni)來內嵌網頁

本文參照了Vincent Chou的個人博客文章:cocos2d-xiOS/Android雙平臺上嵌入WebView 和 Cocos2d-x中通過JNI進行C++調用Java代碼


1.基本說明 

要通過jnicocos2d-xc++代碼調用java函數,要使用到cocos2d-x中有一個JniHelper類。

頭文件:#include "platform/android/jni/JniHelper.h"

       需要使用的接口如下:

const char *className, const char *methodName, const char *paramCode);
static bool getMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode);
每個參數的意義和使用方法:
//函數信息結構體
    JniMethodInfo minfo;
    bool isHave = JniHelper::getStaticMethodInfo(minfo,/*JniMethodInfo的引用*/
                                                 "com/omega/MyApp",/*類的路徑*/
                                                 "getJavaActivity",/*函數名*/
                                                 "()Ljava/lang/Object;");/*函數類型簡寫*/
    jobject activityObj;
    if (isHave)
    {
        //CallStaticObjectMethod調用java函數,並把返回值賦值給activityObj
        activityObj = minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID);
    }

這裏重點要說明一下("com/omega/MyApp",/*類的路徑*/),這個類的路徑,我弄了很久才搞明白,它其實是你在創建android時使用的包名,比如com.xxx.xxx,如果你不知道或者忘記了是什麼可以打開 proj.android目錄下的AndroidManifest.xml文件查看, package="com.cocos2dx.example" 中的 "com.cocos2dx.example" 就是你的包名。下面繼續


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.cocos2dx.example"
      android:versionCode="1"
      android:versionName="1.0">

  .....



源文件是放在:youProject\proj.android\src\org\cocos2dx\cpp\AppActivity.java下,比如我的JAVA函數是寫在AppActivity.java文件當,那麼最終這裏類的路徑就是: "proj.android\src\org\cocos2dx\cpp\AppActivity.java" .

AppActivity.java 代碼如下:

/****************************************************************************
Copyright (c) 2008-2010 Ricardo Quesada
Copyright (c) 2010-2012 cocos2d-x.org
Copyright (c) 2011      Zynga Inc.
Copyright (c) 2013-2014 Chukong Technologies Inc.
 
http://www.cocos2d-x.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
package org.cocos2dx.cpp;

import org.cocos2dx.lib.Cocos2dxActivity;
import org.cocos2dx.lib.Cocos2dxGLSurfaceView;

import org.cocos2dx.hellocpp.R;

import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class AppActivity extends Cocos2dxActivity{
	
    static AppActivity test  = null;
	WebView m_webView;
    ImageView m_imageView;
    FrameLayout m_webLayout;
    LinearLayout m_topLayout;
    Button m_backButton;

	
    protected void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
        test=this;
        Log.v("cccccc","onCreate");
        //初始化一個空佈局
        m_webLayout = new FrameLayout(this);
        FrameLayout.LayoutParams lytp = new FrameLayout.LayoutParams(800,640);
        lytp .gravity = Gravity.CENTER;
        addContentView(m_webLayout, lytp);
	}
    
  //返回實例
    public static AppActivity getInstance() {
        Log.v("aaaaa","getInstance");
    	return test;
    }
    public void openWebview() {
    	this.runOnUiThread(new Runnable() {//在主線程裏添加別的控件
            public void run() {   
                //初始化webView
                m_webView = new WebView(test);
                //設置webView能夠執行javascript腳本
                m_webView.getSettings().setJavaScriptEnabled(true);            
                //設置可以支持縮放
                m_webView.getSettings().setSupportZoom(true);//設置出現縮放工具
                m_webView.getSettings().setBuiltInZoomControls(true);
                //載入URL
                m_webView.loadUrl("http://www.baidu.com");
                //使頁面獲得焦點
                m_webView.requestFocus();
                //如果頁面中鏈接,如果希望點擊鏈接繼續在當前browser中響應
                m_webView.setWebViewClient(new WebViewClient(){       
                    public boolean shouldOverrideUrlLoading(WebView view, String url) {   
                        if(url.indexOf("tel:")<0){
                            view.loadUrl(url); 
                        }
                        return true;       
                    }    
                });
                
                //背景圖
                m_imageView = new ImageView(test);
                m_imageView.setImageResource(R.drawable.bkgnd);
                m_imageView.setScaleType(ImageView.ScaleType.FIT_XY);
                //初始化線性佈局 裏面加按鈕和webView
                m_topLayout = new LinearLayout(test);      
                m_topLayout.setOrientation(LinearLayout.VERTICAL);
                //初始化返回按鈕
                m_backButton = new Button(test);
                Log.v("zzzz2", "openWebView");
             //   m_backButton.setBackgroundResource(R.drawable.btn);
                Log.v("zzzz3", "openWebView");
                LinearLayout.LayoutParams lypt=new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
                lypt.gravity=Gravity.RIGHT;
                m_backButton.setLayoutParams(lypt);            
                m_backButton.setOnClickListener(new OnClickListener() {                    
                    public void onClick(View v) {
                        removeWebView();
                    }
                });
                //把image加到主佈局裏
                m_webLayout.addView(m_imageView);
                //把webView加入到線性佈局
                m_topLayout.addView(m_backButton);
                m_topLayout.addView(m_webView);                
                //再把線性佈局加入到主佈局
                m_webLayout.addView(m_topLayout);
            }
        });
    }
    //移除webView
    public void removeWebView() {              
    	m_webLayout.removeView(m_imageView);
        m_imageView.destroyDrawingCache();
        
        m_webLayout.removeView(m_topLayout);
        m_topLayout.destroyDrawingCache();
                
        m_topLayout.removeView(m_webView);
        m_webView.destroy();
                
        m_topLayout.removeView(m_backButton);
        m_backButton.destroyDrawingCache();
    }
    
    //重寫return鍵
    public boolean onKeyDown(int keyCoder,KeyEvent event)
    {
    	//如果網頁能回退則後退,如果不能後退移除WebView
    	if(m_webView.canGoBack() && keyCoder == KeyEvent.KEYCODE_BACK){
            m_webView.goBack();
        }else{
            removeWebView();
        }
        return false;      
    }

    public Cocos2dxGLSurfaceView onCreateView() {
    	Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this);
    	// Test should create stencil buffer
    	glSurfaceView.setEGLConfigChooser(5, 6, 5, 0, 16, 8);
    	
    	return glSurfaceView;
    }

    static {
    	  
        System.loadLibrary("cocos2dcpp");
    }     
}


HelloWord.cpp 代碼如下:

#include "HelloWorldScene.h"

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include <jni.h>
#include "platform/android/jni/JniHelper.h"
#endif

USING_NS_CC;

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

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

    // return the scene
    return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() )
    {
        return false;
    }
    
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();

    /////////////////////////////
    // 2. add a menu item with "X" image, which is clicked to quit the program
    //    you may modify it.

    // add a "close" icon to exit the progress. it's an autorelease object
    auto closeItem = MenuItemImage::create(
                                           "CloseNormal.png",
                                           "CloseSelected.png",
                                           CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
    
	closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
                                origin.y + closeItem->getContentSize().height/2));

    // create menu, it's an autorelease object
    auto menu = Menu::create(closeItem, NULL);
    menu->setPosition(Vec2::ZERO);
    this->addChild(menu, 1);

    /////////////////////////////
    // 3. add your codes below...

    // add a label shows "Hello World"
    // create and initialize a label
    
    auto label = Label::createWithTTF("Hello World", "fonts/Marker Felt.ttf", 24);
    
    // position the label on the center of the screen
    label->setPosition(Vec2(origin.x + visibleSize.width/2,
                            origin.y + visibleSize.height - label->getContentSize().height));

    // add the label as a child to this layer
    this->addChild(label, 1);

    // add "HelloWorld" splash screen"
    auto sprite = Sprite::create("HelloWorld.png");

    // position the sprite on the center of the screen
    sprite->setPosition(Vec2(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));

    // add the sprite as a child to this layer
    this->addChild(sprite, 0);
    
    return true;
}


void HelloWorld::menuCloseCallback(Ref* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
	JniMethodInfo minfo;
	//getStaticMethodInfo,判斷Java靜態函數是否存在,並且把信息保存到minfo裏
	//參數1:JniMethodInfo
	//參數2:Java類包名+類名
	//參數3:Java函數名稱
	//參數4:函數參數類型和返回值類型
	bool isHave = JniHelper::getStaticMethodInfo(minfo,"org/cocos2dx/cpp/AppActivity","getInstance","()Lorg/cocos2dx/cpp/AppActivity;");
	jobject jobj;//存對象
//	log("aaa=%s,bbb=%s",minfo.classID,minfo.methodID);
	if (isHave) {
		//這裏的調用getInstance,返回Test類的對象。
		jobj = minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID);
		if(jobj!=NULL){
			isHave = JniHelper::getMethodInfo(minfo,"org/cocos2dx/cpp/AppActivity","openWebview","()V");
			if (isHave) {				
				//調用openWebview, 參數1:Test對象   參數2:方法ID
				minfo.env->CallVoidMethod(jobj, minfo.methodID);
			
			}
		}
	}
#else
    CCDirector::sharedDirector()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
#endif
//#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
//	MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
//    return;
//#endif
//
//    Director::getInstance()->end();
//
//#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
//    exit(0);
//#endif
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章