有兩種方法可以寫,一種是透過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 (Enumerationen = 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
刪除