Showing posts with label Cordova. Show all posts
Showing posts with label Cordova. Show all posts

Thursday, 8 August 2019

Commands to Check Ionic, Cordova and Plugin Version

Cordova
see installed version
cordova -v
or
cordova --version
see the latest version available
npm info cordova
to upgrade to latest version
npm update -g cordova
-g means install globally

otherwise need to uninstall and reinstall
npm uninstall -g cordova
npm install -g cordova

Ionic CLI

installed version
ionic -v
or
ionic --version
latest version available
npm info ionic
to upgrade to latest version
npm update -g ionic
-g means install globally

otherwise need to uninstall and reinstall
npm uninstall -g ionic
npm install -g ionic

Plugin of an Cordova app
installed version
npm list thePluginName
latest version available
npm info thePluginName
to upgrade to latest version
npm update thePluginName

otherwise need to uninstall and reinstall

or you can try to use cordova-check-plugins plugin
to add to project
cordova plugin add thePluginName
or
ionic cordova plugin add thePluginName
to remove from project
cordova plugin remove thePluginName
or
ionic cordova plugin remove thePluginName

You can also use
ionic info
command in an App directory to check Ionic CLI, Ionic Framework, Cordova CLI, Platforms, Plugins installed and other information.

Friday, 21 June 2019

Should I Change My App's WebSQL Database to Other?

Recently I have been doing app upgrade due to requirements by Google Play and Apple App Store. I have been doing some research about the latest technologies for the app. I tried to find out more about latest database technology and was trying to figure out whether I should change my WebSQL database.

These are the findings that I had in bullet points:
  • It is mentioned that WebSQL has been deprecated but is still supported by Android and iOS. They do not have any plan to remove it anytime in the future.
  • The SQLite alternative is seemed to be supported by individuals/small group as well as those who developed WebSQL. There is no clarity about the support and future as well.
  • IndexedDB seems good but is not supported by iOS
  • Some opinions said that WebSQL is deprecated simply because it does not fulfill a standard for client side storage but the standard does not really exist and not accepted by all parties.
  • SQLite also does not fullfil the standard
Since there is no alternative and clarity about this and major operating systems have no plan to remove WebSQL in the future, I think it is better to keep using WebSQL in my upgraded app.


References:
https://softwareengineering.stackexchange.com/questions/220254/why-is-web-sql-database-deprecated
https://www.reddit.com/r/SQL/comments/8woehg/sqlite_being_deprecatedreplaced_as_database/
https://cordova.apache.org/docs/en/latest/cordova/storage/storage.html

Monday, 14 January 2019

My Notes of Switching from Visual Studio to Ionic CLI

Recently, I tried to update my app in Google Play and Apple Store but failed to do so because they mentioned that I need to use later version of Android or iOS. I have been using Visual Studio 2013 then Visual Studio 2016 with Tools for Apache Cordova however when checking the latest supported Android and iOS versions, they have not progressed much in the last two years. After some research, I decided to use Apache Cordova directly, together with Ionic, Angular and Node.js. Apache Cordova and Ionic are still progressing and very much alive. I still use Visual Studio 2017 though for code editor only. All project configurations, simulator settings and others will be done at lower level, using Apache Cordova directly. As my app was written in JavaScript and HTML using Ionic 1 so I think it is a good choice.

The notes below are my journey to move from Visual Studio Tool for Apache Cordova to the CLI option. I use same machine to install the required new components. Hopefully it can help anyone who chooses a similar path as mine.


SETTING UP FRAMEWORKS
First I had Node.js, recent Cordova and Ionic installed. Once they were installed I tried to create a new test app by running:
ionic start myApp sidemenu
then it will show:
+ ionic@4.2.1
added 242 packages from 151 contributors in 43.756s
? Integrate your new app with Cordova to target native iOS and Android?
Chose yes and continued with the installation.
After installation:
cd myApp
ionic serve
I made sure the app could be compiled successfully and showed in a browser.

Then I added Android platform:
ionic cordova platform add android
To check the installed version run:
cordova platform version android
Then it showed:
7.1.1 is the latest version


SETTING UP EMULATOR
Next, I tried to set up the emulator with latest version of Android. But first I wanted to make sure that I could run an existing virtual device from AVD Manager.

