1. 程式人生 > >Android客戶端實現註冊/登入詳解(一)

Android客戶端實現註冊/登入詳解(一)

前言

我們在開發安卓App時難免要與伺服器打交道,尤其是對於使用者賬號資訊的註冊與登入更是每個android開發人員必須掌握的技能,本文將對客戶端的註冊/登入功能的實現進行分析,不到之處還請指出。

在這裡我們僅討論客戶端如何請求伺服器進行註冊,而伺服器在收到客戶端請求後進行的一系列操作並不在本文所述範圍內,有興趣大家可以參考

請求伺服器

客戶端在進行使用者資訊的註冊和登入時一般使用post請求(攜帶引數)去伺服器。以volley框架請求伺服器為例,真正與伺服器進行互動的就是如下程式碼:

StringRequest request=new StringRequest(Method.POST, url, new Listener<String>() {

        //請求成功
        @Override
        public void onResponse(String s) {
            //執行請求成功的回撥
            callback.onSuccess()
        }

    }, new ErrorListener() {

        //請求錯誤
        @Override
        public void onErrorResponse(VolleyError volleyError) {
            //執行請求失敗的回撥
            callback.onFailure()
        }
    }){

        //攜帶引數(Map集合)
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            return parames;
        }
    };

    //將請求新增到請求佇列中
    Volley.newRequestQueue(context).add(request);

當然,我們在請求伺服器成功或失敗時應該設定相應的回撥方法,讓我們能夠進行一些操作。

  • callback.onSuccess() //請求成功的回撥

    1.儲存使用者註冊資訊(SP中和Application中)
    2.跳轉到主頁面
    
  • callback.onFailure() //請求失敗的回撥

    1.提示錯誤資訊
    

下面通過一個具體的demo來介紹
(宣告:此demo為阿福老師IT藍豹App的程式碼擷取)

注:我們在與伺服器進行互動時,必須按照規定的介面和規則進行請求,這裡使用的是IT藍豹App中的伺服器,伺服器的註冊介面資料格式如下

1.url:http://www.itlanbao.com/api/app/users/user_register_Handler.ashx

2.引數說明
    nickname       必須有    暱稱
    email          必須有    郵箱
    password       必須有    密碼
    accesstoken    必須有    簽名md5(nickname+email+password+"雙方平臺約定公鑰")

3.請求方式:POST

4.返回值格式:
    成功
    {
        "ret":0,
        "errcode":0,
        "msg":"介面呼叫成功",
        "data":{
            "userid":"16489",
            "email":"
[email protected]
", "nickname":"duss", "userhead":"http://img.itlanbao.com/avatar.png" } } 失敗 { "ret":1, "errcode":1, "msg":"介面呼叫失敗" }

demo演示

主要實現程式碼(demo會在文章最後給出)

1.註冊頁面中(RegisterActivity),點選註冊按鈕

registBtn.setOnClickListener(new Button.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            //獲得使用者輸入的資訊
            String nick = loginNick.getText().toString();
            String emailStr = email.getText().toString();
            String passwordStr = password.getText().toString();
            if (!TextUtils.isEmpty(nick) &&
                    !TextUtils.isEmpty(emailStr)
                    && !TextUtils.isEmpty(passwordStr)) {
                if (Utils.isEmail(emailStr)) {//驗證郵箱格式是否符合

                    //呼叫RequestApiData中的getRegistData()方法進行註冊,傳入使用者輸入的暱稱,郵箱、密碼,以及解析資料的bean物件和callback物件(回撥到自身)
                    RequestApiData.getInstance().getRegistData(nick, emailStr, passwordStr,
                            AnalyticalRegistInfo.class, RegisterActivity.this);
                } else {
                    Toast.makeText(RegisterActivity.this, "輸入郵箱有誤", Toast.LENGTH_SHORT).show();
                }
            } else {
                Toast.makeText(RegisterActivity.this, "輸入資訊未完全", Toast.LENGTH_SHORT).show();
            }
        }
    });

