Ionic file download not working - android

I am building an ionic app for wallpapers.
In the app,there is an image stored in www/assets/img displayed.I have build 2 buttons below,for downloading and retrieving the displayed image to the mobile device memory.
When i click download button,a dialog is shown,saying "Download Succeeded!Pug.jpg was successfully downloaded to: filepath".But when i check the phone memory no such file is there.Also when i click "Retrieve"Button it's showing dialog saying"File retrieval succeed!Pug.jpg was successfully retrieved from: filepath""even though file is not present in the phone memory.
This is home.ts code
import {Component} from '#angular/core';
import {NavController, Platform, AlertController} from 'ionic-angular';
import {Transfer, TransferObject} from '#ionic-native/transfer';
import {File} from '#ionic-native/file';
declare var cordova: any;
#Component({
selector: 'page-home',
templateUrl: 'home.html',
providers: [Transfer, TransferObject, File]
})
export class HomePage {
storageDirectory: string = '';
constructor(public navCtrl: NavController, public platform: Platform, private transfer: Transfer, private file: File, public alertCtrl: AlertController) {
this.platform.ready().then(() => {
// make sure this is on a device, not an emulation (e.g. chrome tools device mode)
if(!this.platform.is('cordova')) {
return false;
}
if (this.platform.is('ios')) {
this.storageDirectory = cordova.file.documentsDirectory;
}
else if(this.platform.is('android')) {
this.storageDirectory = cordova.file.dataDirectory;
}
else {
// exit otherwise, but you could add further types here e.g. Windows
return false;
}
});
}
downloadImage(image) {
this.platform.ready().then(() => {
const fileTransfer: TransferObject = this.transfer.create();
const imageLocation = `${cordova.file.applicationDirectory}www/assets/img/${image}`;
fileTransfer.download(imageLocation, this.storageDirectory + image).then((entry) => {
const alertSuccess = this.alertCtrl.create({
title: `Download Succeeded!`,
subTitle: `${image} was successfully downloaded to: ${entry.toURL()}`,
buttons: ['Ok']
});
alertSuccess.present();
}, (error) => {
const alertFailure = this.alertCtrl.create({
title: `Download Failed!`,
subTitle: `${image} was not successfully downloaded. Error code: ${error.code}`,
buttons: ['Ok']
});
alertFailure.present();
});
});
}
retrieveImage(image) {
this.file.checkFile(this.storageDirectory, image)
.then(() => {
const alertSuccess = this.alertCtrl.create({
title: `File retrieval Succeeded!`,
subTitle: `${image} was successfully retrieved from: ${this.storageDirectory}`,
buttons: ['Ok']
});
return alertSuccess.present();
})
.catch((err) => {
const alertFailure = this.alertCtrl.create({
title: `File retrieval Failed!`,
subTitle: `${image} was not successfully retrieved. Error Code: ${err.code}`,
buttons: ['Ok']
});
return alertFailure.present();
});
}
}
This is home.html code
<ion-header>
<ion-navbar>
<ion-title>
File Transfer Example
</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-card>
<ion-card-header>
Ionic 3 File Transfer Example
</ion-card-header>
<ion-card-content>
<img src="assets/img/pug.jpg" alt="Cute Pug">
<button ion-button (click)="downloadImage('pug.jpg')" color="secondary">Download image</button>
<button ion-button (click)="retrieveImage('pug.jpg')" color="secondary">Retrieve downloaded image</button>
</ion-card-content>
</ion-card>
</ion-content>
I build this ionic app based on this Github code example
I actually want the ionic app to first create a folder(app named folder) in internal memory and put all images there.So users can access files in that folder.For example,if app name is "Appsample" then all images should be in Appsample folder in internal memory.
How can i develop for above purpose?
Thanks.

