Android圖片上傳(頭像裁切+原圖原樣)
先看一下效果圖:
(一)頭像裁切、上傳伺服器(效果圖)
一般都是有圓形顯示頭像的,這裡我自定義了一個ImageView,頁面很乾淨但是看著很上檔次吧!
點選頭像從底部彈出一個對話方塊,提示使用者頭像來自相機或者相簿,這都是常規流程。
上傳完成後預設的“程式設計師頭像”換成了萌妹子
(二)普通圖片上傳伺服器(效果圖)
模仿QQ空間發動態的佈局隨意捏造一個介面出來
點選新增圖片從底部彈出一個對話方塊,提示使用者圖片來自相機或者相簿,這也都是常規流程。
上傳過程中,有可能圖片很大,顯示一個進度圈(其實頭像上傳也有,只是檔案小,還沒顯示就上傳完成了)
上傳完成後把剛才的照片亮出來顯示到按鈕的地方,當然大家根據需要還可以自己擴充套件(比如長按抖動出現刪除、繼續新增N張等等)。
下面簡單鋪一下程式碼:
(一)頭像裁切、上傳伺服器(程式碼)
這裡上邊的按鈕是頭像的點選事件,彈出底部的頭像選擇框,下邊的按鈕跳到下個頁面,進行原圖上傳。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@Override public
void
onClick(View v) { switch
(v.getId()) { case
R.id.avatarImg: //
更換頭像點選事件 menuWindow
= new
SelectPicPopupWindow(mContext, itemsOnClick); menuWindow.showAtLocation(findViewById(R.id.mainLayout),
Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL,
0 ,
0 );
break ; case
R.id.loginBtn: //登入按鈕跳轉事件 startActivity( new
Intent(mContext, UploadActivity. class )); break ; default : break ; } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
//為彈出視窗實現監聽類
private
OnClickListener itemsOnClick = new
OnClickListener() { @Override public
void
onClick(View v) { menuWindow.dismiss(); switch
(v.getId()) { //
拍照 case
R.id.takePhotoBtn: Intent
takeIntent = new
Intent(MediaStore.ACTION_IMAGE_CAPTURE); //下面這句指定呼叫相機拍照後的照片儲存的路徑 takeIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile( new
File(Environment.getExternalStorageDirectory(), IMAGE_FILE_NAME))); startActivityForResult(takeIntent,
REQUESTCODE_TAKE); break ; //
相簿選擇圖片 case
R.id.pickPhotoBtn: Intent
pickIntent = new
Intent(Intent.ACTION_PICK, null ); //
如果朋友們要限制上傳到伺服器的圖片型別時可以直接寫如:image/jpeg 、 image/png等的型別 pickIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
image/*); startActivityForResult(pickIntent,
REQUESTCODE_PICK); break ; default : break ; } } }; |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
@Override public
void
onActivityResult( int
requestCode, int
resultCode, Intent data) { switch
(requestCode) { case
REQUESTCODE_PICK: //
直接從相簿獲取 try
{ startPhotoZoom(data.getData()); }
catch
(NullPointerException e) { e.printStackTrace(); //
使用者點選取消操作 } break ; case
REQUESTCODE_TAKE: //
呼叫相機拍照 File
temp = new
File(Environment.getExternalStorageDirectory() + / + IMAGE_FILE_NAME); startPhotoZoom(Uri.fromFile(temp)); break ; case
REQUESTCODE_CUTTING: //
取得裁剪後的圖片 if
(data != null )
{ setPicToView(data); } break ; } super .onActivityResult(requestCode,
resultCode, data); } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
/** *
裁剪圖片方法實現 *
@param uri */ public
void
startPhotoZoom(Uri uri) { Intent
intent = new
Intent(com.android.camera.action.CROP); intent.setDataAndType(uri,
image /*); //
crop=true是設定在開啟的Intent中設定顯示的VIEW可裁剪 intent.putExtra(crop,
true); //
aspectX aspectY 是寬高的比例 intent.putExtra(aspectX,
1); intent.putExtra(aspectY,
1); //
outputX outputY 是裁剪圖片寬高 intent.putExtra(outputX,
300); intent.putExtra(outputY,
300); intent.putExtra(return-data,
true); startActivityForResult(intent,
REQUESTCODE_CUTTING); } /** *
儲存裁剪之後的圖片資料 *
@param picdata */ private
void
setPicToView(Intent picdata) { Bundle
extras = picdata.getExtras(); if
(extras != null )
{ //
取得SDCard圖片路徑做顯示 Bitmap
photo = extras.getParcelable(data); Drawable
drawable = new
BitmapDrawable( null ,
photo); urlpath
= FileUtil.saveFile(mContext, temphead.jpg, photo); avatarImg.setImageDrawable(drawable); //
新執行緒後臺上傳服務端 pd
= ProgressDialog.show(mContext, null ,
正在上傳圖片,請稍候...); new
Thread(uploadImageRunnable).start(); } } /** *
使用HttpUrlConnection模擬post表單進行檔案 *
上傳平時很少使用,比較麻煩 *
原理是: 分析檔案上傳的資料格式,然後根據格式構造相應的傳送給伺服器的字串。 */ Runnable
uploadImageRunnable = new
Runnable() { @Override public
void
run() { if (TextUtils.isEmpty(imgUrl)){ Toast.makeText(mContext,
還沒有設定上傳伺服器的路徑!, Toast.LENGTH_SHORT).show(); return ; } Map<string,
string= "" >
textParams = new
HashMap<string, string= "" >(); Map<string,
file= "" >
fileparams = new
HashMap<string, file= "" >(); try
{ //
建立一個URL物件 URL
url = new
URL(imgUrl); textParams
= new
HashMap<string, string= "" >(); fileparams
= new
HashMap<string, file= "" >(); //
要上傳的圖片檔案 File
file = new
File(urlpath); fileparams.put(image,
file); //
利用HttpURLConnection物件從網路中獲取網頁資料 HttpURLConnection
conn = (HttpURLConnection) url.openConnection(); //
設定連線超時(記得設定連線超時,如果網路不好,Android系統在超過預設時間會收回資源中斷操作) conn.setConnectTimeout( 5000 ); //
設定允許輸出(傳送POST請求必須設定允許輸出) conn.setDoOutput( true ); //
設定使用POST的方式傳送 conn.setRequestMethod(POST); //
設定不使用快取(容易出現問題) conn.setUseCaches( false ); conn.setRequestProperty(Charset,
UTF- 8 ); //設定編碼
//
在開始用HttpURLConnection物件的setRequestProperty()設定,就是生成HTML檔案頭 conn.setRequestProperty(ser-Agent,
Fiddler); //
設定contentType conn.setRequestProperty(Content-Type,
multipart/form-data; boundary= + NetUtil.BOUNDARY); OutputStream
os = conn.getOutputStream(); DataOutputStream
ds = new
DataOutputStream(os); NetUtil.writeStringParams(textParams,
ds); NetUtil.writeFileParams(fileparams,
ds); NetUtil.paramsEnd(ds); //
對檔案流操作完,要記得及時關閉 os.close(); //
伺服器返回的響應嗎 int
code = conn.getResponseCode(); //
從Internet獲取網頁,傳送請求,將網頁以流的形式讀回來 //
對響應碼進行判斷 if
(code == 200 )
{ //
返回的響應碼200,是成功 //
得到網路返回的輸入流 InputStream
is = conn.getInputStream(); resultStr
= NetUtil.readString(is); }
else
{ Toast.makeText(mContext,
請求URL失敗!, Toast.LENGTH_SHORT).show(); } }
catch
(Exception e) { e.printStackTrace(); } handler.sendEmptyMessage( 0 ); //
執行耗時的方法之後傳送消給handler } }; Handler
handler = new
Handler( new
Handler.Callback() { @Override public
boolean
handleMessage(Message msg) { switch
(msg.what) { case
0 : pd.dismiss(); try
{ //
返回資料示例,根據需求和後臺資料靈活處理 //
{status:1,statusMessage:上傳成功,imageUrl:http://120.24.219.49/726287_temphead.jpg} JSONObject
jsonObject = new
JSONObject(resultStr); //
服務端以字串“1”作為操作成功標記 if
(jsonObject.optString(status).equals( 1 ))
{ BitmapFactory.Options
option = new
BitmapFactory.Options(); //
壓縮圖片:表示縮圖大小為原始圖片大小的幾分之一,1為原圖,3為三分之一 option.inSampleSize
= 1 ; //
服務端返回的JsonObject物件中提取到圖片的網路URL路徑 String
imageUrl = jsonObject.optString(imageUrl); Toast.makeText(mContext,
imageUrl, Toast.LENGTH_SHORT).show(); } else { Toast.makeText(mContext,
jsonObject.optString(statusMessage), Toast.LENGTH_SHORT).show(); } }
catch
(JSONException e) { e.printStackTrace(); } break ; default : break ; } return
false ; } });</string,></string,></string,></string,></string,></string,> |
(二)普通圖片上傳伺服器(程式碼)
直接從這裡開始,和頭像那裡基本沒什麼區別,我把拍照什麼的單獨抽出了方法,思路更清晰
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//為彈出視窗實現監聽類
private
OnClickListener itemsOnClick = new
OnClickListener() { @Override public
void
onClick(View v) { //
隱藏彈出視窗 menuWindow.dismiss(); switch
(v.getId()) { case
R.id.takePhotoBtn: //
拍照 takePhoto(); break ; case
R.id.pickPhotoBtn: //
相簿選擇圖片 pickPhoto(); break ; case
R.id.cancelBtn: //
取消 break ; default : break ; } } }; |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
/** *
拍照獲取圖片 */ private
void
takePhoto() { //
執行拍照前,應該先判斷SD卡是否存在 String
SDState = Environment.getExternalStorageState(); if
(SDState.equals(Environment.MEDIA_MOUNTED)) { Intent
intent = new
Intent(MediaStore.ACTION_IMAGE_CAPTURE); /*** *
需要說明一下,以下操作使用照相機拍照,拍照後的圖片會存放在相簿中的 *
這裡使用的這種方式有一個好處就是獲取的圖片是拍照後的原圖 *
如果不使用ContentValues存放照片路徑的話,拍照後獲取的圖片為縮圖不清晰 */ ContentValues
values = new
ContentValues(); photoUri
= getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT,
photoUri); startActivityForResult(intent,
SELECT_PIC_BY_TACK_PHOTO); }
else
{ Toast.makeText( this ,
記憶體卡不存在, Toast.LENGTH_LONG).show(); } } /*** *
從相簿中取圖片 */ private
void
pickPhoto() { Intent
intent = new
Intent(); //
如果要限制上傳到伺服器的圖片型別時可以直接寫如:image/jpeg 、 image/png等的型別 intent.setType(image/*); intent.setAction(Intent.ACTION_GET_CONTENT); startActivityForResult(intent,
SELECT_PIC_BY_PICK_PHOTO); } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
@Override protected
void
onActivityResult( int
requestCode, int
resultCode, Intent data) { //
點選取消按鈕 if (resultCode
== RESULT_CANCELED){ return ; } //
可以使用同一個方法,這裡分開寫為了防止以後擴充套件不同的需求 switch
(requestCode) { case
SELECT_PIC_BY_PICK_PHOTO: //
如果是直接從相簿獲取 doPhoto(requestCode,
data); break ; case
SELECT_PIC_BY_TACK_PHOTO: //
如果是呼叫相機拍照時 doPhoto(requestCode,
data); break ; } super .onActivityResult(requestCode,
resultCode, data); } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
/** *
選擇圖片後,獲取圖片的路徑 *
*
@param requestCode *
@param data */ private
void
doPhoto( int
requestCode, Intent data) { //
從相簿取圖片,有些手機有異常情況,請注意 if
(requestCode == SELECT_PIC_BY_PICK_PHOTO) { if
(data == null )
{ Toast.makeText( this ,
選擇圖片檔案出錯, Toast.LENGTH_LONG).show(); return ; } photoUri
= data.getData(); if
(photoUri == null )
{ Toast.makeText( this ,
選擇圖片檔案出錯, Toast.LENGTH_LONG).show(); return ; } } String[]
pojo = { MediaColumns.DATA }; //
The method managedQuery() from the type Activity is deprecated //Cursor
cursor = managedQuery(photoUri, pojo, null, null, null); Cursor
cursor = mContext.getContentResolver().query(photoUri, pojo, null ,
null ,
null ); if
(cursor != null )
{ int
columnIndex = cursor.getColumnIndexOrThrow(pojo[ 0 ]); cursor.moveToFirst(); picPath
= cursor.getString(columnIndex); //
4.0以上的版本會自動關閉 (4.0--14;; 4.0.3--15) if
(Integer.parseInt(Build.VERSION.SDK) < 14 )
{ cursor.close(); } } //
如果圖片符合要求將其上傳到伺服器 if
(picPath != null
&& ( picPath.endsWith(.png) || picPath.endsWith(.PNG)
|| picPath.endsWith(.jpg)
|| picPath.endsWith(.JPG)))
{ BitmapFactory.Options
option = new
BitmapFactory.Options(); //
壓縮圖片:表示縮圖大小為原始圖片大小的幾分之一,1為原圖 option.inSampleSize
= 1 ; //
根據圖片的SDCard路徑讀出Bitmap Bitmap
bm = BitmapFactory.decodeFile(picPath, option); //
顯示在圖片控制元件上 picImg.setImageBitmap(bm); pd
= ProgressDialog.show(mContext, null ,
正在上傳圖片,請稍候...); new
Thread(uploadImageRunnable).start(); }
else
{ Toast.makeText( this ,
選擇圖片檔案不正確, Toast.LENGTH_LONG).show(); } } /** *
使用HttpUrlConnection模擬post表單進行檔案 *
上傳平時很少使用,比較麻煩 *
原理是: 分析檔案上傳的資料格式,然後根據格式構造相應的傳送給伺服器的字串。 */ Runnable
uploadImageRunnable = new
Runnable() { @Override public
void
run() { if (TextUtils.isEmpty(imgUrl)){ Toast.makeText(mContext,
還沒有設定上傳伺服器的路徑!, Toast.LENGTH_SHORT).show(); return ; } Map<string,
string= "" >
textParams = new
HashMap<string, string= "" >(); Map<string,
file= "" >
fileparams = new
HashMap<string, file= "" >(); try
{ //
建立一個URL物件 URL
url = new
URL(imgUrl); textParams
= new
HashMap<string, string= "" >(); fileparams
= new
HashMap<string, file= "" >(); //
要上傳的圖片檔案 File
file = new
File(picPath); fileparams.put(image,
file); //
利用HttpURLConnection物件從網路中獲取網頁資料 HttpURLConnection
conn = (HttpURLConnection) url.openConnection(); //
設定連線超時(記得設定連線超時,如果網路不好,Android系統在超過預設時間會收回資源中斷操作) conn.setConnectTimeout( 5000 ); //
設定允許輸出(傳送POST請求必須設定允許輸出) conn.setDoOutput( true ); //
設定使用POST的方式傳送 conn.setRequestMethod(POST); //
設定不使用快取(容易出現問題) conn.setUseCaches( false ); //
在開始用HttpURLConnection物件的setRequestProperty()設定,就是生成HTML檔案頭 conn.setRequestProperty(ser-Agent,
Fiddler); //
設定contentType conn.setRequestProperty(Content-Type,
multipart/form-data; boundary= + NetUtil.BOUNDARY); OutputStream
os = conn.getOutputStream(); DataOutputStream
ds = new
DataOutputStream(os); NetUtil.writeStringParams(textParams,
ds); NetUtil.writeFileParams(fileparams,
ds); NetUtil.paramsEnd(ds); //
對檔案流操作完,要記得及時關閉 os.close(); //
伺服器返回的響應嗎 int
code = conn.getResponseCode(); //
從Internet獲取網頁,傳送請求,將網頁以流的形式讀回來 //
對響應碼進行判斷 if
(code == 200 )
{ //
返回的響應碼200,是成功 //
得到網路返回的輸入流 InputStream
is = conn.getInputStream(); resultStr
= NetUtil.readString(is); }
else
{ Toast.makeText(mContext,
請求URL失敗!, Toast.LENGTH_SHORT).show(); } }
catch
(Exception e) { e.printStackTrace(); } handler.sendEmptyMessage( 0 ); //
執行耗時的方法之後傳送消給handler } }; Handler
handler = new
Handler( new
Handler.Callback() { @Override public
boolean
handleMessage(Message msg) { switch
(msg.what) { case
0 : pd.dismiss(); try
{ JSONObject
jsonObject = new
JSONObject(resultStr); //
服務端以字串“1”作為操作成功標記 if
(jsonObject.optString(status).equals( 1 ))
{ //
用於拼接釋出說說時用到的圖片路徑 //
服務端返回的JsonObject物件中提取到圖片的網路URL路徑 String
imageUrl = jsonObject.optString(imageUrl); //
獲取快取中的圖片路徑 Toast.makeText(mContext,
imageUrl, Toast.LENGTH_SHORT).show(); }
else
{ Toast.makeText(mContext,
jsonObject.optString(statusMessage), Toast.LENGTH_SHORT).show(); } }
catch
(JSONException e) { e.printStackTrace(); } break ; default : break ; } return
false ; } });</string,></string,></string,></string,></string,></string,> |
相關文章
- laravel圖片/頭像上傳通用方法Laravel
- java,springboot + thymeleaf 上傳圖片、刪除圖片到伺服器、本地,壓縮圖片上傳(有些圖片會失真),原圖上傳JavaSpring Boot伺服器
- [Laravel Admin] 檔案 / 圖片上傳功能之擴充套件 -- 上傳新圖且保留原圖Laravel套件
- Android本地圖片上傳(拍照+相簿)Android地圖
- WebRTC從攝像頭獲取圖片傳入canvasWebCanvas
- 上傳圖片
- 圖片上傳及圖片處理
- Android圖片Base64加密+文字上傳Android加密
- 1小時搞定cropper.js製作頭像/圖片上傳、裁剪、併傳送至後端JS後端
- 擷取圖片生成頭像外掛
- 仿釘釘頭像(有頭像顯示圖片拼接,無圖顯示暱稱)
- electron上傳圖片
- 上傳圖片jsJS
- 裁剪上傳圖片
- ugui 縮放圖片使圖片的四個角和四邊保持原樣UGUI
- 上傳圖片 以及做成縮圖
- Android圖片上傳到阿里雲OSS小案例Android阿里
- vue 上傳圖片進行壓縮圖片Vue
- Laravel 後臺擴充套件包 Laravel-admin 檔案 / 圖片上傳功能之擴充 -- 實現上傳新圖且保留原圖Laravel套件
- 圖片 base64 編碼還原成圖片
- 多圖片formpost上傳ORM
- spring boot 圖片上傳Spring Boot
- 測試圖片上傳
- input file圖片上傳
- 本地Markdown上傳圖片
- .Net 圖片縮圖上傳通用方法
- PbootCMS上傳圖片變模糊、上傳圖片尺寸受限的解決方案boot
- Ueditor 上傳圖片自動新增水印(只能上傳圖片,上傳檔案報錯)
- 圖片等比例縮放裁切詳解
- 自定義上傳圖片拼圖遊戲遊戲
- js上傳圖片壓縮JS
- 圖片上傳方案詳解
- vue圖片預覽上傳Vue
- springboot+wangEditor圖片上傳Spring Boot
- js圖片上傳預覽JS
- 通用mapper、圖片上傳、nginxAPPNginx
- Laravel 使用 FastDFS 上傳圖片LaravelAST
- koa 圖片上傳詳解
- wangEditor上傳圖片問題