Sharing code between Flex and AIR - apache-flex

As you know, we could build a RIA application based on flex. Also, we could build an desktop application based on AIR. I have a question, If we want to build web & desktop application simultaneously. Could we use the same codes to ship our production to web & desktop?

If you design your application for it, you should have no problems in sharing 99% of your codebase between your Flex and AIR builds.
You will need a separate application MXML for the Flex / AIR versions as AIR uses a WindowedApplication and Flex uses Application
You will need to abstract your usage of any AIR-only APIs. That is, any class, property or method marked with the AIR-only icon (
) in the Online Documentation. You might find this process easier if you are using a Dependency Injection container like Swift Suspenders.
Alternatively, you can split your service definitions into two different source trees. This would result in your AIR project and Flex project sharing one source path, but also having their own source path. This way, code that accesses com.application.MyService would be shared across AIR and Flex but the implementation of com.application.MyService would differ depending on which 'service source path' was being used.
You may find it useful to configure each build with a compiler flag like -define+=CONFIG::AIR. This allows you to use conditional compilation so that you can compile the same file for both builds, but include specific code for the AIR build.
Here is an exmaple of conditional compilation:
public function getMyService() : IMyService
{
CONIFG::AIR
{
return new MyServiceThatUsesAnAIROnlyAPI();
}
return new FallbackServiceForFlex();
}
Unfortunately there is no way to 'negate' a conditional flag (ie. !CONFIG::AIR) so you either need to be smart about your usage of it, or include two flags (CONFIG::AIR and CONFIG::FLEX)

I'm surprised no one said it yet, but this is how I would do it:
Create a library project. this project will include all your
shared code.
Create a Flex project for web deployment
Create an AIR Project for AIR deployment
Both the Flex and AIR projects can reference and use code in the library project. The AIR project can use AIR specific functionality without affecting the web project.
If you need to perform different actions differently based on whether using the web project or the AIR project, you can create interfaces in the library project and implement them in the main project to use the respective APIs.

yes, you can do it.
there are some conditions you have to control in code.
Keep in mind, if the application is also a flex app, then it will be a single window app.
for every project I make needing this I create 3 projects
code base (the main control is a group or a canvas)
flex exporter => when you build this you will end up with a flex application
it has a control from #1 inside the main application
air exporter => when you build this you will end up with an Air app
it has a control from #1 inside the main window.

Related

How to use .NET 6-windows and .NET 6 targets in one library