When trying to run one, I got this error:
“Could not find an installed version of Gradle either in Android Studio,
or on your system to install the gradle wrapper. Please include gradle
in your path, or install Android Studio
[ERROR] An error occurred while running subprocess cordova.”
I installed Gradle from the website and set an environment variable for it.

The second error I got after trying to run the emulator:
“Could not unzip C:\Users\rical\.gradle\wrapper\dists\gradle-4.1-all\bzyivzo6n839fup2jbap0tjew\gradle-4.1-all.zip to C:\Users\rical\.gradle\wrapper\dists\gradle-4.1-all\bzyivzo6n839fup2jbap0tjew.
Reason: error in opening zip file
Exception in thread "main" java.util.zip.ZipException: error in opening zip file”
I deleted the zip folder and run the command again.

Then I got another error:
“Error occurred during initialization of VM
Could not reserve enough space for 2097152KB object heap”
I went to Start -> Control Panel -> System -> Advanced(tab) -> Environment Variables -> System Variables and add new variable:
Variable name: _JAVA_OPTIONS
Variable value: -Xmx512M

After trying to run the emulator again, another error shown up:
“A problem occurred configuring project ':CordovaLib'.
> You have not accepted the license agreements of the following SDK components:
[Android SDK Platform 27, Android SDK Build-Tools 26.0.2].
Before building your project, you need to accept the license agreements and complete the installation of the missing components using the Android Studio SDK Manager.”
Went to SDK Manager and install SDK Platform 27 and Android SDK Build-Tools 26.0.2.

The emulator is working now, but I received a warning:
“Running an x86 based Android Virtual Device (AVD) is 10x faster. We strongly recommend creating a new AVD.”
Solved this by installing Intel x86 Atom_64 or Intel x86 Atom and setting the emulator (AVD) to use one of them.
I received another error “PANIC: Cannot find AVD system path. Please define ANDROID_SDK_ROOT”. I created a new environment variable called ANDROID_SDK_ROOT that has my SDK path, something like "C:\Program Files (x86)\Android\android-sdk". Then restarted the machine.

I wanted to use recent version of Android which is version 8 or 9 but after installing the system images, I got this error:
“This AVD's configuration is missing a kernel file! Please ensure the file "kernel-qemu" is in the same location as your system image”
I found a great article to solve the issue https://www.andreszsogon.com/using-android-8-and-9-emulators-without-android-studio
I followed the instructions:
- download emulator-windows-4848055.zip
- uninstall my current Android 8 and newer system images
- close my Android SDK Manager and AVD Manager tools if open
- extract the contents from the ZIP file into my android-sdk/tools
- download the desired emulator’s System Images from the SDK Manager
- create a new emulator from the AVD Manager
- start a virtual device

Received another error:
“emulator: ERROR: x86 emulation currently requires hardware acceleration!
Please ensure Windows Hypervisor Platform (WHPX) is properly installed and usable.
CPU acceleration status: HAXM is not installed on this machine”
Went to Turn Windows features on and off, checked Windows Hypervisor Platform.

Finally, I could run a virtual device from the AVD Manager.

When I tried to run from command prompt:
ionic cordova emulate --target=My_Android_9_Virtual_Device  android
I got another error:
“A problem occurred configuring project ':CordovaLib'.
> Failed to find Platform SDK with path: platforms;android-27”
I found out that cordova-android 7.1.1 only supports up to Android 8.1 (SDK 27). So I needed to download the SDK Platform and a choice of system image of the newer version.

Finally, the emulator from command prompt is working!

Friday, 5 October 2018

Attempt to use Visual Studio 2017 for Older Apache Cordova App

I have an Ionic 1 with Apache Cordova built using Visual Studio 2015. As time goes by, I couldn't upload package to Apple Store and Google Play anymore as they were asking more recent iOS and Android versions supported in the package. Then thinking to target more recent mobile phone OS, I decided to try Visual Studio 2017 on the same machine. After installing and trying to build, I got some errors.

First error I got is:
Could not resolve com.android.tools.build:gradle:2.1.0. 
Could not get resource 'https://repo1.maven.org/maven2/com/android/tools/build/gradle/2.1.0/gradle-2.1.0.pom'.
Could not HEAD 'https://repo1.maven.org/maven2/com/android/tools/build/gradle/2.1.0/gradle-2.1.0.pom'.
Could not get resource 'https://jcenter.bintray.com/com/android/tools/build/gradle/2.1.0/gradle-2.1.0.pom'.
Could not HEAD 'https://jcenter.bintray.com/com/android/tools/build/gradle/2.1.0/gradle-2.1.0.pom'.

After some googling, it seemed that I had issue with contacting the target servers using HTTPS. I changed these lines on platforms\adroid\build.gradle file:
buildscript {
    repositories {  
        //mavenCentral()
        //jcenter()
        // change to use HTTP explicitly
        jcenter {
   url "http://jcenter.bintray.com/"
  }
    }
    . . .
}

. . .

allprojects {
    repositories {
        //mavenCentral()
        //jcenter()
        // change to use HTTP explicitly
        jcenter {
   url "http://jcenter.bintray.com/"
  }  
    }
}
Also on platforms\adroid\CordovaLib\build.gradle:
buildscript {
    repositories {
        //mavenCentral()
        // change to use HTTP explicitly 
        maven { url 'http://repo1.maven.org/maven2' }
        jcenter {
   url "http://jcenter.bintray.com/"
  }
    }
    . . .
}

Then I found another issue:
cordova-build error : java.lang.UnsupportedClassVersionError: com/android/dx/command/Main : Unsupported major.minor version 52.0

This was fixed by updating the project to use the latest Java installed. Go to Tools -> Options -> Tools for Apache Cordova -> Environment Variable Overrides, then change the JAVA_HOME folder.

Then I tried to run Google Emulator and it was still using the old AVD that had been installed previously. And when I checked config.xml file, VS2017 only supports Cordova 6.3.1 and Global Cordova 7.0.1 by default. I was expecting it supports a more recent version of Cordova that supports the recent versions of Android and iOS. This is the main reason I tried to upgrade to catch up with recent version of Android and iOS in the market. Seeing so many hassles and no update from Visual Studio Tool for Apache Cordova team for almost two years, I think I will try to upgrade my app using Cordova CLI itself.

Tuesday, 2 January 2018

Single Launch Screen for iOS

When building a project for iOS in Visual Studio Tools for Apache Cordova, I noticed that the launch or splash screen was always shown in iOS devices. This is because iOS always needs a launch/splash screen and this is cannot be removed. So I read some documentation and found out that we can use a single image to be applied to all kind of iOS devices.
All we need to do is add this setting in the project's config.xml file:
<splash src="res/screen/ios/Default@2x~universal~anyany.png" />
I used the same name suggested. It may work if we use other file name but I haven't tested it. For the resolution and layout, I tried to follow the default splash.png file in the resources folder. I made my main image in the center and leave plenty amount of spaces around it, knowing that the image will be cropped significantly in some smaller resolution iOS devices. The image size I used is the same as the default image size, which is 2208 x 2208 pixels.

Reference:
https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-splashscreen/

Thursday, 5 October 2017

Some Visual Studio 2015 Apache Cordova Project iOS Deployment Issues

Recently, I tried to deploy my Visual Studio Tools for Apache Cordova project into iOS mobile device. The project is built in Visual Studio 2015 using Cordova CLI 6.0.0. The Visual Studio is on a Windows machine. I also have a Mac laptop with XCode 8.3. After following the steps on this page https://taco.visualstudio.com/en-us/docs/ios-guide, I ran into some issues.

The first error message I received is "Remotebuild requires your projects to use cordova-ios 4.3.0 or greater with XCode 8.3. Please update your cordova-ios version".
It seemed that the iOS version of the project is less than 4.3.0 and XCode expected the version to be at least 4.3.0.
The solution:
1. on my Windows machine, went to command prompt and installed Cordova; npm install -g cordova
2. changed package.json file in the project to have the later version of iOS:
{
  "android": "5.1.1",
  "ios": "4.3.0"
}
3. then on the command prompt, went to the 'platforms' folder of the project and deleted and recreated the iOS version of the project. I ran the command; cordova platform add ios@4.3.0

