編輯:關於Android編程
單線程下載很簡單,就是開啟一個線程去下載資源再進行本地保存;
多線程下載是通過RandomAccessFile(隨機文件讀寫操作類)來設置每個線程讀取文件的起始點位置,起始點之間的長度即為該線程需要下載的文件大小
下載開始位置:線程id*每條線程下載的數據長度 = ?
下載結束位置:(線程id+1)*每條線程下載的數據長度-1=?
這裡用的是URLConnection
public class DownloadActivity extends Activity implements View.OnClickListener {
private Button mButtonSingle;
private Button mButtonMuti;
private SeekBar mSeekBarDownload;
private int fileLength;
//handler用於接收多線程下載線程的消息Message,並得到文件下載進度寫入進度條SeekBar
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case 0x23:
mSeekBarDownload.setProgress(msg.arg1*100/fileLength);
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_download);
mSeekBarDownload = (SeekBar) findViewById(R.id.seekBar_download);
mButtonSingle = (Button) findViewById(R.id.button_download_single);
mButtonMuti = (Button) findViewById(R.id.button_download_muti);
mButtonSingle.setOnClickListener(this);
mButtonMuti.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.button_download_single:
new SingleDownloadTask().execute();
break;
case R.id.button_download_muti:
new Thread(new Runnable() {
@Override
public void run() {
downloadMuti();
}
}).start();
break;
default:
break;
}
}
/**
* 多線程下載方式
* 作用是打開網絡連接,建立被下載文件存放路徑,開啟多個下載線程並發送文件下載進度的消息
*/
private void downloadMuti() {
try {
String urlPath = http://192.168.0.30:8080/MyWebTest/music/aa.mp3;
URL url = new URL(urlPath);
//連接下載地址
URLConnection connection = url.openConnection();
//得到文件長度
fileLength = connection.getContentLength();
//找到或創建下載文件的存放路徑
File file = new File(Environment.getExternalStorageDirectory(),ee.mp3);
if(!file.exists()){
file.createNewFile();
}
MutiThread[] threads = new MutiThread[5];
//進行五次分段下載,因為int型的整除會捨棄余數,最後一個進程下載的長度是從文件長度的4/5到文件總長度
for(int i=0;i<5;i++){
MutiThread thread = null;
if(i==4){
thread = new MutiThread(fileLength/5*4,fileLength,urlPath,file.getAbsolutePath());
}else{
thread = new MutiThread(fileLength/5*i,fileLength/5*(i+1)-1,urlPath,file.getAbsolutePath());
}
thread.start();
threads[i] = thread;
}
boolean isFinish = true;
//如果沒有下載完全時不斷的更新下載進度,數據通過Message傳遞給handler
while (isFinish){
int sum=0;
for(MutiThread thread:threads){
sum+=thread.getSum();
}
Message msg = handler.obtainMessage();
msg.what = 0x23;
msg.arg1 = sum;
handler.sendMessage(msg);
//一般一個被下載的文件可能無法下載完全
if(sum+10>fileLength){
isFinish=false;
}
//被隔一秒,更新一次進度
Thread.sleep(1000);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//單線程下載,用的是AsyncTask線程
class SingleDownloadTask extends AsyncTask{
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
mSeekBarDownload.setProgress((int) (values[0]*100.0/values[1]));
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
@Override
protected String doInBackground(String... params) {
try {
URL url = new URL(http://192.168.0.30:8080/MyWebTest/music/aa.mp3);
URLConnection connection = url.openConnection();
int length = connection.getContentLength();
InputStream is = connection.getInputStream();
File file = new File(Environment.getExternalStorageDirectory(),aa.mp3);
if(!file.exists()){
file.createNewFile();
}
FileOutputStream fos = new FileOutputStream(file);
byte[] array = new byte[1024];
int index = is.read(array);
int progress = 0;
while(index!=-1){
fos.write(array,0,index);
progress+=index;
publishProgress(progress,length);
index = is.read(array);
}
fos.flush();
fos.close();
is.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
}
多線程的下載線程的寫法
public class MutiThread extends Thread {
private int sum = 0;
private long start;
private long end;
private String urlPath;
private String filePath;
public MutiThread(long start, long end, String urlPath, String filePath) {
this.start = start;
this.end = end;
this.urlPath = urlPath;
this.filePath = filePath;
}
public int getSum() {
return sum;
}
@Override
public void run() {
try {
URL url = new URL(urlPath);
URLConnection connection = url.openConnection();
connection.setAllowUserInteraction(true);
//設置當前線程下載的起點,終點
connection.setRequestProperty(Range, bytes= + start + - + end);
InputStream is = connection.getInputStream();
byte[] array = new byte[1024];
File file = new File(filePath);
//使用java中的RandomAccessFile 對文件進行隨機讀寫操作
RandomAccessFile randomAccessFile = new RandomAccessFile(file,rw);
//設置開始寫文件的位置
randomAccessFile.seek(start);
int index = is.read(array);
//開始循環以流的形式讀寫文件
while(index!=-1){
randomAccessFile.write(array,0,index);
sum += index;
index = is.read(array);
}
randomAccessFile.close();
is.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
結果演示:
單線程下載:
多線程下載:
顯然,多線程下載要比單線程下載快得多,但前提是手機是多核的。
有時候,我們的實體類中會有一些屬性,但是數據庫中沒有對應的類型,這個時候我們就需要自定義轉換器進行類型轉換。很常見的處理就是Date類型一般如果精度要求不高的話我們會轉換
在微信的運營過程中難免會出現一些無法預料的事情,比如在朋友圈被惡評,甚至被某些別有用
前言首先我們需要分析MobSF的源碼,明白一個apk的靜態分析的步驟是什麼。經過分析,如何將apk文件解壓就是進行apk行為分析的第一步,確切的說應該是第二步,第一步應該
運行結果:為了在坦克上方畫血條 。血條首先要有坐標x,y 寬和高width和height血量的多少life也要有。所以新建類Life要有這些參數Life類如下: