Firefox webapp file input - webapp2

I'm developing a webapp for firefox aurora (android). And i have an file input.
But when users click on the input they can't choose files from sdcard or filesystem only pictures, music or videos.
I search at MOZILLA DEVELOPER NETWORK, but couldn't find anything helpful.
In my manifest.webbapp i have device-storage permission:
"permissions": {
"device-storage:sdcard":{ "access": "readonly" }
},

I assume you are currently simply using the markup ?
The device-storage:sdcard is for a very different set of use cases really. And we don't have that implemented on Firefox for Android yet.
The list of applications being shown is just the set of applications that we're getting from the Android Intents system. I would imagine that if the user has some sort of filebrowser app installed it might respond to that intent and it'd pop up there.
But of course that's not something you can rely on in your app.
I'm honestly somewhat surprised that there's no default applications on android that provide that functionality, but I guess that's how it is. Or does someone know of a way to also get a filepicker intent that we can hook up to?
Medium term you will be able to use the DeviceStorage API. This will give you direct JS access to the sdcard which will allow you to build your own UI for choosing a file from the SD card. But that extra power comes with quite a few downsides. It's a privileged API which means that you'll have to write the app as a packaged app and you have to use CSP. And you'll have to go through the Firefox marketplace review process (all privileged apps have to go through code review).
So it's a pretty distant second choice.
Other than that there aren't any solutions. The best would of course be if there was a way we could plopp up an Android file picker, but I'm not sure if that's doable. And it's definitely not implemented yet.

According to the source code, this permission is only granted to apps that are packaged and privileged, the latter also means the app has to be signed by the Marketplace.
You can find more about packaged apps and privileged app types here:
https://developer.mozilla.org/en-US/docs/Apps/Packaged_apps

