How to save a file on shared space in Cordova with Android? - android-file

I am using Apache Cordova with cordova-plugin-file to develop some android app. Since Android API 29 (Android 10), apps no longer have access to shared space directly due to privacy issues.
I was storing some pdf file on file:///storage/emulated/0/Download/ from where the user could then open the pdf file.
window.resolveLocalFileSystemURL('file:///storage/emulated/0/Download/', function (dir) {
dir.getFile(filename, { create: true }, function (file) {
file.createWriter(function (fileWriter) {
console.log('Writing content to file')
fileWriter.onwriteend = function () {
console.log('Successful file write...')
}
fileWriter.onerror = onerror
fileWriter.write(DataBlob)
}, onerror)
}, onerror)
}, onerror)
But that stopped working on Android 10.
How can I store now a file to be accessible by the user?

window.resolveLocalFileSystemURL(cordova.file.externalRootDirectory + "/Download" used to work
This should work as is when targeting API 28 (now forbidden by Google Play)
This should work when targeting API 29 with the dev version of the plugin (which has the android:requestLegacyExternalStorage="true"), alternatively you can use the edit-config to add this flag.
This won't work when targeting API 30, as API 30 ignores the android:requestLegacyExternalStorage attribute.
It's important to read the Android Notes before you target API 30. You may need to migrate your files to another folder to maintain access to them when targeting API 30 using the new APIs. Source.
Solution for up to Android 10 (API 29)
Use the dev version of the plugin
cordova plugin rm cordova-plugin-file
cordova plugin add https://github.com/apache/cordova-plugin-file.git
I tested it and it allows me to use cordova.file.externalRootDirectory + "/Download" in Android 10 (API 29)

Related

.NET / React App not serving /.well-known/filename

I'm trying to setup Apple Pay via Stripe, which requests access to a file to verify domain ownership. The problem I'm having is that this file has no extension, so either React, Azure or my .NET application does not like it!
I've tried various solutions to date within the web.config but to no avail.
The file in question is: /.well-known/apple-developer-merchantid-domain-association
My project is a .NET project running a React SPA. I've added the file mentioned above to the /public folder, too.
I can access .txt files in the same folder, so the path/folder is accessible - It seems to be a problem with the lack of extension.
I've managed to resolve this with the following, and ensuring the ./well-known and subfiles are in my project root.
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, #".well-known")),
RequestPath = new PathString("/.well-known"),
DefaultContentType = "application/json",
ServeUnknownFileTypes = true
});

NextJs: The Serverless Function exceeds the maximum size limit of 50mb