I just posted an answer to nearly the same question, see:
Download not working using filetransfer plugin.
The main problem here is that you are using the following directory to save your file:
else if(this.platform.is('android')) {
this.storageDirectory = cordova.file.dataDirectory;
}
As stated in the cordova docs (https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/#where-to-store-files), "cordova.file.dataDirectory" is the persistent and private data storage within the application's sandbox using internal memory.
Use cordova.file.externalDataDirectory to fit your purpose. Then the file should be placed somewhere here: "file:///storage/emulated/0/Android/data/subdomain.domainname.toplevdomain/files/...".
On Android, external storage directories always exist. If the device doesn't have a physical card, Android will emulate it.

You can use this way, it's working file
Capacitor
npm install cordova-plugin-whitelist
npx cap sync
Cordova
npm install cordova-plugin-whitelist
npx cap update
download() {
const url = 'http://www.example.com/file.pdf';
fileTransfer.download(url, this.file.dataDirectory + 'file.pdf').then((entry) => {
console.log('download complete: ' + entry.toURL());
}, (error) => {
// handle error
});
}

I Have the same issue when i wrote my download code it worked but i couldn't see the file on my phone
1. Write download method
2. Write Permission method, Call Permission method
3. Call download method inside Permission, the phone will pop up and ask for permission for file read if it has not been set.
4. After download you might not be able to see where the file is on phone, you will now use photoViewer to view it on phone if it is
image or use document viewer if it is pdf or other document related.
The plugins needed
private transfer: FileTransfer,
private fileTransfer: FileTransferObject,
private file: File,
private androidPermissions: AndroidPermissions,
private photoViewer: PhotoViewer,
getPermission() {
// get permission from device to save
this.androidPermissions.checkPermission(this.androidPermissions.PERMISSION.READ_EXTERNAL_STORAGE).then(
result =>//,
err => this.androidPermissions.requestPermission(this.androidPermissions.PERMISSION.READ_EXTERNAL_STORAGE)
);
// get permission from device to save
this.androidPermissions.hasPermission(this.androidPermissions.PERMISSION.WRITE_EXTERNAL_STORAGE)
.then(status => {
if (status.hasPermission) {
this.download('k');
}
else {
this.androidPermissions.requestPermission(this.androidPermissions.PERMISSION.WRITE_EXTERNAL_STORAGE)
.then(status => {
if (status.hasPermission) {
this.download('');
}
});
}
});
}
public download() {
let url = encodeURI(this.imgUrl);
var imagePath = this.file.dataDirectory + "myDP.png";
const fileTransfer = this.transfer.create();
fileTransfer.download(url, imagePath).then((entry) => {
this.generalProvider.showToast('download completed: ' + imagePath);
this.photoViewer.show(entry.toURL());
}, (error) => {
});
}

Related

Angular Cordova Project (Android) doesn't open Razorpay external page (Enter OTP/ Enter Login credential page)

Razor pay works properly when opening in a browser but when i convert the project into an android app, external page which is supposed to be opened to submit OTP doesn't show up. I understand i need an inAppBrowser to open the link but it is not controlled by me. Razorpay will open the link automatically when the user chooses card payment or internet banking. How to solve this? please help!
window-ref.service.ts
import {Injectable} from '#angular/core';
// declare var cordova:any;
export interface ICustomWindow extends Window {
__custom_global_stuff: string;
}
function getWindow(): any {
return window;
}
#Injectable({
providedIn: 'root'
})
export class WindowRefService {
get nativeWindow(): ICustomWindow {
return getWindow();
}
}
app.component.ts
constructor(private winRef: WindowRefService) {
this._window = this.winRef.nativeWindow;
}
private _window: ICustomWindow;
public rzp: any;
public options: any = {
key: 'KEY', // add razorpay key here
name: 'Bunto Couriers Pvt. Ltd.',
description: 'Delivery Fee',
amount: this.price*100, // razorpay takes amount in paisa
prefill: {
name: '',
email: '', // add your email id
},
image: 'https://isell-bunto.000webhostapp.com/assets/img/loader.png',
notes: {},
theme: {
color: '#3880FG'
},
handler: this.paymentHandler.bind(this),
modal: {
ondismiss: (() => {
this.zone.run(() => {
// add current page routing if payment fails
this.toastr.error("Payment Error!");
})
})
}
};
initPay(): void {
this.rzp = new this.winRef.nativeWindow['Razorpay'](this.options);
this.rzp.open();
}
paymentHandler(res: any) {
this.zone.run(() => {
// add API call here
console.log(res);
});
}
this is a pop up window which opens fine in both browser and in android app
this external page doesn't show up in the app
in the app, this is as far as it goes. external url doesn't open after this stage
I'm not sure how the Javascript library will work while we don't have the control over showing it using the InAppBrowser.
For this, I really suggest to use the native Cordova Razorpay plugin for more compatibility and stability: https://github.com/razorpay/razorpay-cordova
You can check their sample apps (Cordova and Ionic)
Add command: cordova plugin add https://github.com/razorpay/razorpay-cordova.git --save
var options = {
description: 'Credits towards consultation',
image: 'https://i.imgur.com/3g7nmJC.png',
currency: 'INR',
key: 'rzp_test_1DP5mmOlF5G5ag',
order_id: 'order_7HtFNLS98dSj8x',
amount: '5000',
name: 'foo',
theme: {
color: '#F37254'
}
}
var successCallback = function(success) {
alert('payment_id: ' + success.razorpay_payment_id)
var orderId = success.razorpay_order_id
var signature = success.razorpay_signature
}
var cancelCallback = function(error) {
alert(error.description + ' (Error '+error.code+')')
}
RazorpayCheckout.on('payment.success', successCallback)
RazorpayCheckout.on('payment.cancel', cancelCallback)
RazorpayCheckout.open(options)

