界面布局 代码 知识点
<?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:background="@drawable/logo2"
android:gravity="center_horizontal"
android:orientation="vertical"
android:id="@+id/ll_splash_main"
>
<TextView
android:id="@+id/tv_splash_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="280dip"
android:text="版本号"
android:textColor="#FF01b6f8"
android:textSize="20sp" />
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dip" />
</LinearLayout>
package cn.itcast.mobilesafe.ui;
import java.io.File;
import cn.itcast.mobilesafe.R;
import cn.itcast.mobilesafe.R.layout;
import cn.itcast.mobilesafe.domain.UpdataInfo;
import cn.itcast.mobilesafe.engine.DownLoadFileTask;
import cn.itcast.mobilesafe.engine.UpdataInfoService;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.ProgressDialog;
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.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class SplashActivity extends Activity {
private static final String TAG = "SplashActivity";
private TextView tv_splash_version;
private LinearLayout ll_splash_main;
private UpdataInfo info;
private ProgressDialog pd ;
private String versiontext;
//ProgressBar xml文件中没有使用.
//使用了AlertDialog.Builder来显示确定更新和取消更新按钮.
//ProgressDialog用来显示一个一直转圈圈的进度.
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
//调用默认的父类方法.
super.handleMessage(msg);
// 判断服务器版本号 和客户端的版本号 是否相同
//将弹出的if判断放入handler的handleMessage方法中.
//是因为(ˇˍˇ) 想使延迟两秒.
if (isNeedUpdate(versiontext)) {
Log.i(TAG, "弹出来升级对话框");
//
showUpdataDialog();
}
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 取消标题栏
requestWindowFeature(Window.FEATURE_NO_TITLE);
//设置布局
setContentView(R.layout.splash);
//得到控件pb
pd = new ProgressDialog(this);
//设置样式
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
//pb设置消息内容.
pd.setMessage("正在下载...");
//得到线性布局控件
ll_splash_main = (LinearLayout) this.findViewById(R.id.ll_splash_main);
//得到文本的控件
tv_splash_version = (TextView) this
.findViewById(R.id.tv_splash_version);
//通过自定义的方法得到版本号文字
versiontext = getVersion();
// 在此activity延时两秒钟 检查更新 .开启一个线程
new Thread(){
@Override
public void run() {
super.run();
try {
//延迟两秒
sleep(2000);
//发送一个空消息.之后handler就处理判断的逻辑.
handler.sendEmptyMessage(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
//tv设置文字.
tv_splash_version.setText(versiontext);
//得到渐变动画.
AlphaAnimation aa = new AlphaAnimation(0.0f, 1.0f);
aa.setDuration(2000);
//现形布局开启动画播放
ll_splash_main.startAnimation(aa);
// 完成窗体的全屏显示 // 取消掉状态栏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
/**
* 升级的对话框
*/
//弹出的升级对话框
private void showUpdataDialog() {
//得到builder this是当前acitivity的上下文.不能是getApplicationContext().
//若果是toast.操作数据库 .sharedpreference等.属于整个应用程序.
//应用程序的上下文,进程在他就在
// acitivity的上下文. acitivity在acitivity的上下文在.
AlertDialog.Builder buider = new Builder(this);
buider.setIcon(R.drawable.icon5);
buider.setTitle("升级提醒");
buider.setMessage(info.getDescription());
buider.setCancelable(false); // 让用户不能取消对话框
//当点击确定时,从网络上下载到sd卡并安装apk.
buider.setPositiveButton("确定", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Log.i(TAG, "下载apk文件" + info.getApkurl());
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
//开启线程,实现runnable接口.下载.得到路径,安装到sd卡.
DownLoadFileThreadTask task = new DownLoadFileThreadTask(info.getApkurl(), "/sdcard/new.apk");
//正在下载的进度条显示.
pd.show();
//new出线程,开启线程
new Thread(task).start();
}else{
Toast.makeText(getApplicationContext(), "sd卡不可用", 1).show();
//进入主界面
loadMainUI();
}
}
});
//取消的话,就直接进入主界面.
buider.setNegativeButton("取消", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Log.i(TAG, "用户取消进入程序主界面");
loadMainUI();
}
});
//builder创建显示.
buider.create().show();
}
//下载apk的方法.
private class DownLoadFileThreadTask implements Runnable {
private String path; // 服务器路径
private String filepath; // 本地文件路径
//构造方法,传入apk的路径和apk本地要保存的路径.
public DownLoadFileThreadTask(String path, String filepath) {
this.path = path;
this.filepath = filepath;
}
public void run() {
try {
//DownLoadFileTask类里面定义一个下载的方法,让这里直接用.
File file = DownLoadFileTask.getFile(path, filepath,pd);
Log.i(TAG,"下载成功");
pd.dismiss();
install(file);
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "下载文件失败", 0).show();
pd.dismiss();
loadMainUI();
}
}
}
/**
*
* @param versiontext
* 当前客户端的版本号信息
* @return 是否需要更新
*/
//做一个判断,看是否需要升级. 如果返回为true.向主界面发出消息,弹出升级对话框.
private boolean isNeedUpdate(String versiontext) {
//得到engine包里的UpdataInfoService.
UpdataInfoService service = new UpdataInfoService(this);
try {
//得到实体信息.
info = service.getUpdataInfo(R.string.updataurl);
//得到网络的版本号
String version = info.getVersion();
if (versiontext.equals(version)) {
Log.i(TAG, "版本相同,无需升级, 进入主界面");
loadMainUI();
return false;
} else {
Log.i(TAG, "版本不同,需要升级");
return true;
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(this, "获取更新信息异常", 0).show();
Log.i(TAG, "获取更新信息异常, 进入主界面");
loadMainUI();
return false;
}
}
/**
* 获取当前应用程序的版本号
*
* @return
*/
//得到包管理器 得到包信息 得到版本号
private String getVersion() {
try {
PackageManager manager = getPackageManager();
PackageInfo info = manager.getPackageInfo(getPackageName(), 0);
return info.versionName;
} catch (Exception e) {
e.printStackTrace();
return "版本号未知";
}
}
private void loadMainUI() {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
finish(); // 把当前activity从任务栈里面移除
}
/**
* 安装apk
* @param file
*/
private void install(File file){
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
finish();
startActivity(intent);
}
}
package cn.itcast.mobilesafe.engine;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.ProgressDialog;
public class DownLoadFileTask {
/**
*
* @param path 服务器文件路径
* @param filepath 本地文件路径
* @return 本地文件对象
* @throws Exception
*/
public static File getFile(String path,String filepath,ProgressDialog pd) throws Exception{
//得到apk的网络路径
URL url = new URL(path);
//得到连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
if(conn.getResponseCode() == 200){
//得到文件的大小.
int total = conn.getContentLength();
//pd
pd.setMax(total);
//得到输入流
InputStream is = conn.getInputStream();
//new出文件对象.
File file = new File(filepath);
//得到文件输出流
FileOutputStream fos = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int len = 0;
int process = 0;
while((len = is.read(buffer))!=-1){
//将流写入文件
fos.write(buffer, 0, len);
//process随着下载的增加而增加
process +=len;
//pd设置进度.自动会有一个百分比和 (当前下载/总len)的视图.
pd.setProgress(process);
}
fos.flush();
fos.close();
is.close();
return file;
}
return null;
}
}