package com.example.facedemo; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.text.Spannable; import android.text.SpannableString; import android.text.TextUtils; import android.text.style.ImageSpan; import android.util.Log; /** * ****************************************** * @author 廖乃波 * @文件名称 : FaceConversionUtil.java * @创建时间 : 2013-1-27 下午02:34:09 * @文件描述 : 表情轉換工具 ****************************************** */ public class FaceConversionUtil { /** 每一页表情的个数 */ private int pageSize = 20; private static FaceConversionUtil mFaceConversionUtil; /** 保存于内存中的表情HashMap */ private HashMap<String, String> emojiMap = new HashMap<String, String>(); /** 保存于内存中的表情集合 */ private List<ChatEmoji> emojis = new ArrayList<ChatEmoji>(); /** 表情分页的结果集合 */ public List<List<ChatEmoji>> emojiLists = new ArrayList<List<ChatEmoji>>(); private FaceConversionUtil() { } public static FaceConversionUtil getInstace() { if (mFaceConversionUtil == null) { mFaceConversionUtil = new FaceConversionUtil(); } return mFaceConversionUtil; } /** * 得到一个SpanableString对象,通过传入的字符串,并进行正则判断 * * @param context * @param str * @return */ public SpannableString getExpressionString(Context context, String str) { SpannableString spannableString = new SpannableString(str); // 正则表达式比配字符串里是否含有表情,如: 我好[开心]啊 String zhengze = "\\[[^\\]]+\\]"; // 通过传入的正则表达式来生成一个pattern Pattern sinaPatten = Pattern.compile(zhengze, Pattern.CASE_INSENSITIVE); try { dealExpression(context, spannableString, sinaPatten, 0); } catch (Exception e) { Log.e("dealExpression", e.getMessage()); } return spannableString; } /** * 添加表情 * * @param context * @param imgId * @param spannableString * @return */ public SpannableString addFace(Context context, int imgId, String spannableString) { if (TextUtils.isEmpty(spannableString)) { return null; } Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), imgId); bitmap = Bitmap.createScaledBitmap(bitmap, 35, 35, true); ImageSpan imageSpan = new ImageSpan(context, bitmap); SpannableString spannable = new SpannableString(spannableString); spannable.setSpan(imageSpan, 0, spannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); return spannable; } /** * 对spanableString进行正则判断,如果符合要求,则以表情图片代替 * * @param context * @param spannableString * @param patten * @param start * @throws Exception */ private void dealExpression(Context context, SpannableString spannableString, Pattern patten, int start) throws Exception { Matcher matcher = patten.matcher(spannableString); while (matcher.find()) { String key = matcher.group(); // 返回第一个字符的索引的文本匹配整个正则表达式,ture 则继续递归 if (matcher.start() < start) { continue; } String value = emojiMap.get(key); if (TextUtils.isEmpty(value)) { continue; } int resId = context.getResources().getIdentifier(value, "drawable", context.getPackageName()); // 通过上面匹配得到的字符串来生成图片资源id,下边的方法可用,但是你工程混淆的时候就有事了,你懂的。不是我介绍的重点 // Field field=R.drawable.class.getDeclaredField(value); // int resId=Integer.parseInt(field.get(null).toString()); if (resId != 0) { Bitmap bitmap = BitmapFactory.decodeResource( context.getResources(), resId); bitmap = Bitmap.createScaledBitmap(bitmap, 50, 50, true); // 通过图片资源id来得到bitmap,用一个ImageSpan来包装 ImageSpan imageSpan = new ImageSpan(bitmap); // 计算该图片名字的长度,也就是要替换的字符串的长度 int end = matcher.start() + key.length(); // 将该图片替换字符串中规定的位置中 spannableString.setSpan(imageSpan, matcher.start(), end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); if (end < spannableString.length()) { // 如果整个字符串还未验证完,则继续。。 dealExpression(context, spannableString, patten, end); } break; } } } public void getFileText(Context context) { ParseData(FileUtils.getEmojiFile(context), context); } /** * 解析字符 * * @param data */ private void ParseData(List<String> data, Context context) { if (data == null) { return; } ChatEmoji emojEentry; try { for (String str : data) { String[] text = str.split(","); String fileName = text[0] .substring(0, text[0].lastIndexOf(".")); emojiMap.put(text[1], fileName); int resID = context.getResources().getIdentifier(fileName, "drawable", context.getPackageName()); if (resID != 0) { emojEentry = new ChatEmoji(); emojEentry.setId(resID); emojEentry.setCharacter(text[1]); emojEentry.setFaceName(fileName); emojis.add(emojEentry); } } int pageCount = (int) Math.ceil(emojis.size() / 20 + 0.1); for (int i = 0; i < pageCount; i++) { emojiLists.add(getData(i)); } } catch (Exception e) { e.printStackTrace(); } } /** * 获取分页数据 * * @param page * @return */ private List<ChatEmoji> getData(int page) { int startIndex = page * pageSize; int endIndex = startIndex + pageSize; if (endIndex > emojis.size()) { endIndex = emojis.size(); } // 不这么写,会在viewpager加载中报集合操作异常,我也不知道为什么 List<ChatEmoji> list = new ArrayList<ChatEmoji>(); list.addAll(emojis.subList(startIndex, endIndex)); if (list.size() < pageSize) { for (int i = list.size(); i < pageSize; i++) { ChatEmoji object = new ChatEmoji(); list.add(object); } } if (list.size() == pageSize) { ChatEmoji object = new ChatEmoji(); object.setId(R.drawable.face_del_icon); list.add(object); } return list; } }
package com.example.facedemo; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.text.SpannableString; import android.text.TextUtils; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.EditText; import android.widget.GridView; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; /** * ****************************************** * @author 廖乃波 * @文件名称 : FaceRelativeLayout.java * @创建时间 : 2013-1-27 下午02:34:17 * @文件描述 : 带表情的自定义输入框 ****************************************** */ public class FaceRelativeLayout extends RelativeLayout implements OnItemClickListener, OnClickListener { private Context context; /** 表情页的监听事件 */ private OnCorpusSelectedListener mListener; /** 显示表情页的viewpager */ private ViewPager vp_face; /** 表情页界面集合 */ private ArrayList<View> pageViews; /** 游标显示布局 */ private LinearLayout layout_point; /** 游标点集合 */ private ArrayList<ImageView> pointViews; /** 表情集合 */ private List<List<ChatEmoji>> emojis; /** 表情区域 */ private View view; /** 输入框 */ private EditText et_sendmessage; /** 表情数据填充器 */ private List<FaceAdapter> faceAdapters; /** 当前表情页 */ private int current = 0; public FaceRelativeLayout(Context context) { super(context); this.context = context; } public FaceRelativeLayout(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; } public FaceRelativeLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.context = context; } public void setOnCorpusSelectedListener(OnCorpusSelectedListener listener) { mListener = listener; } /** * 表情选择监听 * * @author naibo-liao * @时间: 2013-1-15下午04:32:54 */ public interface OnCorpusSelectedListener { void onCorpusSelected(ChatEmoji emoji); void onCorpusDeleted(); } @Override protected void onFinishInflate() { super.onFinishInflate(); emojis = FaceConversionUtil.getInstace().emojiLists; onCreate(); } private void onCreate() { Init_View(); Init_viewPager(); Init_Point(); Init_Data(); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_face: // 隐藏表情选择框 if (view.getVisibility() == View.VISIBLE) { view.setVisibility(View.GONE); } else { view.setVisibility(View.VISIBLE); } break; case R.id.et_sendmessage: // 隐藏表情选择框 if (view.getVisibility() == View.VISIBLE) { view.setVisibility(View.GONE); } break; } } /** * 隐藏表情选择框 */ public boolean hideFaceView() { // 隐藏表情选择框 if (view.getVisibility() == View.VISIBLE) { view.setVisibility(View.GONE); return true; } return false; } /** * 初始化控件 */ private void Init_View() { vp_face = (ViewPager) findViewById(R.id.vp_contains); et_sendmessage = (EditText) findViewById(R.id.et_sendmessage); layout_point = (LinearLayout) findViewById(R.id.iv_image); et_sendmessage.setOnClickListener(this); findViewById(R.id.btn_face).setOnClickListener(this); view = findViewById(R.id.ll_facechoose); } /** * 初始化显示表情的viewpager */ private void Init_viewPager() { pageViews = new ArrayList<View>(); // 左侧添加空页 View nullView1 = new View(context); // 设置透明背景 nullView1.setBackgroundColor(Color.TRANSPARENT); pageViews.add(nullView1); // 中间添加表情页 faceAdapters = new ArrayList<FaceAdapter>(); for (int i = 0; i < emojis.size(); i++) { GridView view = new GridView(context); FaceAdapter adapter = new FaceAdapter(context, emojis.get(i)); view.setAdapter(adapter); faceAdapters.add(adapter); view.setOnItemClickListener(this); view.setNumColumns(7); view.setBackgroundColor(Color.TRANSPARENT); view.setHorizontalSpacing(1); view.setVerticalSpacing(1); view.setStretchMode(GridView.STRETCH_COLUMN_WIDTH); view.setCacheColorHint(0); view.setPadding(5, 0, 5, 0); view.setSelector(new ColorDrawable(Color.TRANSPARENT)); view.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); view.setGravity(Gravity.CENTER); pageViews.add(view); } // 右侧添加空页面 View nullView2 = new View(context); // 设置透明背景 nullView2.setBackgroundColor(Color.TRANSPARENT); pageViews.add(nullView2); } /** * 初始化游标 */ private void Init_Point() { pointViews = new ArrayList<ImageView>(); ImageView imageView; for (int i = 0; i < pageViews.size(); i++) { imageView = new ImageView(context); imageView.setBackgroundResource(R.drawable.d1); LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); layoutParams.leftMargin = 10; layoutParams.rightMargin = 10; layoutParams.width = 8; layoutParams.height = 8; layout_point.addView(imageView, layoutParams); if (i == 0 || i == pageViews.size() - 1) { imageView.setVisibility(View.GONE); } if (i == 1) { imageView.setBackgroundResource(R.drawable.d2); } pointViews.add(imageView); } } /** * 填充数据 */ private void Init_Data() { vp_face.setAdapter(new ViewPagerAdapter(pageViews)); vp_face.setCurrentItem(1); current = 0; vp_face.setOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int arg0) { current = arg0 - 1; // 描绘分页点 draw_Point(arg0); // 如果是第一屏或者是最后一屏禁止滑动,其实这里实现的是如果滑动的是第一屏则跳转至第二屏,如果是最后一屏则跳转到倒数第二屏. if (arg0 == pointViews.size() - 1 || arg0 == 0) { if (arg0 == 0) { vp_face.setCurrentItem(arg0 + 1);// 第二屏 会再次实现该回调方法实现跳转. pointViews.get(1).setBackgroundResource(R.drawable.d2); } else { vp_face.setCurrentItem(arg0 - 1);// 倒数第二屏 pointViews.get(arg0 - 1).setBackgroundResource( R.drawable.d2); } } } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageScrollStateChanged(int arg0) { } }); } /** * 绘制游标背景 */ public void draw_Point(int index) { for (int i = 1; i < pointViews.size(); i++) { if (index == i) { pointViews.get(i).setBackgroundResource(R.drawable.d2); } else { pointViews.get(i).setBackgroundResource(R.drawable.d1); } } } @Override public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { ChatEmoji emoji = (ChatEmoji) faceAdapters.get(current).getItem(arg2); if (emoji.getId() == R.drawable.face_del_icon) { int selection = et_sendmessage.getSelectionStart(); String text = et_sendmessage.getText().toString(); if (selection > 0) { String text2 = text.substring(selection - 1); if ("]".equals(text2)) { int start = text.lastIndexOf("["); int end = selection; et_sendmessage.getText().delete(start, end); return; } et_sendmessage.getText().delete(selection - 1, selection); } } if (!TextUtils.isEmpty(emoji.getCharacter())) { if (mListener != null) mListener.onCorpusSelected(emoji); SpannableString spannableString = FaceConversionUtil.getInstace() .addFace(getContext(), emoji.getId(), emoji.getCharacter()); et_sendmessage.append(spannableString); } } }
package com.example.facedemo; import android.content.Context; import android.text.SpannableString; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import java.util.List; /** * ****************************************** * @author 廖乃波 * @文件名称 : ChatMsgAdapter.java * @创建时间 : 2013-1-27 下午02:33:16 * @文件描述 : 消息数据填充起 ****************************************** */ public class ChatMsgAdapter extends BaseAdapter { public static interface IMsgViewType { int IMVT_COM_MSG = 0; int IMVT_TO_MSG = 1; } private List<ChatMsgEntity> coll; private LayoutInflater mInflater; private Context context; public ChatMsgAdapter(Context context, List<ChatMsgEntity> coll) { this.coll = coll; mInflater = LayoutInflater.from(context); this.context = context; } public int getCount() { return coll.size(); } public Object getItem(int position) { return coll.get(position); } public long getItemId(int position) { return position; } public int getItemViewType(int position) { ChatMsgEntity entity = coll.get(position); if (entity.getMsgType()) { return IMsgViewType.IMVT_COM_MSG; } else { return IMsgViewType.IMVT_TO_MSG; } } public int getViewTypeCount() { return 2; } public View getView(int position, View convertView, ViewGroup parent) { ChatMsgEntity entity = coll.get(position); boolean isComMsg = entity.getMsgType(); ViewHolder viewHolder = null; if (convertView == null) { if (isComMsg) { convertView = mInflater.inflate( R.layout.chatting_item_msg_text_left, null); } else { convertView = mInflater.inflate( R.layout.chatting_item_msg_text_right, null); } viewHolder = new ViewHolder(); viewHolder.tvSendTime = (TextView) convertView .findViewById(R.id.tv_sendtime); viewHolder.tvContent = (TextView) convertView .findViewById(R.id.tv_chatcontent); viewHolder.isComMsg = isComMsg; convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.tvSendTime.setText(entity.getDate()); SpannableString spannableString = FaceConversionUtil.getInstace().getExpressionString(context, entity.getText()); viewHolder.tvContent.setText(spannableString); return convertView; } class ViewHolder { public TextView tvSendTime; public TextView tvContent; public boolean isComMsg = true; } }
package com.example.facedemo; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; import android.content.Context; /** * ****************************************** * @author 廖乃波 * @文件名称 : FileUtils.java * @创建时间 : 2013-1-27 下午02:35:09 * @文件描述 : 文件工具类 ****************************************** */ public class FileUtils { /** * 读取表情配置文件 * * @param context * @return */ public static List<String> getEmojiFile(Context context) { try { List<String> list = new ArrayList<String>(); InputStream in = context.getResources().getAssets().open("emoji"); BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8")); String str = null; while ((str = br.readLine()) != null) { list.add(str); } return list; } catch (IOException e) { e.printStackTrace(); } return null; } }
package com.example.facedemo; import java.util.List; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.view.View; /** * ****************************************** * @author 廖乃波 * @文件名称 : ViewPagerAdapter.java * @创建时间 : 2013-1-27 下午02:35:27 * @文件描述 : ViewPager 数据填充器,切记做其他操作!!!只填充View!!!! ****************************************** */ public class ViewPagerAdapter extends PagerAdapter { private List<View> pageViews; public ViewPagerAdapter(List<View> pageViews) { super(); this.pageViews=pageViews; } // 显示数目 @Override public int getCount() { return pageViews.size(); } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } @Override public int getItemPosition(Object object) { return super.getItemPosition(object); } @Override public void destroyItem(View arg0, int arg1, Object arg2) { ((ViewPager)arg0).removeView(pageViews.get(arg1)); } /*** * 获取每一个item 类于listview中的getview */ @Override public Object instantiateItem(View arg0, int arg1) { ((ViewPager)arg0).addView(pageViews.get(arg1)); return pageViews.get(arg1); } }
emoji_1.png,[可爱] emoji_2.png,[笑脸] emoji_3.png,[囧] emoji_4.png,[生气] emoji_5.png,[鬼脸] emoji_6.png,[花心] emoji_7.png,[害怕] emoji_8.png,[我汗] emoji_9.png,[尴尬] emoji_10.png,[哼哼] emoji_11.png,[忧郁] emoji_12.png,[呲牙] emoji_13.png,[媚眼] emoji_14.png,[累] emoji_15.png,[苦逼] emoji_16.png,[瞌睡] emoji_17.png,[哎呀] emoji_18.png,[刺瞎] emoji_19.png,[哭] emoji_20.png,[激动] emoji_21.png,[难过] emoji_22.png,[害羞] emoji_23.png,[高兴] emoji_24.png,[愤怒] emoji_25.png,[亲] emoji_26.png,[飞吻] emoji_27.png,[得意] emoji_28.png,[惊恐] emoji_29.png,[口罩] emoji_30.png,[惊讶] emoji_31.png,[委屈] emoji_32.png,[生病] emoji_33.png,[红心] emoji_34.png,[心碎] emoji_35.png,[玫瑰] emoji_36.png,[花] emoji_37.png,[外星人] emoji_38.png,[金牛座] emoji_39.png,[双子座] emoji_40.png,[巨蟹座] emoji_41.png,[狮子座] emoji_42.png,[处女座] emoji_43.png,[天平座] emoji_44.png,[天蝎座] emoji_45.png,[射手座] emoji_46.png,[摩羯座] emoji_47.png,[水瓶座] emoji_48.png,[白羊座] emoji_49.png,[双鱼座] emoji_50.png,[星座] emoji_51.png,[男孩] emoji_52.png,[女孩] emoji_53.png,[嘴唇] emoji_54.png,[爸爸] emoji_55.png,[妈妈] emoji_56.png,[衣服] emoji_57.png,[皮鞋] emoji_58.png,[照相] emoji_59.png,[电话] emoji_60.png,[石头] emoji_61.png,[胜利] emoji_62.png,[禁止] emoji_63.png,[滑雪] emoji_64.png,[高尔夫] emoji_65.png,[网球] emoji_66.png,[棒球] emoji_67.png,[冲浪] emoji_68.png,[足球] emoji_69.png,[小鱼] emoji_70.png,[问号] emoji_71.png,[叹号] emoji_179.png,[顶] emoji_180.png,[写字] emoji_181.png,[衬衫] emoji_182.png,[小花] emoji_183.png,[郁金香] emoji_184.png,[向日葵] emoji_185.png,[鲜花] emoji_186.png,[椰树] emoji_187.png,[仙人掌] emoji_188.png,[气球] emoji_189.png,[炸弹] emoji_190.png,[喝彩] emoji_191.png,[剪子] emoji_192.png,[蝴蝶结] emoji_193.png,[机密] emoji_194.png,[铃声] emoji_195.png,[女帽] emoji_196.png,[裙子] emoji_197.png,[理发店] emoji_198.png,[和服] emoji_199.png,[比基尼] emoji_200.png,[拎包] emoji_201.png,[拍摄] emoji_202.png,[铃铛] emoji_203.png,[音乐] emoji_204.png,[心星] emoji_205.png,[粉心] emoji_206.png,[丘比特] emoji_207.png,[吹气] emoji_208.png,[口水] emoji_209.png,[对] emoji_210.png,[错] emoji_211.png,[绿茶] emoji_212.png,[面包] emoji_213.png,[面条] emoji_214.png,[咖喱饭] emoji_215.png,[饭团] emoji_216.png,[麻辣烫] emoji_217.png,[寿司] emoji_218.png,[苹果] emoji_219.png,[橙子] emoji_220.png,[草莓] emoji_221.png,[西瓜] emoji_222.png,[柿子] emoji_223.png,[眼睛] emoji_224.png,[好的]
<?xml version="1.0" encoding="utf-8"?> <com.example.facedemo.FaceRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/FaceRelativeLayout" android:layout_width="fill_parent" android:layout_height="wrap_content" > <RelativeLayout android:id="@+id/rl_input" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@drawable/chat_footer_bg" > <ImageButton android:id="@+id/btn_face" android:layout_width="40dip" android:layout_height="40dip" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:layout_marginLeft="8dip" android:background="@drawable/chat_send_btn" android:src="@drawable/ib_face" /> <Button android:id="@+id/btn_send" android:layout_width="60dp" android:layout_height="40dp" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:layout_marginRight="10dp" android:background="@drawable/chat_send_btn" android:text="发送" /> <EditText android:id="@+id/et_sendmessage" android:layout_width="fill_parent" android:layout_height="40dp" android:layout_centerVertical="true" android:layout_marginLeft="8dp" android:layout_marginRight="10dp" android:layout_toLeftOf="@id/btn_send" android:layout_toRightOf="@id/btn_face" android:background="@drawable/login_edit_normal" android:singleLine="true" android:textSize="18sp" /> </RelativeLayout> <RelativeLayout android:id="@+id/ll_facechoose" android:layout_width="fill_parent" android:layout_height="124dip" android:layout_below="@id/rl_input" android:background="#f6f5f5" android:visibility="gone" > <android.support.v4.view.ViewPager android:id="@+id/vp_contains" android:layout_width="match_parent" android:layout_height="match_parent" > </android.support.v4.view.ViewPager> <LinearLayout android:id="@+id/iv_image" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="6dip" android:gravity="center" android:orientation="horizontal" > </LinearLayout> </RelativeLayout> </com.example.facedemo.FaceRelativeLayout>
来源:即时通讯网 - 即时通讯开发者社区!
轻量级开源移动端即时通讯框架。
快速入门 / 性能 / 指南 / 提问
轻量级Web端即时通讯框架。
详细介绍 / 精编源码 / 手册教程
移动端实时音视频框架。
详细介绍 / 性能测试 / 安装体验
基于MobileIMSDK的移动IM系统。
详细介绍 / 产品截图 / 安装体验
一套产品级Web端IM系统。
详细介绍 / 产品截图 / 演示视频
精华主题数超过100个。
连续任职达2年以上的合格正式版主
为论区做出突出贡献的开发者、版主等。
在线时长累积7天(即7 * 8 = 56小时)。
持有金钱达到500。
光棍节活动纪念章。
积极发起、参与各类话题的讨论等,主题、发帖内容较有价值。
本人属:猪
本人属:猴
在线时长累积30天(即30 * 8 = 240小时)。
Copyright © 2014-2024 即时通讯网 - 即时通讯开发者社区 / 版本 V4.4
苏州网际时代信息科技有限公司 (苏ICP备16005070号-1)
Processed in 0.218750 second(s), 49 queries , Gzip On.