注意:這個註冊的方法中,我們傳入的最後一個引數是回撥的物件,這裡我們傳入的是RegisterActivity自身,所以它需要實現HttpResponeCallBack介面

RequestApiData.getInstance().getRegistData(nick, emailStr, passwordStr,
                            AnalyticalRegistInfo.class, RegisterActivity.this);

2.請求伺服器的回撥介面(HttpResponeCallBack)

public interface HttpResponeCallBack {
    public void onResponeStart(String apiName);

    /**
     * 此回撥只有呼叫download方法下載資料時才生效
     * 
     * @param apiName
     * @param count
     * @param current
     */
    public void onLoading(String apiName, long count, long current);

    public void onSuccess(String apiName, Object object);

    public void onFailure(String apiName, Throwable t, int errorNo, String strMsg);

}

3.網路介面類(RequestApiData)

public class RequestApiData {
    private static RequestApiData instance = null;
    private HttpResponeCallBack mCallBack = null;

    //建立介面物件
    public static RequestApiData getInstance() {
        if (instance == null) {
            instance = new RequestApiData();
        }
        return instance;
    }

    /**
     * 4.6註冊使用者介面
     * @param nickname  暱稱
     * @param email 郵箱
     * @param password 密碼
     * @param clazz  資料返回的解析物件
     * @param callback 回撥
     * 特別要注意引數位置不能變要根據文件來
     * 請求方式:POST
     */
    public void getRegistData(String nickname,String email
            ,String password, Class<AnalyticalRegistInfo> clazz,
           HttpResponeCallBack callback) {
         mCallBack = callback;
         //這是每一個介面的唯一標示
         String tagUrl = UrlConstance.KEY_REGIST_INFO;//註冊介面
         //將註冊的資訊儲存在map中(須和伺服器端一致)
         HashMap<String, String> parameter = new HashMap<String, String>();
         parameter.put("nickname", nickname);
         parameter.put("email",email);
         parameter.put("password",password);

        //拼接引數資訊,暱稱,郵箱,密碼,公鑰,並用md5進行加密
        StringBuilder builder = new StringBuilder();
        builder.append(nickname);
        builder.append(email);
        builder.append(password);
        builder.append(UrlConstance.PUBLIC_KEY);

        parameter.put(UrlConstance.ACCESSTOKEN_KEY,MD5Util.getMD5Str(builder.toString()));

         //呼叫RequestManager的post方法,請求伺服器
         RequestManager.post(UrlConstance.APP_URL,tagUrl, parameter, clazz, callback);

    }
}

4.網路請求處理的類(RequestManager)

public class RequestManager {
    private static RequestQueue mRequestQueue;
    private static ImageLoader mImageLoader;


    private synchronized static void initRequestQueue() {
        if (mRequestQueue == null) {
            //建立一個請求佇列(使用Volley框架)
            mRequestQueue = Volley.newRequestQueue(ItLanbaoLibApplication.getInstance());
        }
    }


    /**
     * 新增請求到請求佇列中
     * @param request
     * @param tag
     */
    private static void addRequest(Request<?> request, Object tag) {
        if (tag != null) {
            request.setTag(tag);
        }
        mRequestQueue.add(request);
    }

    /**
     * post 請求資料
     *
     * @param app_url     公共的介面字首 http://www.itlanbao.com/api/app/
     * @param tag_url     介面名稱,eg:users/user_register_Handler.ashx(註冊介面)
     * @param parameter  請求引數封裝物件
     * @param clazz      返回資料封裝物件,如果傳null,則直接返回String
     * @param callback   介面回撥監聽
     */
    public static <T> void post(final String app_url, final String tag_url, final HashMap<String, String> parameter, Class<T> clazz,
                                final HttpResponeCallBack callback) {
        //傳送post請求伺服器
        post(app_url, tag_url, parameter, clazz, callback, Priority.NORMAL);
    }


