Android 上傳圖片到服務器 okhttp一


 【目錄】

 (一)上傳圖片到服務器一 ---------------------------------Android代碼

 (二)上傳圖片到服務器二---------------------------------Android 系統7.0以上調用相機兼容問題

 (三)上傳圖片到服務器三 -----------------------------------后台服務器代碼

 

一、相關知識

①Android權限申請

②網絡訪問框架OKHttp

③內存溢出問題:圖片壓縮

④Android 系統7.0以上調用系統相機無效

⑤有關圖片上傳過程中遇到的內存溢出問題

 

二、效果展示

 

 

二、代碼

①HTML

 1          <LinearLayout  2                 android:layout_width="match_parent"
 3  android:layout_height="wrap_content"
 4  android:orientation="vertical"
 5  android:background="@color/white"
 6                 >
 7                 <android.support.v7.widget.RecyclerView  8                     android:id="@+id/rvPic"
 9  android:layout_width="wrap_content"
10  android:layout_height="match_parent"
11  android:layout_gravity="center_horizontal">
12 
13                 </android.support.v7.widget.RecyclerView>
14 
15                 <TextView 16                     android:id="@+id/tvNum"
17  android:layout_width="wrap_content"
18  android:layout_height="wrap_content"
19  android:text="0/8"
20  android:textColor="#666666"
21  android:layout_gravity="right|bottom"
22  android:paddingRight="@dimen/dp_10"/>
23 
24 
25             </LinearLayout>
26      <Button 27 
28         android:id="@+id/btn_Enter"
29  android:layout_width="match_parent"
30  android:layout_height="@dimen/dp_45"
31  android:layout_alignParentBottom="true"
32  android:background="@drawable/selecter_button"
33  android:text="確認上傳"
34  android:textColor="@color/inButtonText"
35  android:textSize="@dimen/dp_18" />

 

 

②Java代碼

<基本功能>

 實體類

 1 public class LoadFileVo {  2 
 3  File file;  4 
 5     int pg; //圖片下方的進度條
 6 
 7     boolean isUpload = false; //標識該文件是否上傳
 8 
 9  Bitmap bitmap; 10 
11     public Bitmap getBitmap() { 12         return bitmap; 13  } 14 
15     public void setBitmap(Bitmap bitmap) { 16         this.bitmap = bitmap; 17  } 18 
19     public boolean isUpload() { 20         return isUpload; 21  } 22 
23     public void setUpload(boolean upload) { 24         isUpload = upload; 25  } 26 
27     public LoadFileVo() { 28  } 29 
30     public LoadFileVo(File file, int pg) { 31         this.file = file; 32         this.pg = pg; 33  } 34 
35     public LoadFileVo(File file, boolean isUpload, int pg,Bitmap bitmap) { 36         this.file = file; 37         this.pg = pg; 38         this.isUpload = isUpload; 39         this.bitmap = bitmap; 40  } 41 
42     public File getFile() { 43         return file; 44  } 45 
46     public void setFile(File file) { 47         this.file = file; 48  } 49 
50     public int getPg() { 51         return pg; 52  } 53 
54     public void setPg(int pg) { 55         this.pg = pg; 56  } 57 }

 

