有关cocos2dx游戏中android复制与粘贴的问题
一、问题的来由
问题的主要来由是在现在的游戏中需要复制用户的id号,进行游戏内查找,同时也需要支持跨APP间的复制粘贴(也就是微信中的问题可以剪切到游戏中进行粘贴搜索或者发布到聊天系统内)
二、主要的思路
主要的思路是借助安卓系统的剪切板来进行操作。但是需要注意一般的游戏中,游戏的逻辑都是新建的一个线程,所有网上很多的代码是不能直接使用的,这里涉及到跨线程的数据共享(操作)。当然这里只是提供一种思路:c++层先调用安卓的剪切板(游戏线程),进入安卓的JAVA层获取(安卓的主线程),将获取到的字符串返回到c++等(即回到游戏线程),用于显示。
三、详细的实现
1.最开始的解决方案:
c++层的调用
void main()
{
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
TextField* pInput = static_cast<TextField*>(m_pWindow->getChildByPath("Root/Wnd/Page_1/Search/Input"));
if (pInput)
{
DeviceManager::Instance().PasteFromClipboard();
}
}
std::string DeviceManager::PasteFromClipboard()
{
//粘贴功能
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
cocos2d::log("PasteFromClipboard");
JniMethodInfo info;
jstring ret;
std::string cacheData = "";
bool bHave = JniHelper::getStaticMethodInfo(info, CLASS_NAME, "getFromClipboard", "()Ljava/lang/String;");
if (bHave){
ret = (jstring)info.env->CallStaticObjectMethod(info.classID, info.methodID);
cacheData = JniHelper::jstring2string(ret);
info.env->DeleteLocalRef(info.classID);
info.env->DeleteLocalRef(ret);
}
return cacheData;
#elif CC_TARGET_PLATFORM == CC_PLATFORM_IOS
return IOSHelper::pasteFromClipboard();
#endif
}
JAVA 层调用
public static String getFromClipboard() {
final Context context = getContext();
ClipboardManager clipboard = (ClipboardManager)context.getSystemService(Context.CLIPBOARD_SERVICE);
if(clipboard.getText() != null)
{
return clipboard.getText().toString();
}
else
{
return "";
}
这里的方式可以带大多数安卓机器上运行成功,但是会有意外的,例如在三星note4上就有问题,特别是为空的之后会崩溃。
也就是这里的核心问题就是线程的不安全性,为什么这里你想想一想。
2.最后的解决方案
这里c++层的调用基本不用改,只改变JAVA层,但是思路是采用回调的这种形式,也就是当c++等调用之后,JAVA层处理好以后,再回调c++等的函数执行即可。
c++等增加回调函数
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
extern "C" {
JNIEXPORT void JNICALL Java_org_cocos2dx_cpp_AppActivity_GetFromClipboardCallBack(JNIEnv* env, jobject clazz, jstring resultData)
{
const char* str = env->GetStringUTFChars(resultData, NULL);
cocos2d::log("GetFromClipboardCallBack %s", str);
const std::string s(str);
StringArgs args(s);
LOGIC_EVENT.onPasteEvent.FireEvent(args);
cocos2d::log("GetFromClipboardCallBack111");
}
}
#endif
JAVA层的调用
public static String getFromClipboard() {
//final Context context = getContext();
//ClipboardManager clipboard = (ClipboardManager)context.getSystemService(Context.CLIPBOARD_SERVICE);
//return clipboard.getText().toString();
Cocos2dxActivity sCocos2dxActivity = (Cocos2dxActivity) Cocos2dxActivity.getContext();
sCocos2dxActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
final Context context = getContext();
ClipboardManager clipboard = (ClipboardManager)context.getSystemService(Context.CLIPBOARD_SERVICE);
if(clipboard.getText() != null)
{
final String text = clipboard.getText().toString();
Cocos2dxActivity activity = (Cocos2dxActivity)Cocos2dxActivity.getContext();
activity.runOnGLThread(new Runnable() {
@Override
public void run() {
AppActivity.GetFromClipboardCallBack(text);
}
});
}
else
{
final String text = "";
Cocos2dxActivity activity = (Cocos2dxActivity)Cocos2dxActivity.getContext();
activity.runOnGLThread(new Runnable() {
@Override
public void run() {
AppActivity.GetFromClipboardCallBack(text);
}
});
}
//Log.e("Clipboard4", "22222222222222");
}
});
return "";
}
public static native void GetFromClipboardCallBack(String resultData);
我这里runOnUiThread是安卓的主线程,runOnGLThread是游戏线程。