I'm new working with NextJs and when trying to deploy my project to Vercel I'm getting the following error:
Error! The Serverless Function "api/auth" is 50.55mb which exceeds the maximum size limit of 50mb.
I have spent a lot of my time trying to find a proper answer but I didn't find any. Here is the code of the api request I'm making:
const { auth: adminAuth } = require("firebase/admin");
export default async function auth(req, res) {
const tokenId = req.query.token;
return new Promise((resolve) => {
adminAuth
.verifyIdToken(tokenId)
.then((user) => {
res.json(user);
resolve();
})
.catch(() => {
res.status(302).send("Invalid authentication");
resolve();
});
});
}
I'll be really grateful if anybody can help me, thanks y'all!
I've been dealing with the same issue. It appears that when bundling the serverless function vercel is pulling in ALL assets within your project. So 50.55MB is likely the size of your current entire build. I'm researching how to only include certain files within the vercel.json but have so far not figured exactly how to do that. For now you could probably just remove a few files from your public assets to get under the limit.
This is likely caused by firebase/admin including everything in the firebase package, not just the "admin" parts.
You can verify this by creating a file with only the import and running #vercel/nft to trace the files.
npm init -y
npm add firebase
echo "const { auth: adminAuth } = require('firebase/admin')" > index.js
npm i -g #vercel/nft
nft print index.js
The entire firebase package is quite large, so its best to follow the recommendation from the firebase team and use the firebase-admin package inside Serverless Functions.
This SDK (firebase) is intended for end-user client access from environments such as the Web, mobile Web (e.g. React Native, Ionic), Node.js desktop (e.g. Electron), or IoT devices running Node.js. If you are instead interested in using a Node.js SDK which grants you admin access from a privileged environment (like a server), you should use the Firebase Admin Node.js SDK (firebase-admin).
source: firebase NPM
You could add .vercelignore file to avoid this
Ref: https://vercel.com/guides/prevent-uploading-sourcepaths-with-vercelignore
# Ignore everything (folders and files) on root only
/*
!api
!vercel.json
!*.html
!*.css

Uploading image files to AmazonS3 using ReactJs

I am fairly new to web development (currently enrolled in a bootcamp) and have struggled finding the needed resources to incorporate uploading to Amazon S3 in my project. I apologize for the vagueness ahead of time.
I currently have a react app that is pulling images from my AmazonS3 account but I am intending to give the user the ability to upload to my bucket and use/view the images on my website.
I have tried watching tutorials and looking at various GitHub Repo's to identify what I am missing but have been unable to locate a tutorial that involves React, JSX and Javascript. (I've seen jquery, PHP, etc). Ultimately, I know this task is difficult and I am willing to put in the work but felt the need to ask if anyone knows of a useful resource that can help me?
I've tried using the 'aws-nodejs-sample' repo, 'themetoerchef/uploading-with-react' repo, watched a youTube tutorial, I've looked into FineUploader and have read the react-S3-uploader npm files but am unable to connect the dots. Additionally, I've included my AWS access keys in my .env file and tried making query strings to access the S3 bucket.
Is there a better way to go about this or are there other ways to upload with react that may be useful outside of S3?
To upload to s3 from the browser you need to get a signedUrl from an aws sdk which is how aws verifies your identity. In my last application I used skd for nodejs to generate the signedUrl and pass it to my front end application to use in pushing files to s3. You don't have to go that route there is an sdk that can be used by javascript within the browser.
Check this aws link for more
Go to your project directory and run
npm install --save react-aws-s3
https://www.npmjs.com/package/react-aws-s3
And add the code in your component as per the NPM document
import S3 from 'react-aws-s3';
const config = {
bucketName: 'myBucket',
dirName: 'media', /* optional */
region: 'eu-west-1',
accessKeyId: 'JAJHAFJFHJDFJSDHFSDHFJKDSF',
secretAccessKey: 'jhsdf99845fd98qwed42ebdyeqwd-3r98f373f=qwrq3rfr3rf',
s3Url: 'https:/your-custom-s3-url.com/', /* optional */
}
const ReactS3Client = new S3(config);
/* Notice that if you don't provide a dirName, the file will be automatically uploaded to the root of your bucket */
/* This is optional */
const newFileName = 'test-file';
ReactS3Client
.uploadFile(file, newFileName)
.then(data => console.log(data))
.catch(err => console.error(err))
/**
* {
* Response: {
* bucket: "myBucket",
* key: "image/test-image.jpg",
* location: "https://myBucket.s3.amazonaws.com/media/test-file.jpg"
* }
* }
*/
});
Now its everything is done, make sure to load your keys and secrets from Process ENV.
NOTE: Please don't forget to add the CORS policy on the AWS bucket if you see corse error, see here the detailed example.
thanks

Cannot find hostname in file:/// error when using Ionic and OAuth.io