    /**
     * post 請求資料
     *
     * @param app_url    路徑
     * @param url        介面名稱
     * @param parameter  請求引數封裝物件
     * @param clazz      返回資料封裝物件,如果傳null,則直接返回String
     * @param callback   介面回撥監聽
     * @param priority   指定介面請求執行緒優先順序
     */
    public static <T> void post(final String app_url, final String url, final HashMap<String, String> parameter, final Class<T> clazz,
                                final HttpResponeCallBack callback, Priority priority) {
        if (callback != null) {
            callback.onResponeStart(url);//回撥請求開始
        }

        //初始化請求佇列
        initRequestQueue();

        //將公共的介面字首和介面名稱拼接
        //eg:拼接成註冊的介面  http://www.itlanbao.com/api/app/users/user_register_Handler.ashx
        StringBuilder builder = new StringBuilder(app_url);
        builder.append(url);

        {// 檢查當前網路是否可用
            final NetworkUtils networkUtils = new NetworkUtils(ItLanbaoLibApplication.getInstance());

            if (!networkUtils.isNetworkConnected() && android.os.Build.VERSION.SDK_INT > 10) {
                if (callback != null) {
                    callback.onFailure(url, null, 0, "網路出錯");//回撥請求失敗
                    return;
                }
            }
        }

        /**
         * 使用Volley框架真正去請求伺服器
         * Method.POST:請求方式為post
         * builder.toString():請求的連結
         * Listener<String>:監聽
         */
        StringRequest request = new StringRequest(Method.POST, builder.toString(),
                new Listener<String>() {

                    @Override
                    public void onResponse(String response) {
                        // TODO Auto-generated method stub
                        try {
                            if (response != null && callback != null) {
                                Gson gson = new Gson();
                                //回撥請求成功,傳入url和解析的物件
                                callback.onSuccess(url, gson.fromJson(response, clazz));

                            }

                        } catch (Exception e) {
                            // TODO: handle exception
                            if (callback != null) {
                                //回撥請求失敗--解析異常
                                callback.onFailure(url, e, 0, "解析異常");
                                return;
                            }
                        }


                    }
                }, new ErrorListener() {
            //請求出錯的監聽
            @Override
            public void onErrorResponse(VolleyError error) {
                if (callback != null) {
                    if (error != null) {
                        callback.onFailure(url, error.getCause(), 0,
                                error.getMessage());
                    } else {
                        callback.onFailure(url, null, 0, "");
                    }
                }
            }
        }) {
            //post請求的引數資訊
            protected Map<String, String> getParams() {
                return getPostApiParmes(parameter);
            }
        };

        //新增請求到請求佇列中
        addRequest(request, url);
    }


    /*
     * post引數
     * 
     * ts:時間戳 sign: 介面簽名 parms = 按文件引數拼接 parm[0]+ … + parm[n-1] sign =
     * md5(parms+"雙方平臺約定公鑰")
     */
    private static ApiParams getPostApiParmes(final HashMap<String, String> parameter) {
        ApiParams api = new ApiParams();
        for (Entry<String, String> entry : parameter.entrySet()) {
            api.with(entry.getKey(), entry.getValue());
        }
        return api;
    }

}