After passing that, I got another error, "Severity Code Description Project File Line Suppression State Error Warning developmentTeam is missing from your build.json.".
The solution:
- added some configuration settings on my build.json file based on the information on this link https://cordova.apache.org/docs/en/latest/guide/platforms/ios/#using-flags.
So my build.json had something like this:
{
  "android": {
    . . .
  },
  "ios": {
    "debug": {
      "codeSignIdentity": "iPhone Developer",
      "provisioningProfile": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
      "developmentTeam": "XXXXXXXXXX",
      "packageType": "development"
    },
    "release": { }
  }
}
According to the article, codeSignIdentity should use "iPhone Developer" value for both debug and release mode. provisioningProfile is the profile that I set on Apple Developer website. The filename of the downloaded profile has the same key value. developmentTeam is the team name that is set on Apple Developer website. packageType values are either 'development', 'enterprise', 'ad-hoc', and 'app-store'.

Once this is solved, I got another error:
Severity Code Description Project File Line Suppression State
Error Error: Remote build error from the build server Build failed with error ios-deploy was not found. Please download, build and install version 1.9.0 or greater from https://github.com/phonegap/ios-deploy into your path, or do 'npm install -g ios-deploy' - 1

Solution:
- on my Windows machine I ran; npm install -g ios-deploy.

Then another error:
No certificate matching 'iPhone Development' for team 'XXXXXXXXXX': Select a different signing certificate for CODE_SIGN_IDENTITY, a team that matches your selected certificate, or switch to automatic provisioning.
Code signing is required for product type 'Application' in SDK 'iOS 10.3'

Solution:
- on the Mac computer, I went to Applications > Utilities > KeyChain Access folder and found there were more than one certificates related to the profile downloaded. This was due to a mistake I did earlier when generating provisioning profile. So I deleted the incorrect one.

Finally I got this error:
Failed to launch iOS remote for build C:\myProjectDirectory\bld\ios\Debug\buildInfo.json to http://192.168.1.118:3000/cordova :
Http 404: Error mounting developer disk image
------ Cordova tools 6.0.0 already installed.
Requesting debug on remote iOS device for buildNumber 23139 on server http://192.168.1.118:3000/cordova...
Failed to Debug iOS remote for build C:\myProjectDirectory\bld\ios\Debug\buildInfo.json to http://192.168.1.118:3000/cordova :
Http 500: No devices found to debug. Please ensure that a device is connected and awake and retry.

Solution:
- on my Mac machine I ran; brew upgrade libimobiledevice --HEAD


References and further details:
https://github.com/Microsoft/remotebuild/issues/5
https://stackoverflow.com/questions/43944273/apache-cordova-visual-studio-2015-xcode-8-3-cannot-remotebuild

Monday, 14 December 2015

Bulk Insert in Web SQL

Below is a snippet of how to do bulk insert of records in Web SQL:
// db is the database object that is usually initialise with openDatabase() function
db.transaction(function (tx) {  
  // insert each record
  $.each(myArray, function (i, item) {
   tx.executeSql("INSERT INTO MyTable(name, value) VALUES (?, ?)", [item.name, item.value]);
  });   
},
// error
function (error) {
 . . .
},
// success - the transaction() function does not pass any object to its success callback
function () {
 . . .
});

Web SQL does not understand the Standard SQL bulk insert syntax such as
Insert Into tbl (col1, col2) Values ('val1', 'val2'), ('val3', 'val4'), ...
but each insert statement needs to be executed using executeSql() function. A transaction is usually used to wrap these insert commands.

Wednesday, 30 September 2015

[INSTALL_PARSE_FAILED_MANIFEST_MALFORMED] Error

If you encounter an issue when trying to run a Cordova app in an Android emulator with the error messages similar like the following:
  Installing app on device...
C:\Users\Me\Documents\Visual Studio 2015\Projects\MyApp\MyApp\platforms\android\cordova\node_modules\q\q.js:126
throw e;
^
ERROR: Failed to launch application on device: ERROR: Failed to install apk to device:  pkg: /data/local/tmp/android-debug.apk
Failure [INSTALL_PARSE_FAILED_MANIFEST_MALFORMED]
  Command finished with error code 1: cmd /s /c ""C:\Users\Me\Documents\Visual Studio 2015\Projects\MyApp\MyApp\platforms\android\cordova\run.bat" --nobuild --target=169.254.56.136:5555 --debug "--buildConfig=C:\Users\Me\Documents\Visual Studio 2015\Projects\MyApp\MyApp\build.json""
  ERROR running one or more of the platforms: Error: cmd: Command failed with exit code 1
  You may not have the required environment or OS to run this project
try to make sure that Package Name in config.xml is in lower case then rebuild/rerun the app.

