編輯:關於Android編程
之前一直在做SiteCheck的項目,所用到的知識大部分都涉及到網絡編程方面,所以現在有時間先把它的使用方法及一些注意事項記錄下來。在這裡我用兩種例子讓大家了解它的使用方法:
(1)上傳圖片及相應參數到服務器 (2)上傳語音及相應參數到服務器。代碼比較多。。。。
先貼上代碼,再解析:
UploadFileTask .java : (實現異步上傳的執行類)
public class UploadFileTask extends AsyncTask{ /** * 可變長的輸入參數,與AsyncTask.exucute()對應 */ private ProgressDialog pdialog; private Activity context=null; public UploadFileTask(Activity ctx){ this.context=ctx; pdialog=ProgressDialog.show(context, "正在加載...", "系統正在處理您的請求"); } @Override protected void onPostExecute(String result) { // 返回HTML頁面的內容 pdialog.dismiss(); if(UploadUtils.taskSUCCESS.equals(result)){ Toast.makeText(context, "上傳成功!",Toast.LENGTH_LONG ).show(); int size = Bimp.tempSelectBitmap.size(); while(size>0){ ImageItem imageItem = Bimp.tempSelectBitmap.get(size-1); String imgPath = imageItem.getImagePath(); //從SD卡中刪除圖片 FileUtils.delFile(imgPath); Bimp.tempSelectBitmap.remove(imageItem); Bimp.max--; //獲取對應照片的音頻數據 List mDatas = StaticVariable.mapVoice.get(imgPath); if(mDatas!=null){ int voiceNum = mDatas.size(); for(int j=0;j 0){ ImageItem imageItem = Bimp.terminalSelectBitmap.get(size-1); if(imageItem.isCamera()){ //從SD卡中刪除 FileUtils.delFile(imageItem.getImagePath()); } Bimp.terminalSelectBitmap.remove(imageItem); Bimp.terminalmax--; size--; } UpdateTerminalFragment.terminalAdapter.notifyDataSetChanged(); }else{ Toast.makeText(context, "上傳失敗!",Toast.LENGTH_LONG ).show(); @Override protected String doInBackground(String... params) { String result = ""; //上傳終端圖片 if(params[0].equals(StaticVariable.TERMINAL_UPLOAD_IMG)){ //獲取對應照片的文件 ArrayList terBitmap = Bimp.terminalSelectBitmap; File[] files = null; if(terBitmap!=null){ int imgNum = terBitmap.size(); files = new File[imgNum]; for(int i=0;i tempBitmap = Bimp.tempSelectBitmap; for(int i=0;i mDatas = StaticVariable.mapVoice.get(imgPath); File[] voiceFiles = null; if(mDatas!=null){ int voiceNum = mDatas.size(); voiceFiles = new File[voiceNum]; for(int j=0;j
這個異步上傳處理類是比較簡單的:
在要上傳的地方執行下面代碼就會進入到異步處理類中進行相應的操作:
UploadFileTask uploadFileTask=new UploadFileTask(activity);
uploadFileTask.execute(StaticVariable.TASK_UPLOAD_IMG);
下面解析一下對上傳類的操作:
result = UploadUtils.uploadFile(file, voiceFiles, StaticUrl.urlAddImg);
file: 這裡是圖片文件參數
voiceFiles:這個是語音文件,是一個文件數組
StaticUrl.urlAddImg: 文件上傳的地址
resutl:返回結果
UploadUtils .java:
public class UploadUtils { private static final int TIME_OUT = 10*10000000; //超時時間 private static final String CHARSET = "utf-8"; //設置編碼 public static final String FAILURE="0"; //上傳失敗的返回結果 public static final String taskSUCCESS="1"; //上傳成功的返回結果 public static final String terSUCCESS = "2"; //上傳任務信息 public static String uploadFile(File file, File[] files, String RequestURL) { String BOUNDARY = UUID.randomUUID().toString(); //邊界標識 隨機生成(也可以自定義) String PREFIX = "--" , LINE_END = "\r\n"; String CONTENT_TYPE = "multipart/form-data"; //內容類型(這是標准通用型,不過最好指明明確的文件類型) try { URL url = new URL(RequestURL); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(TIME_OUT); conn.setConnectTimeout(TIME_OUT); conn.setDoInput(true); //允許輸入流 conn.setDoOutput(true); //允許輸出流 conn.setUseCaches(false); //不允許使用緩存 conn.setRequestMethod("POST"); //請求方式 conn.setRequestProperty("Charset", CHARSET); //設置編碼 conn.setRequestProperty("connection", "keep-alive"); conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY); if(file!=null) { /** * 當文件不為空,把文件包裝並且上傳 */ OutputStream outputSteam=conn.getOutputStream(); //獲得網絡傳輸的輸出流 DataOutputStream dos = new DataOutputStream(outputSteam); StringBuffer sb = new StringBuffer(); sb.append(PREFIX); sb.append(BOUNDARY); sb.append(LINE_END); sb.append("Content-Disposition: form-data; name=\"uid\"" + LINE_END); //uid 作為上傳參數的key(服務器端接收這個參數要對應這個key) sb.append(LINE_END); sb.append(LoginActivity.uid + LINE_END); //LoginActivity.uid 是要上傳參數的值 if(IScreateRecordHttp.hasSameRecord==0){ sb.append(PREFIX); sb.append(BOUNDARY); sb.append(LINE_END); sb.append("Content-Disposition: form-data; name=\"hasSameRecord\""+LINE_END); sb.append(LINE_END); sb.append(0+LINE_END); sb.append(PREFIX); sb.append(BOUNDARY); sb.append(LINE_END); sb.append("Content-Disposition: form-data; name=\"isid\""+LINE_END); sb.append(LINE_END); sb.append(SeeTaskFragment.isid+LINE_END); }else if(IScreateRecordHttp.hasSameRecord==1){ sb.append(PREFIX); sb.append(BOUNDARY); sb.append(LINE_END); sb.append("Content-Disposition: form-data; name=\"hasSameRecord\""+LINE_END); sb.append(LINE_END); sb.append(1+LINE_END); sb.append(PREFIX); sb.append(BOUNDARY); sb.append(LINE_END); sb.append("Content-Disposition: form-data; name=\"rid\""+LINE_END); sb.append(LINE_END); sb.append(IScreateRecordHttp.rid+LINE_END); } sb.append(PREFIX); sb.append(BOUNDARY); sb.append(LINE_END); sb.append("Content-Disposition: form-data; name=\"remark\""+LINE_END); sb.append(LINE_END); sb.append(FieldFragment.getRemark() + LINE_END); /** * 這裡重點注意: * name裡面的值為服務器端需要key 只有這個key 才可以得到對應的文件 * filename是文件的名字,包含後綴名的 比如:abc.png */ sb.append(PREFIX); sb.append(BOUNDARY); sb.append(LINE_END); sb.append("Content-Disposition: form-data; name=\"file\"; filename=\""+file.getName()+"\""+LINE_END); sb.append("Content-Type: image/jpeg"); //指明文件類型為圖片jpeg類型 sb.append(LINE_END);sb.append(LINE_END); dos.write(sb.toString().getBytes()); InputStream is = new FileInputStream(file); //把圖片文件轉換成二進制流的方式 寫入到dos中 byte[] bytes = new byte[1024]; int len = 0; while((len=is.read(bytes))!=-1) { dos.write(bytes, 0, len); } is.close(); dos.write(LINE_END.getBytes()); byte[] end_data = (PREFIX+BOUNDARY+PREFIX+LINE_END).getBytes(); dos.write(end_data); dos.flush(); //釋放流 /** * 獲取響應碼 200=成功 * 當響應成功,獲取響應的流 */ int res = conn.getResponseCode(); Log.e("Mine", "response code:"+res); if(res==200) { //這裡是上傳成功就繼續上傳音頻文件,假如不需要就直接 return InputStream isre = conn.getInputStream(); BufferedReader buffer = new BufferedReader( new InputStreamReader(isre,"gbk")); String line = ""; StringBuffer sbre = new StringBuffer(); while ((line = buffer.readLine()) != null) { sbre.append(line); } String result = sbre.toString(); //獲取返回結果 Log.e("Mine",result); try{ JSONObject jsonObject = new JSONObject(result); int iid = jsonObject.getInt("iid"); String type = jsonObject.getString("type"); String msg = jsonObject.getString("msg"); if(type.equals("SUCCESS")){ /* 在AsyncTask異步處理方法裡面不可以再使用異步處理, 會導致UI(主)線程執行錯誤 */ uploadVoice(iid,files); } }catch(JSONException e){ e.printStackTrace(); }catch(ParseException e1){ e1.printStackTrace(); } return taskSUCCESS; } } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return FAILURE; } //上傳圖片對應的語言 private static void uploadVoice(int iid,File[] files) { String BOUNDARY = UUID.randomUUID().toString(); //邊界標識 隨機生成 String PREFIX = "--" , LINE_END = "\r\n"; String CONTENT_TYPE = "multipart/form-data"; //內容類型 try{ String RequestURL = StaticUrl.urlAddVoices; URL url = new URL(RequestURL); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(TIME_OUT); conn.setConnectTimeout(TIME_OUT); conn.setDoInput(true); //允許輸入流 conn.setDoOutput(true); //允許輸出流 conn.setUseCaches(false); //不允許使用緩存 conn.setRequestMethod("POST"); //請求方式 conn.setRequestProperty("Charset", CHARSET); //設置編碼 conn.setRequestProperty("connection", "keep-alive"); conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY); if(files!=null) { /** * 當文件不為空,把文件包裝並且上傳 */ OutputStream outputSteam=conn.getOutputStream(); DataOutputStream dos = new DataOutputStream(outputSteam); StringBuffer sb = new StringBuffer(); sb.append(PREFIX); sb.append(BOUNDARY); sb.append(LINE_END); sb.append("Content-Disposition: form-data; name=\"uid\"" + LINE_END); sb.append(LINE_END); sb.append(LoginActivity.uid + LINE_END); sb.append(PREFIX); sb.append(BOUNDARY); sb.append(LINE_END); sb.append("Content-Disposition: form-data; name=\"iid\""+LINE_END); sb.append(LINE_END); sb.append(iid+LINE_END); dos.write(sb.toString().getBytes()); for(File file : files){ //多文件上傳,用循環 StringBuffer sbImgs = new StringBuffer(); //這裡面要注意:重新實例化一個StringBuffer,不然導致StringBuffer的重用,原來的參數也跟後來的參數一起傳到服務器了。 // set 頭部 sbImgs.append(PREFIX); sbImgs.append(BOUNDARY); sbImgs.append(LINE_END); sbImgs.append("Content-Disposition: form-data; name=\"voices\"; filename=\""+file.getName()+"\""+LINE_END); sbImgs.append("Content-Type: audio/mp3"+LINE_END); sbImgs.append(LINE_END); // 1. write sb dos.writeBytes(sbImgs.toString()); // 取得文件的FileInputStream FileInputStream fis = new FileInputStream(file); // 設置每次寫入1024bytes int bufferSize = 1024; byte[] buffer = new byte[bufferSize]; int length = -1; // 從文件讀取數據至緩沖區 while ((length = fis.read(buffer)) != -1) { dos.write(buffer, 0, length); } dos.writeBytes(LINE_END); fis.close(); dos.writeBytes(LINE_END); dos.writeBytes(LINE_END); } byte[] end_data = (PREFIX+BOUNDARY+PREFIX+LINE_END).getBytes(); dos.write(end_data); dos.flush(); /** * 獲取響應碼 200=成功 * 當響應成功,獲取響應的流 */ int res = conn.getResponseCode(); Log.e("Mine", "response code:"+res); if(res==200) { // return terSUCCESS; } } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // return FAILURE; } //上傳終端圖片 public static String uploadTerFile(File[] files, String RequestURL) { String BOUNDARY = UUID.randomUUID().toString(); //邊界標識 隨機生成 String PREFIX = "--" , LINE_END = "\r\n"; String CONTENT_TYPE = "multipart/form-data"; //內容類型 try{ URL url = new URL(RequestURL); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setReadTimeout(TIME_OUT); conn.setConnectTimeout(TIME_OUT); conn.setDoInput(true); //允許輸入流 conn.setDoOutput(true); //允許輸出流 conn.setUseCaches(false); //不允許使用緩存 conn.setRequestMethod("POST"); //請求方式 conn.setRequestProperty("Charset", CHARSET); //設置編碼 conn.setRequestProperty("connection", "keep-alive"); conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";boundary=" + BOUNDARY); if(files!=null) { /** * 當文件不為空,把文件包裝並且上傳 */ OutputStream outputSteam=conn.getOutputStream(); DataOutputStream dos = new DataOutputStream(outputSteam); StringBuffer sb = new StringBuffer(); sb.append(PREFIX); sb.append(BOUNDARY); sb.append(LINE_END); sb.append("Content-Disposition: form-data; name=\"uid\"" + LINE_END); sb.append(LINE_END); sb.append(LoginActivity.uid + LINE_END); sb.append(PREFIX); sb.append(BOUNDARY); sb.append(LINE_END); sb.append("Content-Disposition: form-data; name=\"tid\""+LINE_END); sb.append(LINE_END); sb.append(TerminalInfo.tid+LINE_END); sb.append(PREFIX); sb.append(BOUNDARY); sb.append(LINE_END); sb.append("Content-Disposition: form-data; name=\"remark\""+LINE_END); sb.append(LINE_END); sb.append("備注" + LINE_END); dos.write(sb.toString().getBytes()); for(File file : files){ StringBuffer sbImgs = new StringBuffer(); // set 頭部 sbImgs.append(PREFIX); sbImgs.append(BOUNDARY); sbImgs.append(LINE_END); sbImgs.append("Content-Disposition: form-data; name=\"imgs\"; filename=\""+file.getName()+"\""+LINE_END); sbImgs.append("Content-Type: image/jpeg"+LINE_END); sbImgs.append(LINE_END); // 1. write sb dos.writeBytes(sbImgs.toString()); // 取得文件的FileInputStream FileInputStream fis = new FileInputStream(file); // 設置每次寫入1024bytes int bufferSize = 1024; byte[] buffer = new byte[bufferSize]; int length = -1; // 從文件讀取數據至緩沖區 while ((length = fis.read(buffer)) != -1) { dos.write(buffer, 0, length); } dos.writeBytes(LINE_END); fis.close(); dos.writeBytes(LINE_END); dos.writeBytes(LINE_END); } byte[] end_data = (PREFIX+BOUNDARY+PREFIX+LINE_END).getBytes(); dos.write(end_data); dos.flush(); /** * 獲取響應碼 200=成功 * 當響應成功,獲取響應的流 */ int res = conn.getResponseCode(); Log.e("Mine", "response code:"+res); if(res==200) { return terSUCCESS; } } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return FAILURE; } }
基本上掌握了這些方法,上傳文件的操作就剩下套路了,以二進制流的方式上傳文件要注意文件,參數它們的頭,和尾,就是那些邊界值。
本章介紹android高級開發中,對於性能方面的處理。主要包括電量,視圖,內存三個性能方面的知識點。1.視圖性能(1)Overdraw簡介 &nbs
最近在網上看到時間軸的布局效果,嘗試按照這個原理,實現物流跟蹤的效果,目前已經實現了,效果如下圖。 界面布局主要是通過listView來
這次做一個圖片加載器,裡面涉及到線程池,bitmap的高效加載,LruCache,DiskLruCache。接下來我先介紹這四個知識點一.線程池優點:(1)重用線程池中的
在Android中,對Fragment的操作都是通過FragmentTransaction來執行。而從Fragment的結果來看,FragmentTransaction中