界面布局 代码 知识点
<?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; } }