Monday, 3 August 2015

Memory Issue when Building Cordova Project in Visual Studio 2015

I have just upgraded my desktop to Windows 10 and installed Visual Studio 2015 Community Edition. When trying to build my first Apache Cordova project in VS2015, I got these errors:
Could not create the Java virtual machine
Error occurred during initialization of VM
Could not reserve enough space for object heap


After trying to google for the solution, I found one that is better than the others. It told me to add a new system variable _JAVA_OPTIONS with -Xmx512M as the value.

Below is the detail:
Go to Control Panel -> System -> Advanced, then click Environment Variables. Click New on the System variables section then put:
Variable name: _JAVA_OPTIONS
Variable value: -Xmx512M

Solved my issue right away.

Tuesday, 14 July 2015

Generating Android Release Keystore for Visual Studio Apache Cordova Project

Below are the steps to generate an Android keystore for publishing a release version of an app built using Visual Studio Apache Cordova:
1. Make sure you have Java SDK installed.

2. Run keytool command like below:
keytool -genkey -v -keystore YOUR_KEY_NAME.keystore -alias KEY_ALIAS -keyalg RSA -keysize 2048 -validity 20000
Use greater than 10,000 days (i.e. 20,000 days) validity to avoid expiration issue when uploading the package to Google App store.
For example:
C:\Program Files (x86)\Java\jdk1.7.0_55\bin>keytool -genkey -v -keystore c:\users\rical\my-release-key.keystore -alias rical_blog_app_key -keyalg RSA -keysize 2048 -validity 20000
Then you will be prompted with some questions:
Enter keystore password: *****
Re-enter new password: *****
What is your first and last name? 
  [Unknown]:  Rical Wirawan 
What is the name of your organizational unit? 
  [Unknown]:  Organisation
What is the name of your organization? 
  [Unknown]:  MyOrg
What is the name of your City or Locality? 
  [Unknown]:  MyCity 
What is the name of your State or Province? 
  [Unknown]:  NSW
What is the two-letter country code for this unit? 
  [Unknown]:  61 
Is CN=Rical Wirawan, OU=Organisation, O=MyOrg, L=MyCity, ST=NSW, C=61 correct? 
  [no]:  yes 

Generating 2,048 bit RSA key pair and self-signed certificate (SHA256withRSA) with a validity of 10,000 days 
        for: CN=Rical Wirawan, OU=Organisation, O=MyOrg, L=MyCity, ST=NSW, C=61 
Enter key password for  
        (RETURN if same as keystore password): 
[Storing my-release-key.keystore] 

3. The key file will be generated in the specified folder.

4. If you use a recent version of Cordova CLI, open build.json file in the root folder of the project. If it does not exist yet then create the file manually. Then put the details in the file, continuing our example:
{
 "android": {
     "release": {
         "keystore":"C:\\users\\rical\\my-release-key.keystore",
         "storePassword":"*****",
         "alias":"rical_blog_app_key",
         "password":"*****",
         "keystoreType":""
       }
   }
}

If your Cordova CLI version is less than 5.0, open ant.properties file (under 'your_project_name\res\cert\android' folder). Then put the key details in the ant.properties file, continuing our example:
key.store=c:\\users\\rical\\my-release-key.keystore
key.alias=rical_blog_app_key
key.store.password=*****
key.alias.password=*****

6. Build the app in Release mode with Device or one of Android emulator platforms option. Do not use any of the Ripple emulators option.

7. The package will be created inside 'bin/Android/Release' folder. The file to be deployed to Google App store is the one that does not end with (-unaligned.apk), e.g. "android-release.apk".

Friday, 27 March 2015

How to Pull File from an Android App

The other day when I tested my Apache Cordova based app, I tried to get a file from my Android phone to test that the file was created correctly by the app. I wanted to copy the file to a location somewhere in my Windows based desktop. Below are the steps of how I do this:
- open a command prompt
- enter 'adb shell', you might need to run this inside a folder that has adb.exe if that is not accessible globally
- enter 'run-as    your.application.name'
- enter 'chmod 777    targeted_File_Path' in order to give full access to the file
So after entering these commands, the command prompt would look like this:
C:\Users\Me>adb shell
shell@zara:/ $ run-as your.application.name
run-as your.application.name
shell@zara:/data/data/your.application.name $ chmod 777 /data/data/your.application.name/files/filename.jpg
data/data/your.application.name/files/filename.jpg                   <
shell@zara:/data/data/your.application.name $ 
- quit the adb shell or open a new command prompt window
- enter 'adb pull    targeted_File_Path    destination_Desktop_Folder'
On command prompt, it will be something like:
C:\Users\Me>adb pull /data/data/your.application.name/files/filename.jpg c:/DestinationDirectory
2097 KB/s (19335 bytes in 0.009s)