適配器

 1 /*
 2  *Create By 小群子 2018/12/10  3  */
 4 
 5 public class LoadPicAdapter extends RecyclerView.Adapter<LoadPicAdapter.MyViewHolder> {  6 
 7  Context context;  8     List<LoadFileVo> fileList = null;  9  View view;  10     int picNum = 8;//列表的圖片個數最大值
 11 
 12     public LoadPicAdapter(Context context, List<LoadFileVo> fileList) {  13         this.context = context;  14         this.fileList = fileList;  15  }  16 
 17     public LoadPicAdapter(Context context, List<LoadFileVo> fileList, int picNum) {  18         this.context = context;  19         this.fileList = fileList;  20         this.picNum = picNum;  21  }  22 
 23     public interface OnItemClickListener {  24         void click(View view, int positon);  25 
 26         void del(View view);  27  }  28 
 29  OnItemClickListener listener;  30 
 31     public void setListener(OnItemClickListener listener) {  32         this.listener = listener;  33  }  34 
 35  @Override  36     public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {  37 
 38         view = LayoutInflater.from(context).inflate(R.layout.load_item_pic, parent, false);  39         return new MyViewHolder(view);  40  }  41 
 42  @Override  43     public void onBindViewHolder(MyViewHolder holder, final int position) {  44 
 45         //通過默認設置第一個為空文件為添加退保,且在文件個數小於最大限制值的情況。當圖片個數等於最大限制值,第一個則不是添加按鈕
 46         if (position == 0&&fileList.get(position).getBitmap()==null) {  47             holder.ivPic.setImageResource(R.drawable.addpic);//加號圖片
 48             holder.ivPic.setOnClickListener(new View.OnClickListener() {  49  @Override  50                 public void onClick(View view) {  51  listener.click(view, position);  52  }  53  });  54  holder.ivDel.setVisibility(View.INVISIBLE);  55  holder.bg_progressbar.setVisibility(View.GONE);  56 
 57         } else {  58 // Uri uri = Uri.parse(fileList.get(position).getFile().getPath());  59 // holder.ivPic.setImageURI(uri);
 60 
 61  holder.ivPic.setImageBitmap(fileList.get(position).getBitmap());  62             //使用壓縮后的圖片進行填充到界面上  63            
64 65 66 holder.ivDel.setVisibility(View.VISIBLE); 67 holder.bg_progressbar.setVisibility(View.VISIBLE); 68 holder.bg_progressbar.setProgress(fileList.get(position).getPg()); 69 } 70 71 72 holder.ivDel.setOnClickListener(new View.OnClickListener() { 73 @Override 74 public void onClick(View view) { 75 //判斷圖片是否上傳,上傳后將無法刪除 76 if (fileList.get(position).isUpload()) { 77 Toast.makeText(context, "該圖片已上傳!", Toast.LENGTH_SHORT).show(); 78 } else { 79 fileList.remove(position); 80 if (fileList.size()==picNum-1&&fileList.get(0).getBitmap()!=null){ 81 fileList.add(0,new LoadFileVo()); 82 }//如果數量達到最大數時,前面的加號去掉,然后再減去時,則添加前面的加號 83 notifyDataSetChanged(); 84 if (listener!=null){ 85 listener.del(view);//傳遞接口,計算圖片個數顯示在界面中 86 } 87 88 } 89 } 90 }); 91 92 93 } 94 95 @Override 96 public int getItemCount() { 97 return fileList.size(); 98 } 99 100 101 static class MyViewHolder extends RecyclerView.ViewHolder { 102 @BindView(R.id.ivPic) 103 ImageView ivPic; 104 @BindView(R.id.ivDel) 105 ImageView ivDel; 106 @BindView(R.id.bg_progressbar) 107 ProgressBar bg_progressbar; 108 109 View view; 110 111 112 MyViewHolder(View view) { 113 super(view); 114 this.view = view; 115 ButterKnife.bind(this, view); 116 } 117 } 118 }

 

item 布局//布局自行優化

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     android:layout_width="@dimen/dp_110"
 3     android:layout_height="@dimen/dp_115"
 4 
 5     >
 6 
 7     <LinearLayout  8         android:layout_width="match_parent"
 9         android:layout_height="match_parent"
10         android:orientation="vertical"
11         android:padding="@dimen/dp_5">
12 
13         <ImageView 14             android:id="@+id/ivPic"
15             android:layout_width="match_parent"
16             android:layout_height="@dimen/dp_100"
17             android:scaleType="centerCrop"
18             android:src="@drawable/ic_pick"
19             />
20 
21         <ProgressBar 22             android:id="@+id/bg_progressbar"
23             style="@style/StyleProgressBarMini"
24             android:layout_width="match_parent"
25             android:layout_height="@dimen/dp_5"
26             android:background="@drawable/shape_progressbar_mini"
27             android:max="100"
28             android:progress="60" />
29     </LinearLayout>
30     <ImageView 31         android:id="@+id/ivDel"
32         android:layout_width="@dimen/dp_25"
33         android:layout_height="@dimen/dp_25"
34         android:src="@drawable/delete_round"
35         android:layout_alignParentRight="true"/>
36 
37 </RelativeLayout>

 

 1 List<LoadFileVo> fileList = new ArrayList<>();  2 LoadPicAdapter adapter = null;  3 
 4   //這里使用ButterKnife
 5  @BindView(R.id.rvPic)  6  RecyclerView rvPic;  7 
 8     @BindView(R.id.tvNum)  9  TextView tvNum; 10 
11 
12     //初始化Adapter 13     //設置圖片選擇的接口
14     private void initAdapter() { 15         fileList.add(new LoadFileVo()); 16         adapter = new LoadPicAdapter(this, fileList,8); 17  rvPic.setAdapter(adapter); 18         rvPic.setLayoutManager(new GridLayoutManager(this, 3)); 19         adapter.setListener(new LoadPicAdapter.OnItemClickListener() { 20  @Override 21             public void click(View view, int positon) { 22                 if (fileList.size()>8){ 23                     showShortToast("一次最多上傳8張圖片!"); 24                 }else { 25                     selectPic();  //選擇添加圖片方法
26  } 27 
28  } 29 
30  @Override 31             public void del(View view) { 32                 tvNum.setText((fileList.size()-1)+"/8"); 33  } 34  }); 35     }

 

《核心代碼》

 1 String mPhtotPath;  2 Uri uriImage;  3 File mPhotoFile = null;  4 
 5 
 6 //選擇圖片
 7 private void selectPic() {  8 
 9 //動態請求權限,除此之外還需進行Androidmanifest.xml中進行請求
10 
11         if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) 12                 != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, 13                 Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED 14                 || ContextCompat.checkSelfPermission(this, 15                 Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { 16             ActivityCompat.requestPermissions(this, 17                     new String[]{Manifest.permission.CAMERA, 18  Manifest.permission.READ_EXTERNAL_STORAGE, 19  Manifest.permission.WRITE_EXTERNAL_STORAGE}, 20                     1); 21  } 22 
23 
24         final CharSequence[] items = {"相冊", "拍照"}; 25         AlertDialog.Builder dlg = new AlertDialog.Builder(EndLoadMstActivity.this); 26         dlg.setTitle("添加圖片"); 27         dlg.setItems(items, new DialogInterface.OnClickListener() { 28             public void onClick(DialogInterface dialog, int item) { 29                 // 這里item是根據選擇的方式,
30                 if (item == 0) { 31                     Intent intent = new Intent(Intent.ACTION_PICK); 32                     intent.setType("image/*"); 33                     startActivityForResult(intent, 0); 34                 } else { 35                     try { 36                         Intent intent = new Intent("android.media.action.IMAGE_CAPTURE"); 37                         mPhtotPath = getSDPath() + "/" + getPhotoFileName(); 38                         mPhotoFile = new File(mPhtotPath); 39                         if (!mPhotoFile.exists()) { 40  mPhotoFile.createNewFile(); 41  } 42 // uriImage = FileProvider.getUriForFile(EndLoadMstActivity.this, getPackageName() + ".provider", createImageFile());
43 
44                         uriImage = FileProvider.getUriForFile(EndLoadMstActivity.this, "com.ahbcd.app.tms.provider", mPhotoFile); 45                         Log.i("TAG", "onClick: "+mPhtotPath+"---------" + getPackageName() + ".provider"); 46                         // uriImage = Uri.fromFile(mPhotoFile);以上一句代替解決相機兼容問題
47  intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 48  intent.putExtra(MediaStore.EXTRA_OUTPUT, uriImage); 49 
50                         startActivityForResult(intent, 1); 51 
52                     } catch (Exception e) { 53  e.printStackTrace(); 54  } 55  } 56  } 57  }).create(); 58  dlg.show(); 59  } 60 
61 public String getSDPath() { 62         File sdDir = null; 63         boolean sdCardExsit = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); 64         if (sdCardExsit) { 65             sdDir = Environment.getExternalStorageDirectory(); 66  } 67         return sdDir.toString(); 68  } 69 
70     private String getPhotoFileName() { 71         Date date = new Date(System.currentTimeMillis()); 72         SimpleDateFormat dateFormat = new SimpleDateFormat("'IMG'_yyyyMMdd_HHmmss"); 73         return dateFormat.format(date) + ".jpg"; 74     }

 

注:這里需要在Android中配置一個proveder 具體請參考 Android 系統7.0以上調用相機兼容問題

《獲取返回的圖片》

 1 //重寫onActivityResult方法
 2 @Override  3     protected void onActivityResult(int requestCode, int resultCode, Intent data) {  4         super.onActivityResult(requestCode, resultCode, data);  5         if (requestCode == 1) {  6             BitmapFactory.Options options = new BitmapFactory.Options();  7             options.inSampleSize = 2; //圖片寬高都為原來的二分之一,即圖片為原來的四分之一
 8             Bitmap bitmap = BitmapFactory.decodeFile(mPhtotPath, options);  9             if (bitmap != null) { 10                 if (uriImage != null) { 11                     saveUritoFile(uriImage,1); 12  } 13 
14                 if (!bitmap.isRecycled()) { 15                     bitmap.recycle(); //回收圖片所占的內存
16                     System.gc(); //提醒系統及時回收
17  } 18  } 19  } 20         if (requestCode == 0) { 21             if (data != null) { 22                 Uri uri = data.getData(); 23                 saveUritoFile(uri,0); 24  } 25  } 26 
27  } 28 
29 //將Uri圖片類型轉換成File,BitMap類型 30 //在界面上顯示BitMap圖片,以防止內存溢出 31 //上傳可選擇File文件上傳
32 
33     private void saveUritoFile(Uri uriImage,int type) { 34         Bitmap photoBmp = null; 35 
36         if (uriImage != null) { 37             try { 38 // photoBmp = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uriImage); 39 // ByteArrayOutputStream fos = new ByteArrayOutputStream(); 40 // photoBmp.compress(Bitmap.CompressFormat.JPEG, 80, fos); 41                 //以上代碼壓縮不行,還是會造成內存溢出
42 
43                 BitmapFactory.Options options = new BitmapFactory.Options(); 44                 options.inSampleSize = 2; //圖片寬高都為原來的二分之一,即圖片為原來的四分之一
45                 photoBmp = BitmapFactory.decodeStream(this.getContentResolver() 46                         .openInputStream(uriImage), null, options); 47 
48                 File file = new File(""); 49                 if (type==0){ 50                     file = FileParseUtils.getFileByUri(this, uriImage); 51 
52                 }else { 53                     if (mPhotoFile!=null){ 54                         file = mPhotoFile; 55  } 56 
57  } 58 // File file = new File(""); 59 // try { 60 // file = new File(new URI(uriImage.toString())); 61 // } catch (URISyntaxException e) { 62 // e.printStackTrace(); 63 // }
64                 fileList.add(new LoadFileVo(file, false, 0, photoBmp)); 65                 tvNum.setText((fileList.size()-1)+"/8"); 66                 if (fileList.size()>8){ //判斷時候達到最大數量,如果達到最大數量,則去掉前面的加號 67                     fileList.remove(0); 68  } 69 
70  adapter.notifyDataSetChanged(); 71 
72             } catch (IOException e) { 73  e.printStackTrace(); 74                 Log.i("TAG", "saveUritoFile: ---------壓縮圖片異常!"); 75  } 76 
77 
78  } 79 
80     }

 

圖片上傳到后台OKhttp

 1 //一張張圖片輪流上傳
 2 public void netUpload(int i, final String joData) {//用jsonOject方式轉string傳遞其他參數
 3         try {  4 
 5             if (!isRequestHttp) {  6                 isRequestHttp = true;  7                 final int finalI = i;  8                 enterEnable(false);  9 
 10                 if (fileList.get(finalI).isUpload()) {  11                     netUpload(finalI + 1, joData);  12                 } else {  13 
 14         RequestBody requestBody = new MultipartBody.Builder()  15  .setType(MultipartBody.FORM)  16                 .addFormDataPart("mstjson",msg)  //其他信息
 17                 .addFormDataPart("file", file.getName(),  18                         RequestBody.create(MediaType.parse("application/octet-stream"), file))//文件
 19  .build();  20         Request request = new Request.Builder()  21                 .url(uploadPic---這里是圖片上傳的地址).post(requestBody)  22  .build();  23         okHttpClient.newCall(request).enqueue(new UICallBack() {  24  @Override  25                         public void onFailureUI(Call call, IOException e) {  26                             showShortToast("連接服務器失敗");  27                             isRequestHttp = true;  28                             enterEnable(true);  29 
 30  }  31 
 32  @Override  33                         public void onResponseUI(Call call, Response response) {  34                             try {  35 
 36                                 isRequestHttp = false;  37 
 38                                 String result = response.body().string();  39                                 Utils.log("上傳圖片結果:" + result);  40 
 41 
 42                                 if (!response.isSuccessful()) {  43                                     Utils.log("響應失敗:" + response.code());  44                                     showShortToast("響應失敗:" + response.code());  45                                     enterEnable(true);  46 
 47                                     return;  48  }  49                                 if (result.equals("{}")) {  50                                     showShortToast("獲取服務端數據為空");  51                                     enterEnable(true);  52 
 53                                     return;  54  }  55                                 JSONObject jsonObject = new JSONObject(result);  56                                 if (jsonObject.getString("IsError").equals("true")) {  57                                     showShortToast(jsonObject.getString("ErrMsg"));  58                                     enterEnable(true);  59 
 60                                 } else {  61                                     String Data = jsonObject.getString("Data");  62                                     fileList.get(finalI).setPg(100);  63                                     fileList.get(finalI).setUpload(true);  64  adapter.notifyDataSetChanged();  65 
 66                                     if (finalI == fileList.size() - 1) {  67                                         showShortToast("上傳成功!");  68 
 69                                         btnEnter.setText("已上傳");  70                                        
 71                                     } else {  72                                         netUpload((finalI + 1), joData);  73  }  74 
 75  }  76                             } catch (Exception e) {  77                                 isRequestHttp = true;  78  hideLoadingDialog();  79                                 showShortToast("上傳憑證發生異常!");  80                                 LogToFile.e("上傳憑證發生異常," + e);  81                                 enterEnable(true);  82 
 83  }  84  }  85  });  86 
 87  }  88  }  89         } catch (Exception e) {  90             isRequestHttp = true;  91  hideLoadingDialog();  92 
 93             showShortToast("上傳圖片請求異常!");  94             LogToFile.e("上傳圖片請求異常," + e);  95             enterEnable(true);  96 
 97  }  98  }  99 
100 
101 //用來提示用戶文件上傳的情況。同時也是避免同時反復操作
102 public void enterEnable(boolean isEnabled) { 103         if (isEnabled) { 104             btnEnter.setText("重新上傳"); 105             btnEnter.setEnabled(true); 106  btnEnter.setBackgroundResource(R.drawable.selecter_button); 107  btnEnter.setTextColor(getResources().getColor(R.color.inButtonText)); 108 
109         } else { 110             btnEnter.setText("正在上傳···"); 111             btnEnter.setEnabled(false); 112  btnEnter.setBackgroundResource(R.drawable.buttonshap); 113  btnEnter.setTextColor(getResources().getColor(R.color.outButtonText)); 114  } 115     }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM