首先,要先搞懂Thread / Handler是甚麼,不然這篇往下看沒有意義(因為會看不懂)
在MainActivity的部分,這邊負責主要的UI介面+Handler+Thread呼叫
package com.example.thread_example;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import android.annotation.SuppressLint;
import android.net.wifi.WifiInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.StrictMode;
import android.support.v7.app.ActionBarActivity;
import android.text.format.Time;
import android.util.Log;
import android.widget.TextView;
@SuppressLint("NewApi")
public class MainActivity extends ActionBarActivity {
public static Handler exHandler;
private TextView txv;
private ChatServer chatserver;
private ChatSender chatsender;
public static InetAddress IP;
public WifiInfo mwifiInfo;
@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);
}
txv = (TextView) findViewById(R.id.textView);
//利用handler來顯示接收到的文字
exHandler=new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
String msgString = (String)msg.obj;
Log.d("Handler","Now in Handler");
txv.setText(null);
txv.setText(msgString+"\n"+txv.getText().toString());
}
};
//獲得Wifi的內部網路IP
StringBuilder IFCONFIG=new StringBuilder();
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress() && !inetAddress.isLinkLocalAddress() && inetAddress.isSiteLocalAddress()) {
IFCONFIG.append(inetAddress.getHostAddress().toString()+"\n");
}
}
}
txv.setText(IFCONFIG.toString());
Log.d("LOG_Text", IFCONFIG.toString());
} catch (SocketException ex) {
Log.e("LOG_TAG", ex.toString());
}
try{
chatserver = new ChatServer();
chatserver.start();
chatsender = new ChatSender();
chatsender.start();
Log.d("User","Thread start...");
}catch(Exception e)
{
String str = e.toString();
Log.e("Error by User", str);
}
}
protected void onPause(){
super.onPause();
if(chatserver != null)
{
if(!chatserver.isInterrupted())
{
chatserver.interrupt();
}
}
}
}
有一點長,這邊元件只有拉一個TextView而已,十分簡單。
IFCONFIG
這邊負責顯示WIFI的IP
Thread--chatserver/chatsender
則是另外開兩個java檔(與mainActivity.java同層)分別做為接收與傳送,.start()就是讓他啟動而已。
exHandler
這邊負責顯示接收到的資訊(不能用static來傳值,因為Android不支援,至於為什麼我也不清楚),並把他印出來在textview上面。
Receiver部分(chatserver.java)
package com.example.thread_example;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
public class ChatServer extends Thread{
private DatagramSocket server = null;
private static final int PORT = 8000;
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();
}
}
這邊宣告一個1024的byte來接收資料(按照你的資料量大小來調整宣告大小)
一定要宣告datagramSocket,datagramPacket,一個是連線,一個是接收封包用,至於handler這邊的
sendMessage就是回傳到MainActivity來讓textview顯示接收的資訊而已。結構上有兩個while(),第
一個while會卡在receive()這邊,一直到有封包進來才會往下跑到第二個while(),第二個則是印出資
訊,沒有甚麼特別的地方(Log是debug用的)
Sender的部分(chatsender.java)
package com.example.thread_example;
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;
public class ChatSender extends Thread{
public void run(){
DatagramSocket socket = null;
try
{
socket = new DatagramSocket();
InetAddress serverAddress = InetAddress.getByName("192.168.10.105");
Log.d("IP Address", serverAddress.toString());
String str = "Test Thread sender";
//創建一個用於發送的DatagramPacket對象
DatagramPacket packet=new DatagramPacket(str.getBytes(),str.length(),serverAddress,2000);
//發送數據
while(true)
{
socket.send(packet);
Thread.sleep(10000);
}
}
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();
}
}
}
}
這邊設了固定的IP(未來會再調整),只要一跑進去thread.run()就會不停的對指定IP/Port丟資訊,每
次丟完休息一秒。
記得要開啟權限在AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.thread_example"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.thread_example.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
-------------開這兩個---------------
<uses-permission android:name="android.permission.INTERNET"/><uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
完整jar檔案在此: 點這邊
*後記: Android UDP真的不是很好做,有很多很多細節 2.3.5版本跟 4.0版本已上又有差別
不過大部分比較大的問題都有寫在前面文章,有需要可以看一下。
您好, 請問有沒有 apk 檔可以直接安裝? 畫面長甚麼樣子呢?
回覆刪除您好, 請問有沒有 apk 檔可以直接安裝? 畫面長甚麼樣子呢?
回覆刪除沒有喔 整個apk檔是很大的,這是取一部分而已
刪除