Sencha Touch is rich in APIs which makes it best HTML5 framework for hybrid mobile application development. Along with this important API for accessing device File System with the leverage of Apache Cordova. There are many other standard APIs available for the storage like localstorage, SQLite which supports many browsers but device File System API are yet to evolve in mobile platform.
In this article we will see how we can use Apache Cordova File API abstraction in Sencha Touch to interact with your mobile device file system.
Problem Statement
In many mobile native application you might have to interact with native device file system for various purposes like file system, reading the file, downloading the file from remote url, open the file to read, directory listing etc.
In this article we will see how you can use Apache Cordova File API abstraction in Sencha Touch to interact with your mobile device file system to perform standard following operations:
- Reading File System
- Downloading the file from remote url and
- Open the file with inAppBrowser
Pre-requisite
- Sencha Touch development environment (Sencha cmd, Touch SDK ( V – 2.3.X ) etc)
- NodeJS 10.x
- Cordova 2.x
- Android development environment setup
- Working knowledge of Sencha Touch
Details
Step 1 : Create a Sencha Touch application using Sencha CMD
Run the following command to generate your Sencha Touch app
sencha –sdk <sdk path> generate app <app-namespace> <app-location>
E.g. sencha –sdk /Users/wtc/sdk/touch-2.3.0 generate app WTC /Applications/XAMPP/htdocs/STFile
Step 2 : Enable support for Cordova
Now change your directory to your app directory and run the following command
To change the directory to app directory
cd /Applications/XAMPP/htdocs/STFile
To enable support for Cordova
sencha cordova init
Step 3 : Using Cordova File plugin and InAppBrowser plugin
In order to use the Apache Cordova File API in your app you need to add the Cordova plugin.
To add these plugins change to cordova directory in your app directory.
cd /Applications/XAMPP/htdocs/STFile/cordova
Run the file command to add File plugins
cordova plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-file.git
cordova plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer.git
Run the file command to add inAppBrowser plugin
cordova plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-inappbrowser.git
Now we are ready to use the native device file system using the Sencha Touch File API which is Cordova file abstractions
Step 4: Accessing the device File System
Ext.device.FileSystem is singleton class which provides an API to navigate file system hierarchies on your device.
Past following piece of code in launch function in app.js file , which will tell you the file system root path for your device.
1 2 3 4 5 6 7 8 9 10 11 12 |
Ext.device.FileSystem.requestFileSystem({ type: window.PERSISTENT, size: 0, success: function(fileSystem) { Ext.Msg.alert('File System',fileSystem.fs.root.fullPath); }, failure: function(error) { Ext.Msg.alert('File System path', error); } }); |
Now build the app for native device.
Go to application directory and change the cordova.local.propeties file for Android native package by changing the platform value as below:
cordova.platforms=android
Now run the following command from application directory.
sencha app build native
Deploy the .apk file in your emulator or real device to test the app.
You will see following output
Step 4: Download file from remote url and open using inAppBrowser of device
In order to download the remote file and to view you need to do following steps:
- Get the filesystem instance
- Get file entry instance for file to be downloaded and
- download file
- Open the file using inAppBrowser
Remove the launch function in app.js and copy following code and paste in app.js file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
launch: function() { // Destroy the #appLoadingIndicator element Ext.fly('appLoadingIndicator').destroy(); var me = this; var downloadBtn = { xtype:'button', text: 'Download File', height:10,width:200, handler: function() { me.downloadFile(); } }; var openBtn = { xtype:'button', text: 'Open File', height:10,width:200, handler: function() { me.openFile('sample.pdf'); } }; var cont = Ext.create('Ext.Container', { centered:true, items: [ downloadBtn,{xtype:'spacer',padding:20},openBtn ] }); Ext.Viewport.add(cont); }, downloadFile: function() { var me = this; var fileName = 'sample.pdf'; // Edit this file name var remoteDocUrl = 'http://www.saronicferries.gr/content/pdfFiles/sample.pdf'; // Edit this file url this.getLocalFileEntry(fileName, function(fileEntry) { if (!Ext.isEmpty(fileEntry.download) && Ext.isFunction(fileEntry.download)) { fileEntry.download({ source: remoteDocUrl, trustAllHosts: true, options: {}, success: function(fe) { Ext.Msg.alert(fileName ,'File downloaded successfully.'); }, failure: function(error) { Ext.Msg.alert('Download fail'); } }); } else { console.log('download API not available!!'); } }, function(error) {}); }, getLocalFileEntry: function(fileName, successCbk, failureCbk) { Ext.device.FileSystem.requestFileSystem({ type: window.PERSISTENT, size: 0, success: function(fileSystem) { var newFilePath = fileSystem.fs.root.fullPath + '/' + fileName; var fileEntry = new Ext.device.filesystem.FileEntry(newFilePath, fileSystem); successCbk(fileEntry);}, failure: function(error) { console.log('Failed to get the filesystem: ' + error); failureCbk(error); Ext.Msg.alert('getLocalFileEntry fail' + error); } }); }, openFile: function(fileName){ //get the local file path using the file name and open the document this.getLocalFileEntry(fileName, function(fileEntry){ //open the file using InAppBrowser Ext.device.Browser.open({ url: fileEntry.path, showToolbar: true, options: 'location=yes', listeners: { loadstart: function() { console.log('Started loading..'); Ext.Msg.alert('Started loading..'); }, loadstop: function() { console.log('Stopped loading..'); Ext.Msg.alert('Stopped loading..'); }, loaderror: function() { console.log('Error loading..'); Ext.Msg.alert('Error loading..'); },close: function() { console.log('Closing.'); Ext.Msg.alert('Closing..'); } }}); }, function(error){ });}, |
Create an native package and install the package on your device, you will able to see following view.
Tap on Download File to download the file and once file downloaded i.e. you will see an alert ( Note : In application you can show loading indicator as this is just to show the functionality using alert feature ).
Observe the downloaded file in your device file system.
Now to open the downloaded file tap on Open File button to view the file in the device inAppBrowser
Note : If fails to open using inAppBrowser in Android then you need to make some changes to Cordova InAppBrowser plugin as below
cordova/platforms/android/src/org/apache/cordova/inappbrowser/InAppBrowser.java, execute method line no 147, comment out replace with
1 |
result = openPdfFile(url); |
i.e.
else part will look as below
1 2 3 4 |
else { Log.d(LOG_TAG, "in blank"); //result = showWebPage(url, features); result = openPdfFile(url);} |
Also add following method to the file
1 2 3 4 5 6 7 8 9 10 |
public String openPdfFile(String url) { try { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.parse(url), "application/pdf"); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); cordova.getActivity().startActivity(intent); return ""; } catch (android.content.ActivityNotFoundException e) { LOG.e(LOG_TAG, "Error opening " + url + ": " + e.toString()); return e.toString(); }} |
There are more APIs available in Sencha Touch to perform additional operations on file and interact with native device file system.
Conclusion
In this article you saw how we can leverage the Apache Cordova FIle API in Sencha Touch and perform different file operations and interact with native device file system, which are common in any enterprise mobile application.
Excellent tutorial! I am developing an app in Sencha Touch and need exactly such tutorial but as applied to getting the Contacts from the smartphone device. My development environment was set up fine and I added one plugin – cordova contacts plugin, it looks like it was added correctly, but I don’t seem to get any results past step 3. Do you have any tutorials specifically for getting the Contacts? I purchased your Sencha Touch Cookbook Second Edition but the Contacts example there does not use Sencha Touch 2.3 & Cordova, it’s more of a strictly cordova build (this tutorial is perfect for my needs, albeit for file system). The reference to the Sencha API being shown in the “next chapter” is in Chapter 10, the last chapter of the book, so I did not find the Sencha APi example. Any help would be appreciated.