Flex通信篇——Flex和外部进行异步通信

news/2024/5/19 19:27:15 标签: flex, string, flash, dialog, function, filter

ExternalInterface.call的问题

请留意以下情景,要利用外部应用程序弹出文件选择窗体,并返回所选的文件路径。

使用ExternalInterface.call来实现,当用户60秒(Flex已经设置最长的等待时间)内未能够完成文件选择会弹出"1502"的错误,严重影响用户体现。

所以,一些比较耗时的操作(超过60s),或无法确定何时调用完成的方法(如上述),应该使用异步调用的方式,当方法执行完成后进行回调。

<![CDATA[

实现异步调用机制

Flex端

定义一个Dictionary,用来缓存回调的方法

private var m_AsyncDict:Dictionary;

 

定义OpenFileDialogAsync方法,用fscommand来实现,fscommand是单向的调用,不存在60秒超时的问题。

//弹出打开文件窗口,选择单个文件

public function OpenFileDialogAsync(title:String = "请选择1个文件", initFolder:String = "", filter:String = "", callbackString:Function = null):void

{

    //创建异步ID

    var id:String = mx.utils.UIDUtil.createUID();

    //创建自定义异步请求

    var request:String = "<args>";

    request += "<arg>" + id + "</arg>";

    request += "<arg>" + title + "</arg>";

    request += "<arg>" + initFolder + "</arg>";

    request += "<arg>" + filter + "</arg>";

    request += "</args>";

    //缓存回调方法

    if (callbackString != null)

        m_AsyncDict[id] = callbackString;

    flash.system.fscommand(FLASH_TO_APP_OPEN_FILE_DIALOG_ASYNC, request);

}

定义并注册AsyncCallback和CancelAsyncCall方法,让外部应用程序能够响应异步回调或取消异步回调。

public function AsyncCallback(id:String, value:Object):void

{

    if (m_AsyncDict[id])

    {

        //执行回调方法

        m_AsyncDict[id](value);

        delete m_AsyncDict[id];

    }

}

public function CancelAsyncCall(id:String):void

{

    if (m_AsyncDict[id])

    {

        delete m_AsyncDict[id];

    }

}

if (ExternalInterface.available)

{

    ExternalInterface.addCallback(APP_TO_FLASH_ASYNC_CALLBACK, AsyncCallback);

    ExternalInterface.addCallback(APP_TO_FLASH_CANCEL_ASYNC_CALL, CancelAsyncCall);

}

EXE端

为ShockwaveFlashObject注册FSCommand事件,并添加事件处理的方法。

axShockwaveFlash1.FlashCall += new AxShockwaveFlashObjects._IShockwaveFlashEvents_FlashCallEventHandler(axShockwaveFlash1_FlashCall);

void axShockwaveFlash1_FSCommand(object sender, AxShockwaveFlashObjects._IShockwaveFlashEvents_FSCommandEvent e)

{

//请求e.args是自定义Xml格式

XmlDocument request = new XmlDocument();

request.LoadXml(e.args);

if (e.command == FLASH_TO_APP_OPEN_FILE_DIALOG_ASYNC)

{

//获取回调的键值

string asyncId = request.DocumentElement.ChildNodes[0].InnerText;

//获取窗体参数

string title = request.DocumentElement.ChildNodes[1].InnerText;

string initFolder = request.DocumentElement.ChildNodes[2].InnerText;

string filter = request.DocumentElement.ChildNodes[3].InnerText;

using (OpenFileDialog dlg = new OpenFileDialog())

{

dlg.Title = title;

dlg.InitialDirectory = initFolder;

dlg.Filter = filter;

if (dlg.ShowDialog() == DialogResult.OK)

{

AsyncCallback(asyncId, dlg.FileName);

}

else

{

CancelAsyncCall(asyncId);

}

}

}

}

定义2个方法调用Flex里注册的AsyncCallback和CancelAsyncCall方法。

//异步回调

public void AsyncCallback(string asyncId, string value)

{

StringBuilder sb = new StringBuilder();

sb.Append("<invoke name=/"").Append(APP_TO_FLASH_ASYNC_CALLBACK).Append("/" returntype=/"xml/">");

sb.Append("<arguments>");

sb.Append("<string>").Append(asyncId).Append("</string>");

sb.Append("<string>").Append(value).Append("</string>");

sb.Append("</arguments>");

sb.Append("</invoke>");

axShockwaveFlash1.CallFunction(sb.ToString());

}

//撤销异步回调

private void CancelAsyncCall(string asyncId)

{

StringBuilder sb = new StringBuilder();

sb.Append("<invoke name=/"").Append(APP_TO_FLASH_CANCEL_ASYNC_CALL).Append("/" returntype=/"xml/">");

sb.Append("<arguments>");

sb.Append("<string>").Append(asyncId).Append("</string>");

sb.Append("</arguments>");

sb.Append("</invoke>");

axShockwaveFlash1.CallFunction(sb.ToString());

}

完整代码

Flex端

LocalAPI.as

package

{

    import flash.external.ExternalInterface;

    import flash.system.fscommand;

    import flash.utils.Dictionary;

    import mx.utils.UIDUtil;

    public class LocalAPI

    {

        //通讯命令定义

        private static const FLASH_TO_APP_OPEN_FILE_DIALOG:String = "OpenFileDialog";

        private static const FLASH_TO_APP_OPEN_FILE_DIALOG_ASYNC:String = "OpenFileDialogAsync";        

        private static const APP_TO_FLASH_ASYNC_CALLBACK:String = "AsyncCallback";

        private static const APP_TO_FLASH_CANCEL_ASYNC_CALL:String = "CancelAsyncCall";

        //Async dict

        private var m_AsyncDict:Dictionary;

        //Singleton static obj

        private static var g_Instance:LocalAPI = null;

        //获取LocalAPI单件实例

        public static function get Instance():LocalAPI

        {

            if (g_Instance == null)

            {

                g_Instance = new LocalAPI();

            }

            return g_Instance;

        }

        public function LocalAPI()

        {

            if (g_Instance != null)

                throw new Error("Singleton class. Please use Instance static filed.");

            m_AsyncDict = new Dictionary();

            if (ExternalInterface.available)

            {

                ExternalInterface.addCallback(APP_TO_FLASH_ASYNC_CALLBACK, AsyncCallback);

                ExternalInterface.addCallback(APP_TO_FLASH_CANCEL_ASYNC_CALL, CancelAsyncCall);

            }

        }

        //弹出打开文件窗口,选择单个文件(60s局限)

        public function OpenFileDialog(title:String = "请选择1个文件", initFolder:String = "", filter:String = ""):String

        {

            if(!ExternalInterface.available) return null;

            return ExternalInterface.call(FLASH_TO_APP_OPEN_FILE_DIALOG, title, initFolder, filter);

        }

        //异步通信

        //弹出打开文件窗口,选择单个文件

        public function OpenFileDialogAsync(title:String = "请选择1个文件", initFolder:String = "", filter:String = "", callbackString:Function = null):void

        {

            //创建异步ID

            var id:String = mx.utils.UIDUtil.createUID();

            //创建自定义异步请求

            var request:String = "<args>";

            request += "<arg>" + id + "</arg>";

            request += "<arg>" + title + "</arg>";

            request += "<arg>" + initFolder + "</arg>";

            request += "<arg>" + filter + "</arg>";

            request += "</args>";

            //缓存回调方法

            if (callbackString != null)

                m_AsyncDict[id] = callbackString;

            flash.system.fscommand(FLASH_TO_APP_OPEN_FILE_DIALOG_ASYNC, request);

        }

        public function AsyncCallback(id:String, value:Object):void

        {

            if (m_AsyncDict[id])

            {

                //执行回调方法

                m_AsyncDict[id](value);

                delete m_AsyncDict[id];

            }

        }

        public function CancelAsyncCall(id:String):void

        {

            if (m_AsyncDict[id])

            {

                delete m_AsyncDict[id];

            }

        }

    }

}

Demo.mxml

<?xml version="1.0" encoding="utf-8"?>

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" fontSize="12">

    <mx:Script>

        private function GetFilePath():void

        {

            var path:String = LocalAPI.Instance.OpenFileDialog();

            if (path != null)

                _Path1.text = path;

        }

            //异步方式

        private function GetFilePathAsync():void

        {

            LocalAPI.Instance.OpenFileDialogAsync("请选择1个文件", "", "", function(result:String):void

            {

                _Path2.text = result;

            });

        }

    </mx:Script>

    <mx:Button x="445.75" y="100" label="浏览1" click="GetFilePath()"/>

    <mx:Button x="445.75" y="147" label="浏览2" click="GetFilePathAsync()"/>

    <mx:Label x="71" y="102" text="文件路径"/>

    <mx:TextInput x="188.25" y="100" width="249.5" id="_Path1"/>

    <mx:TextInput x="188.25" y="147" width="249.5" id="_Path2"/>

    <mx:Label x="71" y="149" text="文件路径(异步方式)"/>

    <mx:Text x="71" y="196" width="459.75" height="213" id="_Trace"/>

</mx:Application>

EXE端

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Xml;

 

namespace WinFormDemo

{

    public partial class Form1 : Form

    {

        //定义通信命令

        private string FLASH_TO_APP_OPEN_FILE_DIALOG = "OpenFileDialog";

        private string FLASH_TO_APP_OPEN_FILE_DIALOG_ASYNC = "OpenFileDialogAsync";

        private string APP_TO_FLASH_ASYNC_CALLBACK = "AsyncCallback";

        private string APP_TO_FLASH_CANCEL_ASYNC_CALL = "CancelAsyncCall";

        private bool m_Init = false;

        public Form1()

        {

            InitializeComponent();

        }

        private void Form1_Load(object sender, EventArgs e)

        {

            if (m_Init) return;

            string swf = System.IO.Path.Combine(Application.StartupPath, "Demo.swf");

            axShockwaveFlash1.FSCommand += new AxShockwaveFlashObjects._IShockwaveFlashEvents_FSCommandEventHandler(axShockwaveFlash1_FSCommand);

            axShockwaveFlash1.FlashCall += new AxShockwaveFlashObjects._IShockwaveFlashEvents_FlashCallEventHandler(axShockwaveFlash1_FlashCall);

            axShockwaveFlash1.Movie = swf;

            m_Init = true;

        }

        void axShockwaveFlash1_FlashCall(object sender, AxShockwaveFlashObjects._IShockwaveFlashEvents_FlashCallEvent e)

        {

            //请求e.request是Xml格式,详细请查阅文档

            XmlDocument request = new XmlDocument();

            request.LoadXml(e.request);

            string command = request.DocumentElement.Attributes["name"].Value;

            if (command == FLASH_TO_APP_OPEN_FILE_DIALOG)

            {

                //获取窗体参数

                string title = request.DocumentElement.ChildNodes[0].ChildNodes[0].InnerText;

                string initFolder = request.DocumentElement.ChildNodes[0].ChildNodes[1].InnerText;

                string filter = request.DocumentElement.ChildNodes[0].ChildNodes[2].InnerText;

                using (OpenFileDialog dlg = new OpenFileDialog())

                {

                    dlg.Title = title;

                    dlg.InitialDirectory = initFolder;

                    dlg.Filter = filter;

                    if (dlg.ShowDialog() == DialogResult.OK)

                    {

                        axShockwaveFlash1.SetReturnValue("<string>" + dlg.FileName + "</string>");

                    }

                    else

                    {

                        axShockwaveFlash1.SetReturnValue("<null/>");

                    }

                }

            }

        }

 

        void axShockwaveFlash1_FSCommand(object sender, AxShockwaveFlashObjects._IShockwaveFlashEvents_FSCommandEvent e)

        {

            //请求e.args是自定义Xml格式

            XmlDocument request = new XmlDocument();

            request.LoadXml(e.args);

            if (e.command == FLASH_TO_APP_OPEN_FILE_DIALOG_ASYNC)

            {

                //获取回调的键值

                string asyncId = request.DocumentElement.ChildNodes[0].InnerText;

                //获取窗体参数

                string title = request.DocumentElement.ChildNodes[1].InnerText;

                string initFolder = request.DocumentElement.ChildNodes[2].InnerText;

                string filter = request.DocumentElement.ChildNodes[3].InnerText;

                using (OpenFileDialog dlg = new OpenFileDialog())

                {

                    dlg.Title = title;

                    dlg.InitialDirectory = initFolder;

                    dlg.Filter = filter;

                    if (dlg.ShowDialog() == DialogResult.OK)

                    {

                        AsyncCallback(asyncId, dlg.FileName);

                    }

                    else

                    {

                        CancelAsyncCall(asyncId);

                    }

                }

            }

        }

        //异步回调

        public void AsyncCallback(string asyncId, string value)

        {

            StringBuilder sb = new StringBuilder();

            sb.Append("<invoke name=/"").Append(APP_TO_FLASH_ASYNC_CALLBACK).Append("/" returntype=/"xml/">");

            sb.Append("<arguments>");

            sb.Append("<string>").Append(asyncId).Append("</string>");

            sb.Append("<string>").Append(value).Append("</string>");

            sb.Append("</arguments>");

            sb.Append("</invoke>");

            axShockwaveFlash1.CallFunction(sb.ToString());

        }

        //撤销异步回调

        private void CancelAsyncCall(string asyncId)

        {

            StringBuilder sb = new StringBuilder();

            sb.Append("<invoke name=/"").Append(APP_TO_FLASH_CANCEL_ASYNC_CALL).Append("/" returntype=/"xml/">");

            sb.Append("<arguments>");

            sb.Append("<string>").Append(asyncId).Append("</string>");

            sb.Append("</arguments>");

            sb.Append("</invoke>");

            axShockwaveFlash1.CallFunction(sb.ToString());

        }

    }

}

系列索引

Flex通信篇——Flex和外部应用程序进行通信

Flex通信篇——Flex和外部进行异步通信

Flex通信篇——Flex键盘组合键

Flex通信篇——构建企业级HTTP通信层

]]>


