继上篇博客,我接下来做的是一个九宫格界面,但是对之前的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;
} } }