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