Flex standalone application with no database - apache-flex

I am trying to develop an application which can be used locally by my team mates. its a sort of issue tracking application with report generation. am planning to do it on flex. in my company environment, i do have a lots of restrictions like, can't install AIR, no database, etc.
so am planning to develop on flex app, and put it in a shared drive. now the main problem is how can i store data. i have an idea like using excel files as database. I want opinion about this option, as well as, if anyone has tried reading and writing excel files from Flex application I want the suggestions also.
Thanks, Anoop

Flex provides the RemoteObject, WebService, and HTTPService tags for accessing remote data and services. AIR Expands that a bit with some APIs for local file access (File) and SQL Lite database.
Without AIR APIs you won't be able to write local files; and I doubt you can write them. You could try to use HTTPService with a "file://" URL. I would expect cross domain issues.
Can you set up the Flex app to access a remote server? If so, you can have the server deal with creating and editing the excel files. but, if you could do that why not use a real database?
You can look at other tools to create desktop applications from Flex. I believe Janus is one option ( http://www.janus-flash.com/ ). You could also use Flash Pro and publish to an executable; but it would be difficult, but possible, to make that support Flex code. Zinc is another option ( http://www.multidmedia.com/ ).
If AIR isn't allowed, I'm not sure why these other options would be, though. I can't help but wonder if you're better off exploring an MS Access solution instead of trying to turn client/server technologies into desktop technologies.

You can read/write to local files using the FileReference class. I've used the FileReference class for opening and saving images without using serverside code.
Here is an example:
package
{
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.net.FileFilter;
import flash.net.FileReference;
import flash.net.FileReferenceList;
public class Main extends Sprite
{
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
//load a file when the application starts
var fileRef:FileReference = new FileReference();
var fileRefList:FileReferenceList;
fileRefList = new FileReferenceList();
fileRef.addEventListener(Event.SELECT, function(evt:Event):void {
fileRef.load();
});
fileRef.addEventListener(Event.COMPLETE, function(evt:Event):void
{
//do something with the loaded data here
trace(fileRef.data);
onSave();
});
var arr:Array = [];
arr.push(new FileFilter("Data file", "*.dat"));
//prompt the user for the file to load
fileRef.browse(arr);
}
private function onSave():void
{
var fileRef:FileReference = new FileReference();
fileRef.save("this is my data to save");
}
}
}

Related

Using Lit with Javascript and no build tools

