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; } } }
原文地址:https://www.cnblogs.com/kangyaping/p/5500228.html