Android 斷點(diǎn)下載和自動(dòng)安裝的示例代碼
今天說一下Android中下載App到手機(jī)中并自動(dòng)安裝,啥也不說了先上效果圖了!


上面呢是下載中的一個(gè)圖片和下載后會(huì)自動(dòng)提示你安裝的一個(gè)圖片,二話不說,這接開代碼吧!
首先來一個(gè)下布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="zhangtao.bwie.com.continutransform.MainActivity">
<ProgressBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/progress"
style="?android:attr/progressBarStyleHorizontal"
android:max="100"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:textSize="22sp"
android:text=""
android:id="@+id/pro_text"
android:layout_below="@id/progress"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/start_btn"
android:text="開始下載"
android:layout_below="@id/pro_text"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/stop_btn"
android:text="停止下載"
android:layout_below="@id/start_btn"
/>
</RelativeLayout>
布局隨便寫了,只要是你想要的布局
然后我么來一個(gè)接口,用來幫助我么將要寫的下載工具類傳輸數(shù)據(jù)的:
package Download;
public interface DownloadListener {
void startDownload();
void stopDownload();
void finishDownload();
void downloadProgress(long progress);
}
這個(gè)接口寫了4個(gè)接口方法,分別是開始下載、停止下載、完成下載以及下載是的進(jìn)度。
接下來就是寫下載工具類了,下載呢就使用OkHttp進(jìn)行請(qǐng)求網(wǎng)絡(luò)數(shù)據(jù)了,這里把這個(gè)工具類寫成單利模式,方便使用!
package Download;
import android.text.TextUtils;
import android.util.Log;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
public class DownloadUtils {
private static volatile DownloadUtils instance;
private final OkHttpClient client;
private DownloadListener mlistener;
private File file;
private String fileAbsolutePath;
public File downloadFile;
private long startPosition;
private Call call;
public DownloadUtils() {
client = new OkHttpClient();
}
public void setListener(DownloadListener listener) {
this.mlistener = listener;
}
/**
* 初始化下載父路徑
* @return
*/
public void initDownload(String path) {
file = new File(path);
if(!file.getParentFile().exists()) {
file.getParentFile().mkdir();
}
if(!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
fileAbsolutePath = file.getAbsolutePath();
Log.d("zzz",fileAbsolutePath.toString());
}
public static DownloadUtils getInstance() {
if(instance == null) {
synchronized (DownloadUtils.class) {
if(instance == null) {
instance = new DownloadUtils();
}
}
}
return instance;
}
public void startDownload(String url) {
if(TextUtils.isEmpty(url)) {
return ;
}
if(url.contains(".")) {
String typename = url.substring(url.lastIndexOf(".") + 1);
if(url.contains("/")) {
String filename = url.substring(url.lastIndexOf("/") + 1, url.lastIndexOf("."));
String fn = filename+"."+typename;
downloadFile = new File(this.file, fn);
Log.d("zzz","downloadFile"+downloadFile.toString());
}
}
startPosition = 0;
if(downloadFile.exists()) {
startPosition = downloadFile.length();
}
final Request request = new Request.Builder()
.addHeader("RANGE","bytes="+startPosition+"-")
.url(url)
.build();
call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
mlistener.startDownload();
ResponseBody body = response.body();
// startPosition
long totalLength = body.contentLength() ;
Log.d("zzz", "totalLength: " + totalLength + "----");
InputStream is = body.byteStream();
byte[] bytes = new byte[2048];
int len = 0;
long totalNum = startPosition;
RandomAccessFile raf = new RandomAccessFile(downloadFile, "rw");
while ((len = is.read(bytes,0,bytes.length)) != -1) {
raf.seek(totalNum);
raf.write(bytes,0,len);
totalNum +=len;
mlistener.downloadProgress(totalNum * 100 / totalLength);
}
mlistener.finishDownload();
body.close();
}
});
}
public void stopDownload() {
mlistener.startDownload();
if(call != null && call.isExecuted()) {
call.cancel();
}
}
}
這里做斷點(diǎn)下載是使用了RandomAccessFile,大家可以網(wǎng)上去了解一下RandomAccessFile的作用。
下面是主界面的功能實(shí)現(xiàn)和調(diào)用,基本就是些獲取控件和調(diào)用剛才寫好的工具類:
package zhangtao.bwie.com.continutransform;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.io.File;
import Download.DownloadListener;
import Download.DownloadUtils;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private TextView pro_text;
private Button start_btn;
private Button stop_btn;
private String downloadUrl = "http://d.988wan.com/zft/qmzft32_988wan_01.apk";
private String path = "/ZhangTao/";
private ProgressBar pro_bar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
setOnClick();
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
File storageDirectory = Environment.getExternalStorageDirectory();
final String absolutePath = storageDirectory.getAbsolutePath();
path = absolutePath + path;
DownloadUtils.getInstance().initDownload(path);
DownloadUtils.getInstance().setListener(new DownloadListener() {
@Override
public void startDownload() {
}
@Override
public void stopDownload() {
}
@Override
public void finishDownload() {
File downloadFile = DownloadUtils.getInstance().downloadFile;
installApk(downloadFile);
}
@Override
public void downloadProgress(final long progress) {
runOnUiThread(new Runnable() {
@Override
public void run() {
pro_bar.setProgress((int) progress);
pro_text.setText(progress+"%");
}
});
}
});
}
}
private void initView() {
pro_text = (TextView) findViewById(R.id.pro_text);
start_btn = (Button) findViewById(R.id.start_btn);
stop_btn = (Button) findViewById(R.id.stop_btn);
pro_bar = (ProgressBar) findViewById(R.id.progress);
}
private void setOnClick() {
start_btn.setOnClickListener(this);
stop_btn.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.start_btn:
DownloadUtils.getInstance().startDownload(downloadUrl);
break;
case R.id.stop_btn:
DownloadUtils.getInstance().stopDownload();
break;
}
}
/**
* 安裝apk
* @param file
*/
private void installApk(File file) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.addCategory("android.intent.category.DEFAULT");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
startActivity(intent);
android.os.Process.killProcess(android.os.Process.myPid());
}
}
上面的自動(dòng)安裝是installApk這個(gè)方法,這個(gè)沒必要去了解太多,都是Android的一個(gè)固定方法,一般網(wǎng)上都會(huì)有的,希望可以幫到大家!
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- android多線程斷點(diǎn)下載-帶進(jìn)度條和百分比進(jìn)度顯示效果
- Android HttpURLConnection斷點(diǎn)下載(單線程)
- Android原生實(shí)現(xiàn)多線程斷點(diǎn)下載實(shí)例代碼
- 詳解Android中的多線程斷點(diǎn)下載
- Android入門:多線程斷點(diǎn)下載詳細(xì)介紹
- Android使用多線程實(shí)現(xiàn)斷點(diǎn)下載
- Android實(shí)現(xiàn)斷點(diǎn)下載的方法
- Android實(shí)現(xiàn)多線程斷點(diǎn)下載的方法
- Android實(shí)現(xiàn)斷點(diǎn)多線程下載
相關(guān)文章
Android通過ExifInterface判斷Camera圖片方向的方法
今天小編就為大家分享一篇關(guān)于Android通過ExifInterface判斷相機(jī)圖片朝向的方法,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2018-12-12
Android開發(fā)Kotlin語言協(xié)程中的并發(fā)問題和互斥鎖
Android開發(fā)Kotlin語言提供了多種機(jī)制來處理并發(fā)和同步,其中包括高層次和低層次的工具,對(duì)于常規(guī)的并發(fā)任務(wù),可以利用 Kotlin 協(xié)程提供的結(jié)構(gòu)化并發(fā)方式,而對(duì)于需要更低層次的鎖定機(jī)制,可以使用Mutex(互斥鎖)來實(shí)現(xiàn)對(duì)共享資源的線程安全訪問2024-06-06
flutter實(shí)現(xiàn)底部不規(guī)則導(dǎo)航欄
這篇文章主要為大家詳細(xì)介紹了flutter實(shí)現(xiàn)底部不規(guī)則導(dǎo)航欄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07
Android簡單實(shí)現(xiàn)動(dòng)態(tài)權(quán)限獲取相機(jī)權(quán)限及存儲(chǔ)空間等多權(quán)限
這篇文章主要介紹了Android簡單實(shí)現(xiàn)動(dòng)態(tài)權(quán)限獲取相機(jī)權(quán)限及存儲(chǔ)空間等多權(quán)限,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下2022-07-07
Android Studio+Servlet+MySql實(shí)現(xiàn)登錄注冊
對(duì)于大多數(shù)的APP都有登錄注冊這個(gè)功能,本文就來介紹一下Android Studio+Servlet+MySql實(shí)現(xiàn)登錄注冊,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05
Android Activity中使用Intent實(shí)現(xiàn)頁面跳轉(zhuǎn)與參數(shù)傳遞的方法
這篇文章主要介紹了Android Activity中使用Intent實(shí)現(xiàn)頁面跳轉(zhuǎn)與參數(shù)傳遞的方法,結(jié)合實(shí)例形式簡單分析了Android中的Activity交互操作相關(guān)技巧,需要的朋友可以參考下2016-07-07
Android實(shí)現(xiàn)閱讀進(jìn)度記憶功能
這篇文章主要介紹了Android實(shí)現(xiàn)閱讀進(jìn)度記憶功能,Android控件WebView實(shí)現(xiàn)保存閱讀進(jìn)度,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
Android自定義view實(shí)現(xiàn)多色進(jìn)度條GradientProgressView的繪制
我們常使用shape實(shí)現(xiàn)漸變色,但是shape的極限卻只有三色,如果有超過三種顏色的View的要求,那么我們就不得不去自定義View來實(shí)現(xiàn)這個(gè)需求,所以下面我們就來看看如何自定義view實(shí)現(xiàn)多色進(jìn)度條的繪制吧2023-08-08