Share images and files on react-native using Expo

I've saved the file i want to share locally using FileSystem.downloadAsync
Share.share works fine for iOS. How can I share an image I have saved locally on Android?
I've tried
https://github.com/lucasferreira/react-native-send-intent
https://github.com/react-native-community/react-native-share
Both these solutions do not seem to work with Expo.
I'm using react-native version : https://github.com/expo/react-native/archive/sdk-31.0.0.tar.gz
FileSystem.downloadAsync(url, FileSystem.documentDirectory+filename).then(({uri})=>{
if(Platform.OS == "android"){
// ???
}
else{
Share.share({url:uri});
}
})
Is there something i'm missing?
Since SDK33, you can use Expo Sharing to share any type of file to other apps that can handle its file type even if you're on Android.
See : https://docs.expo.io/versions/latest/sdk/sharing/
Usage is pretty simple :
import * as Sharing from 'expo-sharing'; // Import the library
Sharing.shareAsync(url) // And share your file !
In order for users to share content saved within our (Expo) app, we structured it like this. (This is working across iOS & Android).
IMPORT SHARING:
import * as FileSystem from 'expo-file-system';
import * as Sharing from 'expo-sharing';
ADD ONPRESS TO BUTTON (OR WHEREVER):
<Button
name="share"
onPress={() =>
openShareDialogAsync(media, {
video: media.meta.fileType === 'video',
})
}
/>
SHARE VIDEO OR IMAGE TO ANY APP IN USERS HANDSET
const openShareDialogAsync = async (mediaProp, options) => {
const fileDetails = {
extension: options.video ? '.mp4' : '.jpg',
shareOptions: {
mimeType: options.video ? 'video/mp4' : 'image/jpeg',
dialosTitle: options.video
? 'Check out this video!'
: 'Check out this image!',
UTI: options.video ? 'video/mp4' : 'image/jpeg',
},
};
const downloadPath = `${FileSystem.cacheDirectory}${mediaProp.media_id}${fileDetails.extension}`;
const { uri: localUrl } = await FileSystem.downloadAsync(
mediaProp.url,
downloadPath
);
if (!(await Sharing.isAvailableAsync())) {
showMessage({
message: 'Sharing is not available',
description: 'Your device does not allow sharing',
type: 'danger',
});
return;
}
await Sharing.shareAsync(localUrl, fileDetails.shareOptions);
};
Hope this helps :]

Saving file to Downloads directory using Ionic 3