I've segregated my WinUI 3 application into different layers: Application, Infrastructure, Presentation etc.
And all the projects have targets: net6.0-windows and I want to move it to the Uno Platform.
So, I've added a new target: net6.0
And at this moment the problem arises:
Type [WinUI] component already defines a member, called InitializeComponent or some problems with binding.
Is it possible to make such type of library with targets to net6-windows and net6.0?
For the Windows app project itself, you need to use net6-windows, as that provides additional dependencies specific to Windows app projects. All other libraries (non-app projects) can then use net6.0.
Regarding the specific error message, you are getting, the reason might be the generated files have some kind of conflict - you can try deleting the obj and bin folders and rebuild.
The easiest way to make existing Windows app support Uno would probably be to create a blank Uno solution and then migrate the code there (as the solution has already the required setup for platform-specific projects prepared and you can then just add your code.
Uno also provides templates for cross-targeted libraries, so you might be able to use similar approach. The one linked is for "UWP" solution however, so to make it WinUI, you would need to switch from uap10.0.18362 to net6-windows.

bundle optimization in distributed software architecture

We have an architecture where one big application is split into multiple Angular applications maintained by different teams with different deploy schedules.
These separate Angular applications in an ASP.NET context are deployed on a server and run as one big application.
Every application is deployed on a separate app pool and they all have the same layout and framework code.
Each application would use a bundle optimized by using the AOT compiler and a module bundler (rollup or webpack 2).
Each application would also use centralized JavaScript code which needs to be centralized in the big application (framework code). This code would also use Angular components and contain things such as a centralized layout component, multiple angular services making web API calls, etc...
So each application would use this same frameworke code.
The goal is also that when a change occurs to that framework code no single application would have to update and deploy again.
The standard way that I see is that es2015 imports are used and that a module bundler interprets the imports and only adds the necessary code into the module (tree shaking). Mostly the Angular framework stuff that you need is also included in the bundle (no use of CDN).
But in this case there are 3 parties delivering code:
Angular and other vendor code
The centralized custom-made framework code used through all applications also using Angular and also providing a bundle
The application itself providing one bundle
How would you go about to split and optimize the bundles?
Make a separate bundle with all Angular/vendor stuff that the centralized framework code and the application need to use
Angular stuff would be excluded from the main bundle
Use a CDN-like way to centralize the custom framework stuff and referencing that bundle (without angular code in the bundle)
So you would end up with something like this:
<script src="vendor-bundle.js"></script>
<script src="/central-location/frameworking-bundle.js"></script>
<script src="app-bundle.js">/script>;
What is the best approach in this specific case? I cannot find good examples for this kind of architecture setup.
Just use this kind of construction:
<script src="vendor-bundle.js"></script>
<script src="/central-location/frameworking-bundle.js"></script>
<script src="app-bundle.js">/script>;
And use eTags/last modified caching on the frameworking-bundle.js
This way the file is downloaded again if modified.
Users will always get latest version without using versions/hashing/query string. It won't have to do modifications to the code.
https://betterexplained.com/articles/how-to-optimize-your-site-with-http-caching/
The frameworking code should exclude the vendor code and the application should define it. In the same way that for example Kendo requires you to have JQuery.

how to implement Exif.PCL in xamarin forms?

I am trying to create a project in which picture is taken to upload from mobile camera, but when it is taken with front camera it rotates upside down (especially Android). I have read suggestions to use Exif.PCL nuget package but dont know how to implement the same. Can anybody help me out with this ?
Thanks
Background
I had the same problem in one of my apps. After trying different approaches I've found several problems with current implementations. Generally I use XLabs, which has media picking capabilities.
Issues
First of all it lacked support for scaling and autorotating images after they are taken. That's your question. So, first of all I had to implement some after-processing as soon as the image was picked.
Second, there are problems with Android and Xamarin.Forms due do how Activities are handled in Android. The way it works on Android is you launch CameraActivity or PhotoGalleryActivity which are actually hosted in a different application. Those Activities use substential amount of system memory, and due to this operating system will try to kill non-forground processes, including your app :) Workarround for this was completely implementing photo taking flow inside of my application by creating photo taking activities from scratch. Thus, I will never leave my app, and Android runtime will never kill my application.
Solution
Taking account all of this, I've implement my own flow of Image capturing. You can find the source code HERE. The basic architecture is following:
I've created IImageService, which has methods for picking images from camera or library.
public interface IImageService
{
Task<IImage> GetImageFromLibrary();
Task<IImage> GetImageFromCamera();
}
Then I've implemented this for iOS and Android separately and used dependency injection. For iOS I use XLabs implementation, cause it works as it should there are no problems with it. For Android I've created several activities to support picking images from Camera and Library: CameraActivity, PhotoGaleryActivity, which basically replace the native image picking activities.
After I pick the image I do scaling and rotating procedure. For iOS I've created UIImageToolbox static class which has GetScaledAndRotatedImage method. For Android it's BitmapToolbox static class which has GetScaledAndRotatedBitmap method.
In my sample application I've created ImageViewModel and ImagePage to demonstrate the usage of IImageService. It should be straightforward.
How to use the sample app?
Let me give a small remark. You can use only XLabs implementation for both iOS and Android and just use BitmapToolbox and UIImageToolbox to implement the scaling and rotation. And this is answer to your question. However, if you want your app to be stable on Android you need to go a little bit dipper.
Install all the necessary nuget packages to your Forms, Droid and iOS projects. You can find the packages that are used by sample application in packages.config file of each project
I use MvvmCross Messenger plugin for broadcast messaging, if you have alternative you can easily replace it. But if you want to use it, don't forget to register dependencies in your AppDelegate and MainActivity
DependencyService.Register();
Add necessary classes to your Forms, iOS and Android projects from sample application. You can use Resharper to fix namespaces for you.
For xaml files, if you drug and drop to forms project default build action and Custom Tool are set to wrong values. Thus click the xaml file, select properties set Build Action to Embedded Resource, and Custom Tool to MSBuild:UpdateDesignTimeXaml
For android project add necessary resources from drawable, drawable-xxhdpi, layout and values folders.
In grid_cell_photo_galery_item.axml file fix namespaces. Replace ImageSample.Droid.Views.SquareRelativeLayout by your namespace.
For Android, right click Android project, select properties, go to Android Manifest and add CAMERA, READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions.
For Android, right click Android project, select properties, go to Advanced and set Max Heap Size to something like 1G, this is needed because PhotoGalaryActivity uses substantial amount of memory to display images and we need an increased heap size.
For iOS, don't forget to add dependency injection for MediaPicker in AppDelegate - DependencyService.Register<MediaPicker>();
That's all.