I am building a desktop app that monitors some things and generates data about what it is monitoring. When the user wants to interact with the data the app starts a very simple web server. The server serves static pages and has a basic http API to serve the data. I use html as a universal UI, the user uses their browser to view and interact with the data.
I would like to rewrite my html/css/js into a component based web app using Google's Lit 2. I like the idea of plain web components but I noticed that Lit offers some great additional features. Not surprisingly, most of the Lit docs are geared toward a more traditional web environment with a build step. I want to see if I can keep my server as simple as possible and avoid traditional backend tools (typescript compilation, minification, etc). I would like to replace my current static html/css/js with Lit components in a series of simple js files.
Currently, my server serves my pages from a 'public' directory and has a minimal http API:
- public/
-- js/
-- css/
-- index.html
How should I use Lit in a system without a build step? What is the minimum set of Lit files I would need to serve along with my own javascript classes that inherit from LitElement?
2022 update: Starting with version 2.2.0, lit is also available as a pre-built bundle, see https://lit.dev/docs/getting-started/#use-bundles
<simple-greeting name="World"></simple-greeting>
<script type="module">
import {html, css, LitElement} from 'https://cdn.jsdelivr.net/gh/lit/dist#2.4.0/core/lit-core.min.js';
export class SimpleGreeting extends LitElement {
static get styles() {
return css`p { color: blue }`;
}
static get properties() {
return {
name: {type: String}
}
}
constructor() {
super();
this.name = 'Somebody';
}
render() {
return html`<p>Hello, ${this.name}!</p>`;
}
}
customElements.define('simple-greeting', SimpleGreeting);
</script>
Original answer:
The Lit team doesn't provide a pre-built bundle as of 2021-08-01, you have to build yourself (to resolve the bare module specifiers, such as import .. from 'lit-html', which are not supported by browsers yet)
If you're fine with relying on a third-party CDN and supporting modern browsers only, skypack is very useful, as you can simply import lit from 'https://cdn.skypack.dev/lit'; in a web page.
(If you open https://cdn.skypack.dev/lit and then the pinned URL specified in comments, you can see there are only 5 JS modules involved, so extracting them from lit's source by hand to host as part of your application shouldn't be very hard either.)

Xamarin Forms: Open downloaded file in default Android/iOS application

I am using Xamarin Forms. I would like to download jpg file (it is done) and then open that jpg in default application on Android/iOS (opening photo browser with this photo). Of course photo is single example, I would like to open any file in default application.
I found several solutions native-only but my application is designed to be cross-platform. I though that I can use Launcher from Xamarin.Essentials package but apparently I can't.
How to achieve this?
You can have a try with Xamarin.Essentials: Launcher:
var fn = "File.txt";
var file = Path.Combine(FileSystem.CacheDirectory, fn);
File.WriteAllText(file, "Hello World");
await Launcher.OpenAsync(new OpenFileRequest
{
File = new ReadOnlyFile(file)
});
I found several solutions native-only
Opening something in another app is quite close to the system for a mobile application and there are some things to consider, which dependend on the platform. Usually, mobile apps run in a sandbox with very limited access to the surrounding system. Particularly this means that, if you downloaded a file to the sandbox of your app, other apps (which native viewers are), aren't allowed to access the file.
On Android, you can copy the file to a shared space (see Application.Context.GetExternalFilesDir(null)) and then open it. This might be possible with Essentials, but I'm not quite sure, but since we're on the Android platform anyway now, you could create an intent now anyway.
On iOS you create controllers from within your app (for example the QLPreviewController to preview the file) that may access items in your sandbox. Depending on the type of controller (e.g. UIActivityViewController) they may open other apps.
How to use this platform-independently?
Since you are programming a platform independent app, you'll have to take care that the correct class is called to the platform dependent work. There are several options how you can achieve this
Use the DependencyService
Use a real dependency injection framework
Use an abstract base class with initialization in the platform dependent projects
DependencyService
To use the Xamarin.Forms DependencyService you need two things
An interface for the functionality you'd like to implement
One implementation per platform
Assuming you hvae a simple interface to share a file
public IShareFile
{
void ShareFile(string fileName);
}
you can implement an implementation of this interface on each platform and add the DependencyAttribute to the assembly. e.g. for iOS:
[assembly: Dependency(typeof(MyApp.iOS.DeviceOrientationService))]
namespace MyApp.iOS
{
public class ShareFile : IShareFile
{
public void Share(string fileName)
{
// implementation goes here
}
}
}
The general scaffold is the same for Android, albeit the implementation differs.
Using a real dependency injection framework
Basically it's pretty much the same. You can skip the DependencyAttribute, though. In order to make the implementation available you'll have to get hold of the DI container from your platform specific code, which might be tricky. This might be an overshoot for a single dependency, but if you're using a DI container anyway and there are X dependencies, it might be worth the effort.
Using an abstract base class
Add an abstract base class to your project
public abstract class ShareFile
{
public static ShareFile Instance { get; protected set; }
public abstract void Share(string fileName);
}
and in your implementation in the platform specific project, you add an Init() method
internal class ShareFileImpl : ShareFile
{
public static void Init()
{
ShareFile.Instance = new ShareFileImpl();
}
public void Share(string fileName)
{
// implementation goes here
}
}
This init method must be called from your platform specific code. Most likely during initialization. The implementation can then be accessed via its abstraction from your platform independent code (of course you'll see only the abstraction, public methods added to ShareFileImpl won't be visible from your platform independent code).
ShareFile.Instance.Share(fileName);
A combination of the abstract class approach and dependency injection is also conceivable. When registering your classes in the DI framework, you could register the platform instance like
container.RegisterInstance<ShareFile>(ShareFile.Instance);
This way you can make use of the DI container features (e.g. constructor injection), while keeping the hassles of using the DI container from your platform specific project away from you. The drawback is, that you'll still have to call ShareFileImpl.Init() from your platform specfic code.

PhoneGap Local Storage WebSQL, IndexedDB, html5sql, lawnchair

I am trying to figure out the best way to store data in my cross platform app I am developing using PhoneGap.The API instructions suggest using WebSQL however this will no longer be supported, and IndexedDB is currently only for Windows / Blackberry.
There are many different questions on here many of the answers are really old and this, but I cannot seem to find the most popular js library for shipping an app with an existing database? (I.e. a good helper .js to simplify things).
I looked at HTML5SQL but the documentation is very sparse, lawnchair I am not sure about.
I don't know if this question will get flagged for being more preference bound, but I will give my 2 cents if it can help.
I have been able to ship an app with an existing database using SQLite with Phonegap/Cordova. Basically how I did it in Android was using the lite4cordova SQLite plugin:
https://github.com/lite4cordova/Cordova-SQLitePlugin
In the native code on load, I would check the default directory to see if a database with a specific name exists:
try {
File dbFile = getDatabasePath("data.db");
Log.v("info", "dbfiledir: " + dbFile.getAbsolutePath());
if (!dbFile.exists()) {
this.copy("data.db", dbFile.getAbsolutePath());
}
} catch (Exception e) {
e.printStackTrace();
}
And if it does not exist, copy the database file from the assets folder to the default database directory:
void copy(String file, String folder) throws IOException {
File CheckDirectory;
CheckDirectory = new File(folder);
String parentPath = CheckDirectory.getParent();
File filedir = new File(parentPath);
//File file2 = new File(file);
//Log.v("info", "filedir: " + file2.getAbsolutePath());
if (!filedir.exists()) {
if (!filedir.mkdirs()) {
return;
}
}
InputStream in = this.getApplicationContext().getAssets().open(file);
File newfile = new File(folder);
OutputStream out = new FileOutputStream(newfile);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0)
out.write(buf, 0, len);
in.close();
out.close();
}
Now when the app loads, it will only copy if the database does not already exist. I can open the database using simply (Syntax may vary depending on plugin):
db = window.sqlitePlugin.openDatabase({
name : "data"
});
I will soon be performing the same logic on the iOS side, but I think it should be similarly straightforward.
That being said, there is a plugin listed on http://plugreg.com that provides a helper library for shipping prepopulated databases with WebSQL:
https://github.com/Smile-SA/cordova-plugin-websqldatabase-initializer
I wanted to use SQLite for my project so I opted for the copy on load method. Good luck!
Latest Update:
New Cross Platform Cordova WebSQL plugin by MS Open Tech
Microsoft Open Technologies is publishing the new open source WebSQL plugin for Apache Cordova and PhoneGap. This plugin allows developers to integrate a persistent SQL-based local storage solution in their Cordova apps using the exact same JavaScript code across Android, iOS, Windows Phone and Windows Store.

