I am developing a new Phonegap 3 application. I find the development process very slow. Each time I want to test a change in my app, I have to run in the console:
phonegap run android
This command takes about 30 seconds to run! Any idea on how to improve the time to test each change?
If you are developing for android using ecllipse you can use an android handset, connect it with your development machine with usb cable and install necessary drivers from here
.
Drivers are required mostly for windows in mac and linux it is usually not necessary. After set up it is just a matter of clicking run in your ide.
If you have a huge amount of files (libraries with demos, non-minified files, etc.), installing on the app can take a long long time.
I created this hook (added to before_prepare) which only copies the necessary files (specified in "requirements.json" in my project).
You need to run cd hooks/before_prepare && npm install ncp to install the dependency.
hooks/before_prepare/010copy_assets.js
#!/usr/bin/env node
console.log("=== Running copy required assets hook ===");
var fs = require('fs'),
path = require('path');
var mkdirSync = function(path) {
try {
fs.mkdirSync(path);
} catch (e) {
if (e.code != 'EEXIST') throw e;
}
}
var mkdirpSync = function(dirpath) {
var parts = dirpath.split(path.sep);
for (var i = 1; i <= parts.length; i++) {
mkdirSync(path.join.apply(null, parts.slice(0, i)));
}
}
try {
var ncp = require('ncp').ncp
var requirements = require('./../../myproject/requirements.json');
ncp.limit = 200;
ncp.stopOnErr = true;
requirements.forEach(function(requirement) {
var source = './myproject/' + requirement;
var destination = './www/' + requirement;
var folders = destination.split('/');
folders.pop();
mkdirpSync(path.normalize(folders.join('/')));
ncp(source, destination, function(err) {
if (err) {
console.log('====== Error! Did not copy asset from ' + source + ' to ' + destination + ' ======');
console.error(err);
process.exit(1001);
} else
console.log('====== Copied asset from ' + source + ' to ' + destination + ' ======');
});
});
} catch (e) {
console.error(e);
console.error(e.stack);
process.exit(1000);
}
example requirements.json
[
"js",
"css",
"img",
"index.html"
]
Note that you can move stuff directly into the build www directory (inside platforms) but they have different paths under ios and android
Related
I have a small MAUI app i'm testing with. Im trying to read a file that was part of the deployment. I have the code below, which works great in a Windows deploy of the MAUI app, but crashes in Android. What is the proper cross-platform way to do this?
// TODO get from service or xml
var path = AppDomain.CurrentDomain.BaseDirectory;
//var path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
var fullpath = Path.Combine(path, "Services\\questions.json");
var json = File.ReadAllText(fullpath);
MAUI has a new way to access files included with the app: MauiAsset.
Described in blog Announcing .NET MAUI Preview 4, Raw Assets:
.NET MAUI now makes it very easy to add other assets to your project and reference them directly while retaining platform-native performance. For example, if you want to display a static HTML file in a WebView you can add the file to your project and annotate it as a MauiAsset in the properties.
<MauiAsset Include="Resources\Raw\index.html" />
Tip: you can also use wildcards to enable all files in a directory:
... Include="Resources\Raw\*" ...
Then you can use it in your application by filename.
<WebView Source="index.html" />
UPDATE
However, the feature MauiAsset apparently still needs improvement:
open issue - MauiAsset is very hard to use.
There we learn that for now:
Set BuildAction in each file's properties to MauiAsset.
That is, its not recommended to use the "wildcard" approach at this time. Set that build action on each file in solution explorer / your project / the file.
Accessing on Windows requires a work-around:
#if WINDOWS
var stream = await Microsoft.Maui.Essentials.FileSystem.OpenAppPackageFileAsync("Assets/" + filePath);
#else
var stream = await Microsoft.Maui.Essentials.FileSystem.OpenAppPackageFileAsync(filePath);
#endif
NOTE: This will be simplified at some point; follow that issue to see progress.
UPDATE
The current MAUI template is missing some platform-specific flags. For now, add your own flag to identify when the code is running on Windows:
Complete example in ToolmakerSteve - repo MauiSOAnswers. See MauiAssetPage.
MauiAssetPage.xaml:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiTests.MauiAssetPage">
<ContentPage.Content>
<!-- By the time Maui is released, this is all you will need. -->
<!-- The Init code-behind won't be needed. -->
<WebView x:Name="MyWebView" Source="TestWeb.html" />
</ContentPage.Content>
</ContentPage>
MauiAssetPage.xaml.cs:
using Microsoft.Maui.Controls;
using System.Threading.Tasks;
namespace MauiTests
{
public partial class MauiAssetPage : ContentPage
{
public MauiAssetPage()
{
InitializeComponent();
Device.BeginInvokeOnMainThread(async () =>
{
await InitAsync();
});
}
private async Task InitAsync()
{
string filePath = "TestWeb.html";
#if WINDOWS
var stream = await Microsoft.Maui.Essentials.FileSystem.OpenAppPackageFileAsync("Assets/" + filePath);
#else
var stream = await Microsoft.Maui.Essentials.FileSystem.OpenAppPackageFileAsync(filePath);
#endif
if (stream != null)
{
string s = (new System.IO.StreamReader(stream)).ReadToEnd();
this.MyWebView.Source = new HtmlWebViewSource { Html = s };
}
}
}
}
TestWeb.html:
(whatever html you want)
In Solution Explorer, add TestWeb.html to your project. In its Properties, select Build Action = MauiAsset.
I tried looking for a solution to this for months. I ended up hosting the file online then creating a method to download the file during runtime
public async Task DownloadFile(string fileName)
{
if (File.Exists(FileSystem.Current.AppDataDirectory + $"/{fileName}"))
{
return;
}
else
{
try
{
NetworkAccess networkAccess = Connectivity.Current.NetworkAccess;
if (networkAccess == NetworkAccess.Internet)
{
await Task.Run(() =>
{
var uri = new Uri($"https://myhostedfile.com/{fileName}");
WebClient webClient = new WebClient();
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadFileCallback2);//checking if download is complete
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(MaintainProgress);//event handler to check download progress
webClient.DownloadFileAsync(uri, FileSystem.Current.AppDataDirectory + $"/{fileName}");
});
}
else
await Shell.Current.DisplayAlert("No Internet", "Failed to get some files from the internet, confirm if your internet is" +
"working", "OK");
}
catch (Exception)
{
await Shell.Current.DisplayAlert("Error", "Failed to get some files from the internet, confirm if your internet is" +
"working", "OK");
}
}
}
Then you can access your file URL using:
string filePath = FileSystem.Current.AppDataDirectory + $"/myfile.pdf;
I am using visual studio to create cordova mobile application and I'm using Cordova-plugin-file for file manipulation on device.
How to write to a text file in a specific path in android device,
to be able to get it from a fixed location.
You can try below code. Also you can find good explanation for the code in Cordova Example: Writing to a file & Exploring the FileSystem APIs.
As a very short explanation: you should install cordova file plugin, after device ready, you first will ask for a FileSystem then will create the file in a particular path (in my example:cordova.file.dataDirectory) and finally will write to it.
document.addEventListener('deviceready', function () {
window.resolveLocalFileSystemURL(cordova.file.dataDirectory, function (dirEntry) {
dirEntry.getFile("log.txt", { create: true }, function (fileEntry) {
fileEntry.createWriter(function (fileWriter) {
fileWriter.onwriteend = function (e) {
console.log('Write completed.');
};
fileWriter.onerror = function (e) {
console.log('Write failed: ' + e.toString());
};
// Create a new Blob and write it to log.txt.
var blob = new Blob(['Lorem Ipsum'], { type: 'text/plain' });
fileWriter.write(blob);
}, errorHandler);
});
});
}, false);
i have problem to sync local image folder to server, i using titanium. When i run my program using android emulator, it works well. But when i try to run it using actual device, the program can not find the image file.
Below is my code. Please help.
$.btnfiles.addEventListener('click',function(e)
{
var dirTest = Titanium.Filesystem.getFile(Titanium.Filesystem.applicationDataDirectory);
var dirList = dirTest.getDirectoryListing();
Titanium.API.info('Start loop for files length:' + dirList.length);
for ( i = 0; i < dirList.length; ++i){
var f = Titanium.Filesystem.getFile(Titanium.Filesystem.applicationDataDirectory, dirList[i]);
var data_to_send = {
"file": f.read(), "name1":Titanium.Filesystem.applicationDataDirectory
};
xhr = Titanium.Network.createHTTPClient({
// function called when an error occurs, including a timeout
onerror : function(e) {
//Ti.API.debug(e.error);
alert('error');
},
timeout : 5000 // in milliseconds
});
xhr.setRequestHeader("enctype", "multipart/form-data");
xhr.open("POST","upload.php");
xhr.send(data_to_send);
Titanium.API.info('Namef: ' + dirList[i]);
Titanium.API.info('Name: ' + i);
var file = Titanium.Filesystem.getFile(Titanium.Filesystem.applicationDataDirectory,dirList[i]);
if (file.exists()) { file.deleteFile(); }
}
});
i am using cordova-ionic framework to build app. i am new to the iOS or iPhone
in my requirement, i have to read a file in the app. i am reading file in the android app but same code showing error (code: 5).
i am following code types:
in android:
$cordovaFile.writeFile(( 'user.json', data, {'append':false} )).then(function(result) {
alert('file created.');
alert(JSON.stringify(result));
}, function(err) {
// An error occured. Show a message to the user
alert('file writed');
alert(JSON.stringify(err));
});
i can create file, writing, reading data and removing the file but in ios phone i am not able to create file using the same code.
in iPhone:
var data = {"user":{"name":"errer","email":"sdsdff#gmail.com","username":"sdfsdfsd"}};
$cordovaFile.writeFile(( 'user.json', data, {'append':false} )).then(function(result) {
// Success!
alert('file created.');
alert(JSON.stringify(result));
}, function(err) {
// An error occured. Show a message to the user
alert('file writed');
alert(JSON.stringify(err));
});
i just change my directory is cordova.file.cacheDirecotry/cordova.file.applicationDirectory
$cordovaFile.createFile(( cordova.file.cacheDirecotry+'user.json', true )).then(function(result) {
// Success!
alert('file created.');
alert(JSON.stringify(result));
}, function(err) {
// An error occured. Show a message to the user
alert('file writed');
alert(JSON.stringify(err));
});
all way getting the error like code: 12 or code: 5
please help me to solve this or give me a idea to get application file path
I have some progression.
First, I alert my cordova.file.dataDirectory or cordova.file.documentsDirectory.
They are
file:///var/mobile/...../Library/NoCloud
and
file:///var/mobile/..../Documents
Then I create a File without the prefix and succeed. Referring to this https://github.com/driftyco/ng-cordova/issues/362
and the success message shows that the native url of the file is saved in
file:///var/mobile/...../Library/files
Which is quite strange. By the way, I add the
<preference name="iosPersistentFileLocation" value="Library" />
according to https://github.com/apache/cordova-plugin-file/blob/master/doc/index.md#ios-persistent-storage-location
All the tests are running on IOS, i haven't test for Android.
Updates
All the following code worked for me and give success response
$cordovaFile.checkFile('/test.data')
$cordovaFile.createFile('test.data',false)
$cordovaFile.checkDir('/')
Hope this can solve your problems.
/*
Here is what I am using for my Android and IOS apps
Keep attention to a couple of things:
- Android and IOS have other directorynames for files
- Android devices have different root (myFSRootDirectory1 = Samsung Tab 3, msFSRootDirectory2 = Samsung SII)
- $cordovaFile functions prefixes all pathnames with root
$cordovaFileTransfer functions needs absolute pathnames
Here I create the prefixes for File functions and FileTransfer functions for Android and IOS
*/
// The $ionicPlatform and ionic.Platorm are from Ionic framework
//
$ionicPlatform.ready(function() {
if (ionic.Platform.isAndroid()) {
// If running on Android
console.log('cordova.file.externalDataDirectory: ' + cordova.file.externalDataDirectory);
//
// I use cordova.file.externalDataDirectory because this url is for Android devices
// If you remove the app from the device these url are cleared too on the device. So keep it clean.
// Remove the root from cordova.file.externalDataDirectory
//
myFsRootDirectory1 = 'file:///storage/emulated/0/'; // path for tablet
myFsRootDirectory2 = 'file:///storage/sdcard0/'; // path for phone
fileTransferDir = cordova.file.externalDataDirectory;
if (fileTransferDir.indexOf(myFsRootDirectory1) === 0) {
fileDir = fileTransferDir.replace(myFsRootDirectory1, '');
}
if (fileTransferDir.indexOf(myFsRootDirectory2) === 0) {
fileDir = fileTransferDir.replace(myFsRootDirectory2, '');
}
console.log('Android FILETRANSFERDIR: ' + fileTransferDir);
console.log('Android FILEDIR: ' + fileDir);
}
if (ionic.Platform.isIOS()) {
// if running on IOS
console.log('cordova.file.documentsDirectory: ' + cordova.file.documentsDirectory);
// I use cordova.file.documentsDirectory because this url is for IOS (NOT backed on iCloud) devices
fileTransferDir = cordova.file.documentsDirectory;
fileDir = '';
console.log('IOS FILETRANSFERDIR: ' + fileTransferDir);
console.log('IOS FILEDIR: ' + fileDir);
}
if (ionic.Platform.isAndroid() || ionic.Platform.isIOS()) {
//
// Just functions from the list below one by one ( or chain them)
//
}
});
// Download file from 'http://www.yourdomain.com/test.jpg' to test/one/test.jpg on device Filesystem
var hostPath = 'http://www.yourdomain.com/test.jpg';
var clientPath = fileTransferDir + 'test/one/test.jpg';
var fileTransferOptions = {};
$cordovaFile.downloadFile(hostPath, clientPath, true, fileTransferOptions).then (function() {
});
// Create dir test
$cordovaFile.createDir(fileDir + 'test/').then( function(dirEntry) {
});
// Create dir aganin in dir test
$cordovaFile.createDir(fileDir + 'test/one/').then( function(dirEntry) {
});
// Create empty file test.txt in test/again/
$cordovaFile.createFile(fileDir + 'test/one/test.txt', true).then( function(fileEntry) {
});
// List of files in test/again
$cordovaFile.listDir(fileDir + 'test/one/').then( function(entries) {
console.log('list dir: ', entries);
});
// Write some text into file
$cordovaFile.writeFile(fileDir + 'test/one/test.txt', 'Some text te test filewrite', '').then( function(result) {
});
// Read text written in file
$cordovaFile.readAsText(fileDir + 'test/one/test.txt').then( function(result) {
console.log('readAsText: ', result);
});
Perhaps it's because of a typo? You have cordova.file.cacheDirecotry. Shouldn't that be : cordova.file.cacheDirectory ?
Refer to the original documentation :-
https://github.com/apache/cordova-plugin-file/blob/master/doc/index.md#ios-file-system-layout
iOS has some directories as read-only. Try changing your path.
Let me know if it does not work for you.
I am trying to unzip a folder in cordova 3.4. But haven't been successful so far. I have seen many tutorials but none of them seems to work for me. Kindly suggest me some plugin or code if you have already done this and if its working.
File is successfully getting saved using http://weblogs.asp.net/soever/cordova-file-transfer-unzip-and-present-adventures, but unzip is not working.
Here is my code, calling for unzip.
document.getElementById("btnUnzip").onclick = function() {
var that = this,
App = new DownloadApp(),
fileName = "ft-p.zip",
folderName = "content";
console.log("zip button clicked");
App.unzip(folderName, fileName,
/*success*/function() { alert("Unzipped and assigned"); },
/*fail*/function(error) { alert("Unzip failed: " + error.code); }
);
};
Thanks.