Warning when migratring from Flex 3 to Flex 4

I received this warning when I migrated my application from flex 3 to flex 4:
components:MyApp is a module or application that is directly referenced. This will cause components:MyApp and all of its dependencies to be linked in with modules:searchModule. Using an interface is the recommended practice to avoid this. Unknown Flex Problem
MyApp is a class which extends the Application component and in the module named "searchModule" there's this line:
var parentApp:myApp = parentApplication as MyApp;
I then use the variable myApp to call methods defined in the MyApp class from within this module.
This warning is reported 10 times because I am doing the same in other modules.
I want to fix it but I don't understand the part "this will cause its dependencies to be linked in with modules" and how would I make an interface to avoid this? And why there wasn't a warning about it in flex 3?
Thanks in advance
I'm guessing a bit, but...
The Flex Framework is one of those special Adobe-only libraries that can be cached by the Flex player. As such, with certain compile settings, the SWF from the compiler does not contain the Flex library. In lex 4, the framework is not compiled into your application SWf, resulting in significantly smaller application file size.
If you extend the Application class, which it sounds like you done, the compiler cannot count on your new "Application" being in the cached Flex Framework and therefore must compile your new class, and therefore the Application tag into your SWF. This is going to daisy chain significantly; as the Application tag does a lot of Flex Framework setup stuff.
I assume that is what the warning means in terms of dependencies.
Did you really extend Application with additional functionality? Or is "MyApp.mxml" just the name of the your main application file?
You might try this:
var parentApp:Application = parentApplication as Application;
I believe there is a FlexGlobals class introduced in Flex 4, which can also give you access to the top level Application.
In terms of using an interface. Interfaces are designed to help remove specific dependencies. You can create an interface for your new functionality of the new Application class and reference that instead.
var parentApp:myApp = parentApplication as IMyApp
Based on my interpertation of the messages you're seeing that may address the issue.
I had this error when I had Application MXML insted of Component MXML, for example.
Changed Application to Group, in referenced Component, and warning was no more.
Reason for error was, because I worked on component in separate project as application, and later copied it to main project, but I didn't change it to component.

In Flex, is it posible to identify if the code is runing on Web or AIR?

I'm coding an app that runs both in the web and on AIR, to avoid copying code arround, I figured I should do 3 kinds of projects on flex builder: Library, Web and AIR projects.
So all my code is on the Library project.
I have accessData.as that extends EventDispatcher to fetch web services and return them as an event. I plan on using this class to also fetch SQLite data for the desktop version, but to do so I need it to decide from wich source to get the data depending on if its Web or AIR.
Anyone know how to do this?
Please refer to this link Detect AIR versus Flash Player from an actionscript library Its more detailed.
You really should have two build targets, one for Web and one for AIR. And your code should be designed in a way that the rest of the system doesnt care what the implementing part is doing, only that it conforms to a certain interface. This way, each build simply replaces the implementing code for each desired platform.
You may find something useful under System or Capabilities in the docs.
Create 2 projects Air and Standalone and create 2 conditional compilation variables for example "standalone" and "air". (more here).
Go to Project->Properties->Flex Compiler and add
For air project:
-define=CONFIG::standalone,false -define=CONFIG::air,true
and for stanalone:
-define=CONFIG::debugging,true -define=CONFIG::air,false
In your code set:
CONFIG::standalone {
trace("this code will be compiled only when air=false and standalone=true");
}
CONFIG::air {
trace("this code will be compiled only when air=true and standalone=false");
}
umm... I just found out a way
var appName:String = Application.application.name;
this works since the web version is called "" and the desktop version is called " desktop"
but if anyone has a better way please go ahead.
thanks.

Resources