CapacitorJS: File selection issue with Input file on Android - android

I have an issue with file selection on Android by using input type file and capacitor-file-picker plugin. Same issue with both.
When I click on the Browse button, it takes me to the Recent files box. In the sidebar, when I choose Downloads or Documents, it displays files that are disabled.
But if I go to Gallery then I can select the photo and it works fine. It's the same for Audio files. I can select files and get a proper response.
What I'm trying to do is to select a single CSV file and get a response. No other files should be allowed to select. This is my code.
<template>
<input type="file" accept=".csv" #change="handleFileUpload($event)" />
<button fill class="my-3" #click="pickFile">Upload File</button>
</template>
<script setup>
import { FilePicker } from "#robingenz/capacitor-file-picker";
import { ref } from "vue";
const file = ref('');
const content = ref({});
const handleFileUpload = (event) => {
file.value = event.target.files[0];
console.log(file.value);
};
const pickFile = async () => {
const result = await FilePicker.pickFiles({
types: ["text/csv"],
});
if (result) {
content.value = result.files[0];
console.log(content.value);
}
};
</script>
I have tested this on Xiaomi 11T (MIUI v13.0.3, Android v12), OnePlus 5T (PixelExperience, Andoird v12) and Android Studio Emulator Pixel XL Android v11.
Everything works fine on the Windows Chrome browser.
I'm using Capacitor Filesystem plugin for a different purpose (downloading CSV file) and android.permission.READ_EXTERNAL_STORAGE and android.permission.WRITE_EXTERNAL_STORAGE is already set in AndroidManifest.xml.
What am I doing wrong? Any help would be appreciated.
Thanks

type text/comma-separated-values instead of text/csv fixed this issue as suggested by Robin Genz on Github issue for capacitor-file-picker plugin. It's the same for input type="file".
<input type="file" accept="text/comma-separated-values" #change="fileUpload($event)" />

Related

Ionic angular: opening links in (external) mobile browser

I do not want links to open inside my Ionic app, so I'm trying to get the links to open in the mobile browser.
The first example here is working fine. When the URL is inside of the "window.open" command, then the external browser is launched as expected.
<p class="descriptive-class">
<a ng-href="" onclick="window.open('https://stackoverflow.com', '_system', 'location=yes')">
<img src="assets/img/awesome_picture.png" alt="blablabla">
</a>
</p>
The problem lays with this part, where I want to feed a parameter for the URL to the code. I cannot set it directly inside "window.open()", so I have to move it to 'ng-href' and then refer to it via 'this.href'.
Android does not seem to understand this correctly. It shows me the "Complete action using" dialog on Android, and then presents HTML document handler applications. It does not understand the browser link.
How can this be corrected best?
<p class="descriptive-class">
<a href="#" ng-href="item.webURL" onclick="window.open(this.href, '_system', 'location=yes')">
{{ item.webURL }}
</a>
</p>
In this case, the easiest way is to install the In App Browser plugin.
It opens an URL with the installed browser of the device. First add and install the plugin:
*$ ionic cordova plugin add cordova-plugin-inappbrowser*
*$ npm install --save #ionic-native/in-app-browser*
Add it to your app.module.ts
import { InAppBrowser } from '#ionic-native/in-app-browser';
And add it to your providers:
#NgModule({
...
providers: [
...
InAppBrowser
...
]
...
})
Then add on the relevant page:
constructor(private iab: InAppBrowser) { }
openBrowser(){
this.iab.create('https://ionicframework.com/');
}
Call openBrowser() in your (click) method and you're set!
See also: https://ionicframework.com/docs/native/in-app-browser/
As of Feb 2020, this is what works in Ionic 4 & Ionic 5:
1) Install In App Browser plugin. Don't worry, it will open the links externally as you want it. Run the following commands in your project root:
ionic cordova plugin add cordova-plugin-inappbrowser
npm install #ionic-native/in-app-browser
2) In app.module.ts file, add the following code:
Add the import as shown below:
import { InAppBrowser } from '#ionic-native/in-app-browser/ngx';
Add support for InAppBrowser by adding it to the providers array as shown below:
providers: [
StatusBar,
SplashScreen,
InAppBrowser, // ---> Add it here
{provide: RouteReuseStrategy, useClass: IonicRouteStrategy}
],
3) In your desired component TS file or page TS file (example: support.page.ts), add the following code:
Add the import as shown below:
import { InAppBrowser } from '#ionic-native/in-app-browser/ngx';
Add the code in constructor as shown below:
constructor(private iab: InAppBrowser) {}
Add a method that opens the link to your desired webpage as shown below:
openPage(){
this.iab.create('https://stackoverflow.com/'); // --> Change URL here
}
Add click event to your hyperlink as shown below:
{{ item.webURL }}
Result:
Now when you click on the Hyperlink, that should open your desired URL.
NOTE:
If you do not want to hardcode the URL and would rather want to open URLs dynamically, then you can use the following in your HTML page:
{{ item.webURL }}
Add the following in your TS file:
openAnyPage(url){
this.iab.create(url);
}
Result:
Now when you click on any Hyperlink, that should open your desired URL, without the need to hardcode them anywhere.
An update to #Gerben den Boer's answer:
You will run into errors like the following with the import as it is listed.
[ng] ERROR in src/app/components/app-component/app.module.ts(44,5): error TS2322: Type 'InAppBrowserOriginal' is not assignable to type 'Provider'.
[ng] Type 'InAppBrowserOriginal' is not assignable to type 'ClassProvider'.
[ng] Property 'provide' is missing in type 'InAppBrowserOriginal'.
To resolve this use the following import:
import { InAppBrowser } from '#ionic-native/in-app-browser/ngx';
See: https://github.com/ionic-team/ionic-native/issues/2899
Further to #Devner's excellent answer, for a 2021+ (Ionic5) release,
You should do all of the above, but 2 things needed to change for me.
I had multiple variables to pass to it, that suggestion didn't work, but I did overcome the problem with the following:
Open original article.
Also, please note the following that was left off, according to the Cordova Documentation...
A target should be included:
var ref = cordova.InAppBrowser.open(url, target, options);
ref: Reference to the InAppBrowser window when the target is set to '_blank'. (InAppBrowser)
url: The URL to load (String). Call encodeURI() on this if the URL contains Unicode characters.
target: The target in which to load the URL, an optional parameter that defaults to _self. (String)
_system: Opens in the system's web browser.
Therefore, the following code brings it altogether:
openAnyPage(url, wp_id)
{
this.iab.create(url+"index.php?page_id="+wp_id, '_system');
}

