Archive for the ‘Flex/Air’ Category
AdvancedDataGridAccImpl issue
Today I added Kapit Inspect (http://lab.kapit.fr/display/kapinspect/Kap+Inspect) back in to my project to help me debug some strange goings on. The compiler then started complaining with:
- Definition mx.accessibility:AdvancedDataGridAccImpl could not be found.
- Access of undefined property AdvancedDataGridAccImpl in package mx.accessibility.
Explanation (yeah, like it was that easy): Kap Inspect uses AdvancedDataGridAccImpl, which is not included in the base Flex SDK download – it is in the additional data visualisation zip (available from http://www.adobe.com/cfusion/entitlement/index.cfm?e=flex3sdk) which I hadn’t installed on the sdk on this new machine. Doh.
k.
Flex Builder 3 plugin, Eclipse, OS X
Trying to install Flex Builder 3 with Eclipse Galileo on OS X … no dice.
As reported at http://furiouspurpose.blogspot.com/2009/06/flex-builder-3-on-eclipse-35-gallileo.html, after downloading the Eclipse bundle for PHP developers I could install FB3 on Galileo. However,
- Compiler warnings then got displayed one at a time i.e. just displays first problem, had to fix and recompile to reveal the next one – not good for productivity
- When I tried to install the Java Development Kit (from Europa Discovery site) in order to install Ant, the installation failed, saying that only one of JDK or the PHP tools could be installed. I need Ant tools, so that’s a showstopper.
I’ve now gone back to Ganymede which works – though I can’t say I’m delighted with performance on my new MacBookPro
A better e4x example
Given some XML of the following form:
<documents> <document type="salesInv" url="assets/demoData/inv_acme_20090920.pdf"> <metaData type="date" value="20/09/09"/> <metaData type="coName" value="ACME Industrial"/> <metaData type="orderNo" value="1"/> </document> <document type="correspondence" url="assets/demoData/inv_acme_20090616pdf"> <metaData type="date" value="16/06/09"/> <metaData type="from" value="David Davidson"/> <metaData type="to" value="Andrew Andrewson"/> </document> <document type="salesInv" url="assets/demoData/inv_acme_20090820pdf"> <metaData type="date" value="20/08/09"/> <metaData type="coName" value="ACME Industrial"/> <metaData type="orderNo" value="2"/> </document> <document type="salesInv" url="assets/demoData/inv_acme_20090820pdf"> <metaData type="date" value="20/08/09"/> <metaData type="coName" value="Botheringtons"/> <metaData type="orderNo" value="3"/> </document> </documents>
… and using a ‘SearchCriterionVO’ of the following form:
public class SearchCriterionVO { public var fieldId:String; public var value:String; }
… a series of search criteria can be used to filter the XML via:
var filteredDocs:XMLList = documents; for each (var criterion:SearchCriterionVO in searchDetails.criteria) { if (criterion.value.length > 0) { filteredDocs = filteredDocs.(child('metaData').(@type==criterion.fieldId && @value==criterion.value).length() > 0); } }
e4x expression tool and examples
I like Flex, but being a big fan of XSLT and XPath, E4X drives me mad – to me the notation is clunky and counter intuitive (compared to XPath), though I do concede that may be because of what I learned first.
I don’t find myself using non-trivial E4X expressions quite often enough for it all to become second nature … so I find this online e4x expression tool very useful.
While I’m making a note-to-self on the subject of e4x, I have just (re)established, that if you want to find a list of nodes which have at least one non-empty descendent of a certain type, the expression is of the form:
a.b.c.(d.e.(text().length()>0).length() > 0)
I’m not seeing a lot of lists of e4x examples out there, so I’ll try to remember to add further e4x examples as comments to this post – and please feel free to do the same!
kdw
Programmatically getting DataGrid to sort
I’ve just had a merry time getting a DataGrid to sort by a particular column (and show the apt arrow in the header) when it first renders i.e. as if the user had clicked the header.
Googling on the subject suggested (http://blog.flexexamples.com/2008/02/28/displaying-the-sort-arrow-in-a-flex-datagrid-control-without-having-to-click-a-column/) that defining dataProvider.sort then calling dataProvider.refresh() would have the desired effect – however for me it didn’t work: the arrow got displayed, but did not sort the column properly – until the user actually clicked the header, at which point it all came good (and continued to re-sort when items were added).
In the end I had to use a rather literal solution to the problem i.e. simulate the user clicking the header by dispatching a DataGridEvent.HEADER_RELEASE event:
...
var eventOut:DataGridEvent = new DataGridEvent(DataGridEvent.HEADER_RELEASE, false, false, myColIndex);
myGrid.dispatchEvent(eventOut);
...Not ideal, but it worked – so posting here in case it helps anyone else.
kdw.
Use the addedToStage event with care!
Here’s something that just stung me: the addedToStage event can get fired at unexpected times e.g. if a component is sitting inside a container that has a scroll policy of ‘auto’, and something causes scrollbars to appear, the container will re-add all its children as part of introducing the scroll bar – so they will each get an addedToStage event, even though they themselves haven’t changed at all.
Recording audio to local file from an Air app
If you want to record audio from an Air app and store that recording locally, unfortunately you can’t simply write the sound file to disk (despite the fact Air has sufficient permissions to do that) because Flex/Air won’t encode audio or video using any of the formats you’d want to store (e.g. .mp3, .wav etc.).
Flash Player 6 and above uses the proprietary Nellymoser codec, and Flash Player 10 introduced support for the Speex codec – which is Open Source and free – but even using Speex it is not possible to write the recording to the file system (much to the annoyance of a lot of developers).
Until such a time as Adobe allow it directly, if you want to record an audio or video file there are two options (as far as I know):
1) Stream the recording to a media server (such as Adobe’s Flash Media Server, or an alternative such as Wowza) and then at the server end provide a service that will return the audio back to the client in a more useful format (e.g. mp3). This isn’t something I’ve done, but believe it would be relatively straightforward (though does have the cost associated with providing the media server service, and obviously only works while the Air app is online).
or
2) Use another technology to record the sound (e.g. a Java application), and make that talk back and forth with the Air app, e.g. via sockets. For example, it’s possible to implement a recorder using the Java Sound library, then, on windows, install that java app as a service that starts automatically; the Air app can then send messages to the java recorder by setting up a socket along the lines of:
... _recorderSocket = new XMLSocket(); _recorderSocket.addEventListener(DataEvent.DATA, onIncomingData); _recorderSocket.connect("127.0.0.1", _myPortNumber); ... // Messages sent back from the java app will arrive here private function handleIncomingData(event:DataEvent):void { switch (event.data as String) { ... } }
Note that although it is possible to make Java Sound record in .mp3, there are licensing implications. An alternative is to record to .wav format – which Flex/Air won’t play back, but you can play back via Java, using sockets for control in the same way as recording.
This route I have done, and it seems to work just fine (though there are some complications re making Java Sound record on Vista, but I’ll blog on those separately).
HTH.