i know this link: https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/#where-to-store-files
but i would like to save the file in Downloads directory. Is this possible to save the file in any path using Ionic? If so, please, share the example.
Here's the code:
downloadImage(image) {
this.platform.ready().then(() => {
const fileTransfer: TransferObject = this.transfer.create();
const imageLocation = `${cordova.file.applicationDirectory}www/assets/img/${image}`;
fileTransfer.download(imageLocation, cordova.file.externalDataDirectory + image).then((entry) => {
const alertSuccess = this.alertCtrl.create({
title: `Download Succeeded!`,
subTitle: `${image} was successfully downloaded to: ${entry.toURL()}`,
buttons: ['Ok']
});
alertSuccess.present();
}, (error) => {
const alertFailure = this.alertCtrl.create({
title: `Download Failed!`,
subTitle: `${image} was not successfully downloaded. Error code: ${error.code}`,
buttons: ['Ok']
});
alertFailure.present();
});
});
}
Basically I want save the file in location that is visible to the user.
the problem was lack of permission. Here is the working code that can download file to downloads directory:
async downloadFile() {
await this.fileTransfer.download("https://cdn.pixabay.com/photo/2017/01/06/23/21/soap-bubble-1959327_960_720.jpg", this.file.externalRootDirectory +
'/Download/' + "soap-bubble-1959327_960_720.jpg");
}
getPermission() {
this.androidPermissions.hasPermission(this.androidPermissions.PERMISSION.READ_EXTERNAL_STORAGE)
.then(status => {
if (status.hasPermission) {
this.downloadFile();
}
else {
this.androidPermissions.requestPermission(this.androidPermissions.PERMISSION.READ_EXTERNAL_STORAGE)
.then(status => {
if(status.hasPermission) {
this.downloadFile();
}
});
}
});
}
To download the File to the Download directory you need to use Cordova File and FileTransfer Plugins.
import { File } from '#ionic-native/file';
import { FileTransfer } from '#ionic-native/file-transfer';
constructor(private transfer: FileTransfer) { }
fileTransfer: FileTransferObject = this.transfer.create();
//Use your File Url and name
downloadFile(file) {
// Some Loading
this.fileTransfer.download(url, this.file.externalRootDirectory +
'/Download/' + file).then(response => {
console.log(response);
this.dismissLoading();
this.presentToast('File has been downloaded to the Downloads folder. View
it..')
})
.catch(err => {
this.dismissLoading();
console.log(err)
});
}
Hope it helps.
import { File } from '#ionic-native/file';
import { FileTransfer } from '#ionic-native/file-transfer';
constructor(private file: File, private transfer: FileTransfer){}
let link = 'url_to_download_file';
let path = '';
let dir_name = 'Download'; // directory to download - you can also create new directory
let file_name = 'file.txt'; //any file name you like
const fileTransfer: FileTransferObject = this.transfer.create();
let result = this.file.createDir(this.file.externalRootDirectory, dir_name, true);
result.then((resp) => {
path = resp.toURL();
console.log(path);
fileTransfer.download(link, path + file_name).then((entry) => {
console.log('download complete: ' + entry.toURL());
}, (error) => {
console.log(error)
});
}, (err) => {
console.log('error on creating path : ' + err);
});
I know this is late, but I've always had issues with the FileTransfer plugin. Maybe it is just me. I've instead had success with the writeFile() method of the File plugin.
I'm still working on iOS, but for Android here is what I have:
import { File } from "#ionic-native/file";
constructor(private fileSystem: File) {}
Then, in whatever function you have the logic to save the file, we have:
let path = this.fileSystem.externalRootDirectory + '/Download/'; // for Android
let filename = 'myNewFile.pdf';
this.fileSystem.writeFile(path, filename, File, { replace: true }).then(() => {
this.toastCtrl.showToast('File has been downloaded. Please check your downloads folder.');
}, (err) => {
alert("Sorry. An error occurred downloading the file: " + err);
}
);
As I said, I'm still looking out for what path to use for iOS. And I'm still wondering how to pop up the notification that usually comes up when a download actually goes to the download folder. But at least I am able to save directly in the download folder of Android.
This code - ionic 3 capacitor - from josh morony takes a photo from the tmp directory and writes to the Document directory in this section using the FileSystem API the retrieves and manipulates the path
Filesystem.writeFile({
data: result.data,
path: fileName,
directory: FilesystemDirectory.Data
})
getFromPhotos() {
let options = {
resultType: CameraResultType.Uri
};
Camera.getPhoto(options).then(
(photo) => {
Filesystem.readFile({
path: photo.path
}).then((result) => {
// let date = new Date(),
// time = date.getTime(),
time = 'bilder',
fileName = time + '.jpeg';
Filesystem.writeFile({
data: result.data,
path: fileName,
directory: FilesystemDirectory.Data
}).then((result) => {
Filesystem.getUri({
directory: FilesystemDirectory.Data,
path: fileName
}).then((result) => {
console.log(result);
let path = result.uri.replace('file://', '_capacitor_');
this.image = this.sanitizer.bypassSecurityTrustResourceUrl(path);
}, (err) => {
console.log(err);
});
}, (err) => {
console.log(err);
});
}, (err) => {
console.log(err);
});
}, (err) => {
console.log(err);
}
);
}
In ionic 3 you have to use the cordova File plugin - please google. It is pretty straight forward to understand: you define the original directory where the file is, the original name of the file, the target directory, and a new name for the file inside that function. The principle is the same.
To download the File to the Download directory you need to use Cordova File Plugin:
import { File } from '#ionic-native/file/ngx';
constructor(
private file: File,
) { }
this.file.writeFile(this.file.externalRootDirectory + '/Download/', user_log.xlsx, blob, { replace: true })
.then(() => {
alert('File has been downloaded. Please check your downloads folder.')
enter code here
},
(err) => {
alert("Sorry. An error occurred downloading the file: " + err);
enter code here
});
})
It works in Ionic 4 as well.