react native custom fonts

This question has been already here and here, but the answer is not satisfactory there. The fonts are not working on android but on iOS do. Maybe I made some mistake during the linking.
How did I added fonts:
Created folder assets/fonts/ inside root folder.
Added
"rnpm": { "assets": ["./assets/fonts"] }
react-native link
Console output was it successfully added assets to iOS and Android
Added fontFamily: 'MyCustomFontFamily' into styles.
Run on iOS, everything worked fine.
Run on Android, no typeface.
Checked the android project directory and the assets folder was present
I tried adding (Platform.OS === 'ios') ? 'MyCustomFontFamily' : 'fonts/my_custom_font_family' to go with the file name but this did not work wither.
Tried same variation as 9 without path or with extension but no luck
Read here to use weight, tried it, no luck.
I had the same issue, which had to do with the fact that, as you already know, Android will read from the filename whilst iOS will read from the full name property. And, indeed, I had mixed up my fonts' references.
The first thing I did to solve this was to double-check that my fonts were properly located in android/app/src/main/assets/fonts/.
Then I ended up renaming my fonts to the exact same name as the one used by iOS and using that name as a reference. Here is what I mean:
export const sansSerifLight = 'Aileron-Light'; // Filename is 'Aileron-Light.otf'
export const sansSerifRegular = 'Aileron-Regular'; // Filename is 'Aileron-Regular.otf'
export const sansSerifBold = 'Aileron-Bold'; // Filename is 'Aileron-Bold.otf'
export const serifRegular = 'LibreBaskerville-Regular'; // Filename is 'LibreBaskerville-Regular.ttf'
export const serifBold = 'LibreBaskerville-Bold'; // Filename is 'LibreBaskerville-Bold.ttf'
export const serifItalic = 'LibreBaskerville-Italic'; // Filename is 'LibreBaskerville-Italic.ttf'
export const sansSerifTitle = 'ADAM.CG PRO'; // Filename is 'ADAM.CG PRO.otf'
export const serifTitle = 'Oranienbaum'; // Filename is 'Oranienbaum.ttf
And then :
<MyComponent style={{ fontFamily: serifTitle }} />
This really made things way less error-prone and easier to maintain for me.

How To Access Files on Android Device Using Ionic Framework

