zoukankan      html  css  js  c++  java
  • 手机卫士01_业务分包,splash,packageInfo ,版本控制,替换安装,签名

    开题:手机卫士这样的一个项目可以很好的复习基础所学的知识点,因为它覆盖面广,用来做安卓深入学习是一个很好的选择.

    1,开始一个项目

    写一个好的代码不仅是看功能是否实现,而且代码具有较高的可读性

    1.1 代码组织方式:

    ①采用业务逻辑模块组织代码,以小米阅读为例:

    功能一:阅读器reader com.xiaomi.reader

    功能二:分享 share com.xiaomi.share

    功能三:便签 note com.xiaomi.note

    按功能划分包,即使一部分功能被移除了,另外的功能也不会受太大影响.一般用在OA类型的网站,自动化办公的小应用上,各自模块独立

    ②根据代码的类型组织包结构,以安全卫士为例:

    1,界面相关 com.zzx.mobliesafe.activitys

    2,服务相关 com.zzx.mobilesafe.service

    3,业务逻辑 com.zzx.mobilesafe.engine(引擎)

    4,数据库 com.zzx.mobilesafe.db

    5,数据库操作包 com.zzx.mobilesafe.db.dao

    6工具类 com.zzx.mobilesafe.utils

    7自定义view com.zzx.mobilesafe.ui

    2,_splash(,飞洒,卖弄)界面

    ①展现产品的Logo,提高产品知名度(也可以用作广告页面,打开APP的广告:知乎)

    ②初始化应用程序的数据

    ③链接服务器,查找可更新的版本,自动更新

    ④用户操作指南,新版本特性提醒

    布局文件的命名规则:activity_对应的java文件名即可

    2.2,

    设置界面为全屏更美观:

    Android:style/Theme.black.NoTitleBar.FullScreen //黑色全屏没有标题栏的界面

    在主界面显示版本号

    ①获取本地APP的版本号,在清单文件中获取

    packageInfo = getPackageManager().getPackageInfo(getPackageName()(获取当前APP的文件包名),flags(0,可选标示));

    String code = packageInfo.versionName;//清单文件的版本号

    这个 API不仅可以获得本APP,也可以获取别的APP,通过这个特性可以告知用户更新哪些APP.所以可以把这个API获取版本号抽取出来做成一个工具类

    抽取出来的时候要注意,getPackageManager()getPackageName()都是context调用的,所以抽取的方法需要传入一个上下文,其实也需要传入一个包名.

    如果一个方法没有使用类的成员变量就加静态方便调用.

    ②在界面上显示版本号,定义一个textView(ID命名要规范,控件名_Activity_用处)

    最后把版本号赋值给TextView;

    3,源代码的版本控制

    3.1 Android项目中不需要被管理的文件夹:

    .settings,bin,gen,.project,这些是需要ignore忽视的

    需要添加的:

    assets(需要原样封装到apk里面的文件),libs(外部引入的jar ),res(资源),src(源代码),.classpath,AndroidManifest.xml清单文件 ,ic_launcher-web.png图片

    proguard-project.text,project.properties(混淆编译的东西)

    4.软件自动更新

    4.1原理:拿到服务器版本号,跟本地版本号做比较,如果服务器版本号大于本地版本号,就弹出一个对话框,提示用户是否需要更新.

    如果需要更新:下载更新信息,替换安装

    如果不需要更新,那么可以选择让用户继续访问,或者直接退出程序

    如果本地版本号与服务器版本号一致或更高,就进入主界面

    4.2 获取服务器的版本号

    splash界面中,onCreate()方法里,链接网络,获取服务器版本号,因为需要访问网络,所以需要放到子线程中,在这里就定义一个类去实现runable

    CheckVersionTask类实现 Runable,重写run()方法.

    额外:①在tomact服务器中放置一个json文件,保存版本信息:{“version”:”2.0”}

    ②访问网络路径不要写死了,定义在values中的config.xml文件中String字符串

    继续网络访问

    .创建url对象,通过url获取网络链接,设置请求方式,超时时间.

    ,获取返回的状态码,判断是否=200.

    获取输入流转换成字符串,通过以前的工具类,或者再通过ByteArrayOutputStream,内存输出流把输入流中的信息保存在内存中,最后通过toString方法转换成字符串.(这里有需要对字符串进行转码的操作)

    ,json字符串进行解析JsonObject(大括号就是json对象,中括号就是json数组)

    jsonobject.getString(“键的名称”);

    额外:需要添加权限.

    5,应用程序的错误提醒

    当本地版本号小于服务器版本号的时候就需要提示用户更新版本.

    提示用户更新版本是在主线程中更新ui,如果在子线程中更新,需要通过handler发送消息.

    ①创建Message对象 message mes = Message.obtain();

    ②区分消息mes.what=XXXX;

    hanlder.sendMessage(mes);

    ③在主线程中判断发送过来的消息,如果符合就创建一个对话框,另外还有一些问题也需要通知用户(看需求来,不要把所有的异常全部删掉,一般互联网公司要求都比较多,不同的错误异常需要不同的提示)

    实际开发中,主要是把错误代码提示出来(用户不懂什么是异常,但是用户可以把错误代码提交给程序员或者是客服,根据不同的错误代码来区分不同的代码)

    ④升级提醒的对话框(这里可以考虑抽取一个方法,handler显得更简洁)

    AlertDialog.Builder buider = new Builder(上下文);

    指定标题,文本(这里的文本可以在JSON中添加数据,在获取服务器返回的JSON,解析出来更新的描述内容),确认和取消按钮.

    最后记得builder.show();//显示对话框在页面上.

    额外:解析出来的中文字符串乱码,windows系统默认GBK(改他就可以),android默认utf-8.

    6为了测试splash界面,创建一个主界面.配置清单文件,创建对应的布局文件,onCreate()中记得 set指定对应的布局文件(可以直接创建Activity文件,eclipse会自动配置好)

    6.1在提醒的对话框中,取消升级按钮的点击事件中,通过显示意图(速度快)开启界面,同时关闭splash界面finsh();把它销毁掉.

    6.2 确认按钮,在解析的JSON中添加一个path,把新版本的apk下载路径放进去即可.解析到需要更新的时候,把这个路径获取出来,如果用户点了确认,就打开这个路径下载

    额外:使用开源框架进行下载,直接通过输入流获取也行(多线程下载即可).

    这里就用xUtils框架,顺便练习一下使用.

    ①获得解析的apk下载路径

    ②创建httpUtils http = new httpUtis();对象

    http.download(下载路径,存放路径,下载状态回调)

    ③在回调中三个方法,一个成功,一个失败,另一个onLoding()显示下载的进度,显示一个进度条对话框(ProgressDialog),setProgressStyle(ProgressDialog.STYLE_HORIZONTAL)//设置水平方向的进度条,onLoading中设置最大值和进度数值.最后记得pd.show()

    不管是下载成功还是下载失败都记得要dismiss();关闭对话框.

    ④放到存储卡中记得判断 SD卡的状态:Environment.getExtrnalStorangeDirectory()

    如果SD卡不存在就直接进行主界面,并关闭页面,关闭之前提示SD卡不存在

    额外:最后还要添加权限,在服务器配置资源文件

    项目生成的apk bin目录下

    7,替换安装应用程序:模板代码

    ①定义一个意图对象intent  = new intent()//需要激活系统的包安装器packageInstaller.

    ②在上层服务的源码中可以找到它.通过查找清单文件packageInstallerActivity中的意图过滤器,setcategory(类别),setaction添加到意图对象中,指定data数据类型.

    注意:如果同时有schememimeType就要用setDataAndType(scheme(uri.parsefile(file)即可),mimetype).(这里的file并不是文件对象,要通过file.result获取)

    ③最后开启意图

    8,自动更新的细节问题.

    ①如果版本是最新的,进入主界面速度太快,所以需要让splash界面暂停一段时间(套路)

    SystemClock.sleep(xxxx);测试这个的时候,记得服务器版本和本地APP版本的区别

    ②如果用户没有点击对话框,点击别的地方,系统会默认关闭对话框,这时候界面就卡了,通过builder.setCancelable(false);//设置对话框不能被自动关闭.返回键也无效

    ③弹出了错误代码之后界面又卡了,这里需要让用户可以进入默认的主界面

    ④网络太差的时候,再睡两秒就不太合适了,这时候要去动态的获取时间,最开始获取一次时间,最后finally里再获取一次时间,判断两次时间的间隔,如果小于一定时间就睡眠一定时间(两秒减去间隔时间,如果大于两秒就直接进入主界面).

    ⑤代码优化,Message创建放到外面去,handler.handlerMessage()放到finally里面必须执行.

    9,应用程序的签名问题

    直接从项目中拷贝的apk文件,是不能发布到应用市场的,因为没有进行签名,打开这个apk文件,可以看到META-INF,这个签名文件如果被修改,或资源文件被修改,都会导致应用程序的完整性得不到校验,无法再次安装,它的主要作用就是校验应用程序完整性.

    eclipse会自动给一个调试debug的签名,它不能发布到市场上去,在应用程序的META-INFCERT.RSA文件中可以看到debug的字符串

    创造一个签名,一般叫工程名.keystore,在导出项目的时候可以设置签名,设置的密码要保密,不让别人知道,点击next可以配置有效时间(最好大于25),很多额外信息之类.

    在导出项目的时候选择签名,输入密码即可

    如果一个应用程序想要完成替换安装

    签名一致,包名一致,一定要保存好keystore文件

     

    10,制作主界面ui

    预览的时候可以选择没有标题栏,和全屏的预览.

    TextView:希望文本一行显示:singleLine.

    希望文本滚动,ellipsize设置marquee,但是直接定义这个属性是没效果的,它的底层可以看做是类似Web里字符串拼接截取达到的滚动效果,会消耗一定的资源,所以谷歌默认设置它没有焦点的时候就会生效.

    做法:创建一个FocusTextView继承TextView,继承的时候最好继承所有的构造.

    重写, isFocused(),返回一个ture即可.

    使用自定义控件要在布局文件里写全路径名,框架才能找到它.

    ②记得给图标添加动画效果

    shimmer 土豪金文字效果

     

  • 相关阅读:
    从SQL注入谈数据访问层
    Combobox下拉框两级联动
    C#IO流文件操作
    网络电视精灵思路分析
    简单工厂和单例设计模式浅解
    可扩展标记语言
    深入理解多态
    未将对象引用到实例
    Python 项目实践二(生成数据)第一篇
    Python 项目实践一(外星人入侵小游戏)第五篇
  • 原文地址:https://www.cnblogs.com/adventurer/p/5571660.html
Copyright © 2011-2022 走看看