关于emjoy表情在android5.x以上系统触发jni错误的修改(基于cocos2dx2.1.5修改)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013214781/article/details/51209258

一直纠结着这个错误,后来看别人的文章找到灵感,于是完善了基于cocos2dx2.1.5修改的大笑


具体报错:JNI DETECTED ERROR IN APPLICATION: input is not valid Modified UTF-8: illegal continuation byte 0xed

解决办法(基于coocs2dx2.1.5):

在CCImage.cpp里面的getBitmapFromJavaShadowStroke方法中,emjoy表情在jstring jstrText = methodInfo.env->NewStringUTF(text);

的时候触发崩溃,原因大致估计是因为emjoy不能被utf识别,于是绕过NewStringUTF,将之转化为byte[]来绕过.具体屏蔽jstring jstrText = methodInfo.env->NewStringUTF(text);修改为

 bool getBitmapFromJavaShadowStroke(	const char *text,
    									int nWidth,
    									int nHeight,
    									CCImage::ETextAlign eAlignMask,
    									const char * pFontName,
    									float fontSize,
    									float textTintR 		= 1.0,
    									float textTintG 		= 1.0,
    									float textTintB 		= 1.0,
    									bool shadow 			= false,
    									float shadowDeltaX 		= 0.0,
    									float shadowDeltaY 		= 0.0,
    									float shadowBlur 		= 0.0,
    									float shadowIntensity 	= 0.0,
    									bool stroke 			= false,
    									float strokeColorR 		= 0.0,
    									float strokeColorG 		= 0.0,
    									float strokeColorB 		= 0.0,
    									float strokeSize 		= 0.0 )
    {
           JniMethodInfo methodInfo;
           if (! JniHelper::getStaticMethodInfo(methodInfo, "org/cocos2dx/lib/Cocos2dxBitmap", "createTextBitmapShadowStroke",
               "([BLjava/lang/String;IFFFIIIZFFFZFFFF)V"))
           {
               CCLOG("%s %d: error to get methodInfo", __FILE__, __LINE__);
               return false;
           }
        
        
        
           // Do a full lookup for the font path using CCFileUtils in case the given font name is a relative path to a font file asset,
           // or the path has been mapped to a different location in the app package:
           std::string fullPathOrFontName = CCFileUtils::sharedFileUtils()->fullPathForFilename(pFontName);
        
		   // If the path name returned includes the 'assets' dir then that needs to be removed, because the android.content.Context
		   // requires this portion of the path to be omitted for assets inside the app package.
		   if (fullPathOrFontName.find("assets/") == 0)
		   {
               fullPathOrFontName = fullPathOrFontName.substr(strlen("assets/"));	// Chop out the 'assets/' portion of the path.
           }

           /**create bitmap
            * this method call Cococs2dx.createBitmap()(java code) to create the bitmap, the java code
            * will call Java_org_cocos2dx_lib_Cocos2dxBitmap_nativeInitBitmapDC() to init the width, height
            * and data.
            * use this approach to decrease the jni call number
           */
           //jstring jstrText = methodInfo.env->NewStringUTF(text);

		   /**
		    * 修复emioy表情在android5.x以上系统jni崩溃bug
		    * 将string修改为byte[].绕过jni在android5.x以上系统出现emjoy崩溃问题
		    */
		   int strLen = strlen(text);
		   jbyteArray byteArray = methodInfo.env->NewByteArray(strLen);
		   methodInfo.env->SetByteArrayRegion(byteArray, 0, strLen, reinterpret_cast<const jbyte*>(text));
           jstring jstrFont = methodInfo.env->NewStringUTF(fullPathOrFontName.c_str());

           methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, byteArray,
               jstrFont, (int)fontSize, textTintR, textTintG, textTintB, eAlignMask, nWidth, nHeight, shadow, shadowDeltaX, -shadowDeltaY, shadowBlur, stroke, strokeColorR, strokeColorG, strokeColorB, strokeSize);

           methodInfo.env->DeleteLocalRef(byteArray);
           methodInfo.env->DeleteLocalRef(jstrFont);
           methodInfo.env->DeleteLocalRef(methodInfo.classID);

           return true;
    }

同时java对应修改传入参数

Cocos2dxBitmap.java中,createTextBitmapShadowStroke传入参数修改为byte[]类型,然后将byte[]转化为string来正常直接emjoy的输出