http://www.niftyadmin.cn/n/1574772.html

相关文章

分布式缓存Redis应用场景解析

Redis的应用场景非常广泛。虽然Redis是一个key-value的内存数据库&#xff0c;但在实际场景中&#xff0c;Redis经常被作为缓存来使用&#xff0c;如面对数据高并发的读写、海量数据的读写等。 举个例子&#xff0c;A网站首页一天有100万人访问&#xff0c;其中有一个“积分商城…

Flex通信篇——Flex键盘组合键

<![CDATA[ Flex中的键盘事件 要在Flex中响应键盘输入&#xff0c;只需注册keyDown事件即可。 <mx:Application xmlns:mx"http://www.adobe.com/2006/mxml" layout"absolute" keyDown"OnKeyDown(event)"> <mx:Script> pri…

pdf to swf

使用swftools的pdf2swf.exe命令行来完成这项操作&#xff0c;转换效果理想&#xff0c;支持as3&#xff0c;swftools官网&#xff1a;http://www.swftools.org/ 下面是根据使用需要设计的2个方法&#xff1a; /// <summary> /// 获取pdf文件的页数 /// </summary&…

SpringBoot2-第二章:完善在线APIDocs

上一章我们基本完成了项目框架的搭建&#xff0c;我们目前项目是为了完成一个类似传统网站的单机服务器应用&#xff0c;那么我们接着该做一些什么呢&#xff1f; 本项目的GitHub&#xff1a;https://github.com/pc859107393/Go2SpringBoot.git 有兴趣交流springboot进行快速开…

2010年个人产品研发计划

进销存——标准版&#xff08;完成&#xff09; 总结前一代几个产品功能推出一个通用标准版&#xff0c;改用硬件授权。 产品授权管理系统2.0&#xff08;完成&#xff09; 提供新产品的注册、升级、管理等功能的RIA Web系统。 Flex报表引擎&#xff08;完成&#xff0…

jenkins指定具体项目具体分支进行构建部署

知识背景 1、使用码云WebHooks进行持续集成的时候&#xff0c;我们首先应该明白&#xff0c;他的原理大致是这样的&#xff1a;当我们每一次提交代码到码云的时候&#xff0c;码云会帮我们发送一个关于Push的Post请求到我们的Jenkins服务器&#xff0c;然后Jenkins持续集成插件…

inflate()引发NullPointerException

有时候我们在infalete的时候明明什么都对为什么它会提示出错 原意是你的资源layout出错了 注意看有没有把View写成view 这个View应该大写&#xff01;V而不是小写v 踩坑踩了两次了&#xff01;上次以为是个小问题没有注意&#xff0c;这次一定要记录下来&#xff01;&#xff…

用加密狗控制软件的授权(C#)

加密狗授权方式介绍 每只加密狗都有一个固定的序列号&#xff0c;并且一般是无法修改的。软件运行时读取加密狗的序列号进行判断&#xff0c;序列号通过验证后才能正常使用软件。 选购一套加密狗开发套件 我选购了SaftNet的USB软件狗&#xff0c;入手后查阅开发资料(不同…