Android下载更新的安装包以及九宫格界面
继上篇博客,我接下来做的是一个九宫格界面,但是对之前的Splash页面我还有要说的就是,当出现网络异常、json解析异常或者没有更新的时候,我们都必须要跳转到我们的主页面,因为Splash页面仅是展示一下我们的开发的品牌和版本信息,我们没有必要因为网络没有接通等一些异常,就让用户使用不了我们的软件。所以我们应该做的 是当出现这些异常的时候,我们要用Toast提示一下用户到底出现了什么异常。所以在之前的代码基础上我增加了红色的代码。
上篇博客当我们检查到新版本的时候,我们来下载这个安装包。以及显示下载的进度。下面我来展示一下效果图:
package com.itcast.mobilesafe58.activity; import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL; import org.json.JSONException;
import org.json.JSONObject; import com.itcast.mobilesafe58.utils.StreamUtils;
import com.itcast.mobilesafe58.utils.ToastUtils;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack; import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast; /*
* 展示品牌---->初始化数据---->检查版本---->校验合法性
*/
public class SplashActivity extends Activity {
private static final int UPDATE_DIALOG = 1;//更新提醒
private static final int NETWORK_ERROR = 2;//网络异常
private static final int JSON_ERROR = 3;//数据解析失败
private static final int URL_ERROR = 4;//网络异常
private static final int ENTER_HOME = 5;//跳转主页面
//控件初始化
private TextView tvVersion;
private TextView tvProgress;
//服务器的返回值
private String mVersionName;//成员变量
private int mVersionCode;
private String mDescription;
private String mDownloadUrl;
//消息传递
private Handler mHandler = new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case UPDATE_DIALOG:
showUpdateDialog();
break;
case NETWORK_ERROR:
ToastUtils.showToast(getApplicationContext(), "网络异常");
enterHome();
break;
case JSON_ERROR:
ToastUtils.showToast(getApplicationContext(), "数据解析失败");
enterHome();
break;
case URL_ERROR:
ToastUtils.showToast(getApplicationContext(), "网络连接异常");
enterHome();
break;
case ENTER_HOME:
enterHome();
default:
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
tvVersion = (TextView)findViewById(R.id.tv_version);
tvProgress = (TextView)findViewById(R.id.tv_progress);
tvVersion.setText("版本名:"+getVersionName());
checkVersion();//检查版本
}
/*
* 检查版本更新
*/
private void checkVersion() {
// TODO Auto-generated method stub
new Thread(){
long startTime = System.currentTimeMillis();//开始时间
Message msg = Message.obtain();//获取消息
public void run(){
try {
//
URL url = new URL("http://10.0.2.2:8080/versionCode.json");
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setConnectTimeout(2000);//连接网络超时
conn.setReadTimeout(2000);//读取超时
conn.setRequestMethod("GET");//访问方法
conn.connect();//连接网络
int responseCode = conn.getResponseCode();
if(responseCode == 200){
String result = StreamUtils.streamToString(conn.getInputStream());
System.out.println("访问成功--->"+result);
//json数据解析
JSONObject jo = new JSONObject(result);
mVersionName = jo.getString("versionName");
mVersionCode = jo.getInt("versionCode");
mDescription = jo.getString("description");
mDownloadUrl = jo.getString("downloadUrl");
System.out.println("versionCode--->"+mVersionCode);
if (getVersionCode()<mVersionCode) {//如果软件的版本与网络中的版本号不一致,提示用户更新版本
System.out.println("有新版本!!!");
msg.what = UPDATE_DIALOG;
}else{
System.out.println("没有新版本!!!");
//跳转到主页面
msg.what = ENTER_HOME;
}
}
} catch (MalformedURLException e) {
//url异常
// TODO Auto-generated catch block
msg.what = URL_ERROR;
e.printStackTrace();
} catch (IOException e) {
//网络异常
// TODO Auto-generated catch block
msg.what = NETWORK_ERROR;
e.printStackTrace();
}catch (JSONException e) {
//json异常
// TODO Auto-generated catch block
e.printStackTrace();
msg.what = JSON_ERROR;
}finally{
long endTime = System.currentTimeMillis();//访问网络结束时间
long timeUsed = endTime - startTime;//访问网络总的用时
if (timeUsed<2000) {//如果访问网络的时间小于2秒,就展示闪屏页面。目的是凑够两秒,来展示软件的品牌。
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} mHandler.sendMessage(msg);//发送消息
}
} }.start(); }
/*
* 用于提醒用户更新的提示窗
*/
protected void showUpdateDialog() {
// TODO Auto-generated method stub
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("发现新版本:"+mVersionName);
builder.setMessage(mDescription);//新版本的描述
builder.setPositiveButton("立即升级", new OnClickListener() { @Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
System.out.println("发现新版本");
downloadApk();
}
});
builder.setNegativeButton("以后再说", new OnClickListener() { @Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
enterHome();
}
});
builder.show(); }
/*
* 下载安装包
*/
protected void downloadApk(){
String target = Environment.getExternalStorageDirectory().getAbsolutePath()+"/mobilesafe.apk";
tvProgress.setVisibility(View.VISIBLE);
HttpUtils utils = new HttpUtils();
utils.download(mDownloadUrl, target, new RequestCallBack<File>() {
//下载成功
@Override
public void onSuccess(ResponseInfo<File> responseInfo) {
// TODO Auto-generated method stub
System.out.println("下载成功!!!!");
File result = responseInfo.result;
tvProgress.setVisibility(View.GONE);
enterHome();
}
/*
* 正在下载
* total 文件总大小
* current 当前下载的大小
* isUploading 是否正在上传
* (non-Javadoc)
* @see com.lidroid.xutils.http.callback.RequestCallBack#onLoading(long, long, boolean)
*/ public void onLoading(long total, long current, boolean isUploading) {
// TODO Auto-generated method stub
super.onLoading(total, current, isUploading);
//
int percent = (int) ((current*100)/total);
tvProgress.setText("下载进度:"+percent+"%");
}
//下载失败
@Override
public void onFailure(HttpException error, String msg) {
// TODO Auto-generated method stub
System.out.println("下载失败!!!!");
//ToastUtils.showToast(getApplicationContext(),"下载失败!!");
error.printStackTrace(); }
});
}
/*
* 获取版本名
*/
private String getVersionName() {
// TODO Auto-generated method stub
//获取包管理器
PackageManager pm = getPackageManager();
try {
PackageInfo packageInfo = pm.getPackageInfo(getPackageName(), 0);
int versionCode = packageInfo.versionCode;//获取版本号
String versionName = packageInfo.versionName;//获取版本名
System.out.println("versionName"+versionName+",versionCode"+versionCode);
return versionName;
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
/*
* 获取版本号
*/
private int getVersionCode() {
// TODO Auto-generated method stub
//获取包管理器
PackageManager pm = getPackageManager();
try {
PackageInfo packageInfo = pm.getPackageInfo(getPackageName(), 0);
int versionCode = packageInfo.versionCode;//获取版本号
return versionCode;
} catch (NameNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return 0;
}
//跳转到主页面
private void enterHome(){
startActivity(new Intent(this,HomeActivity.class));//开启的新的页面
finish();//结束原来的页面
} }
当我们运行程序的时候就会发现,我们的Splash页面展示的时间太短暂,为了更好的让Splash页面的功能能够体现我们让跳转页面的时间慢一点,这样我们就可以展示一下我们的品牌。但是如果用户的网速特别慢打开软件都需要花费很长时间,我们就没有必要让用户看我们的页面了。这样的话就需要我们来计算一下开始进入程序的时间,以及结束的时间,当用时小于2秒时,我们就让剩下的时间看一会闪屏页面。否则就直接跳转到主页面。所以我在我的程序中添加了一下的代码:上面程序的粉红色部分
好了,上篇的博客补充完毕。接下来介绍一下我做的九宫格页面。先把效果展示一下:
我们做九宫格经常用到的一个控件就是GridView,下面我把我的布局文件写在下面,这样的话可以更好的讲解一下九宫格当中的特殊属性:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/white"
android:orientation="vertical" >
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:background="#8866FF00"
android:textColor="#000"
android:textSize="30sp"
android:text="功能列表" />
<GridView
android:id="@+id/gv_home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:verticalSpacing="15dp" //这是定义每一行和每一行之间的间隔
android:numColumns="3"> //这是定义一行有几个图片 </GridView>
</LinearLayout>
下面是第一个功能模块-----》手机防盗功能的开发,当用户第一次点击手机防盗的时候会弹出一个设置密码的对话框,实现的效果图是:
实现代码是:
package com.itcast.mobilesafe58.activity; import com.itcast.mobilesafe58.utils.ToastUtils; import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Application;
import android.content.Intent;
import android.text.TextUtils;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView; public class HomeActivity extends Activity { private GridView gvHome;
//把需要添加的文字写在一个数组当中
private String[] mHomeList = new String[]{"手机防盗","通讯卫士",
"软件管家","病毒查杀","缓存清理","进程管理","流量统计","高级工具","设置中心"};
//把需要添加的图片放在一个数组当中
private int[] mImageIds = new int[]{R.drawable.shi04xi,
R.drawable.qi08ta,R.drawable.qi06ta,R.drawable.qi07ta,
R.drawable.qi07ta,R.drawable.qi08ta,R.drawable.qi09ta,
R.drawable.qi08ta,R.drawable.qi09ta}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
gvHome = (GridView)findViewById(R.id.gv_home);
gvHome.setAdapter(new HomeAdapter());//与ListView极其相似
//设置条目的点击事件
gvHome.setOnItemClickListener(new OnItemClickListener() {
//parent代表gridview,view代表每个条目的view对象,position代表每个条目的位置
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// TODO Auto-generated method stub
switch (position) {
case 0://手机防盗
showSafeDialog();
break;
case 1://通讯卫士
break;
case 2://软件管家
break;
case 3://病毒查杀
break;
case 4://缓存清理
break;
case 5://进程管理
break;
case 6://流量统计
break;
case 7://高级工具
break;
case 8://设置中心
break;
default:
break;
} } });
}
/*
* 密码弹窗
*/
protected void showSafeDialog() {
// TODO Auto-generated method stub
//弹出设置密码的对话框
showSetUpPswdDialog();
} /*
* 设置密码弹窗
*/
private void showSetUpPswdDialog() {
// TODO Auto-generated method stub
AlertDialog.Builder builder = new AlertDialog.Builder(this);
final AlertDialog dialog = builder.create();//创建dialog对象
View view = View.inflate(this, R.layout.dialog_set_password, null);
dialog.setView(view, 0, 0, 0, 0);//给dialog设置自定义的布局,强制把上下左右边距设置为0,为了兼容2.x版本
final EditText etPassword = (EditText)view.findViewById(R.id.et_password);
final EditText etPasswordConfirm = (EditText)view.findViewById(R.id.et_password_confirm);
Button btn_OK = (Button)view.findViewById(R.id.btn_ok);
Button btn_cancel = (Button)view.findViewById(R.id.btn_cancel);
btn_OK.setOnClickListener(new OnClickListener() {
/*
* 判断两次输入的密码是否为空,两次输入的密码是否一致
* (non-Javadoc)
* @see android.view.View.OnClickListener#onClick(android.view.View)
*/
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
String password = etPassword.getText().toString().trim();
String passwordConfirm = etPasswordConfirm.getText().toString().trim();
if (TextUtils.isEmpty(password)&&TextUtils.isEmpty(passwordConfirm)) {
ToastUtils.showToast(getApplicationContext(), "输入框不能为空");
}else{
if (password .equals(passwordConfirm)) {
ToastUtils.showToast(getApplicationContext(), "登录成功");
dialog.dismiss();//隐藏弹窗
HomeActivity.this.startActivity(new Intent(getApplicationContext(),LostAndFindActivity.class));
}else{
ToastUtils.showToast(getApplicationContext(), "两次输入的密码不一致!");
}
}
} private void startActivity(Application application,
Class<LostAndFindActivity> class1) {
// TODO Auto-generated method stub }
});
btn_cancel.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
// TODO Auto-generated method stub }
});
dialog.show();
}
/*
* 九宫格数据适配器
*/
class HomeAdapter extends BaseAdapter{
//得到item的个数
@Override
public int getCount() {
// TODO Auto-generated method stub
return mHomeList.length;
}
//根据位置获取对象
@Override
public String getItem(int position) {
// TODO Auto-generated method stub
return mHomeList[position];
}
//
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
//初始化每一个item的布局
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View view = View.inflate(getApplicationContext(), R.layout.list_item_home, null);
ImageView ivHome = (ImageView)view.findViewById(R.id.iv_home);
TextView tvHome = (TextView) view.findViewById(R.id.tv_home);
tvHome.setText(mHomeList[position]);
ivHome.setImageResource(mImageIds[position]);
return view;
} } }
Android下载更新的安装包以及九宫格界面的更多相关文章
- 如何离线下载Chrome的安装包
打开Chrome官网(自行搜索)点击下载后下载的是联网安装包,这对部分上网不方便的用户造成了一定的麻烦. http://www.google.cn/chrome/browser/desktop/ind ...
- 如何下载flash离线安装包
如何下载flash离线安装包 CreateTime--2018年4月14日16:02:13 Author:Marydon 1.下载地址 UpdateTime--2018年5月13日16点55分 p ...
- python中安装下载超时,下载不了安装包
python3 -m pip install scapy 执行上面命令报错,下载超时,下载不了安装包 Collecting scapy WARNING: Retrying (Retry(total=4 ...
- 无法从NVIDA官网下载安装CUDA安装包?NVIDA官网怎么了?
最近几天由于不知名的原因,导致很多人无法从官网下载NVIDA的CUDA安装包,下载时,浏览器提示此文件可能危害你的计算机,选择保留下载下来也只是一个42字节的exe文件 双击进行安装又出现以下问题: ...
- mysql官网下载linux版本安装包
原文地址:点击打开链接 今天在Linux上部署项目,用到了Mysql,因此想要下载适用于Linux的安装版本,在Mysql官网找了半天,终于找到怎样下载了,这里写出来,以后大家找的时候就好找了. 第一 ...
- Visual Studio2019下载最新离线安装包
首先可以参考微软官方的离线安装说明-->点击这里打开 =================================================================== 1. ...
- ClickOnce部署(4):下载多个安装包
有时候,我们可能会一次性发布多个安装包,当然在网页上多加几个链接让用户逐个安装也是可取的.不过,也可以弄得更方便些,即用户先安装一个,作为一个"引导程序",然后通过这个程序去下载安 ...
- 微软MSDN订阅用户已可提前手工下载Windows 10安装包
在Windows 10发布之夜,当全世界都在翘首以盼Windows 10免费发布推送的到来,MSDN订阅用户可以立马享受一项令人项目的特殊待遇:手工下载Windows 10完整安装包+免费使用的激活密 ...
- 微信android混淆打包减少安装包大小
首先,感谢微信android团队的分享 微信中的资源混淆工具主要为了混淆资源ID长度(例如将res/drawable/welcome.png混淆为r/s/a.png),同时利用7z深度压缩,大大减少了 ...
随机推荐
- REST vs SOAP
REST vs SOAP These information searched from internet most from stackoverflow. Simple explanation ab ...
- plsql修改表报错:ORA-25150
几次通过plsql修改表结构出现这个错误,为人不求甚解真是要不得.我甚至对老大大言不惭的说没有权限,即便是sql语句都不行.结果赤果果地打脸. 最终找到如下原因: 1.操作用户表空间的默认值问题: 这 ...
- 【Pig源码分析】谈谈Pig的数据模型
1. 数据模型 Schema Pig Latin表达式操作的是relation,FILTER.FOREACH.GROUP.SPLIT等关系操作符所操作的relation就是bag,bag为tuple的 ...
- Elaticsearch REST API常用技巧
在Elasticsearch的REST API中,有很多使用技巧,这里针对官方文档给出的介绍,总结了几个常用的例子. 更多内容参考:Elastisearch文档总结 多索引 ES支持在一次请求中指定多 ...
- 一篇学习HTTP状态码的神文:我与依依的橙色岁月
好的,事情是这样的,数年前,我曾有过一段美好的夏日恋情,在此与大家分享. 依依 这个女孩叫做依依 ,她是 80 后的,生日是 1989 年 3 月吧,忘了哪一天了,分手太久了,记不起来了. 转学生 我 ...
- JS魔法堂:彻底理解0.1 + 0.2 === 0.30000000000000004的背后
Brief 一天有个朋友问我“JS中计算0.7 * 180怎么会等于125.99999999998,坑也太多了吧!”那时我猜测是二进制表示数值时发生round-off error所导致,但并不清楚具体 ...
- linux专题一之文件归档和压缩(tar、file、zip)
本文主要从以下几个方便来说明文件的归档和压缩,同时比较几种不同压缩方法的压缩比率及特点. 文件归档命令tar,tar.gz源码包的安装管理 创建tar包-解压-查询tar包内容 zip命令的用法 为 ...
- Microsoft Visual Studio Ultimate 2013 Update 2 RC 英文版--离线完整安装ISO+简体中文语言包
VS2013.2_RC_EN_Full.iso:名称:Microsoft Visual Studio 2013版本:Ultimate 2013 Update 2 RC语言:English在线下载:ht ...
- 基于ListBox的相关操作
Winform中两个listbox的操作是平时比较常用的操作. 本次将以一个Winform实例来分享一下两个listbox的操作,包括:listbox添加项,项的上移下移等操作. 假设有两个listb ...
- SQL如何增删修改字段
1: 新增字段: ) NULL EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'土地手续办理情况' , @level ...