Cocos2d-x游戏在Android平台使用友盟社会化组件开展截图分享的实现

Cocos2d-x游戏在Android平台使用友盟社会化组件进行截图分享的实现

实现步骤简述

  1. 在Cocos2d-x游戏场景中添加一个按钮;
  2. 在该按钮的点击回调中截取游戏屏幕图像,并且保存到本地路径中;
  3. 将截屏图像的本地路径通过jni传递给java层;
  4. java层构建分享图片UMImage,并且设置给SDK Controller;
  5. 最后打开分享面板,选择平台分享即可。

简单示例

HelloWorld.h
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"

class HelloWorld : public cocos2d::CCLayer
{
public:
    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();  

    // there's no 'id' in cpp, so we recommend returning the class instance pointer
    static cocos2d::CCScene* scene();
    
    // a selector callback
    void menuCloseCallback(CCObject* pSender);
    
    void openShare(CCObject* pSender);

    void saveScreenShot();

    void setScrShotPathToJava(const char* path);

    // implement the "static node()" method manually
    CREATE_FUNC(HelloWorld);

};

#endif // __HELLOWORLD_SCENE_H__

HelloWorld.cpp
#include "HelloWorldScene.h"
#include "platform/android/jni/JniHelper.h"
#include <android/log.h>
#include <jni.h>

USING_NS_CC;
using namespace std;

CCScene* HelloWorld::scene()
{
    // 'scene' is an autorelease object
    CCScene *scene = CCScene::create();
    
    // 'layer' is an autorelease object
    HelloWorld *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 ( !CCLayer::init() )
    {
        return false;
    }
    
    CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
    CCPoint origin = CCDirector::sharedDirector()->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
    CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
                                        "CloseNormal.png",
                                        "CloseSelected.png",
                                        this,
                                        menu_selector(HelloWorld::menuCloseCallback));
    
	pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/2 ,
                                origin.y + pCloseItem->getContentSize().height/2));

        // 授权某平台
    CCMenuItemFont *authTextButton = CCMenuItemFont::create("打开分享面板",this , menu_selector(HelloWorld::openShare));
    authTextButton->setPosition(ccp(150,320));

    // create menu, it's an autorelease object
    CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
    pMenu->setPosition(CCPointZero);
    pMenu->addChild(authTextButton, 1);
    this->addChild(pMenu, 1);

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

    // add a label shows "Hello World"
    // create and initialize a label
    
    CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Arial", 24);
    
    // position the label on the center of the screen
    pLabel->setPosition(ccp(origin.x + visibleSize.width/2,
                            origin.y + visibleSize.height - pLabel->getContentSize().height));

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

    // add "HelloWorld" splash screen"
    CCSprite* pSprite = CCSprite::create("HelloWorld.png");

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

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

// 保存游戏截屏
void HelloWorld::saveScreenShot()
{
      // ***************************************************************************
    // 截屏
    static int index = 0 ;
    CCSize size = CCDirector::sharedDirector()->getWinSize();

    CCLog("Window Size, width = %d, height = %d.", (int)size.width, (int)size.height );
    CCRenderTexture* texture = CCRenderTexture::create((int)size.width, (int)size.height, kCCTexture2DPixelFormat_RGBA8888);    
    texture->setPosition(ccp(size.width/2, size.height/2));    
    texture->begin();
    CCDirector::sharedDirector()->getRunningScene()->visit();
    texture->end();

    string imagePath = CCFileUtils::sharedFileUtils()->getWritablePath() ;
    if ( imagePath.length() == 0 )
    {
      return ;
    }

    // imagePath = imagePath.c_str() ;

    char imgName[20] ;
    sprintf(imgName, "screenshot-%d.jpg", index++);

     //保存为jpeg  
    bool result = texture->saveToFile(imgName, kCCImageFormatJPEG); 
    if ( result ) 
    {
        // imagePath += "screenshot.png";
        imagePath += imgName ;
        CCLog("#save scrshot", "#### COCOS2D-X截图成功");
        // 将图片地址设置给java层
        setScrShotPathToJava(imagePath.c_str());
    } 
}

