下载网络资源并存储到本地
一.知识要求
二.功能设计
三.代码实现
四.注意事项
一.知识要求:
handler基础,网络请求基础,文件操作基础
二.功能设计:
我们要设计一个能下载特定网络文件的小程序,并且能将加载进度实时显示在屏幕上。
功能:
网络请求->下载文件->实时显示->本地文件存储
三.代码实现:
3.1布局文件:
一个比较简单的布局,包含一个按钮和一个进度条。
<android.support.constraint.ConstraintLayout 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=".downLoadActivity">
<Button
android:id="@+id/button2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:max="100"
app:layout_constraintBottom_toTopOf="@+id/button2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
3.2java文件
public class downLoadActivity extends AppCompatActivity {
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_down_load);
/*获取控件实例*/
Button button= findViewById(R.id.button2);
final ProgressBar progressBar = findViewById(R.id.progressBar);
/*动态请求本地文件读写权限*/
ActivityCompat.requestPermissions(downLoadActivity.this,new String[]{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
/*设置点击事件*/
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
downLoad("填写你的下载URL");
}
}).start();
}
});
/*处理子线程返回的消息*/
handler = new Handler()
{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what)
{
case 1001:
{
progressBar.setProgress((Integer) msg.obj);
break;
}
case 1002:
{
Toast.makeText(downLoadActivity.this, "下载失败!", Toast.LENGTH_SHORT).show();
}
}
}
};
}
private void downLoad(String url)
{
try {
/*获取网络连接*/
URL url1 = new URL(url);
URLConnection urlConnection = url1.openConnection();
InputStream inputStream = urlConnection.getInputStream();
int contentLength = urlConnection.getContentLength();
/*设置本地存储路径*/
String downloadFolderName = Environment.getExternalStorageDirectory()
+ File.separator+"file"+File.separator;
File file = new File(downloadFolderName);
if (!file.exists()){
file.mkdir();
}
/*设置下载文件名*/
String fileName = downloadFolderName + your"FileName";
File apkFile = new File(fileName);
if (apkFile.exists()){
apkFile.delete();
}
/*设置下载单元大小*/
int downloadSize=0;
byte[] bytes = new byte[1024];
int length=0;
OutputStream outputStream = new FileOutputStream(fileName);
while((length=inputStream.read(bytes))!=-1)
{
outputStream.write(bytes,0,length);
downloadSize+=length;
/*通知主线程更新进度条*/
Message message = Message.obtain();
message.obj=downloadSize*100/contentLength;
message.what=1001;
handler.sendMessage(message);
}
inputStream.close();;
outputStream.close();
} catch (MalformedURLException e) {
noticeDownlLoadFaile();
e.printStackTrace();
} catch (IOException e) {
noticeDownlLoadFaile();
e.printStackTrace();
}
}
/*下载失败调用*/
private void noticeDownlloadFailed() {
Message message = Message.obtain();
message.what=1002;
handler.sendMessage(message);
}
}
四.注意事项:
- 在布局文件中要设置进度条的总长度
- 在安卓6.0以后的系统中,不仅要在Manifest文件内写入需要的权限,而且要在代码里动态请求权限
- 在安卓9.0系统中,进行url开头是http而非https的网络请求需要配置
- 因为网络请求为耗时任务,所以要在子线程中进行,通过handler实时的将进度数据发出,然后在主线程更新进度条
- 下载结束后要关闭输入输出流,否则可能会造成OOM
效果:
如果有什么错误,欢迎不吝指正。