public static void createTextBitmapShadowStroke(byte[] pString_byte,
		final String pFontName,final int pFontSize,final float fontTintR,
		final float fontTintG,final float fontTintB,final int pAlignment,
		final int pWidth,final int pHeight,final boolean shadow,
		final float shadowDX,final float shadowDY,final float shadowBlur,
		final boolean stroke,final float strokeR,final float strokeG,
		final float strokeB,final float strokeSize) throws UnsupportedEncodingException
	{
		/**
		 * 将string修改为byte[].绕过jni在android5.x以上系统出现emjoy崩溃问题,然后重新转化为string来继续输出emjoy表情
		 * @author lfy
		 */
		String pString=new String(pString_byte,"UTF-8");
		
		final int horizontalAlignment=pAlignment&0x0F;
		final int verticalAlignment=(pAlignment>>4)&0x0F;

		try
		{
			pString=Cocos2dxBitmap.refactorString(pString);
		}
		catch(java.lang.Exception e)
		{

		}
		final Paint paint=Cocos2dxBitmap.newPaint(pFontName,pFontSize,
			horizontalAlignment);

		// set the paint color
		paint.setARGB(255,(int)(255.0*fontTintR),(int)(255.0*fontTintG),
			(int)(255.0*fontTintB));

		// modify some char error... s cdy20140731
		// final TextProperty
		// textProperty=Cocos2dxBitmap.computeTextProperty(
		// pString,pWidth,pHeight,paint);
		// final int bitmapTotalHeight=(pHeight==0?textProperty.mTotalHeight
		// :pHeight);
		TextProperty textProperty=null;
		int bitmapTotalHeight=0;
		textProperty=Cocos2dxBitmap.computeTextProperty(pString,pWidth,
			pHeight,paint);
		bitmapTotalHeight=(pHeight==0?textProperty.mTotalHeight:pHeight);

		if(bitmapTotalHeight<=0||textProperty.mMaxWidth<=0)
		{
			textProperty=Cocos2dxBitmap.computeTextProperty(" ",pWidth,
				pHeight,paint);
			bitmapTotalHeight=(pHeight==0?textProperty.mTotalHeight:pHeight);
		}
		// modify some char error... e

		// padding needed when using shadows (not used otherwise)
		float bitmapPaddingX=0.0f;
		float bitmapPaddingY=0.0f;
		float renderTextDeltaX=0.0f;
		float renderTextDeltaY=0.0f;

		if(shadow)
		{

			int shadowColor=0xff7d7d7d;
			paint.setShadowLayer(shadowBlur,shadowDX,shadowDY,shadowColor);

			bitmapPaddingX=Math.abs(shadowDX);
			bitmapPaddingY=Math.abs(shadowDY);

			if(shadowDX<0.0)
			{
				renderTextDeltaX=bitmapPaddingX;
			}

			if(shadowDY<0.0)
			{
				renderTextDeltaY=bitmapPaddingY;
			}
		}

		final Bitmap bitmap=Bitmap.createBitmap(textProperty.mMaxWidth
			+(int)bitmapPaddingX,bitmapTotalHeight+(int)bitmapPaddingY,
			Bitmap.Config.ARGB_8888);

		final Canvas canvas=new Canvas(bitmap);

		/* Draw string. */
		final FontMetricsInt fontMetricsInt=paint.getFontMetricsInt();

		int x=0;
		int y=Cocos2dxBitmap.computeY(fontMetricsInt,pHeight,
			textProperty.mTotalHeight,verticalAlignment);

		final String[] lines=textProperty.mLines;

		for(final String line:lines)
		{

			x=Cocos2dxBitmap.computeX(line,textProperty.mMaxWidth,
				horizontalAlignment);
			canvas
				.drawText(line,x+renderTextDeltaX,y+renderTextDeltaY,paint);
			y+=textProperty.mHeightPerLine;

		}

		// draw again with stroke on if needed
		if(stroke)
		{

			final Paint paintStroke=Cocos2dxBitmap.newPaint(pFontName,
				pFontSize,horizontalAlignment);
			paintStroke.setStyle(Paint.Style.STROKE);
			paintStroke.setStrokeWidth(strokeSize*0.5f);
			paintStroke.setARGB(255,(int)strokeR*255,(int)strokeG*255,
				(int)strokeB*255);

			x=0;
			y=Cocos2dxBitmap.computeY(fontMetricsInt,pHeight,
				textProperty.mTotalHeight,verticalAlignment);
			final String[] lines2=textProperty.mLines;

			for(final String line:lines2)
			{

				x=Cocos2dxBitmap.computeX(line,textProperty.mMaxWidth,
					horizontalAlignment);
				canvas.drawText(line,x+renderTextDeltaX,y+renderTextDeltaY,
					paintStroke);
				y+=textProperty.mHeightPerLine;

			}

		}

		Cocos2dxBitmap.initNativeObject(bitmap);
	}

如此可以正常在聊天中输入emjoy表情了,如果有什么差错,麻烦指正下,个人QQ1908662823


猜你喜欢

转载自blog.csdn.net/u013214781/article/details/51209258
今日推荐