开题:手机卫士这样的一个项目能够很好的复习基础所学的知识点,由于它覆盖面广,用来作安卓深刻学习是一个很好的选择.java
1,开始一个项目android
写一个好的代码不只是看功能是否实现,并且代码具备较高的可读性程序员
1.1 代码组织方式:web
①采用业务逻辑模块组织代码,以小米阅读为例:数据库
功能一:阅读器reader com.xiaomi.readerjson
功能二:分享 share com.xiaomi.sharewindows
功能三:便签 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数据类型.
注意:若是同时有scheme和mimeType就要用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-INF\CERT.RSA文件中能够看到debug的字符串
创造一个签名,通常叫工程名.keystore,在导出项目的时候能够设置签名,设置的密码要保密,不让别人知道,点击next能够配置有效时间(最好大于25年),不少额外信息之类.
在导出项目的时候选择签名,输入密码便可
若是一个应用程序想要完成替换安装
签名一致,包名一致,必定要保存好keystore文件
10,制做主界面ui
预览的时候能够选择没有标题栏,和全屏的预览.
①TextView:但愿文本一行显示:singleLine.
但愿文本滚动,ellipsize设置marquee,可是直接定义这个属性是没效果的,它的底层能够看作是相似Web里字符串拼接截取达到的滚动效果,会消耗必定的资源,因此谷歌默认设置它没有焦点的时候就会生效.
作法:建立一个FocusTextView继承TextView,继承的时候最好继承全部的构造.
重写, isFocused(),返回一个ture便可.
使用自定义控件要在布局文件里写全路径名,框架才能找到它.
②记得给图标添加动画效果
③shimmer 土豪金文字效果