Android聊天软件的开发(一)--预备知识
一,通信结构
![](/assets/blank.gif)
![](/assets/blank.gif)
二,RSA加解密
public class EncryptUtils {/** RSA加密的公钥 ,与服务端的私钥对应*/private static final String publicKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0dLTXOCN7VMM4MbbxkVIwIRmEjzlKJSbd97uoWiwt3z/Q1u4DQNfTVdeLtDIEFeYUz1/mJPltMdlUDB8/YO2MfHnvipk4DC+C7mZ5DgP/5Qtglvl6alPTL2yhZNpJ5MCJQNvYk7l5A1lDwSwFKkFmBl2vHeGY76C/Y62ofeZYRwIDAQAB";private static char[] HEX_CHAR = { '0', '1', '2', '3', '4', '5', '6', '7','8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };/*** RSA加密*/public static String GetRsaEncrypt(String src) {if (src == null)return "";String enData = null;try {Cipher cipher = Cipher.getInstance("RSA",new BouncyCastleProvider());RSAPublicKey pubKey = GetPublicKey(publicKeyStr);cipher.init(Cipher.ENCRYPT_MODE, pubKey);byte[] output = cipher.doFinal(src.getBytes("UTF-8"));enData = ByteToString(output);} catch (Exception e) {e.printStackTrace();}return enData;}<span style="white-space:pre"> </span>/**将加密后的byte数组转换为String*/private static String ByteToString(byte[] data) {StringBuilder stringBuilder = new StringBuilder();for (int i = 0; i < data.length; i++) {// 取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移stringBuilder.append(HEX_CHAR[(data[i] & 0xf0) >>> 4]);// 取出字节的低四位 作为索引得到相应的十六进制标识符stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);}return stringBuilder.toString();}/*** 将String型私钥转换为RSAPublicKey* * @param publicKeyStr* 公钥数据字符串*/private static RSAPublicKey GetPublicKey(String publicKeyStr) {RSAPublicKey pubKey = null;try {BASE64Decoder base64Decoder = new BASE64Decoder();byte[] buffer = base64Decoder.decodeBuffer(publicKeyStr);KeyFactory keyFactory = KeyFactory.getInstance("RSA");X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);pubKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);} catch (Exception e) {e.printStackTrace();}return pubKey;}}
服务器解密
public class EncryptUtils {/** 服务器端RSA解密的私钥 ,与客户端的公钥对应*/private static final String privateKeyStr = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALR0tNc4I3tUwzgxtvGRUjAhGYSPOUolJt33u6haLC3fP9DW7gNA19NV14u0MgQV5hTPX+Yk+W0x2VQMHz9g7Yx8ee+KmTgML4LuZnkOA//lC2CW+XpqU9MvbKFk2knkwIlA29iTuXkDWUPBLAUqQWYGXa8d4ZjvoL9jrah95lhHAgMBAAECgYEAqpnjFc0HDmP2I7wsXniqoMHKJB5bZRN2iUbZ7LFDLyLua/umDQFSiYOQQY1b86zYVjgvS58NCASml+TV7c8vA5care9HqpQX+1YdBUB1Hw+zloIwJD5894123wumRpbHBK1vkgvX3cKz0K+lNHfnXoov49DLvDeTCtBb9GQQX2ECQQDv1avuF4DlbVavIuTNZFw5YntZM13E2M+JMx84XGODvncuDl8C/TpW+ZsaaKqU7caXtWl2p5ip4UZPYLwyRh65AkEAwJ51buJ5qZhA7kD6is4RC4P7F2LwGkhKrpXxlzHsPeW8m9if62E7AH3B8MGicIVeQjJwxSrsiI3wYEHDlIyu/wJAN7ZzEgPztVgI4vZAIFZH9iyiar478hZLX5u4jOcpVtlP5isAdzlL7Bhfp2rY9W+mymch8KZOGGh0ZMwb67HOQQJAcOw04mXpd3CoGEWF3FxEh+C/Eo3RP0dEaSfEs6Pz4LHPqfoMfvzIj1gqm8+ZQKgfg2V40U6BzuiPlI7Zbzwu1wJAMbq668GPCzMgc0LLImkGTaOPcmjPYUbAYXa4k/90M3sX0t6s9u0kl9NfotSpF9M3AdbFSdKWXoY8XScOkhnpQQ==";/*** RSA解密<BR/>* <BR/>* 用于将客户端上传的,经过RSA加密的参数进行解密* * @param src* @return 解密后的数据*/public static String GetRsaDecrypt(String src) {String deData = null;try {Cipher cipher = Cipher.getInstance("RSA",new BouncyCastleProvider());RSAPrivateKey priKey = GetPrivateKey(privateKeyStr);cipher.init(Cipher.DECRYPT_MODE, priKey);byte[] output = cipher.doFinal(StringToByte(src));deData = new String(output, "utf-8");// 此处如果不指定编码格式,则会产生中文乱码} catch (Exception e) {e.printStackTrace();}return deData;}/*** 将String型私钥转换为RSAPrivateKey* * @param privateKeyStr* @return*/private static RSAPrivateKey GetPrivateKey(String privateKeyStr) {RSAPrivateKey priKey = null;try {BASE64Decoder base64Decoder = new BASE64Decoder();byte[] buffer = base64Decoder.decodeBuffer(privateKeyStr);PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);KeyFactory keyFactory = KeyFactory.getInstance("RSA");priKey = (RSAPrivateKey) keyFactory.generatePrivate(keySpec);} catch (Exception e) {e.printStackTrace();}return priKey;}/**将解密数据转换为byte数组*/private static byte[] StringToByte(String str) {int len = str.length();byte[] data = new byte[len / 2];char[] ch = str.toCharArray();String tmp;int i = 0, j = 0;while (i < len) {//两个char组合成一个bytetmp = String.valueOf(ch[i++]);//高位int high = Integer.parseInt(tmp, 16);tmp = String.valueOf(ch[i++]);//低位int low = Integer.parseInt(tmp, 16);data[j] = (byte) ((high << 4) + low);j++;}return data;}
}
三,Log4j日志输出
Log4j用于在服务器端输出日志。
四,低版本支持ActionBar
![](/assets/blank.gif)
![](/assets/blank.gif)
<activity
<span style="white-space:pre"> </span>android:name=".MainActivity"
<span style="white-space:pre"> </span><span style="color:#cc0000;">android:theme="@style/Theme.AppCompat.Light"</span>
<span style="white-space:pre"> </span>android:windowSoftInputMode="adjustPan"
<span style="white-space:pre"> </span>android:screenOrientation="portrait">
</activity>
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBar.Tab;
import android.support.v7.app.ActionBar.TabListener;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.PopupMenu.OnMenuItemClickListener;
public class MainActivity extends ActionBarActivity implements OnMenuItemClickListener{private Context mContext;private PopupMenu mAddMenu;private PopupMenu mManageMenu;private ActionBar mActionBar;private ChatFragment mChatFragment; private ContactsFragment mContactsFragment;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);mContext = this;mChatFragment = new ChatFragment(); mContactsFragment = new ContactsFragment();setActionBar();}private void setActionBar(){mActionBar = getSupportActionBar();mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// mActionBar.setDisplayShowTitleEnabled(false);//隐藏ActionBar的titleTabListener listener = new MyTabListener();mActionBar.addTab(mActionBar.newTab().setIcon(R.drawable.main_tab_chat).setText(R.string.fragment_chat).setTabListener(listener)); mActionBar.addTab(mActionBar.newTab().setIcon(R.drawable.main_tab_contacts).setText(R.string.fragment_contacts).setTabListener(listener));}/**添加ActionBar的Menu*/@Overridepublic boolean onCreateOptionsMenu(Menu menu) {getMenuInflater().inflate(R.menu.menu_main, menu);return super.onCreateOptionsMenu(menu);}/**添加Menu的下拉子菜单*/@Overridepublic boolean onOptionsItemSelected(MenuItem item) {switch (item.getItemId()) {case R.id.action_manage:if(mManageMenu == null){mManageMenu = new PopupMenu(mContext,findViewById(R.id.action_manage));mManageMenu.inflate(R.menu.main_item_manage);mManageMenu.setOnMenuItemClickListener(this);}mManageMenu.show();return true;default:return super.onOptionsItemSelected(item);}}/**监听子菜单的点击事件*/@Overridepublic boolean onMenuItemClick(MenuItem menuItem) {switch (menuItem.getItemId()) {case R.id.menu_userInfo://TODO ...break;case R.id.menu_setting://TODO ...break;}return false;}/**TabListener实现类*/class MyTabListener implements TabListener{public void onTabSelected(Tab tab, FragmentTransaction arg1) {switch (tab.getPosition()) { case 0://聊天界面getSupportFragmentManager().beginTransaction() .replace(R.id.main_container, mChatFragment).commit(); break; case 1://通讯录界面getSupportFragmentManager().beginTransaction() .replace(R.id.main_container, mContactsFragment).commit(); break; } }public void onTabReselected(Tab arg0, FragmentTransaction arg1) {}public void onTabUnselected(Tab arg0, FragmentTransaction arg1) {}}
}
最后实现的MainActivity界面
![](/assets/blank.gif)
Android聊天软件的开发(一)--预备知识相关推荐
- Android聊天软件的开发(七)--聊天通信
聊天通信通过Socket实现,大概的框架如下图: 通信流程: 1.服务器在启动时开启聊天服务线程 可以通过ServletContextListener监听Servlet的初始化和销毁,来开启和关闭聊天 ...
- Android聊天软件的开发--聊天通信
Android聊天软件的开发(七)--聊天通信 2014-06-20 23:17:49CSDN-vaintwyt-点击数:338 聊天通信通过Socket实现,大概的框架如下图: 通信流程: 1.服 ...
- Android聊天软件的开发(二)--数据库
一,服务器数据库 服务器端的数据库是MySQL,使用Hibernate实现数据的增删改查.主要存储的数据有:用户信息,好友列表. 其中,好友列表中的friend_list ...
- Android聊天软件的开发(四)--通讯录
一,好友排序 好友排序是按照昵称拼音进行A-Z排序.效果如下图: 对好友昵称进行排序,需要先将首字转换为ASCII码,然后根据ASCII码得到对应的拼音,最后根据拼音进行A-Z排序.点 ...
- Android聊天软件的开发(三)--网络连接
一,服务器网络接口 服务器网络接口通过Servlet实现,可以获得客户端提交的数据,对数据进行查询存储操作,以及返回结果数据给客户端.客户端可以通过HTTP协议直接访问网络接口. HTTP ...
- Android聊天软件的开发(六)--表情
表情用于聊天对话的输入,实现的原理主要是:在EditText或TextView中,使用SpannableString,将特定字符串替换为图片. 首先,我们可以规定,表情的字符串为[**],图片名称为s ...
- Android聊天软件界面开发
聊天软件界面开发 前言: 这是开始学习Android的开发的第5天,一直是跟着郭霖大师的第一行代码学习, 这里边发篇博文记录,边帮自己整理下思路,毕竟思路 ...
- 开发简单Android聊天软件(1)
总体介绍 开篇 大概思路 一. 客户端主要依赖 二.包引用完成后,创建wsClient类. 三.连接成功后,就可以在对于业务逻辑调用以下方法开始发送消息 开篇 本人是一位开发新人,将自己的开发学习过程 ...
- 开发简单Android聊天软件(7)
构建离线消息获取流程 在 "开发简单Android聊天软件(6)" 中,完成了完成消息接收和加载,构建一个完整的聊天流程. 但是我们只完成了一半,完成存量历史记录展示,和即时聊天的 ...
- 开发简单Android聊天软件(6)
构建完整消息接收加载流程 在 "开发简单Android聊天软件(5)" 中,完成了会话窗口的绘制,以及消息发送.现在我们来完成消息接收和加载,构建一个完整的聊天流程. 消息加载,那 ...
最新文章
- String,StringBuffer,StringBuilder的区别
- 大白话,讲编程。前端君又回来了!
- [HTML]POST方法和GET方法
- pycharm激活码永久有效2019年5月28日
- 身体指数bmi流程图_理想的身体脂肪百分比是多少?男女不同脂肪数据对照表
- python django的查询语句
- 产品数据管理系统框架与信息安全
- MS Materials Studio 安装
- 来,手写一个Operator (一)
- 颜色的前世今生19·外传之PPI、LPI、DPI疑难问题解答
- python语言是编译型语言-解释型语言与编译型语言
- 210127 课内整理
- 高并发 收获大厂Offer必不可少的利器
- 在线查询12306账号是否泄露
- 分享五年码农生涯历程经验及2018总结 | 掘金年度征文
- 赢胜智能:2021第十六局AMTS上海国际汽车制造技术与装备及材料展
- [python][LXF][homework]操作文件和目录
- WEB2.0时代我还开网店干什么?
- IOTOS物联中台开发驱动支持NB-IoT光电感烟火灾探测报警器设备
- 2020安装CocoaPods