有兩種方法可以寫,一種是透過Thread,另一種是透過AsyncTask(比較推薦),在這邊先用Thread的方法,建立一個可以傳送跟接收UDP Socket的Android App。
首先Android要寫網路有關的功能的話,App要先開權限!(開發的時候常常會忘記)
在AndroidManifest.xml裡面加入這兩行:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
接著分別加入兩個class,分別來負責做傳送跟接收的工作
chatsender.java
package com.example.chris.udp_sample;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import android.util.Log;
class ChatSender extends Thread{
public void run(String strIP, String str, int port){
DatagramSocket socket = null;
try
{
socket = new DatagramSocket();
InetAddress serverAddress = InetAddress.getByName(strIP);
Log.d("IP Address", serverAddress.toString());
DatagramPacket packet;
//send socket
packet=new DatagramPacket(str.getBytes(),str.length(),serverAddress,port);
socket.send(packet);
}
catch(SocketException e)
{
e.printStackTrace();
String error = e.toString();
Log.e("Error by Sender", error);
}
catch(UnknownHostException e)
{
e.printStackTrace();
String error = e.toString();
Log.e("Error by Sender", error);
}
catch(IOException e)
{
e.printStackTrace();
String error = e.toString();
Log.e("Error by Sender", error);
}
catch(Exception e)
{
e.printStackTrace();
String error = e.toString();
Log.e("Error by Sender", error);
}
finally{
if(socket != null){
socket.close();
}
}
}
}
chatserver.java
package com.example.chris.udp_sample;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
class ChatServer extends Thread{
private DatagramSocket server = null;
private static final int PORT = 8008;
public ChatServer() throws IOException {
server = new DatagramSocket(PORT);
Log.d("User","new server socket");
}
public void run(){
byte[] byte1024 = new byte[1024];
//Message msg = new Message();
//Bundle data = new Bundle();
DatagramPacket dPacket = new DatagramPacket(byte1024, 100);
String txt;
try{
Log.d("User","runing run()");
while(true){
server.receive(dPacket);
while(true)
{
txt = new String(byte1024, 0, dPacket.getLength());
MainActivity.exHandler.sendMessage(MainActivity.exHandler.obtainMessage(1,txt));
Log.d("User","Handler send Message");
if(true) break;
}
//CloseSocket(client);
}
}
catch(IOException e)
{}
}
private void CloseSocket(DatagramSocket socket) throws IOException{
socket.close();
}
}
準備好這兩個class之後就可以在MainActivity裡面call來用了,如果要建立server,為了方便檢查自己的IP位址,在一開始有先加入顯示本身IP位址的程式碼。
在這個App中可以自己輸入要傳送的IP位址以及Socket字串內容。以下是MainActivity程式碼:
MainActivity.java
package com.example.chris.udp_sample;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.concurrent.atomic.AtomicBoolean;
import android.net.wifi.WifiInfo;
import android.os.StrictMode;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.format.Time;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
public static Handler exHandler;
private ChatServer chatserver;
private ChatSender chatsender;
private TextView texv_ip, texv_recv, texv_send;
private EditText edt_ip, edt_socket;
private Button button01;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
texv_ip = (TextView) findViewById(R.id.textView);
texv_recv = (TextView) findViewById(R.id.textView2);
texv_send = (TextView) findViewById(R.id.textView5);
edt_ip = (EditText)findViewById(R.id.editText);
edt_socket = (EditText)findViewById(R.id.editText2);
button01 = (Button)findViewById(R.id.btn_send1);
//receive text
exHandler=new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
String msgString = (String)msg.obj;
Log.d("Handler","Now in Handler");
texv_recv.setText(null);
texv_recv.setText("Receive: " + msgString);
}
};
//get wifi IP
StringBuilder IFCONFIG=new StringBuilder();
try {
for (Enumeration en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress() && !inetAddress.isLinkLocalAddress() && inetAddress.isSiteLocalAddress()) {
IFCONFIG.append(inetAddress.getHostAddress().toString()+"\n");
}
}
}
texv_ip.setText("My IP address is: " + IFCONFIG.toString());
Log.d("LOG_Text", IFCONFIG.toString());
} catch (SocketException ex) {
Log.e("LOG_TAG", ex.toString());
}
try{
chatsender = new ChatSender();
chatserver = new ChatServer();
chatserver.start();
Log.d("User","Thread start...");
}catch(Exception e)
{
String str = e.toString();
Log.e("Error by User", str);
}
}
protected void onStart(){
super.onStart();
button01.setOnClickListener(new Button.OnClickListener(){
@Override
public void onClick(View v) {
chatsender.run(edt_ip.getText().toString(), edt_socket.getText().toString(), 8008);
texv_send.setText("Send " + edt_socket.getText().toString() + " to " + edt_ip.getText().toString());
}
});
}
protected void onPause(){
super.onPause();
if(chatserver != null)
{
if(!chatserver.isInterrupted())
{
chatserver.interrupt();
}
}
if(chatsender != null)
{
if(!chatsender.isInterrupted())
{
chatsender.interrupt();
}
}
}
protected void onResume() {
super.onResume();
}
}
以下是layout的部分:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.chris.udp_sample.MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.33"
android:text="My IP address"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="20dp" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.33"
android:text="Receive: null"
android:layout_below="@+id/textView"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="20dp"/>
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.33"
android:text="Send IP: "
android:layout_below="@+id/textView2"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="20dp" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.33"
android:text="Send Socket: "
android:layout_below="@+id/textView3"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="20dp"/>
<EditText
android:id="@+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:text="172.20.10.2"
android:ems="10"
android:layout_alignBaseline="@+id/textView3"
android:layout_alignBottom="@+id/textView3"
android:layout_toRightOf="@+id/textView3"
android:layout_toEndOf="@+id/textView3" />
<EditText
android:id="@+id/editText2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:text="test"
android:ems="10"
android:layout_alignBaseline="@+id/textView4"
android:layout_alignBottom="@+id/textView4"
android:layout_toRightOf="@+id/textView4"
android:layout_toEndOf="@+id/textView4" />
<Button
android:id="@+id/btn_send1"
android:text="Send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView4"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="20dp" />
<TextView
android:id="@+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.33"
android:text="show send socket"
android:layout_below="@+id/btn_send1"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="20dp"/>
</RelativeLayout>
ChatServer.java中并没有start() function
回覆刪除try{
chatsender = new ChatSender();
chatserver = new ChatServer();
chatserver.start(); //------>>>>>>>>>>ChatServer.java中并没有start() function
Log.d("User","Thread start...");
}catch(Exception e)
{
String str = e.toString();
Log.e("Error by User", str);
}
因為ChatServer是繼承Thread來用,start()是Thread裡面的function
刪除