AIR app自动更新的实现方式

很久之前看到很多人都在纠结自动的哪个更新啊
然后我工作很忙一直没有时间去研究这个
今天一个项目需要自动更新 然后就随手也一个

air app的自动更新 是通过Updater类实现的
他有一个静态属性 叫isSupported : Boolean   =true 平台可以自动更新 =false 平台不可以自动更新 一般情况下 肯定为true = =
这个类主要理解就一个方法 update(airFile:File, version:String):void airFile就是xxx.air 文件 version 就是xxx.air的numberVersion值
使用这个类只需要注意1点,更新的时候version值和xxx.air的numberVersion值相同 才可以成功进行更新。
 
  1 package update
2 {
3 import com.OpenFile;
4
5 import flash.desktop.NativeApplication;
6 import flash.desktop.Updater;
7 import flash.events.EventDispatcher;
8 import flash.events.IEventDispatcher;
9 import flash.filesystem.File;
10 import flash.utils.ByteArray;
11 /**
12 * app更新工具
13 * 步骤 1:获取本地config文件
14 * 2:通过config文件中的cfg信息 去服务器拉取最新的config配置文件
15 * 3:比对serverVersion 和 localVersion
16 * a:不同 就通过config中的app路径 下载最新的app 然后更新
17 * b:相同 重写 覆盖本地的config文件
18 *
19 * 注意 每次发布新的版本 要修改app.xml中的numberVersion项 update.xml中version项 2值必须一模一样
20 *
21 * @author wang
22 *
23 */
24 public class AirUpdate extends EventDispatcher
25 {
26 /**
27 * 各种状态的ui
28 * 你需要写一个ui 实现IAirUpdateUI接口
29 */
30 private var ui:IAirUpdateUI;
31
32 /**
33 * 配置文件的地址
34 */
35 private var localConfigPath:String;
36
37 /**
38 * 嗯 就是用这货更新的
39 */
40 private var updater:Updater;
41
42 /**
43 * 重新加载次数
44 */
45 private var reloadcount:int;
46 /**
47 * @param ui
48 * 自动更新时候出现的提示ui
49 * @param configPath
50 * 配置文件的地址
51 */
52 public function AirUpdate(ui:IAirUpdateUI = null,configPath:String = null)
53 {
54 this.ui = ui;
55 if(!configPath){
56 localConfigPath = File.applicationDirectory.nativePath+"/update/update.xml";
57 }else{
58 localConfigPath = configPath;
59 }
60 }
61
62 public static function getCurrentAppVersion():String{
63 var xml:XML = NativeApplication.nativeApplication.applicationDescriptor;
64 var ns:Namespace = xml.namespace();
65 return String(xml.ns::versionNumber);
66 }
67
68 /**
69 * 如果发现处理错误 或者加载错误 那么必须给一个默认的地址重新加载
70 */
71 public function error_action():void{
72 //todo 这部分自己写...
73
74 if(reloadcount++>5){
75 trace("重新加载次数超过5次! 无法更新");
76 return;
77 }
78 if(ui){
79 ui.showMessage("更新错误!")
80 }
81
82 }
83
84
85 private var currentUpdateVO:AirUpdateVO;
86 /**
87 * 检测是否需要更新
88 */
89 public function checkUpdate():void{
90 //用flie去读取本地config数据
91 var f:File = new File(localConfigPath);
92 if(!f.exists /*如果文件不存在*/){
93 error_action();
94 return;
95 }
96
97 var xml:XML;
98 try{
99 //有可能配置文件的格式错误
100 xml = XML(OpenFile.openAsTxt(f));
101 currentUpdateVO = new AirUpdateVO().decode(xml);
102 loadconfig();
103 }catch(e:Error){
104 //本地配置文件加载错误 只能是找个正确的位置加载了
105 error_action();
106 return;
107 }
108 }
109
110 /**
111 * 加载配置文件
112 */
113 private function loadconfig():void{
114 var loader:UpdateLoader = new UpdateLoader();
115 if(ui){
116 ui.loadConfig(true,0,100);
117 }
118 loader.doLoad(currentUpdateVO.cfg,configProgress,configloadComplete);
119 }
120 private function configProgress(current:int,total:int):void{
121 if(ui){
122 ui.loadConfig(true,current,total);
123 }
124 }
125 private function configloadComplete(byte:ByteArray):void{
126 if(ui){
127 ui.loadConfig(false,100,100);
128 }
129 if(!byte){
130 if(ui){
131 ui.showMessage("config文件加载失败");
132 }
133 return;
134 }
135
136
137 //配置文件加载成功
138
139 var xml:XML;
140 try{
141 xml = XML(byte.readMultiByte(byte.bytesAvailable,OpenFile.getFileType(byte)));
142 var serverupdatevo:AirUpdateVO = new AirUpdateVO().decode(xml);
143 if(getCurrentAppVersion() != serverupdatevo.version){
144 //检测到2个版本不一样.开始请求更新
145 currentUpdateVO = serverupdatevo;
146 if(ui){
147 ui.submitUpdate(currentUpdateVO.version,loadapp);
148 }else{
149 loadapp()
150 }
151 }else{
152 //如果版本相同 把下载下来的config写入本地
153 byte.position = 0;
154 OpenFile.write(byte,localConfigPath);
155 }
156 }catch(e:Error){
157 error_action();
158 return;
159 }
160 }
161
162 /**
163 * 加载app;
164 * @param flag
165 * true 加载
166 * false 不加载
167 */
168 public function loadapp(flag:Boolean=true):void{
169 if(!flag){
170 return;
171 }
172 var loader:UpdateLoader = new UpdateLoader();
173 if(ui){
174 ui.loadapp(true,0,100);
175 }
176 loader.doLoad(currentUpdateVO.app,appProgress,appLoadComplete);
177 }
178 private function appProgress(current:int,totle:int):void{
179 if(ui){
180 ui.loadapp(true,current,totle);
181 }
182 }
183 private function appLoadComplete(byte:ByteArray):void{
184 if(ui){
185 ui.loadapp(false,100,100);
186 }
187
188 if(!byte){
189 if(ui){
190 ui.showMessage("app文件加载失败");
191 }
192 return;
193 }
194
195 try{
196 var f:File = OpenFile.write(byte,File.applicationStorageDirectory.nativePath+"/tempApp.air");
197 if(!updater){
198 updater = new Updater();
199 }
200 //更新
201 updater.update(f,currentUpdateVO.version);
202 }catch(e:Error){
203 error_action();
204 return;
205 }
206 }
207 }
208 }
209
210 import flash.events.Event;
211 import flash.events.HTTPStatusEvent;
212 import flash.events.IOErrorEvent;
213 import flash.events.ProgressEvent;
214 import flash.net.URLRequest;
215 import flash.net.URLStream;
216 import flash.utils.ByteArray;
217
218 class UpdateLoader extends URLStream{
219 private var url:String;
220 private var progress:Function;
221 private var complete:Function;
222
223 public var result:ByteArray;
224 public function UpdateLoader():void{
225 }
226
227 public function doLoad(url:String,progress:Function,complete:Function):void{
228 this.url = url;
229 this.progress = progress;
230 this.complete = complete;
231 addEventListener(Event.COMPLETE,loaderHandler,false,int.MAX_VALUE);
232 addEventListener(IOErrorEvent.IO_ERROR,ioHandler);
233 addEventListener(HTTPStatusEvent.HTTP_STATUS,httpHandler);
234 addEventListener(ProgressEvent.PROGRESS,progresshandler);
235 load(new URLRequest(url));
236 }
237
238
239 public function dispose():void{
240 url = null;
241 progress = null;
242 complete = null;
243 result = null
244 removeEventListener(Event.COMPLETE,loaderHandler);
245 removeEventListener(IOErrorEvent.IO_ERROR,ioHandler);
246 removeEventListener(HTTPStatusEvent.HTTP_STATUS,httpHandler);
247 removeEventListener(ProgressEvent.PROGRESS,progresshandler);
248 }
249
250 private function loaderHandler(event:Event):void{
251 result = new ByteArray();
252 readBytes(result);
253 result.position = 0;
254 if(complete!=null){
255 complete(result);
256 }
257 dispose();
258 }
259
260 private function ioHandler(event:Event):void{
261 if(complete!=null){
262 complete(null);
263 }
264 }
265
266 private function httpHandler(event:Event):void{
267
268 }
269
270 private function progresshandler(event:ProgressEvent):void{
271 if(progress!=null){
272 progress(event.bytesLoaded,event.bytesTotal);
273 }
274 }
275 }
代码还真长
嗯 使用的方法其实挺简单的
new AirUpdate().checkUpdate();
别看这么简单 其实还需要一个配置文件
update.xml
<config>
<!-- 版本号 -->
<version>0.0.0</version>
<!-- 配置服务器端cfg文件的地址 启动检查更新的时候用 如:http://127.0.0.1/uapp/update.xml -->
<cfg>http://127.0.0.1/updatetest/update.xml</cfg>
<!-- 配置服务器端app文件的地址 启动检查更新的时候用 如:http://127.0.0.1/uapp/app.air -->
<app>http://127.0.0.1/updatetest/AppUpdate.air</app>
</config>
注释都写好了 应该不用多解释
AirUpdater 里面 提供了一个ui显示接口
package update
{
public interface IAirUpdateUI
{
/**
* 开始加载config
* @param value
* true : 开始加载
* false : 加载完毕
* @param current 当前加载了多少
* @param totle 总共需要加载多少
*/
function loadConfig(value:Boolean,current:int,totle:int):void;

/**
* 请求是否需要加载新版本
* @param updateVersion
* 服务器版本
* @param callbackFunction(value:Boolean)
* @param value true:可以下载 false:不可下载
*/
function submitUpdate(updateVersion:String,callbackFunction:Function):void;
/**
*
* @param value
* true : 开始加载
* false : 加载完毕
* @param current 当前加载了多少
* @param totle 总共需要加载多少
*/
function loadapp(value:Boolean,current:int,totle:int):void;

/**
* 信息提示
* @param str
*/
function showMessage(str:String):void;
}
}
嗯 一个显示的小sprite实现这么几个表现方法 随便搞搞的事情 对吧

最后最后 还是要贴以下这个类的使用方法
  1. new AirUpdate().checkUpdate();
复制代码
因为很多人都是拉到最下面 也许没看到这句话

下面是 源码 appUpdate.zip(6.11 KB)

complete miao~
 

你可能感兴趣的:(AIR)