References:
http://stackoverflow.com/questions/13006315/how-to-access-data-data-folder-in-android-device
http://www.codeproject.com/Articles/825304/Accessing-internal-data-on-Android-device

Thursday, 19 March 2015

Example of Writing Image to File in Apache Cordova

Below is an example of how to writing image to a file in Apache Cordova. To have more understanding of basic file operations, please see my previous post.
window.resolveLocalFileSystemURL(my_Directory_Path,
function (dirEntry) {
 dirEntry.getFile(path_Of_File_To_Be_Written, { create: true }, 
  // getFile() success
  function (fileEntry) {
   fileEntry.createWriter(
    // createWriter() success
    function (fileWriter) {
     fileWriter.onwriteend = function (e) {
      . . .
     };

     fileWriter.onerror = function (e) {
      . . .
     };

     fileWriter.write(dataURIToBlob(getBase64Image(image_To_Be_Written, "image/jpeg")));
     // or if we already have a canvas
     //fileWriter.write(dataURIToBlob(canvas.toDataURL("image/jpeg")));
    }, 
    // createWriter() error
    function (error) {
     . . .
    }
   );
  },
  // getFile() error
  function (error) {
   . . .
  }
 );
});

A function to convert an image's base-64 encoded data to Blob type (this is taken from http://stackoverflow.com/questions/12391628/how-can-i-upload-an-embedded-image-with-javascript):
function dataURIToBlob(dataURI) {
 // serialize the base64/URLEncoded data
 var byteString;
 if (dataURI.split(',')[0].indexOf('base64') >= 0) {
  byteString = atob(dataURI.split(',')[1]);
 }
 else {
  byteString = unescape(dataURI.split(',')[1]);
 }

 // parse the mime type
 var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]

 // construct a Blob of the image data
 var array = [];
 for (var i = 0; i < byteString.length; i++) {
  array.push(byteString.charCodeAt(i));
 }
 return new Blob(
  [new Uint8Array(array)],
  { type: mimeString }
 );
}
Also a function to get base-64 encoded data from an image:
// type is either "image/png" or "image/jpeg"
function getBase64Image(img, type) {
    // create an empty canvas element
    var canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;

    // copy the image contents to the canvas
    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);

    // get the base-64 encoded data
    var dataURL = canvas.toDataURL(type);
 // toDataURL() actually has two optional parameters:
 // - type. The default value is 'image/png'.
 // - jpegQuality. A decimal value ranging from 0 to 1 to determine the quality of the data to be generated from a jpeg type image.
 //   The default value is browser dependant.

    return dataURL;
}

Monday, 16 March 2015

Examples of File Operations in Apache Cordova

To be able to do any operation with directory/file in Apache Cordova, we need to access and get hold of the directory/file entry first. Then only after that we will be able to do any directory/file operation. This could be a very different approach from other frameworks that we have used before in dealing with file and file system.


Creating and Writing File
Let start with an example to create and write a file:
window.resolveLocalFileSystemURL(cordova.file.dataDirectory, function (dirEntry) {
 console.log("got directory entry", dirEntry);
 dirEntry.getFile("myFilename.txt", { create: true }, 
  // getFile() success
  function (fileEntry) {
   console.log("got file entry", fileEntry);
   fileEntry.createWriter(
    // createWriter() success
    function (fileWriter) {
     fileWriter.onwriteend = function (e) {
      console.log('write is successful');
      . . .
     };

     fileWriter.onerror = function (e) {
      console.log('write is failed', e);
      . . .
     };

     var blob = new Blob(['. . . some text . . .'], { type: 'text/plain' });
     fileWriter.write(blob);
    },
    // createWriter() error
    function (error) {
     . . .
    }
   );
  },
  // getFile() error
  function (error) {
   . . .
  }
 );
});

