废话不多说,直接上代码
MainActivity.java 主页面
import java.net.InetSocketAddress; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelOption; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { private static final String TAG = "TAG"; public static int MSG_REC = 0xabc; public static final String HOST = "192.168.2.219"; public static int PORT = 9103; private NioEventLoopGroup group; private Channel mChannel; private ChannelFuture cf; private static Context context; private TextView tv; private Button btn; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == MSG_REC) { Toast.makeText(context, msg.obj.toString(), 0).show(); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); context = this; connected(); tv = (TextView) findViewById(R.id.iv); btn = (Button) findViewById(R.id.btn); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { sendMessage(); } }); } // 连接到Socket服务端 private void connected() { new Thread() { @Override public void run() { group = new NioEventLoopGroup(); try { // Client服务启动器 3.x的ClientBootstrap // 改为Bootstrap,且构造函数变化很大,这里用无参构造。 Bootstrap bootstrap = new Bootstrap(); // 指定EventLoopGroup bootstrap.group(group); // 指定channel类型 bootstrap.channel(NioSocketChannel.class); // 指定Handler bootstrap .handler(new MyClientInitializer(MainActivity.this)); //如果没有数据,这个可以注释看看 bootstrap.option(ChannelOption.SO_KEEPALIVE, true); bootstrap.option(ChannelOption.TCP_NODELAY, true); // 连接到本地的7878端口的服务端 cf = bootstrap.connect(new InetSocketAddress(HOST, PORT)); mChannel = cf.sync().channel(); } catch (Exception e) { e.printStackTrace(); } } }.start(); } // 发送数据 private void sendMessage() { mHandler.post(new Runnable() { @Override public void run() { try { Log.i(TAG, "mChannel.write sth & " + mChannel.isOpen()); mChannel.writeAndFlush("我是android客户端"); mChannel.read(); } catch (Exception e) { e.printStackTrace(); } } }); } @Override protected void onDestroy() { super.onDestroy(); if (group != null) { group.shutdownGracefully(); } } }
MyClientHandler.java
import android.content.Context; import android.content.Intent; import android.os.Handler; import android.os.Message; import android.util.Log; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; public class MyClientHandler extends SimpleChannelInboundHandler<String> { private Context context; public MyClientHandler(Context context) { this.context = context; } @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { Log.d("MyHelloClientHandler", "channelRead0->msg=" + msg); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("Client active"); super.channelActive(ctx); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("Client close "); super.channelInactive(ctx); } }
MyClientInitializer.java
import android.content.Context; import android.os.Handler; import android.util.Log; import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.DelimiterBasedFrameDecoder; import io.netty.handler.codec.Delimiters; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.util.CharsetUtil; public class MyClientInitializer extends ChannelInitializer<SocketChannel> { private Context context; public MyClientInitializer(Context ctx) { this.context = ctx; } @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); /** * 这个地方的必须和服务端对应上。否则无法正常解码和编码 */ // pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, // Delimiters.lineDelimiter())); //这个是解决沾包的问题,但是我发现加上这句话,就读取不到返回值,不知道为什么 pipeline.addLast("decoder", new StringDecoder(CharsetUtil.UTF_8)); pipeline.addLast("encoder", new StringEncoder(CharsetUtil.UTF_8)); // 客户端的逻辑 pipeline.addLast("handler", new MyClientHandler(context)); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("---channelRead--- msg=" + msg); super.channelRead(ctx, msg); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { System.out.println("---channelReadComplete---"); super.channelReadComplete(ctx); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { Log.i("MyClientInitializer", "---channelActive---"); super.channelActive(ctx); } }
既然是网络通信,肯定得加上网络权限
<uses-permission android:name="android.permission.INTERNET" />
要加上netty4 的jar
下载地址:http://netty.io/downloads.html