【开源中国Android客户端】源码分析(一) 启动
来源:互联网 发布:私人网络国债基金产品 编辑:程序博客网 时间:2024/05/16 10:34
程序启动第一个界面类: net.oschina.app.AppStart
AppStart负责几件事情
1. 判断是否已经存在AppStart.class实例
2. 判断版本号
3. 展示动画.动画结束后启动LogUploadService然后跳转到MainActivity
- 利用了动画中的View的渐变动画效果,从半透明到完全不透明,动画持续时间为800ms,动画结束后,完成日志的上传和界面的跳转。
- 日志上传利用服务在后台完成的,无论上传成功还是失败,最后要记得关掉服务。成功后,将旧的日志文件删除,因为我们要进行新的一轮操作,至于在什么地方会保存日志,后面随着逐步分分析应该会找到它的。此处用到了第三方包https://github.com/loopj/android-async-http.
- 在onResume函数中做了以下处理:主要是考虑APP版本升级后,当前的版本大于之前的版本,那么就将之前缓存的图片给清理掉,升级后缓存的图片很有可能没有用处了:此处引用了第三方包 http://kjframe.github.io/ 。 (此包确实强大,可惜的是API文档中没有对启动界面引用的preference的API的详细解释,因此本条分析完全是自己揣摩的。至于图片缓存是App中哪一模块用到的,后面随着逐步分分析应该会找到它的。)
原文地址
代码片段解析
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 防止第三方跳转时出现双实例 //<1> Activity aty = AppManager.getActivity(MainActivity.class); if (aty != null && !aty.isFinishing()) { finish(); } // SystemTool.gc(this); //针对性能好的手机使用,加快应用相应速度 //<2> final View view = View.inflate(this, R.layout.app_start, null); setContentView(view); // 渐变展示启动屏 AlphaAnimation aa = new AlphaAnimation(0.5f, 1.0f); aa.setDuration(800); view.startAnimation(aa); //<3> aa.setAnimationListener(new AnimationListener() { @Override public void onAnimationEnd(Animation arg0) { redirectTo(); } @Override public void onAnimationRepeat(Animation animation) {} @Override public void onAnimationStart(Animation animation) {} }); } @Override protected void onResume() { super.onResume(); //<2> int cacheVersion = PreferenceHelper.readInt(this, "first_install", "first_install", -1); int currentVersion = TDevice.getVersionCode(); if (cacheVersion < currentVersion) { PreferenceHelper.write(this, "first_install", "first_install", currentVersion); cleanImageCache(); } } private void cleanImageCache() { final File folder = FileUtils.getSaveFolder("OSChina/imagecache"); KJAsyncTask.execute(new Runnable() { @Override public void run() { for (File file : folder.listFiles()) { file.delete(); } } }); } /** * 跳转到... */ private void redirectTo() { Intent uploadLog = new Intent(this, LogUploadService.class); //<4> startService(uploadLog); Intent intent = new Intent(this, MainActivity.class); //<5> startActivity(intent); finish(); }}
<1>
进入AppManager.class可以发现其实是一个Activity.class实例的管理类.主要负责用栈的方式管理已经存在的Activity实例.
通过AppManager.getActivity(MainActivity.class)查询是否管理类里面是否已经保存MainActivity.class的实例.如果有则将已经存在的实例finish(防止MainActivity.class双实例)
<2>
通过View.inflate(this, R.layout.app_start, null)生成布局view.选择这样想把布局文件生成一个View实例再调用setContentView(View view)设置布局.出于方便给布局设置动画.
后面也能看到给view设置一个渐变动画.动画结束以后调用redirectTo()函数.
R.layout.app_start布局就是一个线性布局.背景图片是一张480*800的图片(*1)
<3>
处理版本因为在eclipse转过As不久.知道在AndroidMainfest.xml文件可以定义versionName和versionCode属性.但是在As有些许改变.在AndroidMainfest.xml文件依然是可以定义这两个属性.但是如果Gradle编译脚本里面也定义这两个属性这已Gradle编译脚本为准.在Gradle编译脚本没有定义的情况下则使用AndroidMainfest.xml文件所定义的versionName和versionCode属性.
android:versionName=""android:versionCode=""
对于第一次运行
if (cacheVersion < currentVersion)为true
把版本号保存到sharedPreference中并且调用cleanImageCache()函数清楚缓存.(下次运行不在清楚缓存,因为cacheVersion 等于 currentVersion)
cleanImageCache()开启一个线程清空OSChina/iprivate void cleanImageCache() { final File folder = FileUtils.getSaveFolder("OSChina/imagecache"); KJAsyncTask.execute(new Runnable() { @Override public void run() { for (File file : folder.listFiles()) { file.delete(); } } }); }
ervice.class服务,
LogUploadService.class设计出来的目的是查看是否有ErrorLog,发现有ErrorLog通过网络向服务器上报ErrorLog信息.(看到这里深深抽一口气.好设计!)
LogUploadService.class服务查看在/目录是否有OSCLog.log文件.有该文件就像服务器发送log的信息.在回调函数里面可以看到成功发送后把log文件删除.没有log文件那么就没LogUploadService.class的事情了.调用stopSelf()结束该service.
public class LogUploadService extends Service { @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { final File log = FileUtils.getSaveFile("OSChina", "OSCLog.log"); String data = null; try { FileInputStream inputStream = new FileInputStream(log); data = StringUtils.toConvertString(inputStream); } catch (FileNotFoundException e) { e.printStackTrace(); } if (!StringUtils.isEmpty(data)) { OSChinaApi.uploadLog(data, new AsyncHttpResponseHandler() { @Override public void onSuccess(int arg0, Header[] arg1, byte[] arg2) { log.delete(); LogUploadService.this.stopSelf(); } @Override public void onFailure(int arg0, Header[] arg1, byte[] arg2, Throwable arg3) { LogUploadService.this.stopSelf(); } }); } else { LogUploadService.this.stopSelf(); } return super.onStartCommand(intent, flags, startId); }}
<5>
跳转到MainActivity.到这里为止.启动的部分分析就完成了.
注解部分(尚未能解决的问题,留待以后有能力在分析)
- *1 针对不同分辨率480*800图片怎么适配?
- *2 调用到kjframeforandroid的文件管理模块和框架多线程模块
2016.1.28 23:59
对于注解一的解答:
根本就没有适配!!!,把软件作者火蚁在开源中国上的个人空间翻了底朝天,无意中看见了一条他对提问者的回答,结果是这样的:
http://www.oschina.net/question/1433975_243063
- 【开源中国Android客户端】源码分析(一) 启动
- 开源中国android客户端源码分析-学习笔记1
- 开源中国android客户端源码分析-学习笔记2
- 开源中国安卓客户端源码学习(一) 渐变启动界面
- 开源中国源码分析(一)
- 【开源中国Android客户端】源码分析(二)网络数据传输接口
- 开源中国 Android 客户端学习-启动界面
- Android 源码分析 -- (一) Android启动过程
- 分析开源oschina客户端的源码(一)
- 开源中国客户端源码下载地址
- 开源中国客户端源码学习
- 开源中国iPhone客户端源码
- eoe android客户端源码剖析(一)动画启动界面
- 开源中国客户端代码分析
- WordPress Blog Android客户端源码分析(一)
- 传奇源码分析-客户端(游戏逻辑处理源分析一)
- 传奇源码分析-客户端(游戏逻辑处理源分析一)
- 传奇源码分析-客户端(游戏逻辑处理源分析一)
- Transactional超时时间timeout控制
- 关于ffmpeg的例子muxing.c
- Java Script 中算数运算
- 判断一个实体对象是否真的为空
- 算法之美_源代码发布(5)
- 【开源中国Android客户端】源码分析(一) 启动
- 并查集
- 05-iptables_tcp wrapper
- SVN clean失败解决方法
- FTxxx系列-----------修改dclick的初始值
- 智能称体脂称实现(基本原理解释篇)
- ViewPager Indicator的tab数据来自网络出现找不到viewPager的错误
- Linux C Socket编程原理及简单实例
- 浅谈Spring事务隔离级别