基于mina开发的windows客户端和android客户端
server端和windows客户端就是mina官方的源码.
android客户端已经在android2.3.7以及android4.0.3上测试server端 入口地址为 org.apache.mina.example.chat Main.classwindows客户端 入口地址为 org.apache.mina.example.chat.client SwingChatClient.class
================================================================================
android 部分源码
package com.example.minaim; import java.net.InetSocketAddress; import java.net.SocketAddress; import org.apache.mina.core.filterchain.IoFilter; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.transport.socket.SocketConnector; import org.apache.mina.transport.socket.nio.NioSocketConnector; import android.annotation.TargetApi; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.StrictMode; import android.text.TextUtils; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import com.example.minaim.ClientHandler.Callback; public class MainActivity extends Activity implements Callback { private ClientHandler ch; private TextView msgContent; @SuppressWarnings("deprecation") @Override public void onCreate(Bundle savedInstanceState) { // /--------------------- init(); // /--------------------- super.onCreate(savedInstanceState); System.setProperty("java.net.preferIPv6Addresses", "false"); setContentView(R.layout.activity_main); msgContent = (TextView) findViewById(R.id.msgTxt); Button sendBtn = (Button) findViewById(R.id.sendBtn); final EditText sendContent = (EditText) findViewById(R.id.sendContent); msgContent.setEllipsize(TextUtils.TruncateAt.MARQUEE); msgContent.setMarqueeRepeatLimit(6); SocketConnector connector = new NioSocketConnector(); IoFilter filter = new ProtocolCodecFilter(new TextLineCodecFactory()); connector.getFilterChain().addLast("vestigge", filter); SocketAddress soketAddress = new InetSocketAddress("192.168.11.103", 1234); ch = new ClientHandler(MainActivity.this); connector.setHandler(ch); ConnectFuture future = connector.connect(soketAddress); future.join(); if (!future.isConnected()) { System.out.println("连接服务器失败"); future.getException().printStackTrace(); return; } else { final IoSession session = future.getSession(); sendContent.setText(""); session.write("LOGIN " + System.currentTimeMillis() + "\r\n"); session.write("BROADCAST Helloworld\r\n"); sendBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String sendMsgText = "BROADCAST " + sendContent.getText().toString() + "\r\n"; System.out.println(sendMsgText); session.write(sendMsgText); sendContent.setText(""); } }); } } @Override public void connected() { // TODO Auto-generated method stub } @Override public void loggedIn() { // TODO Auto-generated method stub } @Override public void loggedOut() { // TODO Auto-generated method stub } @Override public void disconnected() { // TODO Auto-generated method stub } @Override public void messageReceived(String message) { // BROADCAST OK user6: vg String[] result = message.split(" ", 3); String status = result[1]; System.out.println(status); if ("OK".equals(status)) { msg = new StringBuilder(result[2]); mHandler.postDelayed(mUpdateUITimerTask, 0); } } private StringBuilder msg; // 用于刷新textview, 对于UI的更改要放在线程中 private final Runnable mUpdateUITimerTask = new Runnable() { public void run() { msgContent.append(msg + "\r\n"); final int maxY = (msgContent.getLineCount() * msgContent.getLineHeight() + msgContent.getPaddingTop() + msgContent .getPaddingBottom()) - msgContent.getHeight(); msgContent.scrollTo(0, maxY); msgContent.invalidate(); Log.v("height", maxY + ""); } }; private final Handler mHandler = new Handler(); @Override public void error(String message) { // TODO Auto-generated method stub } private long exitTime = 0; @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) { if ((System.currentTimeMillis() - exitTime) > 2000) { Toast.makeText(getApplicationContext(), "再按一次退出程序", Toast.LENGTH_SHORT).show(); exitTime = System.currentTimeMillis(); } else { finish(); System.exit(0); } return true; } return super.onKeyDown(keyCode, event); } // 判断版本格式,如果版本 > 2.3,就是用相应的程序进行处理,以便影响访问网络 @TargetApi(9) private static void init() { String strVer = android.os.Build.VERSION.RELEASE; // 获得当前系统版本 strVer = strVer.substring(0, 3).trim(); // 截取前3个字符 2.3.3转换成2.3 float fv = Float.valueOf(strVer); if (fv > 2.3) { StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectDiskReads().detectDiskWrites().detectNetwork() .penaltyLog().build()); StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() .detectLeakedSqlLiteObjects().penaltyLog().penaltyDeath() .build()); } } }
================================================================================
效果图如下:
(貌似图片过大,只显示了2/3,请在新页面中单独打开图片)