Http協議與請求
Post請求

    Post請求與Get請求的區別
        Get請求的引數是直接放在url後面的,而Post請求是放在請求體中的
        Get請求引數的長度會根據瀏覽器的不同實現有一定限制,而Post請求引數長度沒有限制
        Get請求方便測試,直接輸入地址即可,而Post請求不方便測試,需要藉助程式碼或者工具進行傳送
        Get請求和Post請求沒有本質的區別,只是定義上的區別,比如如果你非要將get方式的引數放在請求體中,那麼伺服器也是可以接收處理的,同樣,你也可以將post方式的引數拼在url後面
    Post請求的使用場景
        使用Post請求上傳鍵值對
        使用Post請求上傳json串
        使用Post請求上傳單個檔案
        使用Post請求上傳多個檔案

    使用Post方法上傳鍵值對,程式碼如下:

    public void asyncPost(String url,HashMap<String, String> params,TextHttpResponseHandler responseHandler){
        RequestParams requestParams = new RequestParams(params);
        asyncHttpClient.post(url, requestParams, responseHandler);
    }
    /**
     * post提交key-value
     * @param url2
     */
    private void postKeyValue(String url) {
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("username", "俊哥");
        params.put("password", "111");
        HttpHelper.get().asyncPost(url, params, new TextHttpResponseHandler() {
            @Override
            public void onSuccess(int arg0, Header[] arg1, String text) {
                tv_result.setText(text);
            }
            @Override
            public void onFailure(int arg0, Header[] arg1, String arg2, Throwable arg3) {

            }
        });
    }

    使用Post方式上傳檔案,程式碼如下:

    public void asyncUploadFile(String url, String key, File file,TextHttpResponseHandler responseHandler) {
        RequestParams requestParams = new RequestParams();
        try {
            requestParams.put(key, file);
            asyncHttpClient.post(url,requestParams , responseHandler);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
    private void uploadFile() {
        try {
            File file = new File(Environment.getExternalStorageDirectory()+"/dog.jpg");
            HttpHelper.get().asyncUploadFile(upload, "file", file, new TextHttpResponseHandler() {
                @Override
                public void onSuccess(int arg0, Header[] arg1, String text) {
                    tv_result.setText(text);
                }
                @Override
                public void onFailure(int arg0, Header[] arg1, String arg2, Throwable arg3) {

                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    Post請求相關注意事項:
        傳遞中文引數問題,Get請求同樣需要注意,需要對url進行編碼,對應的類有URLEncoder和URLDecoder,否則會亂碼,當然很多第三方http庫已經處理該問題
    常見Content-Type定義:
        普通文字:text/plain
        表單鍵值對:application/x-www-form-urlencoded
        檔案資料:application/octet-stream
        json資料:application/json
        xml資料:text/xml

Android中常見編碼Base64和URL編碼

    URL編碼:http協議中請求的url不支援中文和特殊字元(如&?),所以需要對url進行編碼和解碼,編碼使用的是URLEncoder,解碼使用的是URLDecoder;

    //進行url編碼
    URLEncoder.encode(url)
    //進行url解碼
    URLDecoder.decode(encodeUrl)

    Base64:可以將二進位制資料物件轉為字串,主要用於在http傳輸中將一些比較大的比如二進位制資料,編碼為字串,適合放入url進行傳遞,而且具有非明文行。應用場景如下:

        將檔案進行base64編碼為字串後再上傳,程式碼如下:

     
   private void base64Image() {
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            bitmap.compress(CompressFormat.PNG, 100, baos);

            byte[] encode = Base64.encode(baos.toByteArray(), Base64.DEFAULT);
            tv_result.setText(new String(encode));
        }

        將物件進行base64編碼為字串後,可以進行本地快取,程式碼如下:

        private void base64Object() {
            Object obj = new Object();
            ByteArrayOutputStream bo = new ByteArrayOutputStream();
            ObjectOutputStream oo;
            try {
                oo = new ObjectOutputStream(bo);
                oo.writeObject(obj);
            } catch (IOException e) {
                e.printStackTrace();
            }

            byte[] encode = Base64.encode(bo.toByteArray(), Base64.DEFAULT);
            tv_result.setText(new String(encode));
        }

Android中的數字摘要,加密和解密 數字摘要:是指通過演算法將長資料變為短資料,通常用來標識資料的唯一性,是否被修改,常用的加密演算法有md5和sha1,如安卓app的簽名也是用這2種演算法計算的; md5由於具有不可逆性,也被用來作為密碼加密,並且通常情況下為了讓加密過程變的不可預測,我們會進行加鹽操作,程式碼如下: /** * 使用md5方式進行加密 * @return */
private String md5(String password) {
    StringBuffer sb = new StringBuffer();
    try {
        MessageDigest messageDigest = MessageDigest.getInstance("MD5");
        messageDigest.update(password.getBytes());
        byte[] digest = messageDigest.digest();
        for (int i = 0; i < digest.length; i++) {
            String str = Integer.toHexString(digest[i] & 0xff);

            if (str.length() == 1) {
                str = str + "0";
            }
            sb.append(str);

        }


    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    return sb.toString();
}



sha1也不可逆,比md5長度更長,所以更安全,但是加密的效率比md5要慢一些,如檔案的秒傳功能,以及相同的v4包衝突都是根據檔案的sha1值進行比對的。 /** * 使用sha-1方式進行加密 * @return */
 private String sha1(String password) {
        StringBuffer sb = new StringBuffer();
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
            messageDigest.update(password.getBytes());
            byte[] digest = messageDigest.digest();
            for (int i = 0; i < digest.length; i++) {
                String str = Integer.toHexString(digest[i] & 0xff);

                if (str.length() == 1) {
                    str = str + "0";
                }
                sb.append(str);

            }


        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return sb.toString();
    }



加密和解密,一般分為對稱加密和非對稱加密
對稱加密: 
金鑰可以自己指定,只有一把金鑰,如果金鑰暴露,檔案就會被暴露,
常見對稱加密演算法有DES演算法(Data Encryption Standard)和AES演算法(Advanced Encryption Standard),
特點是加密速度很快,但是缺點是安全性較低,因為只要金鑰暴漏,資料就可以被解密了。 
非對稱加密:有兩把鑰匙(金鑰對),公鑰和私鑰,公鑰的話給別人,私鑰自己儲存 
常見非對稱加密演算法是RSA
2把金鑰通常是通過程式生成,不能自己指定
特點是加密速度慢些,但是安全係數很高
加密和解密的規則是:公鑰加密只能私鑰解密,私鑰加密只能公鑰解密
應用場景舉例:在整合支付寶支付sdk時,需要生成私鑰和公鑰,公鑰需要設定到支付寶網站的管理後臺,在程式中呼叫支付介面的時候,使用我們自己的私鑰進行加密,這樣支付寶由於有公鑰可以解密,其他人即時劫持了資料,但是沒有公鑰,也無法解密。
程式碼實踐,使用hmAndroidUtils中的工具類進行操作
DES加密和解密的程式碼如下:
String data = "我是俊哥";
String desKey = "青龍偃月刀";// 金鑰,口號
boolean isDesEncrypt = false;
private void useDes() {
    try {
        if(isDesEncrypt){
            //解密
            text.setText(Des.decrypt(text.getText().toString(), desKey));
        }else {
            //加密
            text.setText(Des.encrypt(data, desKey));
        }
        isDesEncrypt = !isDesEncrypt;

    } catch (Exception e) {
        e.printStackTrace();
    }
}
RSA加密和解密的程式碼如下:
//1.生成金鑰對,設計口號
try {
    Map<String, Object> genKeyPair = RSACrypt.genKeyPair();
    //2.獲取公鑰
    publicKey = RSACrypt.getPublicKey(genKeyPair);
    //3.獲取私鑰
    privateKey = RSACrypt.getPrivateKey(genKeyPair);
} catch (Exception e) {
    e.printStackTrace();
}
private boolean isRSAEncrypt = false;
protected void useRSA() {
    try {
        if(isRSAEncrypt){
            //公鑰解密
            String str = text.getText().toString();
            byte[] bs = RSACrypt.decryptByPublicKey(RSACrypt.decode(str), publicKey);
            text.setText(new String(bs));
        }else {
            //私鑰加密
            byte[] bs = RSACrypt.encryptByPrivateKey(data.getBytes(), privateKey);
            text.setText(RSACrypt.encode(bs));
        }
        isRSAEncrypt = !isRSAEncrypt;
    } catch (Exception e) {
        e.printStackTrace();
    }
}