Часто встречаю вопрос типа "Как сделать обновление приложения AIR". Не проверял, есть ли в сети что-то подобное (наверняка есть), а просто решил выложить свой класс для этой процедуры. Он далеко не отшлифован и функционал предполагалось значительно расширить. Но сразу не сделал, а времени на это уже нет. Поэтому, кому понравится, может расширять и модернизировать этот класс без всяческих оговорок.
Итак, при запуске (не обязательно) AIR-приложения определяем версию приложения следующим кодом:
var descriptor:XML = nativeApplication.applicationDescriptor; var air:Namespace = descriptor.namespaceDeclarations()[0]; var version:String = String(descriptor.air::version);
Версия же приложения устанавливается в файле application.xml до сборки приложения. Например.
<version>1.0</version>
Затем подключаете мой класс для обновления приложения, который сделает всю работу.
WebUpdate.instance.start(version);
Для функционирования обновления необходимо выложить в сеть для доступа само приложение (файл формата AIR) и текстовый файл с единственной записью, например:
1.0.1
Класс распарсит строку и сделает всё необходимое.
Вот пример кода корневого компонента для тестов:
<?xml version="1.0" encoding="utf-8"?> <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" width="320" height="240" windowComplete="onWindowsComplete(event)" title="AIR Web Update Tutorial" status="AIR Web Update Tutorial" showStatusBar="true"> <mx:Script> <![CDATA[ import flash.events.Event; import ru.pixeltyumen.air.utils.WebUpdate; private function onWindowsComplete (e:Event):void { var descriptor:XML = nativeApplication.applicationDescriptor; var air:Namespace = descriptor.namespaceDeclarations()[0]; var version:String = String(descriptor.air::version); WebUpdate.instance.start(version); } ]]> </mx:Script> <mx:TextArea width="100%" height="100%" editable="false" selectable="false" text="This application is demonstrating the process of WebUpdate class job." /> </mx:WindowedApplication>
А это код самого класса:
package ru.pixeltyumen.air.utils { import air.net.URLMonitor; import flash.desktop.Updater; import flash.events.StatusEvent; import flash.filesystem.File; import flash.filesystem.FileStream; import flash.filesystem.FileMode; import flash.events.Event; import flash.events.IOErrorEvent; import flash.events.ProgressEvent; import flash.events.EventDispatcher; import flash.utils.ByteArray; import mx.events.CloseEvent; import flash.net.URLLoader; import flash.net.URLRequest; import flash.net.URLStream; import mx.controls.Alert; /** * ... * @author .p.i.x.e.l. */ public class WebUpdate extends EventDispatcher { public static const ONLY_UPDATE_ALERT:String = "ONLY_UPDATE_ALERT"; public static const UPDATE_AND_EQUAL_ALERT:String = "UPDATE_AND_EQUAL_ALERT"; public static const DETAILED_ALERT:String = "DETAILED_ALERT"; private static const NEED_UPDATE:String = "NEED_UPDATE"; private static const EQUAL_VERSIONS:String = "EQUAL_VERSIONS"; private static const NEWEST_VERSION:String = "NEWEST_VERSION"; private static var _instance:WebUpdate; private var _netStatus:URLMonitor; private var _currentVersion:String; private var _updateVersion:String; private var _state:String = EQUAL_VERSIONS; private var _mode:String = NEED_UPDATE; private var _versionTextUrl:String = "http://url_for_text_file_with_version_number"; private var _updateAppUrl:String = "http://url_for_last_version_of_application"; // Message strings private var _equalTitleString:String = "Внимание!"; private var _equalTextString:String = "У вас последняя версия приложения, не требующая обновления."; private var _newestTitleString:String = "Внимание!"; private var _newestTextString:String = "Странно, но ваша версия новее!"; private var _olderTitleString:String = "Внимание!"; private var _olderTextString:String = "Ваша версия более старая и требует обновления. Приступить к обновлению?"; private var _errorTitleString:String = "Ошибка!"; private var _errorTextString:String = "Сервер обновлений не доступен! Проверте настройки сети или повторите операцию позже."; /** * Constructor */ public function WebUpdate () { if (_instance != null) { throw new Error("This class ru.pixeltyumen.air.utils.WebUpdate is singleton!"); } _netStatus = new URLMonitor(new URLRequest(_updateAppUrl)); _netStatus.start(); } /** * Instance of class */ static public function get instance ():WebUpdate { if (_instance == null) { _instance = new WebUpdate(); } return _instance; } /** * Setter for URL of application file */ public function set updateAppUrl (s:String):void { _updateAppUrl = s; } /** * Setter for URL of version text-file */ public function set updateVersionUrl (s:String):void { _versionTextUrl = s; } /** * * @param currentVersion * @param mode */ public function start (currentVersion:String, mode:Boolean = false):void { _mode = mode ? UPDATE_AND_EQUAL_ALERT : NEED_UPDATE; _currentVersion = currentVersion; if (!_netStatus.available && mode) { Alert.show(_errorTextString, _errorTitleString); return; } var loader:URLLoader = new URLLoader(); loader.addEventListener(Event.COMPLETE, versionSignComplete); // add another error handlers here... loader.load(new URLRequest(_versionTextUrl)); } /** * Complete handler of getting last version * @param e */ private function versionSignComplete (e:Event):void { _updateVersion = e.target.data as String; compareVersions(); if (_state == EQUAL_VERSIONS && _mode == (UPDATE_AND_EQUAL_ALERT || DETAILED_ALERT)) { Alert.show(_equalTextString, _equalTitleString); } if (_state == NEWEST_VERSION && _mode == DETAILED_ALERT) { Alert.show(_newestTextString, _newestTitleString); } if (_state == NEED_UPDATE) { Alert.show( _olderTextString, _olderTitleString, Alert.YES | Alert.NO, null, confirmUpdate, null ); } } /** * Compare versions */ private function compareVersions ():void { _state = EQUAL_VERSIONS; var curArray:Array = _currentVersion.split("."); var updArray:Array = _updateVersion.split("."); try { for (var i:uint = 0; i < curArray.length; i++) { if (curArray[i] && updArray[i] && uint(curArray[i]) < uint(updArray[i])) { _state = NEED_UPDATE; return; } } } catch (e:Error) { errorHandler(null); } } /** * * @param e */ private function confirmUpdate (e:CloseEvent):void { if (e.detail == Alert.YES) { var stream:URLStream = new URLStream(); //stream.addEventListener(ProgressEvent.PROGRESS, progressHandler); stream.addEventListener(Event.COMPLETE, completeHandler); stream.addEventListener(IOErrorEvent.IO_ERROR, errorHandler); // add other error handler stream.load(new URLRequest(_updateAppUrl)); } } /** * * @param e */ private function progressHandler (e:ProgressEvent):void { "Downloading update " + e.bytesLoaded + " of " + e.bytesTotal + " bytes"; } /** * * @param e */ private function completeHandler (e:Event):void { var urlStream:URLStream = e.target as URLStream; var fileStream:FileStream = new FileStream(); var file:File = File.applicationStorageDirectory.resolvePath("newVersion.air"); fileStream.open(file, FileMode.WRITE); var bytes:ByteArray = new ByteArray(); urlStream.readBytes(bytes); fileStream.writeBytes(bytes); fileStream.close(); var updater:Updater = new Updater(); updater.update(file, _updateVersion); } /** * * @param e */ private function errorHandler (e:Event):void { Alert.show(_errorTextString, _errorTitleString); } } }
Только не забудьте поставить нужные URL в переменные _versionTextUrl и _updateAppUrl.
Комментариев нет:
Отправить комментарий