5.在請求伺服器成功/失敗後會執行回撥方法,而我們傳入的callback物件是自身(RegisterActivity),所以現在我們回到註冊頁面

    @Override
    public void onResponeStart(String apiName) {
        // TODO Auto-generated method stub
        Toast.makeText(RegisterActivity.this, "正在請求資料...", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onLoading(String apiName, long count, long current) {
        Toast.makeText(RegisterActivity.this, "Loading...", Toast.LENGTH_SHORT).show(); 
    }

    @Override
    public void onSuccess(String apiName, Object object) {
        // TODO Auto-generated method stub
        //註冊介面
        if (UrlConstance.KEY_REGIST_INFO.equals(apiName)) {
            if (object != null && object instanceof AnalyticalRegistInfo) {
                AnalyticalRegistInfo info = (AnalyticalRegistInfo) object;
                String successCode = info.getRet();
                //請求成功
                if (successCode.equals(Constant.KEY_SUCCESS)) {
                    UserBaseInfo baseUser = new UserBaseInfo();
                    baseUser.setEmail(info.getEmail());
                    baseUser.setNickname(info.getNickname());
                    baseUser.setUserhead(info.getUserhead());
                    baseUser.setUserid(String.valueOf(info.getUserid()));
                    ItLanBaoApplication.getInstance().setBaseUser(baseUser);
                    UserPreference.save(KeyConstance.IS_USER_ID, String.valueOf(info.getUserid()));
                    UserPreference.save(KeyConstance.IS_USER_ACCOUNT, info.getEmail());
                    UserPreference.save(KeyConstance.IS_USER_PASSWORD, password.getText().toString());


                    Intent intent = new Intent(RegisterActivity.this, MainActivity.class);
                    RegisterActivity.this.startActivity(intent);

                    Toast.makeText(RegisterActivity.this, "註冊成功...", Toast.LENGTH_SHORT).show();

                    RegisterActivity.this.finish();

                } else {
                    Toast.makeText(RegisterActivity.this, "註冊失敗", Toast.LENGTH_SHORT).show();
                }
            }
        }

    }

    @Override
    public void onFailure(String apiName, Throwable t, int errorNo, String strMsg) {
        Toast.makeText(RegisterActivity.this, "Failure", Toast.LENGTH_SHORT).show();
    }

至此,安卓客戶端的註冊功能就實現了,下一篇中將會介紹登入和自動登入的實現

相關推薦

Android客戶實現註冊/登入

前言 我們在開發安卓App時難免要與伺服器打交道,尤其是對於使用者賬號資訊的註冊與登入更是每個android開發人員必須掌握的技能,本文將對客戶端的註冊/登入功能的實現進行分析,不到之處還請指出。 在這裡我們僅討論客戶端如何請求伺服器進行註冊,而伺服器在

Android客戶實現註冊/登入

上文中介紹了安卓客戶端與伺服器互動,實現註冊功能 本文將繼續介紹App與伺服器的互動實現登入和自動登入的功能,上文說到請求伺服器進行註冊主要是通過POST請求攜帶引數實現,起作用的程式碼主要是 StringRequest request=new

Java代理模式實現與原理

關於Java中的代理,我們首先需要了解的是一種常用的設計模式——代理模式,而對於代理,可根據代理類建立的時間點,分為靜態代理和動態代理。今天我們先來了解一下Java中的靜態代理。 1 代理模式 代理模式是一種常用的設計模式,百度百科中對其定義為:為其他物件提供一個代理以控制對某個物件的訪問。

Android使用GPUImage實現濾鏡效果精煉

一、前期基礎知識詳解 “濾鏡通常用於相機鏡頭作為調色、新增效果之用。如UV鏡、偏振鏡、星光鏡、各種色彩濾光片。濾鏡也是繪圖軟體中用於製造特殊效果的工具統稱,以Photoshop為例,它擁有風格化、畫筆描邊、模糊、扭曲、銳化、視訊、素描、紋理、畫素化、渲染、藝術效果、其他

.NET客戶實現Redis中的管道PipeLine與事物Transactions

redis服務器 net 他會 端口 ocs string new equal alt 原文:.NET客戶端實現Redis中的管道(PipeLine)與事物(Transactions)序言 Redis中的管道(PipeLine)特性:簡述一下就是,Redis如何從客戶端一

Android EventBus3.x 使用

led AC target 分解 感覺 div activit .org android事 ?(^∇^*) 五一假期在家無事,新項目中用的是RxJava2+EventBus感覺還不錯,趁這閑暇總結下EventBus 一、概要簡述   EventBus

安卓專案實戰之強大的網路請求框架okGo使用實現get,post基本網路請求,下載上傳進度監聽以及對Callback自定義的深入理解

1.新增依賴 //必須使用 compile 'com.lzy.net:okgo:3.0.4' //以下三個選擇新增,okrx和okrx2不能同時使用,一般選擇新增最新的rx2支援即可 compile 'com.lzy.net:okrx:1.0.2' compile 'com.lzy

Android Paging library

官方文件翻譯 文章目錄 1.概覽 1.1 庫架構 1.2 支援不同的資料架構 1.2.1 網路獲取或者資料庫 1.2.2 網路和資料庫同時獲取 1.2.3 處理網路錯誤 1.2.4 更新

Android Lifecycle

官方文件翻譯 使用生命週期感知元件處理生命週期 Lifecycle Event State LifecycleOwner 實現一個自定義的LifecycleOwner 生命週期感

華為PAT口地址映射配置

type 一個 多個 轉換 .com pin EDA ip地址 server 眾所周知,PAT,,Port Address Translation,即網絡地址轉換。 PAT有以下作用:1.改變數據包的ip地址和端口號;2.能夠大量節約公網IP地址。PAT的類型有以下:1.動

C程式設計|用函式實現模組化程式設計

目錄 一、為什麼要用函式 使用函式可使程式清晰、精煉、簡單、靈活。 函式就是功能。每一個函式用來實現一個特定的功能。函式名應反映其代表的功能。 在設計

UE4移動元件——移動框架與實現原理

前言 關於UE4的移動元件,我寫了一篇非常詳細的分析文件。由於篇幅比較大,我將其拆分成三個部分。分別從移動框架與實現原理,移動的網路同步,移動元件的優化與改造三個方面來寫。這三篇文件中難免有問題和漏洞,所以我也會在發現問題時及時更新和修改,也希望大家能給出一些

Yii2.0登入

在上一篇博文中,筆者講述了yii2應用使用者登陸的基本方法,但是這些方法到底是怎樣實現登陸的呢?底層的原理到底是什麼?在這篇博文筆者將從Yii的原始碼角度分析登陸的基本原理以及cookie自動登陸的原理,通過原始碼的分析,各位對Yii的理解也會更上一層樓。 一、第一次

[Android]ToolBar使用——專案配置

private Toolbar mToolbar; private WebFragment mWebFragment; private long mBeforeTime; @Override protected void onCreate(Bundle savedInst

Yii2.0 使用者登入

一、準備 在開始編寫程式碼之前,我們需要思考一下:使用者登陸模組,實現的是什麼功能?很明顯,是登陸功能,那麼,登陸需要使用者名稱和密碼,我們在資料庫的一張表中就應該準備好使用者名稱和密碼的欄位,再思考一下,如果要實現自動登陸的功能,那麼還需要什麼?Cookie,是專門用

Android 動畫】View Animation

安卓平臺目前提供了兩大類動畫,在Android 3.0之前,一大類是View Animation,包括Tween animation(補間動畫),Frame animation(幀動畫),在android3.0中又引入了一個新的動畫系統:property ani

Android 5.X 新特性——主題、Palette、陰影、著色和裁剪

Android 5.X 系列開始使用新的設計風格Material Design來統一整個Android系統的介面設計風格。 Material Design 主題 Material Design 現在有三種預設的主題可以設定,程式碼如下: @andr

Android 樣式開發:Drawable分類資源彙總

Drawable Resources 解釋為:可繪製物件資源。是指可在螢幕上繪製的圖形,以及可以使用 getDrawable(int) 等 API 檢索或者應用到具有 android:drawable

Android.mk用法

       Android.mk是Android提供的一個makefile檔案,可以將原始檔分組為模組。用來引用的標頭檔案目錄、需要編譯的*.c/*.cpp檔案、jni原始檔、指定編譯生成*.so共享庫檔案或者*.a靜態庫檔案,可以定義一個或多個模組,也可以多個模組中使用同

Android程式設計之DialogFragment原始碼

DialogFragment是Fragment家族成員之一,如果你把它簡單的理解成Dialog,那就錯了。它的確可以做作dialog顯示,還可以顯示出自己定義的Dialog或者AlertDialog,但它同時也是一個Fragment。 按照官方的話來理解就是,你既可以把它當