編輯:關於Android編程
TCP協議:提供IP環境下的數據可靠傳輸,它提供的服務包括數據流傳送、可靠性、有效流控、全雙工操作和多路復用。通過面向連接、端到端和可靠的數據包發送。就如給懸崖上的兩人通信時,他必須先把橋建好,確認橋是沒問題的情況下,才把信件交過去,以後大家每次通信時,都確認下橋沒什麼問題,再通過這座橋來回通信了。
UDP協議:不為IP提供可靠性、流控或差錯恢復功能,在正式通信前不必與對方先建立連接,不管對方狀態就直接發送。這個就是飛鴿傳書了~
雖然UDP可靠性不如TCP協議,但是通信效率高於TCP。在網速極差的情況下優先考慮UDP協議,網速好的話TCP還是很方便使用的。
在Java中使用TCP可以通過java.net.Socket;這個類
建立連接
//實例化一個Socket對象 socket = new Socket(); //與對應的ip、端口進行連接,先要把橋建好 socket.connect(new InetSocketAddress(ip, port), 3000);
發送信息
InputStream ois = socket.getInputStream(); DataInputStream dis = new DataInputStream(new BufferedInputStream(ois)); //讀取服務器發過來的信息,如果沒信息將會阻塞線程 msg = dis.readUTF();
發送信息
//獲得輸出流 DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); //發送數據 dos.writeUTF(msg);
接下來上源碼,為三個Thread的子類,分別對應上面三個
public class SocketThread extends Thread{ private Socket socket; private Client client; private String ip; private int port; private boolean isStart=false; private MessageListener mMessageListener; /** * * 使用TCP協議,連接訪問 * @param ip 目標機器的IP * @param port 端口 * @param mMessageListener 收到服務器端數據時將回調該接口內的 * public void Message(String msg)方法 */ public SocketThread(String ip, int port, MessageListener mMessageListener) { this.ip = ip; this.port = port; this.mMessageListener = mMessageListener; } public void run() { try { //實例化一個Socket對象 socket = new Socket(); //與對應的ip、端口進行連接,先要把橋建好 socket.connect(new InetSocketAddress(ip, port), 3000); if (socket.isConnected()) { System.out.println("Connected.."); client = new Client(socket,mMessageListener); //打開對應的輸入/輸出流監聽 client.start(); isStart=true; } } catch (IOException e) { e.printStackTrace(); isStart=false; } } // 直接通過client得到讀線程 public ClientInputThread getClientInputThread() { return client.getIn(); } // 直接通過client得到寫線程 public ClientOutputThread getClientOutputThread() { return client.getOut(); } //返回Socket狀態 public boolean isStart(){ return isStart; } // 直接通過client停止讀寫消息 public void setIsStart(boolean isStart) { this.isStart = isStart; client.getIn().setStart(isStart); client.getOut().setStart(isStart); } //發送消息 public void sendMsg(String msg){ client.getOut().sendMsg(msg); } public class Client { private ClientInputThread in; private ClientOutputThread out; public Client(Socket socket,MessageListener mMessageListener) { //用這個監聽輸入流線程來接收信息 in = new ClientInputThread(socket); in.setMessageListener(mMessageListener); //以後就用這個監聽輸出流的線程來發送信息了 out = new ClientOutputThread(socket); } public void start() { in.setStart(true); out.setStart(true); in.start(); out.start(); } // 得到讀消息線程 public ClientInputThread getIn() { return in; } // 得到寫消息線程 public ClientOutputThread getOut() { return out; } } }
public class ClientInputThread extends Thread { private Socket socket; private String msg; private boolean isStart = true; private InputStream ois; private DataInputStream dis; private MessageListener messageListener;// 消息監聽接口對象 public ClientInputThread(Socket socket) { this.socket = socket; try { ois = socket.getInputStream(); dis = new DataInputStream(new BufferedInputStream(ois)); } catch (IOException e) { e.printStackTrace(); } } /** * 提供給外部的消息監聽方法 * * @param messageListener * 消息監聽接口對象 */ public void setMessageListener(MessageListener messageListener) { this.messageListener = messageListener; } public void setStart(boolean isStart) { this.isStart = isStart; } @Override public void run() { try { while (isStart) { //讀取信息,如果沒信息將會阻塞線程 msg = dis.readUTF(); // 每收到一條消息,就調用接口的方法Message(String msg) Log.v("收到消息", msg); messageListener.Message(msg); } ois.close(); if (socket != null) socket.close(); } catch (IOException e) { e.printStackTrace(); } } BufferedReader reader=null; public String getInputStreamString() { /* * To convert the InputStream to String we use the * BufferedReader.readLine() method. We iterate until the BufferedReader * return null which means there's no more data to read. Each line will * appended to a StringBuilder and returned as String. */ if (ois != null) { reader = new BufferedReader(new InputStreamReader(ois)); } StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sb.append(line + "\n"); } } catch (IOException e) { e.printStackTrace(); } return sb.toString(); } }
public class ClientOutputThread extends Thread { private Socket socket; private DataOutputStream dos; private boolean isStart = true; private String msg; public ClientOutputThread(Socket socket) { this.socket = socket; try { dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); } catch (IOException e) { e.printStackTrace(); } } public void setStart(boolean isStart) { this.isStart = isStart; } // 這裡處理跟服務器是一樣的 public void sendMsg(String msg) { this.msg = msg; synchronized (this) { notifyAll(); } } @Override public void run() { try { while (isStart) { if (msg != null) { dos.writeUTF(msg); dos.flush(); msg=null; synchronized (this) { wait();// 發送完消息後,線程進入等待狀態 } } } dos.close();// 循環結束後,關閉輸出流和socket if (socket != null) socket.close(); } catch (InterruptedException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
//定義接收到消息時的,處理消息的接口 public interface MessageListener { public void Message(String msg); }
主界面,感覺很丑,將就吧
"
public class MainActivity extends Activity { EditText etMessage; TextView tvSend, tvMessage; SocketThread client; MyHandler myHandler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); setup(); } public void setup() { etMessage = (EditText) findViewById(R.id.etMessage); tvSend = (TextView) findViewById(R.id.tvSend); tvMessage = (TextView) findViewById(R.id.tvMessage); tvSend.setOnClickListener(onClick); myHandler = new MyHandler(); //初始化 client = new SocketThread("10.21.56.226", 8888,new MessageListener() { //收到消息後調用此方法 @Override public void Message(String msg) { // TODO Auto-generated method stub // tvMessage.append(msg); Bundle bundle = new Bundle(); bundle.putString("input", msg); Message isMessage = new Message(); isMessage.setData(bundle); //使用handler轉發 myHandler.sendMessage(isMessage); } }); //正式啟動線程 client.start(); } OnClickListener onClick = new OnClickListener() { public void onClick(android.view.View v) { String message = etMessage.getText().toString(); Log.v("發送消息", message); if (client.isStart()) { client.sendMsg(message); } }; }; private class MyHandler extends Handler { @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub Log.v("處理收到的消息", " "); tvMessage.append(msg.getData().getString("input")); } } }
public class ChatServer { boolean started = false; ServerSocket ss = null; List接下來先運行服務器代碼,再運行手機端就可以了,多台手機可以互相發送信息了。clients = new ArrayList (); public static void main(String[] args) { new ChatServer().start(); } public void start() { try { //ServerSocket監聽8888端口 ss = new ServerSocket(8888); started = true; } catch (BindException e) { System.out.println("start...."); System.out.println("有問題"); e.printStackTrace(); System.exit(0); } catch (IOException e) { e.printStackTrace(); } try { while (started) { Socket s = ss.accept(); Client c = new Client(s); System.out.println("a client connected!"); new Thread(c).start(); clients.add(c); // dis.close(); } } catch (IOException e) { e.printStackTrace(); } finally { try { ss.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class Client implements Runnable { private Socket s; private DataInputStream dis = null; private DataOutputStream dos = null; private boolean bConnected = false; public Client(Socket s) { this.s = s; try { dis = new DataInputStream(s.getInputStream()); dos = new DataOutputStream(s.getOutputStream()); bConnected = true; } catch (IOException e) { e.printStackTrace(); } } public void send(String str) { try { dos.writeUTF(str); } catch (IOException e) { clients.remove(this); System.out.println("關閉一個連接"); // e.printStackTrace(); } } public void run() { try { while (bConnected) { String str = dis.readUTF(); System.out.println(str); for (int i = 0; i < clients.size(); i++) { Client c = clients.get(i); c.send(str); // System.out.println(" a string send !"); } /* * for(Iterator it = clients.iterator(); * it.hasNext(); ) { Client c = it.next(); c.send(str); } */ /* * Iterator it = clients.iterator(); * while(it.hasNext()) { Client c = it.next(); c.send(str); * } */ } } catch (EOFException e) { System.out.println("Client closed!"); } catch (IOException e) { e.printStackTrace(); } finally { try { System.out.println("close All !"); if (dis != null) dis.close(); if (dos != null) dos.close(); if (s != null) { s.close(); // s = null; } } catch (IOException e1) { e1.printStackTrace(); } } } } }
問題:如果圖片很大,全部載入內存,而顯示屏又不大,那麼再大的圖片也不會提高視覺效果的,而且會消耗無謂的內存。 解決辦法就是根據實際需要多大的圖片,然後動態計算應該載入多大
除非迫不得已,要不然不要在你的APP裡面使用數據庫,記不得是哪個書的話了!現在Android平台下的ORM框架very多,比如GreenDao,曾經寫過一篇關於Green
關於安卓上的app分析,有很多的本地化軟件可以勝任, 不過,今天給大家介紹一款在線的安全審計,惡意軟件(android app)檢測和分析工具,mobiseclab,
ExpandableListView介紹 ExpandableListView的引入 ExpandableListView可以顯示一個視圖垂直滾動顯示
今早起來運行程序 一直報這個錯Error running app: In