Android必備:Android Socket編程的瞭解與學習整理

    看這裏:Android必備:Android Socket編程的瞭解與學習整理html

    最近學習Android的過程當中,因爲項目、業務等因素影響,服務端經過Socket進行通訊,因而開始學習Socket編程,以前的開發中,不多涉及此 方面的知識學習,本篇就來簡單的整理一下,經過Android客戶端進行Socket登陸的demo,來進行Adnroid Socket編程的學習。java

    在開始學習以前,先來了解一下Socket,如下內容來自百度百科android

    一般也稱做"套接字",用於描述IP地址和端口,是一個通訊鏈的句柄。在Internet上的主機通常運行了多個服務軟件,同時提供幾種服務。每種服務都打開一個Socket,並綁定到一個端口上,不一樣的端口對應於不一樣的服務。
git

     首先,來介紹一下項目的設計,只包含兩個UI佈局文件:login.xml和main.xml,對應登陸頁和主頁,登陸頁包含一個用戶名的輸入框和登陸按 鈕,點擊登陸按鈕,登陸按鈕顯示文字「正在鏈接,請稍候...」,經過Socket進行登陸,並跳轉到主頁,若是用戶名是admin,則在主頁顯示「登陸 成功!」反之顯示「登陸失敗!」。web

      下面是demo運行後的具體效果圖:編程


    login.xml: 
服務器

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
        >
    <EditText
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:inputType="textPersonName"
            android:hint="請輸入用戶名"
            android:ems="10"
            android:id="@+id/loginName"
            />
    <Button
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:text="登陸"
            android:id="@+id/loginBtn"
            />

</LinearLayout>

        main.xml:網絡

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
        >

<TextView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:gravity="center"
        android:id="@+id/mainText"
        />
</LinearLayout>

      固然經過Socket進行通訊的時候,咱們須要app擁有網絡訪問即Internet或Wifi的權限,將下面兩行添加到AndroidManifest.xml:app

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.INTERNET"/>

        下面開始進行實例的編寫,本篇的學習基於TCP/ IP 進行Socket通訊,說是Android Socket編程,其實使用的是java.net包下提供的ServerSocket和Socket類,這是一種比較底層的編程方式,Socket類用來創建客戶端程序,ServerSocket用來創建服務端程序,首先來看服務端的代碼:socket

package com.xx566.socket.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketServer {

    private static ServerSocket serverSocket;

    public static void main(String[] args) throws IOException {
        serverSocket = new ServerSocket(8888);
        while (true) {
            final Socket socket = serverSocket.accept();
            try {
                // 獲取輸入流
                BufferedReader inputStream = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                // 獲取輸出流
                PrintWriter outputStream = new PrintWriter(socket.getOutputStream());
                // 讀取輸入
                String readString = inputStream.readLine();
                if ("admin".equals(readString)) {
                    outputStream.println("登陸成功!");
                } else {
                    outputStream.println("登陸失敗!");
                }
                outputStream.flush();
                // 關閉
                outputStream.close();
                inputStream.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

    咱們在8888端口,實例化了Socket服務端,經過永真循環,來等待客戶端Socket的鏈接。accept()方法返回一個對應客戶端的Socket,服務端讀取客戶端輸入,若是輸入的是"admin",則輸出"登陸成功!",反之,輸出"登陸失敗!",接下來,咱們主要來看一下客戶端LoginActivity的編寫,須要注意的是,在Android4.0系統以上的系統中,是不容許在主線程中執行網絡相關的請求,不然會拋出NetworkOnMainThreadException異常,因此須要單獨的線程向服務端發送Socket,完整代碼以下:

package com.xx566.socket;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import java.io.*;
import java.net.Socket;

public class LoginActivity extends Activity {

    private Button loginBtn;
    private EditText loginName;
    PrintWriter outputStream;
    BufferedReader inputStream;
    Socket socket;
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            //經過handler處理接收到的消息
            if (msg.what == 1) {
                //跳轉到主頁面,顯示登陸結果
                Intent intent = new Intent(LoginActivity.this, MainActivity.class);
                intent.putExtra("result", msg.getData());
                startActivity(intent);
            }
        }
    };

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.login);
        //登陸按鈕點擊事件
        loginBtn = (Button) findViewById(R.id.loginBtn);
        loginName = (EditText) findViewById(R.id.loginName);
        loginBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //點擊登陸後,顯示正在鏈接服務器
                loginBtn.setText("正在鏈接,請稍候...");
                loginBtn.setClickable(false);
                final String userName = loginName.getText().toString();
                //經過Socket登陸服務器,簡單的傳遞用戶名
                new Thread() {
                    @Override
                    public void run() {
                        //處理接收到的消息
                        Message message = new Message();
                        message.what = 1;
                        Bundle bundle = new Bundle();
                        String result = "";
                        try {
                            socket = new Socket("192.168.0.32", 8888);
                            outputStream = new PrintWriter(socket.getOutputStream());
                            inputStream = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                            outputStream.println(userName);
                            outputStream.flush();
                            //讀取結果
                            while (true) {
                                result = inputStream.readLine();
                                if (!"".equals(result)) {
                                    break;
                                }
                            }
                            //關閉
                            inputStream.close();
                            outputStream.close();
                            socket.close();
                        } catch (Exception e) {
                            result = "網絡異常!";
                        }
                        bundle.putString("result", result);
                        message.setData(bundle);
                        //傳遞消息
                        handler.sendMessage(message);
                    }
                }.start();
            }
        });

    }

    @Override
    protected void onResume() {
        super.onResume();
        loginBtn.setText("登陸");
        loginBtn.setClickable(true);
    }
}

    這裏使用了Android Handler機制進行了線程間消息的傳遞,主要是接收服務端響應的結果,啓動MainActicity。MainActivity裏面顯示登陸結果,代碼以下:

package com.xx566.socket;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {

    private TextView mainText;
    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mainText = (TextView) findViewById(R.id.mainText);
        Bundle bundle = getIntent().getExtras().getBundle("result");
        mainText.setText(bundle.getString("result"));
    }
}

   完整項目地址:http://git.oschina.net/realfighter/SocketDemo

相關文章
相關標籤/搜索