1. 程式人生 > >okhttp完成頭像上傳

okhttp完成頭像上傳

首先 點選頭像的時候 會彈出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 = "網址";