In the example above, we use resolveLocalFileSystemURL() function to get a directory or file entry from a directory/file system path (i.e. cordova.file.dataDirectory). resolveLocalFileSystemURL() has two parameters:
- the first parameter is a directory or file path
- the second one is the callback function to be executed once it succeed. A directory or file reference entry object is passed to the callback function.

Once we have hold of the file or directory entry object, we can do a number of operations such as creating, writing, reading, copying, moving, renaming or deleting the file. In this case, we want to create a new file and write into it. To do this, we need to call getFile() function first. The function has four parameters:
- the filename or file path
- function options (optional parameter). It has two properties with boolean values, namely; create and exclusive. create: true will create a file if it does not exist. To make the function throws an error if the file exists, set exclusive: true.
- on success callback function, passing a file reference entry object
- on error callback function (optional parameter), an error object is passed to the callback
Then after we get the file entry object, we call createWriter() function that will create a file writer object once successful. Next we call its write() function. The file writer object also has onwriteend() and onerror() callback functions.


Reading File
window.resolveLocalFileSystemURL(myFilePath, function (dirEntry) {
 fileEntry.file(
  // success
  function(file) {
     var reader = new FileReader();

     reader.onloadend = function(e) {
       console.log('file is read');
       . . .
     };

     reader.readAsText(file);
  }, 
  // error
  function (error) {
    . . .
  }
 );
});
In the example, we see that after we get a file reference entry object, we use file() method in order to create a file object of the intended file to be passed to FileReader readAsText() function.


Deleting File
window.resolveLocalFileSystemURL(myFilePath, 
 function (fileEntry) { 
  fileEntry.remove(
   // success
   function () { 
    console.log('file is removed'); 
    . . .
   }, 
   // error
   function (error) {
    . . .
   }
  ); 
 } 
); 
In this last example, we call file entry object's remove() function to delete a file.

Wednesday, 25 February 2015

Cordova Build Fails with Exit Code 2 and 8

When building or debugging an Android app using Apache Cordova and Visual Studio, if you encounter this kind of error below:
Could not create the Java Virtual Machine. C:\...\MyApp\EXEC 1 1 MyApp 
A fatal exception has occurred. Program will exit. C:\...\MyApp\EXEC 1 1 MyApp 
C:\...\MyApp\bld\Debug\platforms\android\cordova\build.bat: Command failed with exit code 2 C:\...\MyApp\EXEC 1 1 MyApp 
The command ""C:\Users\Me\AppData\Roaming\npm\node_modules\vs-mda\vs-cli" build --platform "Android" --configuration "Debug" --projectDir . --projectName "MyApp" --language "en-US" --buildServerUrl "" --buildTarget "AndroidDevice"" exited with code 8. C:\Users\Me\AppData\Roaming\npm\node_modules\vs-mda-targets\Microsoft.MDA.targets 99 5 MyApp
You can try to kill Android Debug Bridge process using task manager or command prompt. To do the first way, open Windows Task Manager (ctrl + shift + esc), find adb.exe and then right click and select 'End Process Tree'. Otherwise using command prompt, type adb kill-server and adb start server commands. For example, in my environment:
C:\Users\Me\AppData\Local\Android\android-sdk\platform-tools\adb kill-server
C:\Users\Me\AppData\Local\Android\android-sdk\platform-tools\adb start server
After that, try to build or debug again. If it is still not good then restart Visual Studio.

If you would like to try other ways before restarting Visual Studio, you can try these steps as well:
- close the emulator if you are using emulator
- clean the build files in Visual Studio using 'Clean Solution'
- if still there are files under 'My_App_Name\bld\Debug\platforms' folder then delete those manually
- then try to rebuild or start debugging again

Thursday, 13 November 2014

Cordova Plugin is not Available when Application Starts

If you use a plugin and execute its method when your application starts and have this error:
TypeError: Cannot read property '[your_plugin_name]' of undefined at Object.[plugin_method]
then it is likely that the plugin has not been initialised fully when the method is called.

To solve this issue, wait until deviceready event is fired before calling the plugin's method.

With AngularJS, I like to wait until deviceready event is fired before loading the whole application. To do this, make sure that ng-app declaration is removed from the HTML, then bootstrap the app when deviceready event has fired. document.addEventListener is used to determine whether the event has been fired.
document.addEventListener("deviceready", function() {
    angular.bootstrap(document, ["myApp"]);
}, false);
If you want to apply this to a particular element instead of the whole HTML document (or body), you could use:
var theElement = document.findByID(...) // or document.querySelector(...);
angular.bootstrap(theElement, ["myApp"]);

