編輯:關於Android編程
1、新建一個布局文件,輸入我們想要使用的線程的個數,包括一個主布局文件和一個progressBar
(1)一個包括三個控件的主布局
(2)一個只包含ProgressBar的子布局文件
2、找到三個控件,獲取該Button控件的點擊事件,點擊開始下載
(1)獲取用戶輸入線程的個數
(2)清空所有ProgressBar子控件
(3)根據線程數添加相應數量的ProgressBar
(4)在子線程中運行download()函數,因為主線程不能做時間太長的操作
3、進入download()函數,為每個線程設定下載的開始和結束為止
(1)根據url請求網絡資源
(2)獲取下載資源的大小,並在本地創建占位符
(3)要分配每個線程下載文件的開始位置和結束位置
(4)開啟線程去執行下載
4、開啟線程下載,需要定義一個線程下載類繼承並重寫run()方法
(1)通過map獲取當前線程對應ProgressBar
(2)建立一個SharedPreferences的操作類用來存取斷點信息
(3)設置分段下載的頭信息。Range信息:做分段數據請求用的,也就是設置從哪裡下載到哪裡
(4)請求部分資源成功,開始一邊從服務器讀取一邊寫入sdcard
(5)寫入過程中將下載進度保存的SharedPreferences中,設置ProgressBar的顯示情況
(1)一個包括三個控件的主布局
(3)初步的界面展示如下
如下是一些全局變量的初始化,以及我們在點擊“開始下載”之後處理的內容:
(1)定義一些全局變量,這些我們在下面要使用到
public class MainActivity extends Activity implements OnClickListener{ private EditText et_threadCount; private Context mContext; private LinearLayout ll_progress_layout; private int threadCount = 0; //開啟3個線程 private int blockSize = 0; //每個線程下載的大小 private int runningTrheadCount = 0;//當前運行的線程數 private String path = "http://115.25.200.74:8080/itheima74/feiq.exe"; private Mapmap = new HashMap ();
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mContext = this; findViewById(R.id.bt_download).setOnClickListener(this); ll_progress_layout = (LinearLayout) findViewById(R.id.ll_progress_layout); et_threadCount = (EditText) findViewById(R.id.et_threadCount); }
public void onClick(View v) { //獲取用戶輸入的線程數 String trim = et_threadCount.getText().toString().trim(); threadCount = Integer.parseInt(trim); // 清空所有的子空間 ll_progress_layout.removeAllViews(); //根據線程數添加相應數量的ProgressBar for(int i =0 ;i < threadCount;i++ ){ ProgressBar progressbar = (ProgressBar)View.inflate(mContext, R.layout.child_progressbar_layout, null); map.put(i, progressbar);//將ProgressBar放到map中,方便在線程中獲取並設置進度 //展示progressbar ll_progress_layout.addView(progressbar); } new Thread(new Runnable() { @Override public void run() { download(); } }).start(); }
(1)根據url請求網絡資源
//1.請求url地址獲取服務端資源的大小 URL url = new URL(path); HttpURLConnection openConnection = (HttpURLConnection) url.openConnection(); openConnection.setRequestMethod("GET"); openConnection.setConnectTimeout(10*1000);
int code = openConnection.getResponseCode(); if(code == 200){ //獲取資源的大小 int filelength = openConnection.getContentLength(); //2.在本地創建一個與服務端資源同樣大小的一個文件(占位) RandomAccessFile randomAccessFile = new RandomAccessFile(new File(getFileName(path)), "rw"); randomAccessFile.setLength(filelength);//設置隨機訪問文件的大小
//3.要分配每個線程下載文件的開始位置和結束位置。 blockSize = filelength/threadCount;//計算出每個線程理論下載大小 for(int threadId =0 ;threadId < threadCount;threadId++){ int startIndex = threadId * blockSize;//計算每個線程下載的開始位置 int endIndex = (threadId+1)*blockSize -1;//計算每個線程下載的結束位置 //如果是最後一個線程,結束位置需要單獨計算 if(threadId == threadCount-1){ endIndex = filelength -1; } //4.開啟線程去執行下載 new DownloadThread(threadId, startIndex, endIndex).start();
(1)基本參數的定義和初始化
private int threadId; private int startIndex; private int endIndex; private int lastPostion; private int currentThreadTotalProgress; public DownloadThread(int threadId,int startIndex,int endIndex){ this.threadId = threadId; this.startIndex = startIndex; this.endIndex = endIndex; // 進度條的最大值 this.currentThreadTotalProgress = endIndex -startIndex +1; }
package com.iigt.download; import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; public class SharedUtils { public static int getLastPosition(Context context,int threadId){ SharedPreferences defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); return defaultSharedPreferences.getInt("lastPostion"+threadId, -1); } public static void setLastPosition(Context context,int threadId,int position){ SharedPreferences defaultSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); defaultSharedPreferences.edit().putInt("lastPostion"+threadId, position).commit(); } }
//分段請求網絡連接,分段保存文件到本地 try{ URL url = new URL(path); HttpURLConnection openConnection = (HttpURLConnection) url.openConnection(); openConnection.setRequestMethod("GET"); openConnection.setConnectTimeout(10*1000); System.out.println("理論上下載: 線程:"+threadId+",開始位置:"+startIndex+";結束位置:"+endIndex); if(SharedUtils.getLastPosition(mContext, threadId) != -1){ lastPostion = SharedUtils.getLastPosition(mContext, threadId); //說明該線程已經下載完成 if(lastPostion == endIndex+1){ progressBar.setProgress(currentThreadTotalProgress); runningTrheadCount = runningTrheadCount -1; } //設置分段下載的頭信息。 Range:做分段數據請求用的。 openConnection.setRequestProperty("Range", "bytes:"+lastPostion+"-"+endIndex);//bytes:0-500:請求服務器資源中0-500之間的字節信息 501-1000: System.out.println("實際下載: 線程:"+threadId+",開始位置:"+lastPostion+";結束位置:"+endIndex); }else{ lastPostion = startIndex; //設置分段下載的頭信息。 Range:做分段數據請求用的。 openConnection.setRequestProperty("Range", "bytes:"+lastPostion+"-"+endIndex); System.out.println("實際下載: 線程:"+threadId+",開始位置:"+lastPostion+";結束位置:"+endIndex); }
(4)請求部分資源成功,開始一邊從服務器讀取一邊寫入sdcard
if(openConnection.getResponseCode() == 206){//200:請求全部資源成功, 206代表部分資源請求成功 InputStream inputStream = openConnection.getInputStream(); //請求成功將流寫入本地文件中,已經創建的占位那個文件中 RandomAccessFile randomAccessFile = new RandomAccessFile(new File(getFileName(path)), "rw"); randomAccessFile.seek(lastPostion);//設置隨機文件從哪個位置開始寫。 //將流中的數據寫入文件 byte[] buffer = new byte[1024*100]; int length = -1; int total = 0;//記錄本次線程下載的總大小 while((length= inputStream.read(buffer)) !=-1){ randomAccessFile.write(buffer, 0, length); total = total+ length; //去保存當前線程下載的位置,保存到文件中 int currentThreadPostion = lastPostion + total;//計算出當前線程本次下載的位置 SharedUtils.setLastPosition(mContext, threadId, currentThreadPostion); //計算線程下載的進度並設置進度 int currentprogress = currentThreadPostion -startIndex; progressBar.setMax(currentThreadTotalProgress);//設置進度條的最大值 progressBar.setProgress(currentprogress);//設置進度條當前進度 } //關閉相關的流信息 inputStream.close(); randomAccessFile.close(); System.out.println("線程:"+threadId+",下載完畢");
public String getFileName(String url){ return Environment.getExternalStorageDirectory() + "/"+ url.substring(url.lastIndexOf("/")+1); } public String getFilePath(){ return Environment.getExternalStorageDirectory() + "/"; }
-----------------------------------------------------------------文件上傳操作--------------------------------------------------------------------
1、客戶端上傳操作
(1)編寫布局文件,一個EditText一個Button
(2)獲取輸入的文件地址
(3)使用開源Utils做上傳操作
2、服務器端接收操作
(1)首先判斷上傳的數據是表單數據還是帶文件的數據
(2)如果是帶文件的數據,在本地創建文件目錄
(3)判斷文件的類型,表單打印,文件類型就上傳
二、---布局創建---
(1)編寫布局文件,一個EditText一個Button
(1)獲取輸入的文件地址
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void fileupload(View v){ try{ EditText et_filepath = (EditText) findViewById(R.id.et_filepath); //獲取輸入的文件地址 String filepath = et_filepath.getText().toString().trim();
//使用開源Utils做上傳操作 AsyncHttpClient asyncHttpClient = new AsyncHttpClient(); RequestParams params = new RequestParams(); params.put("filename", new File(filepath)); //url : 請求服務器的url asyncHttpClient.post("http://115.25.200.74:8080/itheima74/servlet/UploaderServlet", params, new AsyncHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) { if(statusCode == 200){ Toast.makeText(MainActivity.this, "上傳成功", 0).show(); } } @Override public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) { } }); }catch (Exception e) { e.printStackTrace(); }
先判斷數據類型,接著再判斷文件類型,如果是文件的話就上傳操作,是表單的話進行打印操作
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //首先判斷上傳的數據是表單數組數據還是一個帶文件的數據 boolean isMultipart = ServletFileUpload.isMultipartContent(request); if (isMultipart) { //如果是true,說明是一個帶有文件的數據 //拿到servlet的真實路徑 String realpath = request.getSession().getServletContext().getRealPath("/files"); //打印一下路徑 System.out.println("realpath-"+realpath); File dir = new File(realpath); if (!dir.exists()) dir.mkdirs(); //如果目標不在就把這個目錄給創建出來 FileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); //獲得上傳文件的對象upload upload.setHeaderEncoding("UTF-8"); try { //判斷一下上傳的數據類型 Listitems = upload.parseRequest(request); for (FileItem item : items) { if (item.isFormField()) { //上傳的數據類型是一個表單類型 String name1 = item.getFieldName();// 得到請求參數的名稱 String value = item.getString("UTF-8");//得到參數值? System.out.println(name1 + "=" + value); } else { //說明這是一個文件類型,進行上傳 item.write(new File(dir, System.currentTimeMillis() + item.getName().substring(item.getName().lastIndexOf(".")))); } } } catch (Exception e) { e.printStackTrace(); }finally{ } } }
1、文件的下載操作在安卓2.3上可以正常的使用,但是在安卓4.1上就不能正常運行,由於是剛剛學習,也不知道怎麼解決
2、下載中開始開啟3個線程,然後中斷,再填寫5個線程,這時只有最後兩個線程運行了
Android存儲五大方式:1 使用SharedPreferences存儲數據2 文件存儲數據3 SQLite數據庫存儲數據4 使用ContentProvider存儲數據
MVP介紹MVP模式(Model-View-Presenter)是MVC模式的一個衍生。主要目的是為了解耦,使項目易於維護。Model 依然是業務邏輯和實體模型 View
前言百度地圖的定位功能和基礎地圖功能是分開的,使用的是另外的jar包和so庫文件,詳情請關注官網:百度定位SDK配置下載對應的jar包和so庫,然後移動到lib目錄下AS
在編寫自定義滑動控件時常常會用到Android觸摸機制和Scroller及VelocityTracker。Android Touch系統簡介(二):實例詳解onInte