Just install an Android file manager app (https://play.google.com/store/search?q=file+manager&c=apps) and you will be able to select files from the SD card. There is no need for specific rights because this is handled automatically by the standard file input.

Accessing the SD Card can only be achieved through a privileged or certified app. Currently to my knowledge, there is no integration the system menus as you are hoping would be the case. Personally, I'm hoping that this will change.
API Documentation: https://developer.mozilla.org/en-US/docs/WebAPI/Device_Storage
You could create your own menu that mimics the the system one; in this way the user gets a seamless experience and they don't know the difference. It would require a little boilerplate though it's not insurmountable levels of boilerplate.
A quick snippet for browsing/enumerating all photos on the the SDCard:
var storage = navigator.getDeviceStorage("sdcard");
sdcard.browse = function () {
var pics = navigator.getDeviceStorage('pictures');
// Let's browse all the images available
var cursor = pics.enumerate();
cursor.onsuccess = function () {
var file = this.result;
alert("File found: " + file.name);
// Once we found a file we check if there are other results
if (!this.done) {
// Then we move to the next result, which call the cursor
// success with the next file as result.
this.continue();
}
}
cursor.onerror = function () {
alert("No files found: " + this.error);
}
};
If you would like some more details for reading, writing, and caulating available storage, I'm currently working on a little wrapper library in my spare time to work with the SDCard more easily (and handle some callbacks to integrate better with other code) in my spare time and can probably help you out.

Related

Issue: Audit usage of navigator.userAgent, navigator.appVersion, and navigator.platform

I started a new project in vue.js. I added navbar. At one point, I noticed issue in the console:
Audit usage of navigator.userAgent, navigator.appVersion, and navigator.platform
I don't understand this, because I don't use any navigator in the project.
Why am I seeing this issue? How can I change it?
The reason one sees the message is well explained in the description of the very same message (audit).
The real question is who/what is the source of it. There is a hint to the file extended-css.js.
Here is an example with another file (as I do not have the extended-css.js):
Right click on the file and then choose Open in new tab.
So there you can see that the reason for the audit message is the hook.js file from the Vue.js devtools extension.
In your case it would be another extension or library you are using - direct or indirect (for example a part of vuetify, etc.).
From there you have 3 choices:
ignore it
wait for the authors of the library to fix the issue and update it
disable the extension/remove the library causing it.
https://blog.chromium.org/2021/05/update-on-user-agent-string-reduction.html
Is helpful to read. Some key points:
"Beginning in M92, we plan to start sending deprecation notices for the navigator.userAgent,
navigator.appVersion, and navigator.platform getters in the DevTools Issues tab."
"If your site, service, library or application relies on certain bits of information being present in the User Agent string such as Chrome minor version, OS version number, or Android device model, you will need to begin the migration to use the User Agent Client Hints API instead."
I know I am not using the navigator getters in question so at this point, it seems I can only wait for an update to the library's .js
(in my case, bootstrap 4) to make the warning go away.

How do you test Firebase Dynamic Links in Unity?

Based on the Firebase Unity documentation, you only need to add Firebase Dynamic Links SDK and then listen for incoming links like this in order to capture Dynamic links:
void Start()
{
DynamicLinks.DynamicLinkReceived += OnDynamicLink;
}
// Display the dynamic link received by the application.
void OnDynamicLink(object sender, EventArgs args)
{
var dynamicLinkEventArgs = args as ReceivedDynamicLinkEventArgs;
Debug.LogFormat("Received dynamic link {0}", dynamicLinkEventArgs.ReceivedDynamicLink.Url.OriginalString);
}
The dynamic link I have previously generated, correctly redirects me to the Google play store where my app exists. When I click on "open" from the play store, my app opens on the device but dynamic link information is not passed at all.
Do I need to create a new alpha version of my app to test this on Play Store?
Some people in Stackoverflow mentioned about Alpha version, but those people don't have an app released, whereas I do.
Also, is there way to test this in Unity editor?
I still need to write the code to parse it and it's kind of ridiculous to blindly code this.
If you are still testing and don't want to release a version with Dynamic Links to production, you can release your build which has Dynamic Links to a beta release so you can be sure it's working as expected.
Otherwise, releasing to production also will work.
The build you are installing from play store needs to have the Dynamic Links library and also the codes anyway.

Wrap website with cordova phonegap. What happens with audio files?

I have a learn new language site, that i want to wrap in cordova phonegap.
The app needs to work offline. I also want to make it available on the app store.
The project budget is very low. I need to find a quick way to create this app within the budget and time frame.
My question.
Is it possible to just wrap the whole site? And save it all offline.
What happens to the database? Do i need to recreate the database for the app, use sqlite ect.
Some pages will have audio files, where user can listen to the word pronunciations. What happens to the audio files. Do i need to rebuild this? Or is there a quicker way.
Can all of this be achieved by using cache?
If there is a better way of doing this please let me know.
Thanks in advance
cordova-plugin-inappbrowser provides a web browser view that displays when calling cordova.InAppBrowser.open().
var ref = cordova.InAppBrowser.open('http://apache.org', '_blank', 'location=yes');
The cordova.InAppBrowser.open() function is defined to be a drop-in
replacement for the window.open() function. Existing window.open()
calls can use the InAppBrowser window, by replacing window.open:
window.open = cordova.InAppBrowser.open;
The InAppBrowser window behaves like a standard web browser, and can't access Cordova APIs. For this reason, the InAppBrowser is recommended if you need to load third-party (untrusted) content, instead of loading that into the main Cordova webview. The InAppBrowser is not subject to the whitelist, nor is opening links in the system browser.

Uploading big Files

I am an amateur ASP.net developer working on my first job (a friends website). ASP.net v4.0, using VS2010.
His company makes 3D models (using a 3D printer). The website is currently in development but can be found here. I would be the first to admit that the code has been a bit rushed and hacked in, but my friend is quite happy with what he has so far.
One of the requirements is that his customers need to be able to upload their model design files, which could be up to 100 MB each (or maybe more). I am struggling to get this to work properly.
I started by using the built in <asp:FileUpload ID="FileUpload1" runat="server" /> tag and an animated gif image, similar to the idea described in Joe Stagner's tutorial - thanks Joe, I like your presentations a lot.
This worked ok for a small test file but doesn't give any indication of upload progress. So I tried to improve my solution using ideas developed from Sunasara Imdadhusen in his code project article. My upload code looks like this:
Task t = Task.Factory.StartNew(() =>
{
byte[] buffer = new byte[UPLOAD_BUFFER_BYTE_SIZE];
// Upload the file in chunks so that we can measure how long it is taking.
using (FileStream fs = new FileStream(Path.Combine(newQuotePath, filename), FileMode.Create))
{
DateTime stopwatch = DateTime.Now;
while (stats.Uploaded < stats.TotalSize)
{
int bytecount = postedFile.InputStream.Read(buffer, 0, UPLOAD_BUFFER_BYTE_SIZE);
fs.Write(buffer, 0, bytecount);
stats.Uploaded += bytecount;
double dRate = UPLOAD_BUFFER_BYTE_SIZE / Math.Abs((DateTime.Now - stopwatch).TotalSeconds);
stats.Rate = (int)(Math.Min(dRate, int.MaxValue));
// Sleep is for debugging only!
//System.Threading.Thread.Sleep(2000);
stopwatch = DateTime.Now;
}
}
}, TaskCreationOptions.LongRunning);
Where stats is a reference to a class that is stored as a session variable, and is accessed from a javascript function running in a setInterval(...) (while the upload is taking place) by the PageMethod:
[System.Web.Services.WebMethod]
[System.Web.Script.Services.ScriptMethod]
public static UploadStatus GetFileUploadStatus()
{
UploadStatus stats = (UploadStatus)HttpContext.Current.Session["UploadFileStatus"];
if ((stats != null) && (stats.IsReady))
{
return stats;
}
else
{
return null;
}
}
This worked on my local machine (using the thread sleep to slow down the upload). So I published it to our host 123-Reg and it didn't work as expected. The animated gif comes on when the upload starts, but the progress bar doesn't start moving. The file input control and the submit button (in an IFrame) that should get disabled as soon as the upload starts take ages to become disabled. Then the web page just hangs there. After waiting for a while I clicked the page refresh button. When the page refreshed it showed that my test file had been uploaded successfully. I tried a 16 KB file and a 1.6 MB file.
Since this worked on my local machine, I suspect that this is happening because our website host (123-Reg) is using a web farm.
Anyway I thought this was going to be easy but it is not, and so I had a look for some open-source upload progress bars. I had a look at NeatUpload but it says "By default, NeatUpload won't work properly on a web garden or web farm", and it also says to get it to work on a web farm "Specify the same random 32-hex-digit decryptionKey attribute in the section of each server's Web.config". But I don't think I have access to 123-Reg's server config files(?).
My friend has suggested that perhaps we could use a service such as dropbox, but I had a look and I have no idea how to add this to our website. This might be a good option since they might be optimized for uploads.
Any advice or suggestions would be very much appreciated - thanks.
EDIT: The story so far ... still struggling with this.
I looked into using dropbox in detail (and other cloud storage providers such as SkyDrive etc). Seems that these services are designed around providing applications that interact with individual user's storage. I wanted all users to be able to upload files to MY dropbox folder but without sharing (customers should not have access to other customer's design files). Anyway I carried on, setup a dropbox account, installed the Sharpbox SDK and reprogrammed my upload code (the bit inside the task action). This seemed to work ok on my local machine, it was a bit slower because it was uploading to the dropbox server (I didn't need the Thread.Sleep). I published the website to the 123-Reg server and got a similar, unusable experience as before.
So far I had been testing on IE9, and I just happend to try it out with Chrome and I noticed a funny thing. Just after clicking the upload button but before the page refreshed Chrome showed an upload % complete dialog in the bottom left. This ran to 100%, then my controls started to show some action before the whole page started to hang again.
According to MSDN the HttpPostedFile:
"By default, all requests, including form fields and uploaded files, larger than 256 KB are buffered to disk"
So does this mean that my Task is being started after the painful part of waiting for the upload (which is actually happening between the client and a buffer)? If this is the case then it would not make sense to make it more painful by then sending the file off to dropbox right? And my progress bar is tracking the progress of the wrong bit?
(Today I am going to check the error handling of my code since I have a feeling that the reason it is hanging is because it is not recovering from an exception properly). It certainly feels like I am learning a lot by doing this.
This might be a bit overkill but you could look into using BluImp's jQuery File Upload tool (Demo site here: http://blueimp.github.com/jQuery-File-Upload/ ) - a developer called Max Pavlov has modified the original version (originally for non-dotnet technologies) for use in MVC 3.
It can be found here on git hub https://github.com/maxpavlov/jQuery-File-Upload.MVC3 . I have successfully implemented this in both MVC 3 and MVC 4 Beta. The only thing I had to do to make it work effectively in MVC 4 is remove some of the ClientDependancy (This is a DLL that handles bundling and minification of JS and CSS files) code as this replicates functionality already in MVC 4 but not in MVC 3. Additionally I have added some pages to the wiki over on GitHub describing what I did although its not complete. If you decide to go down this route I could update some details there with my more recent findings. My notes so far on MVC 4 integration can be found here https://github.com/maxpavlov/jQuery-File-Upload.MVC3/wiki/MVC-4---EnableDefaultBundles .
Incidentally I have managed to upload files up to about 2Gb using this tool and have found it quite flexible!

Air: Possible? Writing into installed application package

This is probably a bad idea or whatever you wan't to call it. Nevertheless, curious to know if Air can write inside it's own installed package. I'm referring to the OSX '.app' files found in great numbers in the applications folder. Since every one of these can be opened as a regular folder, i'm guessing that's what they are.
What other fancy filewriting tricks am i missing out on?
It's definitely a bad idea. That said, it looks like it's probably possible. Something like (untested):
var appDir:File = File.applicationDirectory; // uses app: URI, can't be written to
var appPath:String = appDir.nativePath;
var writeableAppDir:File = new File(appPath);
var newFile:File = writeableAppDir.resolvePath("writeme.txt");
The nativePath and applicationDirectory documentation in the File class are full of warnings against this. Follow them.
From the docs:
Modifying content in the application
directory is a bad practice, for
security reasons. If you want to store
application-specific data, consider
using the application storage
directory
(File.applicationStorageDirectory). If
you want any of the content in the
application storage directory to have
access to the application-priveleged
functionality (AIR APIs), you can
expose that functionality by using a
sandbox bridge.

Resources