Then you can call the rest scripts:
var myApp= angular.module('myApp', [. . .]);

myApp.config(
  . . .
);

Thursday, 23 October 2014

Adding ngCordova Plugin to Visual Studio Cordova Project

We will see how to add a plugin from ngCordova which has a collection of Cordova API plugins wrapped in AngularJS. ngCordova will help even more Cordova developers who are using AngularJS.

1. First, include ng-cordova.js or ng-cordova.min.js file into our project structure. We can use bower to install that or download the zip file from its GitHub repository then find the js file inside.

2. On our project main page, add a reference to it before the reference to cordova.js file.
<script src="some_path/ng-cordova.min.js"></script>
<script src="cordova.js"></script>

3. Include 'ngCordova' in our app module. For example:
var myApp = angular.module('myApp', ['ngCordova', . . .]);

4. Add the intended plugin wrapped by <vs:feature></vs:feature> inside <vs:features> node in our project config.xml file like below:
<vs:features>
  <vs:feature>plugin_id@version_number</vs:feature>
  <vs:feature>plugin_2_id@version_number</vs:feature>
  . . .
</vs:features>
Right click config.xml file then select View Code to do this.

To find the plugin Id and version number, we can check from plugins.cordova.io site or from the plugin.xml file on the plugin repository site. However if we are getting the information from plugin.xml file, that will always be the latest version which sometimes is not the stable one.

An example for the latter one, say we would like to use Local Notification plugin. Go to its site https://github.com/katzer/cordova-plugin-local-notifications then open plugin.xml file located on the root. Inside the plugin element there are 'id' and 'version' attributes.

When building the project, Visual Studio will download the plugin and add to the project if it has not done so.


5. Inject the plugin service into our controller then we can start using it.
For example, to use Local Notification, we need to inject $cordovaLocalNotification like this:
myApp.controller('MyCtrl', ['$cordovaLocalNotification', . . . ,
  function ($cordovaLocalNotification, . . .) {
  . . .
}]);

Thursday, 2 October 2014

Getting Started with Cordova and Ionic in Visual Studio

On this post, we will see how to install Visual Studio Apache Cordova tool and Ionic framework and get started with a sample application.

1. First we need to download and install Apache Cordova tool from here. At the time of writing, the version is CTP 2.0.

2. Then once completed, open Visual Studio to create a new project. On the New Project dialog, go to JavaScript project templates then Multi-Device Hybrid App. Select Blank App (Apache Cordova) then create a project.

3. Install Ionic through NuGet. At the time of writing, the latest version is v1.0.0.0-beta.1. This will add many AngularJS and Ionic files into our project.

4. Install Ionic on local machine so that we could create some sample applications with particular templates and use some of the files in our project. To do this, open Node.js command prompt then run this command:
npm install ionic -g
-g is used to install the package globally

5. On the command prompt, go to a directory where you want to have Ionic sample applications then run this command:
ionic start SideMenuAppExample sidemenu
This command will generate a sample Ionic application with side menu navigation.

6. Go to the generated app folder then to 'www\js' folder then copy app.js and controllers.js into our project.

7. Also copy the whole 'templates' folder and its content into our project.

8. Then on our project index.html file:
- add a reference to 'Content/ionic.css'
- add a reference to 'scripts/ionic.bundle.js'
- add references to the two JavaScript files that we have copied over (app.js and controllers.js)
- add 'ng-app="starter"' in the body
- add <ion-nav-view></ion-nav-view> inside the body content

Once finished, we will have something like this on our index.html:
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>BlankCordovaApp2</title>

    <link href="Content/ionic.css" rel="stylesheet" />
    <link href="css/index.css" rel="stylesheet" />
</head>
<body ng-app="starter">
    <ion-nav-view></ion-nav-view>


    <!--library scripts references-->
    <script src="scripts/ionic.bundle.js"></script>
    <script src="cordova.js"></script>
    <script src="scripts/platformOverrides.js"></script>
    
    <!--custom scripts references-->
    <script src="app.js"></script>
    <script src="controllers.js"></script>
</body>
</html>

Then run the application. We should see a sample app with side menu running.