Where does my image been stored in Ionic application?

I am very new to Ionic and Cordova, for the last couple of days I am trying to download an image that I have upload in firebase storage. I want to transfer the image and store it in my mobile device through my mobile application. I have installed all the plugins needed to do that. I have created two buttons. The first button is to display the image in my application and the second button is to download the image in my device. The source code for that is in my storage.html
<ion-header>
<ion-navbar>
<ion-title>storage</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<button ion-button (click)="display()">Display</button>
<button ion-button (click)="download()">Download</button>
<img src="{{imgsource}}">
</ion-content>
The functionality is in my storage.ts
import { Component, NgZone } from '#angular/core';
import { NavController, Platform, AlertController } from 'ionic-angular';
//import {File,Transfer} from 'ionic-native';
import {FileTransferObject } from '#ionic-native/file-transfer';
import {TransferObject} from '#ionic-native/transfer';
import {Transfer} from '#ionic-native/transfer';
import {File} from '#ionic-native/file';
import firebase from 'firebase';
declare var cordova: any;
#Component({
selector: 'storage-home',
templateUrl: 'storage.html',
providers: [Transfer, TransferObject, File]
})
export class StoragePage {
storageDirectory: string = '';
fileTransfer: FileTransferObject;
nativepath: any;
firestore = firebase.storage();
imgsource: any;
constructor(public navCtrl: NavController, public platform: Platform, public alertCtrl: AlertController, public zone: NgZone) {
this.platform.ready().then(() => {
// make sure this is on a device, not an emulation (e.g. chrome tools device mode)
if(!this.platform.is('cordova')) {
return false;
}
if (this.platform.is('ios')) {
this.storageDirectory = cordova.file.documentsDirectory;
}
else if(this.platform.is('android')) {
this.storageDirectory = cordova.file.dataDirectory;
}
else {
// exit otherwise, but you could add further types here e.g. Windows
return false;
}
});
}
display() {
this.firestore.ref().child('image.jpg').getDownloadURL().then((url) => {
this.zone.run(() => {
this.imgsource = url;
this.fileTransfer.download(url,'image.jpg').then((entry) => {
console.log('download complete: ' + entry.toURL());
}, (error) => {
// handle error
});
})
})
}
downlad() {
this.firestore.ref().child('image.jpg').getDownloadURL().then((url) => {
this.zone.run(() => {
this.imgsource = url;
this.fileTransfer.download(url,cordova.file.dataDirectory +'image.jpg').then((entry) => {
console.log('download complete: ' + entry.toURL());
}, (error) => {
// handle error
});
})
})
}
}
The display button works perfectly as I can see my image when I install the application on my device. The problem though is with the download button as nothing is happening and I don’t know if it’s working as I can’t find my image anywhere in my device. Can anyone please guide me?
Thanks in regards
It looks like you may have a typo on your download function name. In the HTML module you refer to download() and in your code your function is labeled as downlad.

Ionic 3 after running ionic cordova add platform android, error occurs to my ionic-native/file,filepath,transfer