// 将截屏图片的路径通过静态函数传递给java层
void HelloWorld::setScrShotPathToJava(const char* path)
{
        // ***************************************************************************
        JniMethodInfo methodInfo;
        //  获截完屏幕以后将地址设置到java层中
        bool isHave = JniHelper::getStaticMethodInfo(methodInfo,
                                  "com/umeng/game/UmengGameActivity", "setImagePath", "(Ljava/lang/String;)V");
          
        if ( isHave )  
        {
            jstring imgPath = methodInfo.env->NewStringUTF(path) ;
             // 实际调用UmengGameActivity中打开umeng分享平台选择面板  
             methodInfo.env->CallStaticVoidMethod( methodInfo.classID, methodInfo.methodID, imgPath);
             methodInfo.env->DeleteLocalRef(imgPath);
             methodInfo.env->DeleteLocalRef(methodInfo.classID);
        }  
}

// 先截屏,然后将路径传递给java层,最后打开分享面板
void HelloWorld::openShare(CCObject* pSender) {

#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
        saveScreenShot();
    
#elif CC_TARGET_PLATFORM == CC_PLATFORM_IOS
    
    // TODO 
    
#endif

}


void HelloWorld::menuCloseCallback(CCObject* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
    CCMessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
#else
    CCDirector::sharedDirector()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
#endif
}

Android代码层的UmengGameActivity实现
/****************************************************************************
Copyright (c) 2010-2011 cocos2d-x.org

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 com.umeng.game;

import java.io.File;

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

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;

import com.umeng.socialize.controller.RequestType;
import com.umeng.socialize.controller.UMServiceFactory;
import com.umeng.socialize.controller.UMSocialService;
import com.umeng.socialize.media.UMImage;

public class UmengGameActivity extends Cocos2dxActivity {

	/**
	 * Handler, 用于包装友盟的openShare方法,保证openShare方法在UI线程执行
	 */
	private static Handler mHandler = null;
	/**
	 * 保存当前Activity实例, 静态变量
	 */
	private static Cocos2dxActivity mActivity = null;
	/**
	 * 友盟Social SDK实例,整个SDK的Controller
	 */
	private static UMSocialService mController = UMServiceFactory
			.getUMSocialService("com.umeng.cocos2dx", RequestType.SOCIAL);
	/**
	 * 
	 */
	private static final int DELAY = 100;

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.cocos2dx.lib.Cocos2dxActivity#onCreate(android.os.Bundle)
	 */
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		mActivity = this;
		mHandler = new Handler(Looper.getMainLooper());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.cocos2dx.lib.Cocos2dxActivity#onCreateView()
	 */
	public Cocos2dxGLSurfaceView onCreateView() {
		Cocos2dxGLSurfaceView glSurfaceView = new Cocos2dxGLSurfaceView(this);
		// hello should create stencil buffer
		glSurfaceView.setEGLConfigChooser(5, 6, 5, 0, 16, 8);

		return glSurfaceView;
	}

        // 截屏路径
	private static String scrshotImgPath = "";

	/**
	 * 打开分享面板
	 */
	public static void openShare() {

		mHandler.postDelayed(new Runnable() {

			@Override
			public void run() {

				if (!TextUtils.isEmpty(scrshotImgPath)) {
					mController.setShareMedia(new UMImage(mActivity, new File(
							scrshotImgPath)));
					Log.d("", "### 设置截屏图片");
				}
				mController.setShareContent("cocos2d-x截屏分享, 图片地址 : "
						+ scrshotImgPath);
				// 打开友盟的分享平台选择面板
				mController.openShare(mActivity, false);
			}
		}, DELAY);
	}

	/**
	 * 设置图片以后,直接打开分享面板
	 * @param path
	 */
	public static void setImagePath(String path) {
		scrshotImgPath = path;
		// 打开分享面板
		openShare();
	}

	/**
	 * 加载cocos2dcpp.so
	 */
	static {
		System.loadLibrary("cocos2dcpp");
	}
}

注意,scrshotImgPath是静态成员变量,因此使用完图片一次后需要清空,避免使用上次的截图图像。

效果图 

Cocos2d-x游戏在Android平台使用友盟社会化组件开展截图分享的实现

Cocos2d-x游戏在Android平台使用友盟社会化组件开展截图分享的实现