I was working through the Ionic tutorial for using the Cordova Camera API.
http://learn.ionicframework.com/formulas/cordova-camera/
Far as I can tell everything is working correctly with the Camera API functions, but I cannot get my image to display back into the view.
I am able to return a file URI, but when I attempt to put it to the ng-src I get nothing in the view. I am assuming that the application/code cannot access the file location?
My config:
.config(function($stateProvider, $urlRouterProvider, $compileProvider) {
$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|blob|content):|data:image\//);
...
The function in my controller:
$scope.getPhoto = function() {
Camera.getPicture().then(function(imageURI) {
console.log(imageURI);
$scope.cameraPic = imageURI;
}, function(err) {
$scope.cameraPic = "error";
console.err(err);
});
};
My view:
<ion-view>
<ion-content>
<div class="form-group padding-top">
<button class='button button-positive' data-ng-click="getPhoto()">
Take Photo
</button>
</div>
<div class="item item-image">
<img ng-src="{{cameraPic}}"/>
</div>
{{cameraPic}}
</ion-content>
</ion-view>
This appears to be the recommended method by the tutorial, and is also repeated on this thread. It sounds like it should work without using a Cordova file service implementation. I have found one such implementation which I guess I could use, but am I missing something here?
EDIT
Using chrome://inspect/#devices, I was able to look into the Webview/Console. I also rebuilt the project, just to see if that would help.
Definitely looking like a local file access issue.
As it turns out, this is an issue unique to using the emulator. I finally found the following on the ngCordova project:
NOTE: The camera API only works on a real device, and not in the
emulator.
Source: http://ngcordova.com/docs/plugins/camera/
This led me to test the code on an actual device using the USB debugger, where the file is accessed by the application and shared with the view as expected. This should be noted as a quirk of the library.

Angular Js and Trigger.io - Can't follow a link on Android that works on iOS

I am using AngularJS with Trigger.io to develop a mobile application for both iOS and Android.
When I try to open a link that looks like this:
<a ng-href="#/offers/{{featured_offer.Id}}"></a>
It works perfectly fine on iOS, but on Android I get this message in the trigger console, and the link is not navigated to:
[WARNING] Attempted to open a URL which could not be handled: unsafe:content://io.trigger.forge722b6464a0e211e2ba9d12313d00dc45/src/index.html#/offers/8
How can I get this to work in Android the same as it works in iOS?
Looks like Angular adds unsafe: to url schemes it doesn't recognise, I think you want to include something like:
app.config(function($compileProvider){
$compileProvider.urlSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel|content):/);
});
Which adds content: to the accepted url schemes.
I had this same problem, specifically with trying to display an img with a src of a file returned by forge.file.getImage. Angular adds unsafe: to the content: prefix of the local img URL, and as connorhd said, you need to add content: to the url whitelist.
Note that compileProvider's API has changed with recent versions of Angular, so I'm commenting here in case anyone else finds an updated version of this workaround useful.
app.config(['$compileProvider',
function($compileProvider) {
$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel|content|blob):|data:image|/);
// note: you'll also have to do imgSrcSanitizationWhitelist if you want to use general links as well as ng-src on images.
}]);
I too had this problem just add sanitizer in you config.xml
var app = angular.module( 'myApp', [] )
.config( [
'$compileProvider',
function( $compileProvider )
{
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrome-extension):/);
// Angular before v1.2 uses $compileProvider.urlSanitizationWhitelist(...)
}
]);

Showing camera view inside html in android and then snap a picture

Is there a view of showing the live camera view inside html ( e.g. embedded in a div ) before we snap a picture using JavaScript? I have tried PhoneGap but it totally starts a new camera app and totally moves away from my html web app before returning to it. I need something embedded in my app
Thanks
You can install mbppower/CordovaCameraPreview plugin (for android,ios) in your Cordova/phonegap application that allows camera interaction from HTML code. A really amazing plugin it is..
You can access Features such as:
Start a camera preview from HTML code.
Drag the preview box.
Set camera color effect (Android and iOS),Send the preview box to back of the HTML content,Set a custom position for the camera preview box,Set a custom size for the preview box and Maintain HTML interactivity.
Or you can also use donaldp24/CanvasCamera Plugin for your application if it fits to your requirements.Its supported in both android and iOS platforms. I have observed, for iOS its working fine but in android it isn't working.
Now you can install CordovaCameraPreview plugin through Online PhoneGap too. So without using CLI you can directly use it through this by adding
<gap:plugin name="com.mbppower.camerapreview" version="0.0.8" source="plugins.cordova.io" />
in your config.xml file and create ApplicationTemplate.apk/.ipa. For more information regarding this you can ask me. Happy to help.
UPDATE:10th Oct 2017
It used to work well during that time but, donaldp24/CanvasCamera is no longer maintained and currently fails build with the latest Cordova version.
I did it for one of my projects. Check out navigator.getUserMedia(). There are a tonne of things you can do with your webcam and browser, including AR games! Here's just a basic example:
HTML:
<html>
<head>
</head>
<body>
<form><input type='button' id='snapshot' value="snapshot"/></form>
<video autoplay></video>
<canvas id='canvas' width='100' height='100'></canvas>
<script type="text/javascript" src="findit.js"></script>
</body>
</html>
findit.js
var onFailSoHard = function(e)
{
console.log('failed',e);
}
window.URL = window.URL || window.webkitURL ;
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;
var video = document.querySelector('video');
if(navigator.getUserMedia)
{
navigator.getUserMedia({video: true},function(stream) {
video.src = window.URL.createObjectURL(stream);
},onFailSoHard);
}
document.getElementById('snapshot').onclick = function() {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.drawImage(video,0,0);
}
Live Demo:
A personal project
More Resources, this is what I used:
Webcam Access
Update:
This solution is valid only for front camera if our device has one. It's basically a "webcam" solution. Not sure if it'll work for your case. Just in case, check out the resources.
You can use camera.getPicture from cordova-plugin-camera or navigator.device.capture.captureVideo from cordova-plugin-media-capture.
var getUserMedia = navigator.getUserMedia
|| navigator.webkitGetUserMedia
|| navigator.mozGetUserMedia
|| navigator.msGetUserMedia
|| navigator.device.capture.captureVideo
|| navigator.camera
|| camera.getPicture;
Hope it helps.
There is no direct access to the Camera app using javascript. You can either write a custom PhoneGap (Cordova) plugin to do that.

Categories

Resources