当前位置: 首页 > news >正文

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

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

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

运行效果图:175026_nMHz_3630543.png

注意事项:安卓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;
 	   }
}

 

转载于:https://my.oschina.net/u/3630543/blog/1647368

相关文章:

  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • 技术相对论之软件架构
  • Fragment 生命周期怎么来的?
  • Redis和Memcache和MongoDB简介及区别分析(整理)
  • ubuntu16.4安装最新版wine3.0
  • c++中局部变量初始化的问题
  • WordCount
  • 外卖也智能!美团骑手智能助手的技术与实践
  • 【协议转换和消息路由】camel-spring-boot-starter 实践
  • 坑货!阿里奇门中心
  • [ssh]如何设计ARM板上多用户key登录系统
  • 71. Simplify Path
  • numpy 数组运算
  • Java 选择排序selection sort
  • 磁盘管理
  • 【技术性】Search知识
  • Angular4 模板式表单用法以及验证
  • el-input获取焦点 input输入框为空时高亮 el-input值非法时
  • git 常用命令
  • Git同步原始仓库到Fork仓库中
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • JavaScript工作原理(五):深入了解WebSockets,HTTP/2和SSE,以及如何选择
  • Magento 1.x 中文订单打印乱码
  • MySQL常见的两种存储引擎:MyISAM与InnoDB的爱恨情仇
  • node-glob通配符
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • PhantomJS 安装
  • Quartz初级教程
  • ReactNative开发常用的三方模块
  • Swift 中的尾递归和蹦床
  • webgl (原生)基础入门指南【一】
  • Web设计流程优化:网页效果图设计新思路
  • zookeeper系列(七)实战分布式命名服务
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 动态规划入门(以爬楼梯为例)
  • 翻译:Hystrix - How To Use
  • 基于Dubbo+ZooKeeper的分布式服务的实现
  • 使用 QuickBI 搭建酷炫可视化分析
  • 用jquery写贪吃蛇
  • 栈实现走出迷宫(C++)
  • ​2021半年盘点,不想你错过的重磅新书
  • # 数论-逆元
  • #、%和$符号在OGNL表达式中经常出现
  • #《AI中文版》V3 第 1 章 概述
  • #1014 : Trie树
  • #ifdef 的技巧用法
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (09)Hive——CTE 公共表达式
  • (delphi11最新学习资料) Object Pascal 学习笔记---第5章第5节(delphi中的指针)
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (MonoGame从入门到放弃-1) MonoGame环境搭建
  • (windows2012共享文件夹和防火墙设置
  • (附源码)springboot宠物医疗服务网站 毕业设计688413
  • (力扣记录)235. 二叉搜索树的最近公共祖先
  • (论文阅读40-45)图像描述1