Now you’re ready to get into the nitty-gritty details of the project air.offline.demo, which
is used by salespeople and contains the code for monitoring network connectivity, data
synchronization, and integration with Google Maps.
The PharmaSales Application for Salespeople
The PharmaSales application starts with a logon screen (Figure 9-14) that requires the
user to enter a valid full name to retrieve the schedule for that person (the password is
irrelevant here).
Figure 9-14. The PharmaSales logon screen
Just to double-check that the newly inserted schedule gets downloaded to the client’s
computer, log on as a salesperson who has scheduled visits.
Detecting Network Availability
Note the two round indicators at the bottom of the logon screen that show both the
network and the application server statuses. There are two reasons why an AIR appli-
cation might not be able to connect to its server-side components: either there is no
connection to the network or the application server doesn’t respond. Take a look at
PharmaSales Application n | 467
C# pdf to jpg - Convert PDF to JPEG images in C#.net, ASP.NET MVC, WinForms, WPF project
How to convert PDF to JPEG using C#.NET PDF to JPEG conversion / converter library control SDK
convert pdf image to jpg online; pdf to jpeg converter
C# pdf to jpg - VB.NET PDF Convert to Jpeg SDK: Convert PDF to JPEG images in vb.net, ASP.NET MVC, WinForms, WPF project
Online Tutorial for PDF to JPEG (JPG) Conversion in VB.NET Image Application
c# pdf to jpg; convert pdf pages to jpg
how an AIR application can detect whether the network and a URL resource are
available.
Any AIR application automatically has access to a global object called
flash.desktop.NativeApplication
. This object has a number of useful properties and
methods that can give you runtime access to the application descriptor, provide infor-
mation about the number of the opened windows, and also provide other application-
wide information.
You may want to get familiar with yet another useful class called
flash.system.System
. For one thing, this class has a method 
gc()
that
forces the garbage collector to kick in to avoid memory leaks in your
AIR application.
To catch a change in the network connectivity, your application should check the
NativeApplication
’s property 
nativeApplication
, which points to an object dispatch-
ing events when the network status changes. Your application can almost immediately
detect a change in the connectivity by listening to the 
Event.NETWORK_CHANGE
event as
shown here:
flash.desktop.NativeApplication.nativeApplication.addEventListener(
Event.NETWORK_CHANGE, onNetworkChange);
Unfortunately, this event may be triggered with a 10- to 15-second delay after the net-
work status changes, and it does not bear any specific information about the current
status of the network. This means that after receiving this event, you still need to test
the availability of a specific network resource that your application is interested in.
The PharmaSales application uses Google Maps to help salespeople find
the doctors’ offices they need to visit. Hence if the network is not avail-
able, the application would lose the ability to work with maps.goo
gle.com and will have to switch to Plan B, discussed later in the section
“Integrating with Google Maps” on page 487.
If you check the library path of a Flash Builder AIR project, you’ll find there a library
servicemonitor.swc, which includes 
SocketMonitor
and 
URLMonitor
classes. These classes
can monitor the availability of a specific socket or URL resource.
You can start monitoring the status of a specific HTTP-based resource by calling
URLMonitor.start()
and periodically checking the property 
URLMonitor.available
.
Example 9-11 is the complete code of the NetworkStatus.mxml component, which
monitors both the status of the network (http://maps.google.com) and the Pharma-
Sales application server and displays either a red or green light depending on the health
of the corresponding resource.
468 | | Chapter 9: Working with Adobe AIR
Online Convert Jpeg to PDF file. Best free online export Jpg image
All your JPG and PDF files will be permanently erased from our servers after If you want to turn PDF file into image file format in C# application, then
.net convert pdf to jpg; convert pdf file to jpg on
C# Image Convert: How to Convert Adobe PDF to Jpeg, Png, Bmp, &
C# sample code for PDF to jpg image conversion. This demo code convert PDF file all pages to jpg images. C# sample code for PDF to jpg image conversion.
batch pdf to jpg converter online; .pdf to jpg
Example 9-11. Monitoring network status: NetworkStatus.mxml
<?xml version="1.0" encoding="utf-8"?>
width="100%" creationComplete="onCreationComplete()" height="55">
<mx:Canvas width="200" height="55">
<mx:Label text="Server status:"/>
<mx:Image id="serverStatusIcon" x="125" source="{serverConnected ?
<mx:Label text="Google maps status: " y="26"/>
<mx:Image id="googleMapsStatusIcon" x="125" y="26"
</mx:Canvas>
<mx:Script>
<![CDATA[
import air.net.URLMonitor;
import mx.messaging.config.ServerConfig;
//Monitor connection status every second
private static const TIMER_INTERVAL:int=1000;
private static var _googleMapsURLMonitor:URLMonitor;
private static var _serverURLMonitor:URLMonitor;
public function get googleMapsConnected():Boolean{
}
public function get serverConnected():Boolean{
return _serverURLMonitor && _serverURLMonitor.available;
}
public function onCreationComplete():void{
if (_googleMapsURLMonitor == null){
initGoogleMapsURLMonitor();
}
_googleMapsURLMonitor.addEventListener(StatusEvent.STATUS,
if (_serverURLMonitor == null){
initServerURLMonitor();
}
_serverURLMonitor.addEventListener(StatusEvent.STATUS,
}
private function initGoogleMapsURLMonitor():void{
var request:URLRequest=new
request.method="HEAD";
_googleMapsURLMonitor=new URLMonitor(request);
_googleMapsURLMonitor.pollInterval=TIMER_INTERVAL;
_googleMapsURLMonitor.start();
}
PharmaSales Application n | 469
C# Image Convert: How to Convert Tiff Image to Jpeg, Png, Bmp, &
RasterEdge.XDoc.PDF.dll. C# Image Convert: Tiff to Jpeg. String inputFilePath = @"C:\input.tif"; String outputFilePath = @"C:\output.jpg"; // Convert tiff to jpg
.pdf to .jpg online; change pdf to jpg file
C# Create PDF from images Library to convert Jpeg, png images to
Best and professional C# image to PDF converter SDK for Visual Studio .NET. Batch convert PDF documents from multiple image formats, including Jpg, Png, Bmp, Gif
change pdf file to jpg online; convert pdf pictures to jpg
private function initServerURLMonitor():void{
var xml:XML=ServerConfig.serverConfigData;
var channelConfig:XML=channels[0];
var uri:String=
_serverURLMonitor=new URLMonitor(new URLRequest(uri));
_serverURLMonitor.pollInterval=TIMER_INTERVAL;
_serverURLMonitor.start();
}
private function showServerStatus(evt:StatusEvent):void{
serverStatusIcon.source=_serverURLMonitor.available ?
}
private function showGoogleMapsStatus(evt:StatusEvent):void {
}
]]>
</mx:Script>
</mx:ControlBar>
In Example 9-11, the network status is being checked as often as specified in the polling
interval:
_googleMapsURLMonitor.pollInterval=TIMER_INTERVAL;
The 
NetworkStatus
component checks the health of an HTTP resource using the
URLMonitor
object that listens to 
StatusEvent
in the function 
initNetwor
kURLMonitor()
. Based on our experience, the 
pollInterval
does not guarantee that no-
tifications of connectivity changes will arrive at the intervals specified in the 
TIMER_INTER
VAL
constant.
As an alternative, you can create a 
Timer
object and check the value of
URLMonitor.available
in the timer’s event handler function. If you decide to go this
route, keep in mind that it has additional overhead, which comes with any timer object.
Example 9-11 demonstrates yet another useful technique to specify the URI of the
network resource without the need to hardcode it in the program as is done in the
method 
initNetworkURIMonitor()
:
new URLRequest('http://maps.google.com/')
The chances that the URL of Google Maps will change are rather slim. But the URL of
the PharmaSales server will definitely be different, say, in development, QA, and pro-
duction environments. The function 
initServerURIMonitor()
extracts the URI of the
server based on the information about the location of the AMF channel in the server-
config.xml of the JEE server that was specified during the creation of the Flex project.
470 | | Chapter 9: Working with Adobe AIR
Online Convert PDF to Jpeg images. Best free online PDF JPEG
Your PDF and JPG files will be deleted from XDoc.PDF for .NET) supports converting PDF document to in .NET developing platforms using simple C# programming code
convert pdf to jpeg; change from pdf to jpg on
C# TIFF: How to Use C#.NET Code to Compress TIFF Image File
In this part, users can find a complete C# sample code for the string[] imagePaths = { @"C:\demo1.jpg", @"C:\demo2.jpg", @"C:\demo3.jpg" }; // Construct List
convert pdf to jpg file; changing pdf to jpg
This information is available inside the SWF file, and if your PharmaSales server runs
locally, the value of the 
uri
variable from the method 
initServerURIMonitor()
may look
as follows:
http://localhost:8080/air.offline.demo.web/messagebroker/amf
To test this component, you can emulate the network outage by physically unplugging
the network wire. To test whether the monitoring of the PharmaSales server works
properly, just stop the server where the Java portion of the air.offline.demo.web appli-
cation has been deployed (in our case, we were stopping the Apache Tomcat server
configured in Eclipse IDE).
After the Salesperson Logs On
The PharmaSales application is used by salespeople. After a successful logon, the fol-
lowing code is invoked:
private function initCollections():void{
"getVisitsBySalesman", VisitDTO);
visitDataCollection=new OfflineDataCollection(
fill_onClick();
}
...
private function fill_onClick():void {
visitDataCollection.fill(username.text);
visitCollection.fill(username.text);
}
This code populates two collections (
visitCollection
and 
visitDataCollection
) by
bringing the salesperson’s (username.text) data from the server. For example, after
logon, Liz Anthony will see only her schedule of visits.
The 
visitCollection
object will participate in data synchronization with a remote da-
tabase server, as it has to keep the table visits up-to-date.
The 
visitDataCollection
object brings the data from 
visit_schedule
plus the com-
ments field from the table visits. This collection doesn’t need to be synchronized, as
the visit_schedule table is being taken care of by a dispatcher of the corporation Acme
Pharm.
You’ll get familiar with the code of the class 
OfflineDataCollection
later in this chapter,
but for now suffice it to say that its function 
fill()
will retrieve all the data from a Java
class that is configured in the remoting-config.xml file of BlazeDS (or LCDS).
PharmaSales Application n | 471
C# TIFF: C#.NET Code to Convert JPEG Images to TIFF
following C# sample code to transform Jpeg image to Tiff image in your .NET application. // Define Jpeg images list. string[] imagePaths = { @"C:\demo1.jpg", @"
convert pdf to jpg for; convert pdf file to jpg online
C# WPF PDF Viewer SDK to convert and export PDF document to other
Convert PDF to image file formats with high quality, support converting PDF to PNG, JPG, BMP and GIF. C#.NET WPF PDF Viewer Tool: Convert and Export PDF.
best pdf to jpg converter for; .pdf to .jpg converter online
For example, the following code creates an instance of 
OfflineDataCollection
that’s
ready to work with the server-side destination 
com.faratasystems.demo.pharmasales
:
visitCollection = new
OfflineDataCollection("com.farata.demo.pharmasales.Visit",
"getVisitsBySalesman", VisitDTO)
In general, an application developer needs to decide which DTOs are to be saved in the
local storage and should specify them while instantiating one or more
OfflineDataCollection
objects.
The function 
initCollection()
assigns an event listener to the 
visitCollection
just to
display the current status of the data on the UI (e.g., the data is saved in the local
database).
The call of the method 
fill()
on 
OfflineDataCollection
gets converted by BlazeDS to
a server-side call to Java’s method 
getVisitBySalesman()
, which returns instances of
the 
VisitDTO
objects with the information about the visits of the salesperson. The first
argument of the 
OfflineDataCollection
constructor is the name of the remote desti-
nation, the second one is the name of the method to call, and the third one is the type
of the ActionScript DTOs arriving to the client.
When the user logs on to the PharmaSales application, his computer doesn’t have any
local databases. The local database is being created during the first call to the method
fill()
, described in the section on 
OfflineDataCollection
.
Open your application storage directory after running the application for the very first
time, and you’ll find there a file called local.db (in Windows, it’s C:\Documents and
Settings\Administrator\Application Data\PharmaSales\Local Store). This database is not
a copy of all the tables of the remote database—it stores only the data arrived in the
form of DTOs from the server.
As you continue using the application, you’ll find yet another file in the same directory.
The file local.db.bak is a backup copy of the local.db file created when you modified
the data in a disconnected mode.
You’ll better understand when, how, and why these databases are created after reading
the next section of this chapter, which describes the class 
OfflineDataCollection
. At
this point, just remember that after the method 
fill()
is complete, you have two da-
tabases that store application-specific DTOs on your local computer.
When the user starts working with the application, he needs to be able to save and sync
the data with the remote server, which is done in the PharmaSales application in the
function 
onSave()
:
visitCollection.sync();
visitDataCollection.updateLocalDB(); // update visit comments
visitDataCollection.backUp();
visitDataCollection.resetState();
472 | | Chapter 9: Working with Adobe AIR
You sync only the data from the 
visitCollection
here, as it represents the data from
the remote table 
visits
.
The 
visitDataCollection
object represents the remote table visit_schedule, which is not
being changed by the salesperson and hence doesn’t need to be synchronized. You call
the function 
backup()
here just to make the database tables supporting
visitDataCollection
identical in the main and backup databases.
Example 9-12 contains the complete code of the file PharmaSales.mxml. This applica-
tion was initially generated by Clear Data Builder, as explained in Chapter 1. In addition
to generating all the code for Flex and Java, it includes such functionality as master/
detail relationships.
When the user clicks on the visit row in the 
DataGrid
, the detail screen where the sales-
person enters visit details opens up. This application uses the 
DataForm
and
DataFormItem
components described in Chapter 3.
The UI portion of the PharmaSales application contains a 
ViewStack
component that
wraps the following views:
• Logon
• Grid with visits
• Visit details
• Google Maps
Example 9-12. PharmaSales.mxml
<?xml version="1.0" encoding="UTF-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
<mx:ViewStack id="vs" height="100%" width="100%">
<!--   Logon view   -->
<mx:Canvas height="100%" width="100%">
<mx:Panel title="Pharma Sales - Salesman" width="100%"
backgroundImage="assets/PillHand.png">
<mx:Form>
<mx:FormItem label="Username:" required="true">
</mx:FormItem>
<mx:FormItem label="Password:" required="true">
<mx:TextInput id="password" text="p455w0rd" maxChars="16"
displayAsPassword="true"/>
</mx:FormItem>
</mx:Form>
<mx:ControlBar horizontalAlign="right">
<ns1:NetworkStatus/>
<mx:Button id="logon" label="Logon" click="onLogon()"/>
<mx:Button id="reset" label="Reset" click="onReset()"/>
</mx:ControlBar>
PharmaSales Application n | 473
</mx:Panel>
</mx:Canvas>
<!--   Data grid view with visits  -->
<mx:Canvas height="100%" width="100%">
<fx:DataGrid toolTip="Double click for details"
horizontalScrollPolicy="auto" width="100%" id="dg"
<fx:columns>
<fx:DataGridColumn dataField="fullname" editable="false"
headerText="Salesman"/>
<fx:DataGridColumn dataField="fulladdress"
<fx:DataGridColumn dataField="comments" editable="false"
</fx:columns>
</fx:DataGrid>
<mx:ControlBar horizontalAlign="right">
<ns1:NetworkStatus id="network"/>
<mx:Button enabled="{dg.selectedIndex != -1 &&
<mx:Button enabled="{!visitCollection.commitRequired &&
!visitCollection.syncRequired}"
<mx:Button enabled="{ visitCollection.commitRequired ||
<mx:Button click="vs.selectedIndex=0;" label="Log out"/>
</mx:ControlBar>
</mx:Panel>
</mx:Canvas>
<!--   Visit detail view -- >
<mx:Canvas>
<mx:Panel width="100%" height="100%" title="Visit Details">
<fx:DataForm dataProvider="{dg.selectedItem}">
<fx:DataFormItem dataField="fullname" label="Salesman:"
<fx:DataFormItem dataField="fulladdress" label="Address:"
<fx:DataFormItem dataField="scheduled_date" label="Scheduled
</fx:DataForm>
<fx:DataForm dataProvider="{visit}" width="100%">
<fx:DataFormItem dataField="visit_date" label="Visit Date:"
<fx:DataFormItem dataField="contact_name"
<fx:DataFormItem dataField="comments" label="Comments:"
474 | | Chapter 9: Working with Adobe AIR
<mx:TextArea width="100%" height="100"/>
</fx:DataFormItem>
</fx:DataForm>
<mx:ControlBar horizontalAlign="right">
<ns1:NetworkStatus/>
<mx:Button label="Back" click=
</mx:ControlBar>
</mx:Panel>
</mx:Canvas>
<!--   Google Maps integration view-->
<mx:Canvas>
<mx:Panel width="100%" height="100%" title="Google Map">
<maps:Map xmlns:maps="com.google.maps.*" id="map"
key="ABQIAAAAthGneZS6I6ekX8SgzwL2HxSVN_sXTad_Y..."
url="http://code.google.com/apis/maps/"/>
<mx:ControlBar horizontalAlign="right">
<ns1:NetworkStatus/>
<mx:Button click="saveMap()" label="Save"/>
<mx:Button click="vs.selectedIndex=1;" label="Back"/>
</mx:ControlBar>
</mx:Panel>
</mx:Canvas>
<!--   Saved Google map view-->
<mx:Canvas>
<mx:Panel id="map_image" width="100%" height="100%"
title="Google Map">
<mx:Image id="saved_map" width="100%" height="100%"
creationComplete="openMapImage()"/>
<mx:ControlBar horizontalAlign="right">
<ns1:NetworkStatus/>
<mx:Button click="vs.selectedIndex=1;" label="Back"/>
</mx:ControlBar>
</mx:Panel>
</mx:Canvas>
</mx:ViewStack>
<mx:Script>
<![CDATA[
import com.google.maps.overlays.Marker;
import com.google.maps.InfoWindowOptions;
import com.google.maps.LatLng;
import com.google.maps.services.ClientGeocoder;
import mx.graphics.codec.PNGEncoder;
import com.google.maps.controls.ZoomControl;
import com.farata.demo.pharmasales.dto.VisitDataDTO;
import com.farata.demo.pharmasales.dto.VisitDTO;
import com.farata.collections.OfflineDataCollection;
import com.google.maps.services.GeocodingEvent;
import mx.events.PropertyChangeEvent;
PharmaSales Application n | 475
[Bindable]
public var visitDataCollection:OfflineDataCollection;
[Bindable]
public var visitCollection:OfflineDataCollection;
[Bindable]
public var visit:VisitDTO;
private function onSave():void {
visitCollection.sync();
visitDataCollection.updateLocalDB();
visitDataCollection.backUp();
visitDataCollection.resetState();
}
private function onDoubleClick():void {
if (dg.selectedItem){
vs.selectedIndex=2;
calculateVisit(dg.selectedItem);
}
}
private function updateVisitSchedule(obj:Object):void {
var dto:VisitDataDTO=obj as VisitDataDTO;
dto.comments=visit.comments;
}
private function calculateVisit(obj:Object):void {
var dto:VisitDataDTO=obj as VisitDataDTO;
for(var i:int=0; i < visitCollection.length; i++){
var visitDto:VisitDTO=visitCollection[i]as VisitDTO;
if (dto.id == visitDto.visit_schedule_id) {
visit=visitDto;
return ;
}
}
visit=new VisitDTO();
visit.visit_schedule_id=dto.id;
visitCollection.addItem(visit);
}
private function initCollections():void {
visitCollection=new OfflineDataCollection(
"com.farata.demo.pharmasales.Visit",
"getVisitsBySalesman", VisitDTO);
visitCollection.addEventListener(
PropertyChangeEvent.PROPERTY_CHANGE, showStatus);
visitDataCollection=new OfflineDataCollection(
"com.farata.demo.pharmasales.VisitData",
"getVisitDataBySalesman", VisitDataDTO);
fill_onClick();
}
private function showStatus(evt:PropertyChangeEvent):void {
if (evt.property == "statusMessage"){
status=evt.newValue as String;
476 | | Chapter 9: Working with Adobe AIR
Documents you may be interested
Documents you may be interested