这一段时间一直在学习android网络编程这块的内容,由于android3 .0以上不能够在UI线程中访问网络;这里拿android4.0网络编程详解这本书中socket编程的聊天室实例,进行修改使之能够运行在android4.0平台上,以记录作为解决android3.0以上平台不能在UI线程中访问网络的一种方法,当然这种方法也是从网络当中借鉴过来的。
这个方法主要是在onCreate()方法中加入以下代码:
/*由于android3.0以上不能够在主线程中经行网络访问,所以在此处加上这一段代码*/
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads()
.detectDiskWrites().detectNetwork().penaltyLog().build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects()
.penaltyLog().penaltyDeath().build());
/*由于android3.0以上不能够在主线程中经行网络访问,所以在此处加上这一段代码*/
下面就贴出整个聊天室实例的代码:
(1).服务器部分主要包括Broadcast.java,ClientThread.java,Server.java,ServerThread.java这几个代码部分;
Broadcast.java:
package com.jacky.server.internet;
import java.io.IOException;
public class BroadCast extends Thread {
ClientThread clientThread;
ServerThread serverThread;
String str;
public BroadCast(ServerThread serverThread)
{
this.serverThread=serverThread;
}
public void run()
{
while(true)
{
try
{
Thread.sleep(200);
}
catch(InterruptedException E){}
synchronized(serverThread.messages)
{
if(serverThread.messages.isEmpty())
{
continue;
}
str=(String)this.serverThread.messages.firstElement();
}
synchronized(serverThread.clients)
{
for(int i=0;i<serverThread.clients.size();i++)
{
clientThread=(ClientThread)serverThread.clients.elementAt(i);
try
{
clientThread.out.writeUTF(str);
}
catch(IOException E){}
}
this.serverThread.messages.removeElement(str);
}
}
}
}
ClientThread.java:
package com.jacky.server.internet;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
public class ClientThread extends Thread{
Socket clientSocket;
DataInputStream in=null;
DataOutputStream out=null;
ServerThread serverThread;
String str;
public static int ConnectNumber=0;
public ClientThread(Socket socket,ServerThread serverThread)
{
clientSocket=socket;
this.serverThread=serverThread;
try
{
in=new DataInputStream(clientSocket.getInputStream());
out=new DataOutputStream(clientSocket.getOutputStream());
}
catch(IOException e2)
{
System.out.println("发生异常"+e2);
System.out.println("建立I/O通道失败");
System.exit(3);
}
}
public void run()
{
while(true)
{
try
{
String message=in.readUTF();
synchronized(serverThread.messages)
{
if(message!=null)
{
serverThread.messages.addElement(message);
Server.jTextAreal.append( message+'\n');
}
}
}catch(IOException E){break;}
}
}
}
Server.java:
package com.jacky.server.internet;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
public class Server extends JFrame implements ActionListener {
/**
*
*/
private static final long serialVersionUID = -4000885328679526739L;
BorderLayout borderLayout1=new BorderLayout();
BorderLayout borderLayout2=new BorderLayout();
JPanel jPanel1=new JPanel();
JPanel jPanel2=new JPanel();
JButton jButton1=new JButton();
JButton jButton2=new JButton();
JScrollPane jScrollPanel=new JScrollPane();
static JTextArea jTextAreal=new JTextArea();
boolean bool=false,start=false;
ServerThread serverThread;
Thread thread;
public Server()
{
super("Server");
getContentPane().setLayout(borderLayout1);
jButton1.setText("启动服务器");
jButton1.addActionListener(this);
jButton2.setText("关闭服务器");
jButton2.addActionListener(this);
this.getContentPane().add(jPanel1,java.awt.BorderLayout.NORTH);
jPanel1.add(jButton1);
jPanel1.add(jButton2);
jTextAreal.setText("");
jPanel2.setLayout(borderLayout2);
jPanel2.add(jScrollPanel,java.awt.BorderLayout.CENTER);
jScrollPanel.getViewport().add(jTextAreal);
this.getContentPane().add(jPanel2,java.awt.BorderLayout.CENTER);
this.setSize(400,400);
this.setVisible(true);
}
public static void main(String[] args)
{
Server server=new Server();
server.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==jButton1)
{
serverThread=new ServerThread();
serverThread.start();
}else if(e.getSource()==jButton2){
bool=false;
start=false;
serverThread.finalize();
this.setVisible(false);
}
}
}
ServerClient.java:
package com.jacky.server.internet;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Vector;
public class ServerThread extends Thread{
ServerSocket serverSocket;
public static final int PORT=8521;
Vector<ClientThread>clients;
Vector<Object>messages;
BroadCast broadcast;
String ip;
InetAddress myIPaddress=null;
public ServerThread()
{
clients=new Vector<ClientThread>();
messages=new Vector<Object>();
try
{
serverSocket=new ServerSocket(PORT);
}catch(IOException E){}
try{
myIPaddress=InetAddress.getLocalHost();
}catch(UnknownHostException e)
{
System.out.println(e.toString());
}
ip=myIPaddress.getHostAddress();
Server.jTextAreal.append("服务器地址:"+ip+"端口号:"+
String.valueOf(serverSocket.getLocalPort())+"\n");
broadcast=new BroadCast(this);
broadcast.start();
}
public void run()
{
while(true)
{
try
{
Socket socket=serverSocket.accept();
System.out.println(socket.getInetAddress().getHostAddress());
ClientThread clientThread=new ClientThread(socket,this);
clientThread.start();
if(socket!=null)
{
synchronized(clients)
{
clients.addElement(clientThread);
}
}
}catch(IOException E)
{
System.out.println("发生异常:"+E);
System.out.println("建立客户端联机失败!");
System.exit(2);
}
}
}
public void finalize()
{
try
{
serverSocket.close();
}
catch(IOException E){}
serverSocket=null;
}
}
(2).android 客户端部分:
ChatClientActivity.java:
package com.example.chatandroidclient;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.sql.Date;
import java.text.SimpleDateFormat;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.StrictMode;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class ChatClientActivity extends Activity implements Runnable{
private EditText usernameEdit;
private EditText ipEdit;
private EditText historyEdit;
private EditText messageEdit;
private Button loginButton;
private Button sendButton;
private Button leaveButton;
private String username,ip,chat_txt,chat_in;
public static final int PORT=8521;
Socket socket;
Thread thread;
//创建一个数据输入流对象
DataInputStream in;
//创建一个数据输出流对象
DataOutputStream out;
boolean flag=false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/*由于android3.0以上不能够在主线程中经行网络访问,所以在此处加上这一段代码*/
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads()
.detectDiskWrites().detectNetwork().penaltyLog().build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectLeakedSqlLiteObjects()
.penaltyLog().penaltyDeath().build());
/*由于android3.0以上不能够在主线程中经行网络访问,所以在此处加上这一段代码*/
setContentView(R.layout.main);
usernameEdit=(EditText)findViewById(R.id.username);
ipEdit=(EditText)findViewById(R.id.ip);
historyEdit=(EditText)findViewById(R.id.history);
messageEdit=(EditText)findViewById(R.id.message);
loginButton=(Button)findViewById(R.id.LoginButton);
sendButton=(Button)findViewById(R.id.SendButton);
leaveButton=(Button)findViewById(R.id.LeaveButton);
loginButton.setOnClickListener(listener);
sendButton.setOnClickListener(listener);
leaveButton.setOnClickListener(listener);
}
View.OnClickListener listener=new View.OnClickListener()
{
public void onClick(View v)
{
switch(v.getId())
{
case R.id.LoginButton:
if(flag==true){
Toast.makeText(ChatClientActivity.this, "已经登入!!!", Toast.LENGTH_SHORT).show();
return;
}
username=usernameEdit.getText().toString();
ip=ipEdit.getText().toString();
if(username!=""&&username!=null&&username!="用户名输入"&&ip!=null){
try
{
socket=new Socket(ip,PORT);
in=new DataInputStream(socket.getInputStream());
out=new DataOutputStream(socket.getOutputStream());
Date now=new Date(System.currentTimeMillis());
SimpleDateFormat format=new SimpleDateFormat("hh:mm:ss");
String nowStr=format.format(now);
out.writeUTF("$$"+username+" "+nowStr+"上线了!");
}catch(IOException el)
{
System.out.println("can not connect!!");
}
thread=new Thread(ChatClientActivity.this);
thread.start();
flag=true;
}
break;
case R.id.SendButton:
if(flag==false)
{
Toast.makeText(ChatClientActivity.this,"没有登入,请登入!!",Toast.LENGTH_SHORT).show();
return;
}
chat_txt=messageEdit.getText().toString();
if(chat_txt!=null)
{
Date now=new Date(System.currentTimeMillis());
SimpleDateFormat format=new SimpleDateFormat("hh:mm:ss");
String nowStr=format.format(now);
try
{
out.writeUTF("^_^"+username+" "+nowStr+"说\n"+chat_txt);
messageEdit.setText(" ");//清空发送框中的内容
}catch(IOException e2){}
}
else
{
try{out.writeUTF("请说话");}
catch(IOException e3){}
}
break;
case R.id.LeaveButton:
if(flag==true)
{
if(flag==false){
Toast.makeText(ChatClientActivity.this, "没有登入,请登入!!",Toast.LENGTH_SHORT).show();
return;
}
try
{
out.writeUTF("=="+username+"下线了!");
out.close();
in.close();
socket.close();
}catch(IOException e4){}
}
flag=false;
Toast.makeText(ChatClientActivity.this, "已退出!", Toast.LENGTH_SHORT).show();
break;
}
}
};
public void run(){
while(true)
{
try
{
chat_in=in.readUTF();
chat_in=chat_in+"\n";
mHandler.sendMessage(mHandler.obtainMessage());
}catch(IOException e){}
}
}
Handler mHandler=new Handler()
{
public void handleMessage(Message msg)
{
historyEdit.append(chat_in);
super.handleMessage(msg);
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.chat_client, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/usernameText"
android:layout_width="70dp"
android:layout_height="40dp"
android:text="@string/username" />
<EditText
android:id="@+id/username"
android:layout_width="180dp"
android:layout_height="40dp"
android:layout_toRightOf="@id/usernameText"
android:hint="@null"
android:maxLength="10"
android:text=" ">
</EditText>
<Button
android:id="@+id/LoginButton"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_toRightOf="@id/username"
android:text="@string/login" />
<TextView
android:id="@+id/ipText"
android:layout_width="70dp"
android:layout_height="40dp"
android:layout_alignParentLeft="true"
android:layout_below="@id/username"
android:text="@string/ip" />
<EditText
android:id="@+id/ip"
android:layout_width="180dp"
android:layout_height="40dp"
android:layout_alignTop="@id/ipText"
android:layout_toRightOf="@id/ipText"
android:digits=".1234567890"
android:hint="@null"
android:text="192.168.1.108" >
</EditText>
<Button
android:id="@+id/LeaveButton"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_alignTop="@id/ip"
android:layout_toRightOf="@id/ip"
android:text="@string/leave" />
<EditText
android:id="@+id/history"
android:layout_width="fill_parent"
android:layout_height="280dp"
android:hint="@null"
android:layout_below="@id/ipText"
android:inputType="none"
android:gravity="top" >
</EditText>
<EditText
android:id="@+id/message"
android:layout_width="280dp"
android:layout_height="240dp"
android:hint="@null"
android:layout_below="@id/history"
android:gravity="top" >
</EditText>
<Button
android:id="@+id/SendButton"
android:layout_width="wrap_content"
android:layout_height="240dp"
android:layout_alignTop="@id/message"
android:layout_toRightOf="@id/message"
android:text="@string/send" />
</RelativeLayout>