详谈闪屏页相关处理
根据功能模块划分(android开发推荐此方法)
- activity mobilesafe.activty
- 后台服务 mobilesafe.service
- 广播接受者 mobilesafe.receiver
- 数据库 mobilesafe.db.dao
- 对象(java bean) mobilesafe.domain/bean
- 自定义控件 mobilesafe.view
- 工具类 mobilesafe.utils
- 业务逻辑 mobilesafe.engine
闪屏页面(splash)作用:
- 展示logo,公司品牌
- 项目初始化
- 检测版本更新
- 校验程序合法性(比如:判断是否有网络,有的话才运行)
androidminifest.xml 四大组件都需要在这里配置
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mxn.mobilesafe" android:versioncode="1" //版本号 android:versionname="1.0" > //版本名 <uses-sdk android:minsdkversion="16" android:targetsdkversion="21" /> //项目所需的权限 <uses-permission android:name="android.permission.internet" /> <uses-permission android:name="android.permission.write_external_storage" /> <uses-permission android:name="android.permission.read_phone_state" /> <uses-permission android:name="android.permission.receive_boot_completed" /> <uses-permission android:name="android.permission.read_contacts" /> <uses-permission android:name="android.permission.send_sms" /> <uses-permission android:name="android.permission.receive_sms" /> <uses-permission android:name="android.permission.access_fine_location" /> <uses-permission android:name="android.permission.access_coarse_location" /> <uses-permission android:name="android.permission.access_mock_location" /> <uses-permission android:name="android.permission.vibrate" /> <uses-permission android:name="android.permission.process_outgoing_calls" /> <uses-permission android:name="android.permission.kill_background_processes"/> <uses-permission android:name="android.permission.get_package_size"/> <uses-permission android:name="android.permission.clear_app_cache"/> <application android:allowbackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/apptheme" > //主题 //activity的注册 <activity android:name="com.mxn.mobilesafe.activity.splashactivity" android:label="@string/app_name" > <intent-filter> //起始的activity <action android:name="android.intent.action.main" /> <category android:name="android.intent.category.launcher" /> </intent-filter> </activity> <activity android:name="com.mxn.mobilesafe.activity.homeactivity" /> <activity android:name="com.mxn.mobilesafe.activity.settingactivity" /> <activity android:name="com.mxn.mobilesafe.activity.lostfindactivity" > </activity> <activity android:name="com.mxn.mobilesafe.activity.setup1activity" > </activity> <activity android:name="com.mxn.mobilesafe.activity.setup2activity" > </activity> <activity android:name="com.mxn.mobilesafe.activity.setup3activity" > </activity> <activity android:name="com.mxn.mobilesafe.activity.setup4activity" > </activity> <activity android:name="com.mxn.mobilesafe.activity.contactactivity" > </activity> <activity android:name="com.mxn.mobilesafe.activity.atoolsactivity" > </activity> <activity android:name="com.mxn.mobilesafe.activity.addressactivity" > </activity> <activity android:name="com.mxn.mobilesafe.activity.callsafeactivity" > </activity> <activity android:name="com.mxn.mobilesafe.activity.appmanageractivity" > </activity> <activity android:name="com.mxn.mobilesafe.activity.taskmanageractivity"> </activity> <activity android:name="com.mxn.mobilesafe.activity.taskmanagersettingactivity"> </activity> <activity android:name="com.mxn.mobilesafe.activity.antivirusactivity"></activity> <activity android:name="com.mxn.mobilesafe.activity.applockactivity"></activity> <activity android:name="com.mxn.mobilesafe.activity.cleancacheactivity"></activity> //广播接收者的 注册 <receiver android:name=".receiver.bootcompletereceiver" > <intent-filter> <action android:name="android.intent.action.boot_completed" /> </intent-filter> </receiver> <receiver android:name=".receiver.smsreceiver" > <intent-filter android:priority="2147483647" > <action android:name="android.provider.telephony.sms_received" /> </intent-filter> </receiver> <!-- <receiver android:name=".receiver.outcallreceiver" >静态注册的广播 <intent-filter> <action android:name="android.intent.action.new_outgoing_call" /> </intent-filter> </receiver> --> //服务的注册 <service android:name="com.mxn.mobilesafe.service.locationservice" > </service> <service android:name="com.mxn.mobilesafe.service.addressservice" > </service> <service android:name="com.mxn.mobilesafe.service.killprocessservice"></service> <service android:name="com.mxn.mobilesafe.service.watchdogservice"></service> </application> </manifest>
activity_splash.xml
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingbottom="@dimen/activity_vertical_margin" android:paddingleft="@dimen/activity_horizontal_margin" android:paddingright="@dimen/activity_horizontal_margin" android:paddingtop="@dimen/activity_vertical_margin" tools:context="com.mxn.mobilesafe.splashactivity" android:background="@drawable/launcher_bg" android:id="@+id/rl_root"> <textview android:id="@+id/tv_version" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentbottom="true" android:layout_centerhorizontal="true" android:layout_marginbottom="202dp" android:textsize="22sp" android:textcolor="#000" android:shadowcolor="#f00" //对版本号设置阴影 android:shadowdx="1" android:shadowdy="1" android:shadowradius="1" android:text="版本号:1.0" /> <progressbar android:id="@+id/progressbar1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_aligntop="@+id/tv_version" android:layout_centerhorizontal="true" android:layout_margintop="54dp" /> <textview android:id="@+id/tv_progress" android:visibility="gone" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignparentbottom="true" android:layout_alignparentleft="true" android:textcolor="#f00" android:textsize="16sp" android:text="下载进度" /> </relativelayout>
splashactivity.java
public class splashactivity extends activity { protected static final int code_update_dialog; protected static final int code_url_error; protected static final int code_net_error; protected static final int code_json_error; protected static final int code_enter_home; private textview tvversion; private textview tvprogress;// 下载进度展示 // 服务器返回的信息 private string mversionname;// 版本名 private int mversioncode;// 版本号 private string mdesc;// 版本描述 private string mdowmloadurl;// 下载地址 private handler mhandler = new handler() { public void handlemessage(android.os.message msg) { switch (msg.what) { case code_update_dialog: showupdatedialog();//显示升级对话框 break; case code_url_error: toast.maketext(splashactivity.this, "url错误", toast.length_short).show(); enterhome(); break; case code_net_error: toast.maketext(splashactivity.this, "网络错误", toast.length_short).show(); enterhome(); break; case code_json_error: toast.maketext(splashactivity.this, "json数据解析解析错误", toast.length_short).show(); enterhome(); break; case code_enter_home: enterhome(); break; default: break; } }; }; private sharedpreferences sp; private relativelayout rlroot; @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("版本号:" + getversioncode());//给版本号设置内容,动态获取的值 rlroot = (relativelayout) findviewbyid(r.id.rl_root); //判断是否需要自动更新 sp = getsharedpreferences("config", mode_private); boolean autoupdate = sp.getboolean("auto_update", true); copydb("address.db");//拷贝归属地查询数据库 copydb("antivirus.db");//拷贝病毒库 //更新病毒库 updatevirus(); if(autoupdate){ checkversion(); }else{ mhandler.sendemptymessagedelayed(code_enter_home, 2000); } //闪屏页渐变动画效果 alphaanimation anim = new alphaanimation(0.3f, 1f); anim.setduration(2000); rlroot.startanimation(anim); } //更新病毒数据库 private void updatevirus() { //联网从服务器获取到最近数据的md5的特征码 httputils httputils = new httputils(); string url = "http://172.28.3.112:8080/virus.json"; httputils.send(httpmethod.get, url, new requestcallback<string>(){ @override public void onfailure(httpexception arg0, string arg1) { // todo auto-generated method stub } @override public void onsuccess(responseinfo<string> arg0) { // todo auto-generated method stub //system.out.println(arg0.result); // jsonobject jsonobject = new jsonobject(arg0.result); // string md5 = jsonobject.getstring("md5"); // string desc = jsonobject.getstring("desc"); } }); } // 获取本地版本号 private int getversioncode() { packagemanager packgemanager = getpackagemanager();//拿到包的管理者。。包管理器,获取手机里面每个apk的信息(清单文件信息) try {// 获取包的信息。。 getpackagename()当前应用程序的包名 等于 package="com.mxn.mobilesafe" packageinfo packageinfo = packgemanager.getpackageinfo(getpackagename(), 0); int versioncode = packageinfo.versioncode; string versionname = packageinfo.versionname; system.out.println("versionname=" + versionname + ";" + "versioncode=" + versioncode); return versioncode; } catch (namenotfoundexception e) { // 没有找到包名时 e.printstacktrace(); } return -1; } // 从服务器获取版本信息进行校验 private void checkversion() { final long starttime = system.currenttimemillis(); new thread() {// 网络访问在分线程异步加载数据 public void run() { message msg = message.obtain(); httpurlconnection con = null; try {// 本机地址:localhost 如果用模拟器加载本机的地址:用10.0.0.2来替换 url url = new url("http://10.0.2.2:8080/update.json"); // 打开连接 con = (httpurlconnection) url.openconnection(); con.setrequestmethod("get");//设置请求方法 con.setconnecttimeout(5000);// 设置连接超时,5s con.setreadtimeout(5000);// 设置响应超时,链接上了,但服务器迟迟没有响应 con.connect();// 链接服务器 int responsecode = con.getresponsecode();//获取响应码 if (responsecode == 200) { // 获取返回值 inputstream inputstream = con.getinputstream(); // 流转化为字符串 string result = streamutils.readformstream(inputstream);//自己定义的streamutils工具类 system.out.println("网络结果返回:" + result); //result是一个json字符串,进行解析 // 解析json jsonobject jo = new jsonobject(result); mversionname = jo.getstring("versionname");//拿到服务器端的版本名 mversioncode = jo.getint("versioncode");//拿到服务器端的版本号 mdesc = jo.getstring("description");//拿到服务器端的版本描述 mdowmloadurl = jo.getstring("downloadurl");//拿到服务器端的下载链接 system.out.println(mdesc); system.out.println(mversioncode); // 服务器的大于 本地的,判断是否有更新,如果大于 则有更新需要更新,弹出升级对话框 if (mversioncode > getversioncode()) { system.out.println("进行比较,有版本更新"); msg.what = code_update_dialog; // showupdatedialog();//这句是在子线程更新界面,android不能在子线程更新界面,要想在子线程更新界面所以用到handler. } else {// 如果没有版本更新 msg.what = code_enter_home; } } } catch (malformedurlexception e) {// url错误的异常 msg.what = code_url_error; e.printstacktrace(); } catch (ioexception e) {//网络错误异常 // 这个是可以携带数据的msg.obj = msg.what = code_net_error;// what只是一个标识,用来区分消息! e.printstacktrace(); } catch (jsonexception e) {// json解析失败 msg.what = code_json_error; e.printstacktrace(); } finally { long endtime = system.currenttimemillis(); long timeused = endtime - starttime;// 访问网络花费的时间 if (timeused < 2000) { try {// 强制休眠2s,保证闪屏页面2s thread.sleep(2000 - timeused); } catch (interruptedexception e) { // todo auto-generated catch block e.printstacktrace(); } } mhandler.sendmessage(msg);// 消息发送出去,在handlemessage里进行相应的处理 if (con != null) { con.disconnect(); } } } }.start(); } //升级对话框 private void showupdatedialog() { system.out.println("正在升级对话框"); // 升级对话框 alertdialog.builder builder = new alertdialog.builder(this);//context对象 builder.settitle("最新版本" + mversionname); builder.setmessage(mdesc); // builder.setcancelable(false);//不让用户取消对话框,用户体验太差 builder.setpositivebutton("立即更新", new onclicklistener() { @override public void onclick(dialoginterface dialog, int which) { // todo auto-generated method stub system.out.println("立即更新"); // download方法 download(); } }); builder.setnegativebutton("以后再说", new onclicklistener() { @override public void onclick(dialoginterface dialog, int which) { enterhome(); } }); builder.setoncancellistener(new oncancellistener() { // 设置取消监听,用户点击返回键时触发 @override public void oncancel(dialoginterface dialog) { enterhome(); } }); builder.show(); } protected void download() {// 下载服务器端的apk文件 if (environment.getexternalstoragestate().equals(environment.media_mounted)) { // 判断是否有sd卡,sd卡挂载的时候才可以 tvprogress.setvisibility(view.visible);// 显示进度 string target = environment.getexternalstoragedirectory() + "/update.apk";//把文件下载到哪个路径下,sd卡的根目录 // xutils框架,使用httputils工具下载文件,下载一个jar包 httputils utils = new httputils(); utils.download(mdowmloadurl, target, new requestcallback<file>() { @override // 文件下载进度 public void onloading(long total, long current, boolean isuploading) { // todo auto-generated method stub super.onloading(total, current, isuploading); system.out.println("下载进度:" + current + "/" + total); tvprogress.settext("下载进度:" + current * 100 / total + "%"); } @override public void onsuccess(responseinfo<file> arg0) { // todo auto-generated method stub toast.maketext(splashactivity.this, "下载成功", toast.length_short).show(); // 下载完成之后,跳到系统的安装界面。。intent.action_view 是xml的action 标签 intent intent = new intent(intent.action_view);//系统的安装界面 intent.addcategory(intent.category_default); intent.setdataandtype(uri.fromfile(arg0.result), "application/vnd.android.package-archive"); // startactivity(intent); startactivityforresult(intent, 0);// 如果用户取消安装,会返回结果,回调方法onactivityresult,下文定义 } @override public void onfailure(httpexception arg0, string arg1) { // todo auto-generated method stub toast.maketext(splashactivity.this, "下载失败", toast.length_short).show(); } }); } else { toast.maketext(splashactivity.this, "没有sd卡", toast.length_short).show(); } } @override//用户取消安装,回调此方法 protected void onactivityresult(int requestcode, int resultcode, intent data) { // todo auto-generated method stub system.out.println("出现安装界面,用户点击取消时。"); enterhome(); super.onactivityresult(requestcode, resultcode, data); } private void enterhome() {// 进入主界面 intent intent = new intent(this, homeactivity.class); startactivity(intent); finish(); } //拷贝数据库,从assets目录下拷贝到data/data/com.mxn.mobilesafe/files目录下 private void copydb(string dbname){ //获取文件路径 file destfile = new file(getfilesdir(),dbname); if(destfile.exists()){ system.out.println("已存在"); } fileoutputstream out = null; inputstream in = null; try { in = getassets().open(dbname); out = new fileoutputstream(destfile); int len = 0; byte[] buffer = new byte[1024]; while((len = in.read(buffer))!=-1){ out.write(buffer,0,len); } } catch (ioexception e) { // todo auto-generated catch block e.printstacktrace(); }finally{ try { in.close(); out.close(); } catch (ioexception e) { // todo auto-generated catch block e.printstacktrace(); } } } }
streamutils.java
/* * 读取流的工具 * 把流对象转换成字符串对象 */ public class streamutils { //将输入流读取成string后返回 public static string readformstream(inputstream in) throws ioexception{ // 定义字节数组输出流对象 bytearrayoutputstream out = new bytearrayoutputstream(); // 定义读取的长度 int len = 0 ; // 定义读取的缓冲区 byte[] buffer = new byte[1024]; // 按照定义的缓冲区进行循环读取,直到读取完毕为止 while((len=in.read(buffer))!=-1){ // 根据读取的长度写入到字节数组输出流对象中 out.write(buffer,0,len); } string result = out.tostring(); // 关闭流 in.close(); out.close(); return result; // // 把读取的字节数组输出流对象转换成字节数组 // byte data[] = out.tobytearray(); // // 按照指定的编码进行转换成字符串(此编码要与服务端的编码一致就不会出现乱码问题了,android默认的编码为utf-8) // return new string(data, "utf-8"); } }
系统安装界面的activity的配置:
<activity android:name=".packageinstalleractivity" android:configchanges="orientation|keyboardhidden" android:theme="@style/theme.transparent"> <intent-filter> <action android:name="android.intent.action.view" /> <category android:name="android.intent.category.default" /> <data android:scheme="content" /> <data android:scheme="file" /> <data android:mimetype="application/vnd.android.package-archive" /> </intent-filter> </activity>
我们服务器用的是tomcat,里面放置 新版本的apk和update.json:
将代码打包为apk文件:
涉及的知识点:
packagemanager 包管理器,获取手机里面每个apk的信息(清单文件信息)
版本更新流程:
网络请求
> * url
> * httpurlconntetion
json解析
> * jsonobject 专门用来解析json
> * jsonarray
对话框弹出
> alertdialog
> alertdialog.builder
子线程更新ui
> * handler + message
> * runonuithread(runnable)
页面之间的跳转intent
github 一个开源的网站,下载xutils框架,将下载的jar包导入工程。
alertdialog.builder(this)
子类拥有父类的所有方法, 而且可以有更多自己的方法。父类无法有子类的方法
activity(token), context(没有token)
平时,要获取context对象的话, 优先选择activity, 避免bug出现, 尽量不用getapplicationcontext()
activity是context的子类
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!