I have the error like in question, when I'm trying to design my application to call native.camera, I see my console in ionic 3 project, I saw this error :
Native : tried calling Camera.getPicture, but Cordova is not available. Make sure to include cordova.js or run in a device / simulator.
Here is the code that I used to called native camera.
This is the code in my problem.html
<button class="logoCamera" ion-button (click)="presentActionSheet()">
<ion-icon name="camera" ></ion-icon>
This is the code in my problem.ts
import { File } from '#ionic-native/file';
import { Transfer, TransferObject} from '#ionic-native/transfer';
import { FilePath } from '#ionic-native/file-path';
import { Camera } from '#ionic-native/camera';
public presentActionSheet(){
let actionSheet = this.actionSheetCtrl.create({
title: 'Select Image',
buttons: [
{
text: 'Load from Library',
handler: () => {
this.takePicture(this.camera.PictureSourceType.PHOTOLIBRARY);
}
},
{
text: 'Use Camera',
handler: () => {
this.takePicture(this.camera.PictureSourceType.CAMERA);
}
},
{
text: 'Cancel',
role: 'cancel'
}
]
});
actionSheet.present();
}
public takePicture(sourceType){
//Create option for the Camera dialog
var options = {
quality: 100,
sourceType : sourceType,
saveToPhotoAlbum: false,
correctOrientation: true
};
//Get the data of an image
this.camera.getPicture(options).then((imagePath) => {
//special handling for android lib
if(this.platform.is('android') && sourceType === this.camera.PictureSourceType.PHOTOLIBRARY) {
this.filePath.resolveNativePath(imagePath)
.then(filePath => {
let correctPath = filePath.substr(0, filePath.lastIndexOf('/') + 1 );
let currentName = imagePath.substring(imagePath.lastIndexOf('/') + 1, imagePath.lastIndexOf('?'));
this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
});
} else {
var currentName = imagePath.substr(imagePath.lastIndexOf('/') + 1);
var correctPath = imagePath.substr(0, imagePath.lastIndexOf('/')+ 1);
this.copyFileToLocalDir(correctPath, currentName, this.createFileName());
}
}, (err) => {
this.presentToast('Error while selecting Image.');
});
}
//Create a new name for image
private createFileName() {
var d = new Date(),
n = d.getTime(),
newFileName = n + ".jpg";
return newFileName;
}
//copy image to local folder
private copyFileToLocalDir(namePath, currentName, newFileName) {
this.file.copyFile(namePath, currentName, cordova.file.dataDirectory, newFileName).then(success => {
this.lastImage = newFileName;
}, error => {
this.presentToast('Error while storing file.');
});
}
private presentToast(text) {
let toast = this.toastCtrl.create({
message: text,
duration: 3000,
position: 'middle'
});
toast.present();
}
public pathForImage(img){
if (img === null) {
return '';
} else {
return cordova.file.dataDirectory + img;
}
}
public uploadImage() {
//destination URL
var url = "";
//file to upload
var targetPath = this.pathForImage(this.lastImage);
//file name only
var filename = this.lastImage;
var options = {
fileKey: "file",
fileName: filename,
chunkedMode: false,
mimeType: "multipart/form-data",
params: {'fileName': filename}
};
const fileTransfer: TransferObject = this.transfer.create();
this.loading = this.loadingCtrl.create({
content: 'Uploading...',
});
this.loading.present();
//use FileTransfer to upload image
fileTransfer.upload(targetPath, url, options).then(data => {
this.loading.dismissAll()
this.presentToast('Image successful uploaded.');
}, err => {
this.loading.dismissAll()
this.presentToast('Error while uploading file.');
});
}
When I run ionic serve, everything is smooth, no error, no nothing.
But when I click my button to access natve camera, the error shows, please help me figure out the problem, I check a lot of web, and none of it solve my question.
After I try run ionic cordova run ios --simulator, there are error coming out, but I am pretty sure that this error does not exist before I run this command.
May I know how to solve this problem ??
The error message is pretty accurate here:
Native : tried calling Camera.getPicture, but Cordova is not available. Make sure to include cordova.js or run in a device / simulator.
Running ionic serve does not include cordova.js nor does it run your application in a simulator or on a device which is why you get the error. You can fix it either by running your application on the device or simulator:
ionic cordova run android/ios --device/--simulator
Or by adding the browser platform:
cordova platform add browser
And running the browser platform:
ionic cordova run browser

Categories

Resources