With MvvmCross what is the preferred way to copy a prefilled SQLite Database

I am modifying the N-10-KittensDb sample solution.
I See how to create a SQLite database, but I wish to use an existing database. I am guessing that I need to copy the database to the proper UI data folder. Maybe it is done within the Core project? And if so how is the correct path injected into the running Exec? As the Core can be used across many UI's? What method is called to see if the database exists or needs to be copied?
Sample from DataService:
public DataService(ISQLiteConnectionFactory factory)
{
const string file = "Cats.sldb";
var connection = factory.Create(file);
connection.CreateTable<Kitten>();
}
I believe the paths are different for Android vs Phone vs Touch vs Wpf?
Please direct me to a sample piece of code that uses the Cirrious.MvvmCross.Plugins.Sqlite for Phone or Wpf.
Thank you
Dan
Each platform by default creates a database in a folder location appropriate for the platform - e.g. Touch uses:
public ISQLiteConnection Create(string address)
{
var path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
return new SQLiteConnection(Path.Combine(path, address));
}
from https://github.com/slodge/MvvmCross/blob/v3/Plugins/Cirrious/Sqlite/Cirrious.MvvmCross.Plugins.Sqlite.Touch/MvxTouchSQLiteConnectionFactory.cs#L18
To read/write files, MvvmCross does bundle a File plugin - this also operates by default in platform specific locations - but the two may not match perfectly - e.g. see:
protected override string FullPath(string path)
{
if (path.StartsWith(ResScheme))
return path.Substring(ResScheme.Length);
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), path);
}
from https://github.com/slodge/MvvmCross/blob/v3/Plugins/Cirrious/File/Cirrious.MvvmCross.Plugins.File.Touch/MvxTouchFileStore.cs#L22
Because of this mismatch, in order to share the same database-specific copy code across platforms you may find it easier to just inject your own platform specific copy on each platform - for more on injecting platform specific services, see http://slodge.blogspot.co.uk/2013/06/n31-injection-platform-specific.html

Adobe air... launch website but pick which browser?

OK I know that in Adobe Air you can call navigateToURL(new URLRequest(url)) and it will open the users default web browser to open the page.
Also now in AIR 2 you can launch any application.
So I am wondering if there is a way I can launch a particular browser to open a page in?
I it turns out with AIR 2 you can run command ling arguments so I was able to achieve what I wanted like so:
private function openApp():void
{
if(NativeProcess.isSupported)
{
var file:File = File.userDirectory;
file = file.resolvePath("AppData/Local/Google/Chrome/Application/chrome.exe");
var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
nativeProcessStartupInfo.executable = file;
var process:NativeProcess = new NativeProcess();
var args:Vector.<String> = new Vector.<String>();
args.push("https://www.google.com");
nativeProcessStartupInfo.arguments = args;
process.start(nativeProcessStartupInfo);
}
}
If you're using navigateToURL it, basically, passes the URL to the operating system and opens the default application for handling such requests. You can use navigateToURL to open word documents and other files too.
I was pretty sure that the NativeProcess features of AIR 2 allow you to launch applications, but I did not believe they allow you introspect the system to discover what browsers exist and where the DLL / EXE files are.
A good article on the native process stuff: http://www.adobe.com/devnet/air/flex/quickstart/interacting_with_native_process_02.html

Resources