編輯:關於Android編程
在Java中我們可以利用socket編程實現聊天室,在Android中也一樣,因為Android完全支持JDK本身的TCP、UDP網絡通信API。我們可以使用ServerSocket、Socket來建立基於TCP/IP協議的網絡通信;也可以使用DatagramSocket、Datagrampacket、MulticastSocket來建立基於UDP協議的網絡通信。下面實現一個簡單的聊天室,服務器端完全用Java代碼實現,跟Android無關,客戶端用Android應用來實現。
服務器不斷讀取來自客戶端的信息,並即時地將信息發送給每個連接到本服務器上的客戶端,每個客戶端可以向服務器發送消息,並不斷地接收來自服務器的消息,並將消息顯示在界面上。這樣就實現了客戶端與客戶端之間的即時聊天功能,為簡便起見,本文中只寫了一個客戶端,代碼如下:
服務器端:
創建服務器的主類:
[java]
package com.home.server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class MyServer {
// 定義保存所有Socket的集合
public static ArrayList<Socket> socketList = new ArrayList<Socket>();
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(20000);
System.out.println("服務器創建成功!");
System.out.println("等待客戶端的連接。。。");
while (true) {
// 此行代碼會阻塞,等待用戶的連接
Socket socket = ss.accept();
System.out.println("有客戶端連接進來!");
socketList.add(socket);
// 每當客戶端連接後啟動一條ServerThread線程為該客戶端服務
new Thread(new ServerThread(socket)).start();
}
}
}
package com.home.server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class MyServer {
// 定義保存所有Socket的集合
public static ArrayList<Socket> socketList = new ArrayList<Socket>();
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(20000);
System.out.println("服務器創建成功!");
System.out.println("等待客戶端的連接。。。");
while (true) {
// 此行代碼會阻塞,等待用戶的連接
Socket socket = ss.accept();
System.out.println("有客戶端連接進來!");
socketList.add(socket);
// 每當客戶端連接後啟動一條ServerThread線程為該客戶端服務
new Thread(new ServerThread(socket)).start();
}
}
}
服務器的線程類:
[java]
package com.home.server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class ServerThread implements Runnable {
// 定義當前線程所處理的Socket
private Socket socket = null;
// 該線程所處理的Socket所對應的輸入流
BufferedReader br = null;
public ServerThread(Socket socket) throws IOException {
this.socket = socket;
// 初始化該Socket對應的輸入流
br = new BufferedReader(new InputStreamReader(socket.getInputStream(),
"utf-8"));
}
@Override
public void run() {
try {
String content = null;
// 采用循環不斷從Socket中讀取客戶端發送過來的數據
while ((content = readFromClient()) != null) {
// 遍歷socketList中的每個Socket,將讀到的內容向每個Socket發送一次
for (Socket s : MyServer.socketList) {
OutputStream os = s.getOutputStream();
os.write((content + "\n").getBytes("utf-8"));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 定義讀取客戶端數據的方法
*
* @return
*/
private String readFromClient() {
try {
return br.readLine();
}
// 如果捕捉到異常,表明該Socket對應的客戶端已經關閉
catch (Exception e) {
// 刪除該Socket
MyServer.socketList.remove(socket);
e.printStackTrace();
}
return null;
}
}
package com.home.server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class ServerThread implements Runnable {
// 定義當前線程所處理的Socket
private Socket socket = null;
// 該線程所處理的Socket所對應的輸入流
BufferedReader br = null;
public ServerThread(Socket socket) throws IOException {
this.socket = socket;
// 初始化該Socket對應的輸入流
br = new BufferedReader(new InputStreamReader(socket.getInputStream(),
"utf-8"));
}
@Override
public void run() {
try {
String content = null;
// 采用循環不斷從Socket中讀取客戶端發送過來的數據
while ((content = readFromClient()) != null) {
// 遍歷socketList中的每個Socket,將讀到的內容向每個Socket發送一次
for (Socket s : MyServer.socketList) {
OutputStream os = s.getOutputStream();
os.write((content + "\n").getBytes("utf-8"));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 定義讀取客戶端數據的方法
*
* @return
*/
private String readFromClient() {
try {
return br.readLine();
}
// 如果捕捉到異常,表明該Socket對應的客戶端已經關閉
catch (Exception e) {
// 刪除該Socket
MyServer.socketList.remove(socket);
e.printStackTrace();
}
return null;
}
}
客戶端主類(Activity):
[java]
package com.home.activity;
import java.io.OutputStream;
import java.net.Socket;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import com.home.R;
import com.home.util.ClientThread;
public class MultiThreadClient extends Activity {
private EditText input, show;
private Button sendBtn;
private OutputStream os;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
input = (EditText) findViewById(R.id.main_et_input);
show = (EditText) findViewById(R.id.main_et_show);
sendBtn = (Button) findViewById(R.id.main_btn_send);
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 如果消息來自子線程
if (msg.what == 0x234) {
// 將讀取的內容追加顯示在文本框中
show.append("\n" + msg.obj.toString());
}
}
};
Socket socket;
try {
socket = new Socket("192.168.0.101", 20000);
// 客戶端啟動ClientThread線程不斷讀取來自服務器的數據
new Thread(new ClientThread(socket, handler)).start();
os = socket.getOutputStream();
} catch (Exception e) {
e.printStackTrace();
}
sendBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try {
// 將用戶在文本框內輸入的內容寫入網絡
os.write((input.getText().toString() + "\r\n").getBytes());
// 清空input文本框數據
input.setText("");
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
package com.home.activity;
import java.io.OutputStream;
import java.net.Socket;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import com.home.R;
import com.home.util.ClientThread;
public class MultiThreadClient extends Activity {
private EditText input, show;
private Button sendBtn;
private OutputStream os;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
input = (EditText) findViewById(R.id.main_et_input);
show = (EditText) findViewById(R.id.main_et_show);
sendBtn = (Button) findViewById(R.id.main_btn_send);
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 如果消息來自子線程
if (msg.what == 0x234) {
// 將讀取的內容追加顯示在文本框中
show.append("\n" + msg.obj.toString());
}
}
};
Socket socket;
try {
socket = new Socket("192.168.0.101", 20000);
// 客戶端啟動ClientThread線程不斷讀取來自服務器的數據
new Thread(new ClientThread(socket, handler)).start();
os = socket.getOutputStream();
} catch (Exception e) {
e.printStackTrace();
}
sendBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try {
// 將用戶在文本框內輸入的內容寫入網絡
os.write((input.getText().toString() + "\r\n").getBytes());
// 清空input文本框數據
input.setText("");
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
客戶端線程類:
[java]
package com.home.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import android.os.Handler;
import android.os.Message;
public class ClientThread implements Runnable {
private Handler handler;
// 該線程所處理的Socket所對應的輸入流
private BufferedReader br = null;
public ClientThread(Socket socket, Handler handler) throws IOException {
this.handler = handler;
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
@Override
public void run() {
try {
String content = null;
// 不斷讀取Socket輸入流的內容
while ((content = br.readLine()) != null) {
// 每當讀到來自服務器的數據之後,發送消息通知程序界面顯示該數據
Message msg = new Message();
msg.what = 0x234;
msg.obj = content;
handler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.home.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import android.os.Handler;
import android.os.Message;
public class ClientThread implements Runnable {
private Handler handler;
// 該線程所處理的Socket所對應的輸入流
private BufferedReader br = null;
public ClientThread(Socket socket, Handler handler) throws IOException {
this.handler = handler;
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
}
@Override
public void run() {
try {
String content = null;
// 不斷讀取Socket輸入流的內容
while ((content = br.readLine()) != null) {
// 每當讀到來自服務器的數據之後,發送消息通知程序界面顯示該數據
Message msg = new Message();
msg.what = 0x234;
msg.obj = content;
handler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Activity的布局XML:
[html]
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<EditText
android:id="@+id/main_et_input"
android:layout_width="240dp"
android:layout_height="wrap_content" />
<Button
android:id="@+id/main_btn_send"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:text="發送" />
</LinearLayout>
<EditText
android:id="@+id/main_et_show"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cursorVisible="false"
android:editable="false"
android:gravity="top" />
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<EditText
android:id="@+id/main_et_input"
android:layout_width="240dp"
android:layout_height="wrap_content" />
<Button
android:id="@+id/main_btn_send"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:text="發送" />
</LinearLayout>
<EditText
android:id="@+id/main_et_show"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cursorVisible="false"
android:editable="false"
android:gravity="top" />
</LinearLayout>權限:
[html]
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.INTERNET"/>
Android N 通知欄和快捷通知欄帶來的改變Android N 引入了一些新的API,允許應用發布具有高度可見性和交互性的通知。Android N 擴展了現有 Rem
本文實例講述了Android中Market的Loading效果實現方法。分享給大家供大家參考。具體如下:在Android中,要實現Loading效果,一般情況下都使用Pr
接入流程及說明官方地址:https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.erBW90&
ExpandableListView可擴展列表一般可用來開發類似QQ聯系人的界面效果。簡單整理了一下ExpandableListView的使用,希望幫助到需要的親們,由於
本文介紹本文是翻譯自Google 官方課程 Building Apps