您的位置:首页 > 理论基础 > 计算机网络

Android请求网络数据下载APK安装包

2018-03-19 00:00 176 查看
摘要: URLConnection InputStream OutputStream handler thread sd存储

今天写了个输入网址从网络下载一个apk安装包的小例子。把它记录下来以后方便自己使用。

运行效果图:


注意事项:安卓6.0系统以上要动态申请一些危险的权限,就是要主动弹出对话框问用户愿不愿意调取通信录名单,获得存储权限,创建文件权限等等,安卓6.0以前是安装时在Manifest写入的权限默认就拥有了,不需要询问客户。今天我写的程序是没有主动询问客户的代码(动态申请权限),所以在manifest中对uses-sdkVersion要注意,最大的版本要小于23,这样6.0以上手机就知道帮助你用兼容模式运行程序,不然是运行不出来的。

Manifest代码:

<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="22" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

XML代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center" >
<TextView
android:id="@+id/tv_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="文件存放位置" />
<TextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SD卡剩余空间" />
<Button
android:id="@+id/b_click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点击下载文件" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<!-- android:indeterminate="false"flase才是精确显示,开始写true不显示 !-->
<ProgressBar
android:id="@+id/pb_scheduel"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="200dp"
android:layout_height="50dp"
android:layout_centerHorizontal="true"
android:indeterminate="false"
android:progress="0"
android:max="100"/>
<TextView
android:id="@+id/tv_scheduel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_toRightOf="@+id/pb_scheduel"
android:textColor="#000000"
android:layout_centerHorizontal="true"
android:text="0%" />
</RelativeLayout>

</LinearLayout>

JAVA代码:

public class DownLoadFile extends FragmentActivity {
private Handler handler;
private TextView tv_address, tv_size, tv_scheduel;
private Button b_click;
private ProgressBar pb_scheduel;
private URL url;
private Message msg;
double totalLength = 0.0;
String downloadFileDirectory;
InputStream stream;
OutputStream output;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.download_file);
tv_address = (TextView) findViewById(R.id.tv_address);
tv_size = (TextView) findViewById(R.id.tv_size);
b_click = (Button) findViewById(R.id.b_click);
pb_scheduel = (ProgressBar) findViewById(R.id.pb_scheduel);
tv_scheduel = (TextView) findViewById(R.id.tv_scheduel);
pb_scheduel.setProgress(0);

try {
// url=new
// URL("https://clfile.imooc.com/class/assist/119/4858629/Android%206.0%20%E5%8A%A8%E6%80%81%E6%9D%83%E9%99%90%E7%94%B3%E8%AF%B7.pdf");
url = new URL("https://www.imooc.com/mobile/mukewang.apk");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
handler = new myHandler();
b_click.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
Thread thread = new myThread();
thread.start();
}
});
}

class myHandler extends Handler {
int Progress;

@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
if (msg.what == 555) {
Progress = msg.arg1;//handler创建在主线程中,现在的代码运行在主线程中
pb_scheduel.setProgress(Progress);// 设置进度条进度
tv_scheduel.setText(Progress + "%");// 显示
} else if (msg.what == 777) {
tv_size.setText("SD卡剩余空间:" + msg.getData().getString("sd"));// bundle的方式取数据
tv_address.setText("SD卡路径:" + msg.getData().getString("a"));
}
}
}

class myThread extends Thread {

@SuppressWarnings("unused")
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
// 判断存储卡是否存在是否可读可写
if (Environment.MEDIA_MOUNTED.equals(Environment
.getExternalStorageState())) {
downloadFileDirectory = Environment
.getExternalStorageDirectory()
+ File.separator
+ "downSB" + File.separator + "mukewang.apk";// 下载的文件路径
File file = new File(downloadFileDirectory);
if (!file.exists())// 判断文件目录是否存在
file.getParentFile().mkdirs();// File.getParentFile()获取父目录不包括文件名,不存在则创建
try {
file.createNewFile();// 创建what.apk文件
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
URLConnection connect = null;
try {
if (url != null)
connect = url.openConnection();// 返回一个connection
else {
System.out.println("你提供那个的网址不能下载。");
return;
}
totalLength = connect.getContentLength();// 下载的文件总长度
msg = handler.obtainMessage(777);
Bundle bundle = new Bundle();// bundle方式传递数据
bundle.putString("a", Environment
.getExternalStorageDirectory().getPath());
bundle.putString("sd", SDStorage
.GetSDAvailableSize(getApplicationContext()));
msg.setData(bundle);// bundle和msg的联系
handler.sendMessage(msg);
if (totalLength < SDStorage
.GetSDAvailableSize2(getApplicationContext())) {// 错误点看错了,long和double可以比较
int length = 0;
stream = connect.getInputStream();// 返回输入流
byte[] b = new byte[1024];
output = new FileOutputStream(file);// 创建输出到文件的输出流
int downloadSize = 0;// 已经下载的文件长度
while ((length = stream.read(b)) != -1) {// 每次读取到数组b中返回实际读取的字节数
output.write(b,0,length);// 从b数组中拿到往文件中写入
downloadSize += length;
msg = handler.obtainMessage(555);// 555标志消息
msg.arg1 = (int) (downloadSize * 100 / totalLength);// 求出现在的进度
handler.sendMessage(msg);// 发送到主线程更新进度条
}
stream.close();
output.close();
} else {
// Toast.makeText(DownLoadFile.this, "手机存储空间不够",
// 1).show();//子线程中不显示toast,不该写
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} else {
// Toast.makeText(DownLoadFile.this, "您的存储设备不允许使用",
// Toast.LENGTH_LONG).show();
}
}
}

}

SD卡剩余空间的计算代码:

public class SDStorage {
/**
* @获取手机SD卡里剩余可用空间大小
* 存储区域被划分为多个块,有些块不能使用
*/
@SuppressLint("NewApi") public static String GetSDAvailableSize(Context context){
long blockSize=0;//单个存储分块大小
long availableBlocks;//可用的存储分块数
File file=Environment.getExternalStorageDirectory();//获取外部存储设备的抽象形式,SD卡
StatFs statFs=new StatFs(file.getPath());//file.getPath()获取文件的路径,statFs获取存储设备的使用情况的抽象
if(Build.VERSION.SDK_INT>Build.VERSION_CODES.JELLY_BEAN_MR2 ){//安卓API的版本号>18,进build文件看每个版本的常量名
blockSize=statFs.getBlockSizeLong();//获取存储块的大小
availableBlocks=statFs.getAvailableBlocksLong();//获取能使用的存储快数
}else{
blockSize=statFs.getBlockSize();
availableBlocks=statFs.getAvailableBlocks();
}
return Formatter.formatFileSize(context, availableBlocks*blockSize);//long字节转化为字符串GB字节
}
@SuppressLint("NewApi") public static long GetSDAvailableSize2(Context context){
long blockSize=0;//单个存储分块大小
long availableBlocks;//可用的存储分块数
File file=Environment.getExternalStorageDirectory();//获取外部存储设备的抽象形式,SD卡
StatFs statFs=new StatFs(file.getPath());//file.getPath()获取文件的路径,statFs获取存储设备的使用情况的抽象
if(Build.VERSION.SDK_INT>Build.VERSION_CODES.JELLY_BEAN_MR2 ){//安卓API的版本号>18,进build文件看每个版本的常量名
blockSize=statFs.getBlockSizeLong();//获取存储块的大小
availableBlocks=statFs.getAvailableBlocksLong();//获取能使用的存储快数
}else{
blockSize=statFs.getBlockSize();
availableBlocks=statFs.getAvailableBlocks();
}
return blockSize*availableBlocks;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