当前位置: 移动技术网 > IT编程>移动开发>Android > 详谈闪屏页相关处理

详谈闪屏页相关处理

2019年07月24日  | 移动技术网IT编程  | 我要评论

内蒙古seo,平板车,海尔洗衣机故障维修

根据功能模块划分(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的子类

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持移动技术网!

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网