1. 程式人生 > >Native和H5兩種情況的頭像上傳

Native和H5兩種情況的頭像上傳

最近的工作中接觸了一個小的功能,上傳頭像。上傳頭像是很多應用中的東西,描述下自己的應用。上傳頭像應用的地方:
1.最開始進入app的時候會提示註冊,然後就會呼叫。
2.成功的註冊完畢以後,可以在個人資訊裡面修改頭像。
3.在H5(某個WebView)中也可以修改這個頭像。
4.分為上傳成功,上傳失敗和取消上傳的功能。

先想想自己的這個功能,實現1和2只需要將上傳的邏輯寫在一個公共的類就行(例如:LoadUtil.java),要實現3的功能,首先想到也是在一個WebViewActivity中實現上傳,不是直接跟在某個NativeActivity中上傳的邏輯一樣?仔細想想,發現其實不是這樣的,一個WebViewActivity對應的會是很多的H5的介面(例如:

http://wwww.baidu.comhttp://www.google.com 可能都是在同一個WebViewAcitivity)。這樣就會導致我需要在公用的WebViewActivity中加上圖片剪下加上圖片上傳藉口的呼叫。同樣的,我實現1和2的時候也是需要在兩個不同的Activity中去實現圖片的裁剪和呼叫上傳介面。又或者說來個更直接的,如果我圖片的裁剪是系統自帶的,那麼我們還需要在onActivityResult中來取得最後裁剪的資料。根據自己的需求,想了一個程式碼量比較少的做法。可以自己寫一個BaseActivity,將圖片的擷取、圖片的獲得、呼叫圖片上傳的介面都寫在裡面。然後再寫一個工具類來實現圖片的上傳介面,最後在根據每種不同的情況來處理上傳成功,失敗以及取消的操作。
這篇文章主要涉及到知識:

  • 圖片的擷取和Bitmap的生成
  • 上傳檔案的協議以及實現
  • Native和H5複用

圖片的擷取和Bitmap的生成

對於系統的圖片的擷取

Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/*"); //開啟的是系統的相簿
intent.putExtra("crop", "true"); //使用系統自帶的裁剪
intent.putExtra("aspectX", 1); 
intent.putExtra
("aspectY", 1); //兩行表示裁剪寬高比為1:1 intent.putExtra("outputX", WIDTH); intent.putExtra("outputY", HEIGTH); //裁剪以後輸出的寬高值 intent.putExtra("return-data", true); // 返回得到的資料 startActivityForResult(intent, REQUSET_CODE);

然後就可以在onActivityResult(int requestCode,int responseCode,Intent data)中呼叫了。現在需要的是得到Bitmap的值。

if (data != null)
{
    Bitmap bitmap = null;
    if (data.hasExtra("data"))   // 首先會判斷data中是否存在"data"值
    {
        bitmap = data.getParcelableExtra("data");  // 存在就可以直接取了
    }
    else // 不存在的時候則是可以通過BitmapFactory來獲取bitmap的值
    {   
        BitmapFactory.Options options = new BitmapFactory.Options();
        InputStream is = null;
        try
        {
            is = getContentResolver().openInputStream(data.getData());
            bitmap = BitmapFactory.decodeStream(is, null, options);
        }
        catch (Exception e)
        {
        }
        finally
        {
            try
            {
                is.close();
            }
            catch (Exception e)
            {
            }
        }
}

上傳檔案的協議以及實現

分為兩個部分,請求頭和請求的正文。
Headers(請求標頭):
會有一個Content-Type欄位
Content-Type:multipart/form-data;boundary=一串每次請求不一樣的字串
TextView(請求正文):
請求正文裡面的資訊就複雜一點了。
第一行:
兩個減號+與請求頭一樣的字串+回車符號 (markdown中不支援寫減號)
第二行:
Content-Disposition: form-data; name=\”file\”+; filename=\” + filename + \” + 回車符號(這裡面的file的值根據你的後臺的介面而寫,filename則是你的上傳的影象所在的位置)
第三行:
Content-Type: image/jpeg+兩個回車符號(注意是兩個回車符號)
第四行:
將圖片轉化為流寫入。
第五行:
回車符號+與請求頭一樣的字串+兩個減號+回車符號
這樣所有的資訊寫好以後,就完成了圖片上傳的協議。接下來就是讀取後臺返回來的資訊解析出來就行。
使用HttpURLConnection實現。

URL url = new URL(uploadUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            // 允許input,output
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setUseCaches(false);
            // 設定請求頭的資訊
            conn.setRequestProperty("Connection", "Keep-Alive");
            // conn.setRequestProperty("Charset", "UTF-8");
            // conn.setRequestProperty("ENCTYPE", "multipart/form-data");
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("contentType", "utf-8");
            conn.setRequestProperty("Content-Transfer-Encoding", "binary");
            conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
            // 上傳的資訊,ds就是上傳檔案的流
            DataOutputStream ds = new DataOutputStream(conn.getOutputStream());
            // twoHyphens="--",boundary是前面請求頭中的相同的資訊,end="\r\n"
            // 第一行
            ds.writeBytes(twoHyphens + boundary + end);
            // 第二行
            ds.writeBytes("Content-Disposition: form-data; name=\"upload\"; filename=\"" + filename + "\"" + end);
            // 第三行
            ds.writeBytes("Content-Type: image/jpeg" + end + end);
            // 第四行,將Bitmap寫入輸出流,相當於將Bitmap上傳
            bitmap.compress(CompressFormat.JPEG, 100, ds);
            // 第五行
            ds.writeBytes(end+twoHyphens + boundary + twoHyphens + end);
            ds.flush();
            // 得到輸入流,即得到伺服器返回的資料
            InputStream is = conn.getInputStream();
            StringBuffer sb = new StringBuffer();
            String s = null;
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            while ((s = reader.readLine()) != null)
            {
                sb.append(s);
            }
            String result = sb.toString();

這樣就按照上面的協議完成了一個頭像的上傳。

Native和H5複用

現在的應用確實越來越多的APP跟H5緊密相連,因此也有越來越多的功能需要結合H5一起來實現。上傳頭像是一個很常見的功能。前面得到的結論是做一個公共的BaseActivity提供給NativeActivity和WebViewActivity來使用。然後在BaseActivity裡面寫上我們的圖片的擷取以及onActivityResult。

public class BaseActivity extends Activity
{

    public void pickUpPic()
    {
        // 上面操作中的系統的圖片的擷取
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        // 上面操作中的得到Bitmap的操作
    }
}

大概的框架就是這樣,只需要在NativeActivity和WebViewActivity相應的位置呼叫pickUpPic()就行了。
這樣就結束了?No.對於只是上傳頭像來說這樣或許是結束了,但是還有很多的問題還沒有考慮到。
1.請求的引數?
2.返回的結果,成功或失敗提示有差別嗎?
3.使用者在網速慢的情況下取消上傳的操作?
4.友好的提示使用者上傳的資訊?

請求引數
pickUpPic()作為唯一的入口,因此需要將所有的引數(例如:請求的頭像的寬高比、返回的大小、入口的型別等等)。因此需要全部寫在pickUpPic()裡面。

public void pickUpPic(Params parama)
{
    // 將帶入的引數設定一些資訊
    // 帶入的引數設定擷取的影象大小等等資訊
}

這樣就能滿足所有很多不同的需求了。設定的資訊也可以帶入onActivityResult中,在裡面呼叫上傳頭像介面時使用。

提示資訊
注意在UI執行緒中是無法處理網路操作的,我們現在的成功,失敗以及使用者的取消操作都是在子執行緒中操作的(也就是上傳的時候才知道成功失敗等等)。所以最先想到了使用一個Handler來操作,這樣的話,還需要在BaseActivity中加一個handler來處理我們返回來的資訊,同時主要到我們可能會有中不同的結果,success,fail,cancle。還有我們的NativeActivity個WebViewActivity兩個不同的Activity的操作也應該有很大的不同的。大概可以寫一個這樣的Handler。

private Handler handler = new Handler()
{

    @Override
    public void handleMessage(Message msg)
    {
        switch(msg.what)
        {
            case SUCCESS:
                // do somenthing
                listener.onSuccess(msg.obj);
                break;
            case FAIL:
                // do something
                listener.onFail(msg.obj);
                break;
            case CANCLE:
                // do something
                listener.onCancle(msg.obj);
                break;
            default:
                break;
        }

    }
}

只需要分別在NativeActivity和WebViewActivity中去實現不同的操作就行了。
然後,大概就是這樣了。

相關推薦

NativeH5情況頭像

最近的工作中接觸了一個小的功能,上傳頭像。上傳頭像是很多應用中的東西,描述下自己的應用。上傳頭像應用的地方: 1.最開始進入app的時候會提示註冊,然後就會呼叫。 2.成功的註冊完畢以後,可以在個人資訊裡面修改頭像。 3.在H5(某個WebView)中也可以修改

JavaPHP方式實現圖片到新浪微博的圖床

這幾天遇到一個需求,需要將圖片上傳到新浪微博的圖傳,研究了一下, 特此記錄1.模擬登陸,獲取cookie登入地址為:https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)&_=140313

django-將數據庫數據轉換成JSON格式(ORMSQL情況

user 展示 blog serialize 進行 項目開發 不管怎麽說 語句 spa 最近打算搞一個自動化運維平臺,所以在看Django的知識。 在實際項目開發中,遇到一個小問題:前後端發生數據交互主流采用的是JSON。前端傳數據到服務器端比較簡單,稍微麻煩的是服務器端傳

0004-用OpenCV實現影象平移的程式碼(分影象尺寸不變情況)

影象平移是啥東西就不用講了吧!需要注意的是影象平移有兩種,第一種是平移後圖像大小不變,這樣會損失影象的部分;第二種是平移後圖像大小變化,這樣原影象不會有損失。 直接上程式碼,大家看效果吧! 程式碼流程如下: 讀取影象→顯示原影象→呼叫自定義的函式translateTransform,作平移後

基於Spark2.0搭建Hive on Spark環境(Mysql本地遠端情況)

Hive的出現可以讓那些精通SQL技能、但是不熟悉MapReduce 、程式設計能力較弱與不擅長Java語言的使用者能夠在HDFS大規模資料集上很方便地利用SQL 語言查詢、彙總、分析資料,畢竟精通SQL語言的人要比精通Java語言的多得多。Hive適合處理離線非實時資料。h

JAVA args引數輸入 (CMD Eclipse情況)

先貼上測試程式碼: import java.util.*; public class test { public static void main(String args[]) { double r,pi=3.14d;

virtualBox中有線無線情況下centos虛擬機本地機互ping的方案

隨機 需要 保存 bubuko 可能 ping htm 兩個 方案   之前寫微信點餐系統的時候,剛開始是無線連接,然後每次進去虛擬機ip和本地ip都會改變,所以每次都需要配置一下nginx,還有本地的路徑。之後換有線連接,就研究了一下橋接模式有線情況下虛擬機靜態ip設置,

git-檔案狀態與前的準備工作

1.從遠端倉庫拷貝檔案至本地倉庫 git是一個版本控制系統,能夠任意切換提交的任意版本。它的優勢在於可以通過git clone url命令將遠端專案所有資料拷貝到本地(包括歷史版本),這樣即使遠端資料崩潰,也可以通過本地push後完全恢復。 #從github倉庫grit拷貝所有歷

多線程(二)啟動線程:需要不需要情況

void ise tel 線程 reg val adl 方法 委托 1、不需要傳參: class Program7 { private static void ExecuteInForeground() {

Android Mediaplayer error (1, -2147483648) Error (-38,0)解決方案(網路記載本地載入情況)

</pre>在專案中使用surfaceView 或者使用 mediaplayer + surface 來進行網路或者本地視訊播放,經常會遇到  error (1, -2147483648) Error (-38,0)這樣的錯誤,error value (1,

文件到FTP後換行格式發生變化?---記FTP的ASCIIBinary傳輸方式

1.問題由來 之前在公司搭建了一套內網到外網的FTP伺服器,以便內網開發人員上傳需要拷貝的檔案到外網,之前一直好好的,突然有一天發現上傳打包好的jar包之後在外網拷貝,開啟之後和內網的存在格式上的差別,如下圖: 上傳前: 外網下載後: 2.查詢解決 在網

poi匯入excel 根據檔名區分07(.xlsx)03 (.xls)情況進行解析

@RequestMapping(value = "/importMapping", method = RequestMethod.POST) @ResponseBody public void importPos( @RequestParam(value =

談談Shiro的原理及在SSMSpringBoot環境下的使用姿勢(篇)

本篇主要是記錄關於Shiro進行認證和授權的大致原理,然後是單獨在Shiro中實現認證和授權的方式。最後主要說明在傳統SSM的工程中使用Shiro和在SpringBoot的工程中使用Shiro進行整合。關於認證和授權,我這裡採用的是規範的RBAC許可權模型

將eclipse java程式打包成jar的總結(包括工程中沒有引用外部jar包有引用外部jar包情況

一.當eclispe java工程中沒有引用外部jar包時: 選中工程---->右鍵,Export...--->Java--->JAR file--->next-->填寫jar file的路徑及名稱-->next-->next-

AppStore時影象不能包含 alpha通道透明度解決辦法

因為這個每次找美工,有點麻煩,自己百度一下挺簡單的以後在也不用求人了,哈哈哈!1、用自帶瀏覽器開啟檔案—>匯出—>儲存時能看到是否有透明度。2、用PS開啟點選 影象—>模式—>索引顏色—>彈出來的框框裡面就有一個透明度的選擇,去掉對勾儲存就好了。

C#將Word轉換成PDF方法總結(基於OfficeWPS方案)

path ebs htm soft off ros exc 標題 總結  有時候,我們需要在線上預覽word文檔,當然我們可以用NPOI抽出Word中的文字和表格,然後顯示到網頁上面,但是這樣會丟失掉Word中原有的格式和圖片。一個比較好的辦法就是將word轉換成pdf,然

CSS3實現五子棋Web小遊戲,Canvas畫布DOM實現,並且具有悔棋撤銷悔棋功能。

posit oct padding 角色 sar pac osi fse ech 用Canvas實現五子棋的思路: 1、點擊棋盤,獲取坐標x,y,計算出棋子的二維數組坐標i和j, 2、棋子的實現,先arc一個圓,再填充漸變色。 3、下完一步棋後切換畫筆和角色。 4、贏法算法

跨域問題相關知識詳解(原生jsjquery方法實現jsonp跨域)

syn con 加載 developer 兩種方法 ray exe 編寫 分組 1、同源策略 同源策略(Same origin policy),它是由Netscape提出的一個著名的安全策略。同源策略是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽

移動端web頭像實現截取照片方向修復

trac 支持 隱藏 gre jquery 頭像 圖像加載 fun 僅供參考 實戰所需js包: jQuery、Jcrop、EXIF 本次實戰功能是在 app 中的 我的客戶 的客戶信息頁面中實現移動端web的頭像上傳,本次沒有實現圖像拖拽、縮放的觸摸事件功能(Jcro

【spring Boot】spring boot獲取資源文件的三方式【情況下】

不用 ash 12c ica pla bsp foreach set 使用 首先聲明一點,springboot獲取資源文件,需要看是   1》從spring boot默認的application.properties資源文件中獲取   2》還是從自定義的資源文件中獲取