okhttp完成頭像上傳
阿新 • • 發佈:2018-12-08
首先 點選頭像的時候 會彈出PopupWindow 所以寫好頭像的點選事件 之後 去寫一個pop的類
public class Pop implements View.OnClickListener{ private Context context = null; private PopupWindow popupWindow = null; private OnSelectPictureListener listener = null; public Pop(Context context, View popview, OnSelectPictureListener listener) { this.context = context; this.listener = listener; View view = LayoutInflater.from(context).inflate(R.layout.popwindow_layout, null); initView(view, popview); } private void initView(View view, View popview) { popupWindow = new PopupWindow(popview, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); popupWindow.setContentView(view); popupWindow.setBackgroundDrawable(new BitmapDrawable()); popupWindow.setOutsideTouchable(true); popupWindow.setFocusable(true); popupWindow.setOutsideTouchable(true); popupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); popupWindow.showAtLocation(popview, Gravity.BOTTOM, 0, 0);//show() view.findViewById(R.id.popup_select_take_photo).setOnClickListener(this); view.findViewById(R.id.popup_select_take_picture).setOnClickListener(this); view.findViewById(R.id.popup_select_take_cancel).setOnClickListener(this); } @Override public void onClick(View view) { int i = view.getId(); if (i == R.id.popup_select_take_photo) { listener.onTakePhoto(); } else if (i == R.id.popup_select_take_picture) { listener.onSelectPicture(); } else if (i == R.id.popup_select_take_cancel) { listener.onCancel(); } //點選完了之後隱藏 popupWindow.dismiss(); } //點選介面 public interface OnSelectPictureListener { /** * 拍攝 */ void onTakePhoto(); /** * 從相簿選擇 */ void onSelectPicture(); /** * 取消 */ void onCancel(); } }
上面類中所用到的佈局檔案
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_above="@+id/share_main_line" android:layout_margin="10dp" android:background="@drawable/pop_bag" android:orientation="vertical"> <TextView android:id="@+id/popup_select_take_photo" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:padding="10dp" android:text="拍照" android:textColor="#333333" android:textSize="16sp" /> <View android:layout_width="match_parent" android:layout_height="2dp" android:layout_above="@+id/popup_select_take_cancel" android:background="#ebebeb" /> <TextView android:id="@+id/popup_select_take_picture" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:padding="10dp" android:text="從手機相簿選擇" android:textColor="#333333" android:textSize="16sp" /> </LinearLayout> <View android:id="@+id/share_main_line" android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginLeft="19dp" android:layout_marginRight="19dp" android:layout_above="@+id/popup_select_take_cancel" android:background="#ebebeb" /> <TextView android:id="@+id/popup_select_take_cancel" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:background="@drawable/pop_bag" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:gravity="center" android:padding="10dp" android:text="取消" android:textColor="#333" android:textSize="16sp" /> </RelativeLayout>
在這個佈局中又用到了 一個自定義shape和一個半透明的顏色
#7f000000 半透明顏色
<shape xmlns:android="http://schemas.android.com/apk/res/android"
>
<solid android:color="#ffffff"
/>
<corners android:radius="10dp"/>
</shape>
pop 建立完了之後 繼續寫頭像的點選事件
//彈出PopupWindow private void tanpop() { //先去建立一個pop的工具類 //new 呼叫pop工具類 括號裡傳上下文和本頁面佈局整體的id new 介面提示 new Pop(context, chage_pop, new Pop.OnSelectPictureListener() { @Override public void onTakePhoto() { //new 意圖跳轉相機 mediastore .相機 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //意圖傳值mediastor .ex ,uri.fromfile括號new檔案傳獲取系統路徑傳檔名 intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(Environment.getExternalStorageDirectory(), pic))); //回撥方法跳轉相機強轉本頁面0 回撥方法寫在Activity 呼叫方法生成過來 ((LoginLastActivity) context).startActivityForResult(intent, 1); } @Override public void onSelectPicture() { //new 意圖跳轉相簿 Intent intent = new Intent(Intent.ACTION_PICK, null); //意圖設定dataAnd Type mediastore images.media .ex ,imgae/*萬用字元 intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*"); //帶值跳轉1 ((LoginLastActivity) context).startActivityForResult(intent, 0); } @Override public void onCancel() { //取消方法不用寫 } }); }
pop的類中有三個介面 分別是相機相簿取消 上面 已經寫好了實現介面
和activity的帶值跳轉 下面該做的是 寫activity的回撥方法 因為這裡用的是themvp 所以需要去該頁面的Activity中寫onActivityResult
//回撥方法
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//判讀requestcode
switch (requestCode){
case 0:
//當時0的時候呼叫方法生成到persenter 傳resultcode 和data相機回撥
delegate.onCode0(resultCode,data);
break;
case 1:
//當時0的時候呼叫方法生成到persenter 傳resultcode 相簿回撥
delegate.onCode1(resultCode);
break;
case 2:
//當時0的時候呼叫方法生成到persenter 傳rdata 裁剪回撥
delegate.onCode2(data);
break;
}
}
persenter裡的具體實現方法
//生成過來的方法相機
public void onCode0(int resultCode, Intent data) {
//判斷code==RESULT _OK
if (resultCode == RESULT_OK) {
//呼叫裁剪的方法
cropPhoto(data.getData());
}
}
// 相簿回撥
public void onCode1(int resultCode) {
//判斷code==RESULT _OK
if (resultCode == RESULT_OK) {
//new 檔案
File file = new File(Environment.getExternalStorageDirectory() + "/head.png");
//呼叫裁剪方法傳file URI 呼叫filefromfile
cropPhoto(Uri.fromFile(file));
}
}
//裁剪回撥方法
public void onCode2(Intent data) {
// Toast.makeText(context,"哈哈"+data,Toast.LENGTH_SHORT).show();
//先判斷data非空
if (data != null) {
//data 獲取extras 返回值
Bundle extras = data.getExtras();
//判斷等於空直接返回
if (extras == null) {
return;
}
//extras .獲取p傳引號data返回值head 提上去Bitmap型別
head = extras.getParcelable("data");
//判斷判斷head非空
if (head != null) {
//給頭像設定imagebitmap 傳head
// last_tou.setImageBitmap(head);
// //上面封裝的固定路徑+引號/+pic圖片名
String fileNname = path + "/" + pic;
// 呼叫儲存sd卡的方法 傳head
setPicToView(head);
//呼叫ok上傳 傳個filename
Log.i("上傳的時候",fileNname);
uploadImage(fileNname);
//重新儲存頭像的方法
setIcon();
}
}
}
在回撥具體方法裡 又用到了 裁剪 、儲存sd卡 、okhttp上傳頭像 、重新儲存頭像的方法
裁剪
//裁剪回撥方法
public void onCode2(Intent data) {
// Toast.makeText(context,"哈哈"+data,Toast.LENGTH_SHORT).show();
//先判斷data非空
if (data != null) {
//data 獲取extras 返回值
Bundle extras = data.getExtras();
//判斷等於空直接返回
if (extras == null) {
return;
}
//extras .獲取p傳引號data返回值head 提上去Bitmap型別
head = extras.getParcelable("data");
//判斷判斷head非空
if (head != null) {
//給頭像設定imagebitmap 傳head
// last_tou.setImageBitmap(head);
// //上面封裝的固定路徑+引號/+pic圖片名
String fileNname = path + "/" + pic;
// 呼叫儲存sd卡的方法 傳head
setPicToView(head);
//呼叫ok上傳 傳個filename
Log.i("上傳的時候",fileNname);
uploadImage(fileNname);
//重新儲存頭像的方法
setIcon();
}
}
}
儲存sd卡
//儲存sd卡的方法
private void setPicToView(Bitmap mBitmap) {
String sdStatus = Environment.getExternalStorageState();
if (!sdStatus.equals(Environment.MEDIA_MOUNTED)) { // 檢測sd是否可用
return;
}
FileOutputStream b = null;
File file = new File(path);
file.mkdirs();// 建立資料夾
String fileName = path + "/head.png";//圖片名字
try {
b = new FileOutputStream(fileName);
mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, b);// 把資料寫入檔案
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
try {
//關閉流
b.flush();
b.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
okhttp上傳頭像
如果需要換網址 記得在new Request.Builder()的裡面更換網址
//okhttp上傳頭像
private void uploadImage(String path) {
MediaType mediaType = MediaType.parse("multipart/form-data; charset=utf-8");
OkHttpClient mOkHttpClent = new OkHttpClient();
File file = new File(path);
MultipartBody.Builder builder = new MultipartBody.Builder()
.setType(mediaType)
.addFormDataPart("file", pic,
RequestBody.create(MediaType.parse("image/png"), file))
.addFormDataPart("uid", uid);
RequestBody requestBody = builder.build();
Request request = new Request.Builder()
.url("網址")
.post(requestBody)
.build();
Call call = mOkHttpClent.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, final IOException e) {
((LoginLastActivity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
Log.i("TAG", e.getMessage());
Toast.makeText(context, "失敗", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onResponse(Call call, Response response) throws IOException {
((LoginLastActivity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(context, "更換成功", Toast.LENGTH_SHORT).show();
}
});
}
});
}
重新儲存頭像的方法
這個方法 就是 又重新請求了一次服務端 用來更新本地sp中快取的頭像
順便給本頁面的頭像控制元件賦值
//重新儲存頭像的方法
private void setIcon() {
//傳一個uid就可以
HashMap<String, String> map = new HashMap<>();
map.put("uid", uid);
RetrofitUtils.getRetrofitUtils().get(url, map).result(new RetrofitUtils.RetrofitListener() {
@Override
public void success(String s) {
//解析讀取出來的s
UserBean userBean = new Gson().fromJson(s, UserBean.class);
//獲取頭像
//儲存到sp裡面
//往sp裡存東西 暱稱寫在下面判斷和icon to字串 或者加個空字串
SharedPreferences sp = context.getSharedPreferences("config", Context.MODE_PRIVATE);
sp.edit().putString("icon",userBean.getData().getIcon()).commit();
Log.i("儲存的圖",userBean.getData().getIcon());
//重新給圖片賦值
String s1 = path + "/" + pic;
last_tou.setImageBitmap(BitmapFactory.decodeFile(s1));
}
@Override
public void fail() {
//網路錯誤
Toast.makeText(context,"網路竟然崩潰了",Toast.LENGTH_SHORT).show();
}
});
}
在以上的方法中 用到的幾個封裝變數
private String pic = "head.png";
private Bitmap head;
//封裝一個固定路徑
private static String path = "/sdcard/myHead/";//sd路徑
登陸成功的uid 在this.uid=uid在Activity onResume方法裡面更新資料生成在persenter的方法裡獲取uid提上去
private String uid;
//獲取使用者資訊的介面
private String url = "網址";