I am using Ionic and Oauth.io to perform authentication. If I run ionic serve and include the outh.js file in my index everything works good from the browser.
But when I run ionic run ios or install the app in android, I get the following error when I press the auth button (the one that suppose to execute OAuth.popup
I do not know what to do, until now I have checked the following:
In config.xml I have access, allow-intent and allow-navigation full permisive
I have installed and re-installed the plugin ionic plugin add https://github.com/oauth-io/oauth-phonegap.git
I tried to run the native app without the inclusion of the oauth.js file and everything breaks.
Using current versions up to date.
I am new to Ionic, so I don't know how to debug the device-running app or simulator.
Could be similar to this post but not exactly .
Your advices will be appreciated.
I figure it out reading some posts. The OAuth initialization and references should be done after the device is ready, so it is best to put the initialize in this block:
$ionicPlatform.ready(function() {
// ...
if(typeof window.OAuth !== 'undefined'){
$rootScope.OAuth = window.OAuth;
$rootScope.OAuth.initialize('XXX');
}
else{
console.log("plugin not loaded, this is running in a browser");
$.getScript( "lib/oauth.js", function() {
$rootScope.OAuth = OAuth;
$rootScope.OAuth.initialize('XXX');
});
}
});
Now, if the plugin is loaded it initializes the window.OAuth object, else the app is running in browser, so I have to include the oauth.js file. Also I assigned the OAuth to the $rootScope for quick access.
Hope this helps anyone.

Ionic file transfer error

I am using the cordova file transfer and file plugins to go to a server and get some data and image. I am then saving this data to the device's storage, the data format is a .json file and some images. I am able to save all the data to the device.
My problem happens when I try to use that data. When I try to load the local data, I get
Failed to load resource: net::ERR_FILE_NOT_FOUND file:///android_asset/www/Android/data/com.mydomain.myApp/files/data.json
From the console log messages I can see that 'file:///android_asset/www/' is being added to the path when it is being called, is this correct?
I am using the angularjs $resource service.
var localData = $resource(filePath);
If anyone can help I would really appreciate it.
Are you sure that you are storing the files in the right folder?
Reading the Cordova File Plugin documentation you get this:
Where to Store Files
As of v1.2.0, URLs to important file-system
directories are provided. Each URL is in the form
file:///path/to/spot/, and can be converted to a DirectoryEntry using
window.resolveLocalFileSystemURL().
cordova.file.applicationDirectory - Read-only directory where the
application is installed. (iOS, Android, BlackBerry 10)
cordova.file.applicationStorageDirectory - Root directory of the
application's sandbox; on iOS this location is read-only (but specific
subdirectories [like /Documents] are read-write). All data contained
within is private to the app. ( iOS, Android, BlackBerry 10)
cordova.file.dataDirectory - Persistent and private data storage
within the application's sandbox using internal memory (on Android, if
you need to use external memory, use .externalDataDirectory). On iOS,
this directory is not synced with iCloud (use .syncedDataDirectory).
(iOS, Android, BlackBerry 10)
cordova.file.cacheDirectory - Directory for cached data files or any
files that your app can re-create easily. The OS may delete these
files when the device runs low on storage, nevertheless, apps should
not rely on the OS to delete files in here. (iOS, Android, BlackBerry
10)
cordova.file.externalApplicationStorageDirectory - Application space
on external storage. (Android)
cordova.file.externalDataDirectory - Where to put app-specific data
files on external storage. (Android)
cordova.file.externalCacheDirectory - Application cache on external
storage. (Android)
cordova.file.externalRootDirectory - External storage (SD card) root.
(Android, BlackBerry 10)
cordova.file.tempDirectory - Temp directory that the OS can clear at
will. Do not rely on the OS to clear this directory; your app should
always remove files as applicable. (iOS)
cordova.file.syncedDataDirectory - Holds app-specific files that
should be synced (e.g. to iCloud). (iOS)
cordova.file.documentsDirectory - Files private to the app, but that
are meaningful to other application (e.g. Office files). (iOS)
cordova.file.sharedDirectory - Files globally available to all
applications (BlackBerry 10)
Based on this list my advice is for you to usually store files in cordova.file.dataDirectory doing this:
var targetPath = cordova.file.dataDirectory + filename + extension
var fileTransfer = new FileTransfer();
var uri = encodeURI("http://some.server.com/download.php");
fileTransfer.download(
uri,
targetPath,
function(entry) {
console.log("download complete: " + entry.toURL());
},
function(error) {
console.log("download error source " + error.source);
console.log("download error target " + error.target);
console.log("upload error code" + error.code);
},
false,
{
headers: {
"Authorization": "Basic dGVzdHVzZXJuYW1lOnRlc3RwYXNzd29yZA=="
}
}
);
It's both compatible with iOS and Android.
For example you can open your downloaded image using the targetPath variable:
//On your controller assign it to the scope
$scope.targetPath = targetPath;
//then on your view just use it as the src for your img
<img ng-src="targetPath">
Ok, so I was doing this all wrong. Because the data is local I shouldn't be making a $resource request. I have instead used readAsText(path, file) from the ngCordova documentation.
Essentially when I am saving the data to a .json file it is being treated as a text file, I can then use the method about in conjunction with JSON.parse(data); this can then be set to my scope and used in the same way as the remote data.
P.S. I have tried with both 'cordova.file.dataDirectory' and 'cordova.file.externalDataDirectory' and both worked in my tests. And the info offered by 'Fabio Antunes' in this post is worth a read.

Resources