If we want that our app appears on the open with list of android, we need to allow this intent on our AndroidManifest.xml
file.
Required plugins
- cordova-custom-config : We need to change the default configuration of the AndroidManifest.xml but we will not manipulate it manually as the changes may be lost in future builds, therefore we need to use a plugin that adds the custom configuration everytime we build the app with different versions.
- cordova-plugin-intent : When the configuration of the previous plugin is ready, we need to manipulate the file Intents on every call (when the user executes Open With from another app and our app is not initialized etc.)
- Patience !
Before proceeding
We need to know what we're going to do and why.
We need to modify the intent-filter and add the following permissions (this explicit example will make that our app can open all the kind of files, read more about android mimetypes here to filter by your required extensions)
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" />
<data android:mimeType="*/*" />
<data android:pathPattern=".*\\.txt" />
</intent-filter>
Now the problem is that we can't simply add the previous code block to our config.xml
because it will be not recognized, that's where cordova-custom-config will help us to directly modify the AndroidManifest.xml
from config.xml
.
Finally we will use cordova-plugin-intent to manipulate the intent events for our app from javascript.
Enable the use of Intent in your App
An Intent is a messaging object you can use to request an action from another app component. Download the required cordova plugins :
# Install custom configuration
$ cordova plugin add cordova-custom-config
# Then install the intent handler
$ cordova plugin add https://github.com/napolitano/cordova-plugin-intent
Then you need to allow the use of custom configuration to the project, adding the xmlns:android="http://schemas.android.com/apk/res/android"
property to the widget node in the config.xml
file, the widget should look like:
<?xml version='1.0' encoding='utf-8'?>
<!-- Note the xmlns:android="blabla" as property of the widget node -->
<widget id="com.ourcodeworld.ourcodeeditorfree" version="1.3.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
<!-- We will make some changes in this node later -->
<platform name="android">
<allow-intent href="market:*" />
</platform>
<platform name="ios">
<allow-intent href="itms:*" />
<allow-intent href="itms-apps:*" />
</platform>
</widget>
Now modify the config.xml file and add the intent-filter using a config block (the custom-config plugin will add the content of the config-block directly to the AndroidManifest.xml
file without remove any existing node) :
Note: You need to create an extra intent-filter node in your AndroidManifest.xml
file , if you add these properties to an existing intent-filter, your app will compile, but you will not see the icon to start the app later.
<!-- Locate the android platform -->
<platform name="android">
<!--
Add a new intent-filter node to the app activity :
-->
<config-file target="AndroidManifest.xml" parent="./application/activity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="file" />
<data android:mimeType="*/*" />
<data android:pathPattern=".*\\.txt" />
</intent-filter>
</config-file>
</platform>
If you decide to build now your app, your AndroidManifest.xml
should now include the properties inside the intent-filter node :
And if you trigger the open with (of any application) and the mimeType is correct, your app should be appear in that list now, but we still need to manipulate how will be the opened file handled with Javascript.
Handle Intents
Here's when cordova-plugin-intent will help us. We need to do something with the files (file information) that we receive and we will handle it using the following code (after onDeviceReady event):
document.addEventListener('deviceready', function(){
var HandleIntent = function (Intent) {
console.log(intent);
// With intent you'll do almost everything
if(Intent.hasOwnProperty('data')){
// Do something with the File
}else{
// this will happen in getCordovaIntent when the app starts and there's no
// active intent
console.log("The app was opened manually and there's not file to open");
}
};
// Handle the intent when the app is open
// If the app is running in the background, this function
// will handle the opened file
window.plugins.intent.setNewIntentHandler(HandleIntent);
// Handle the intent when the app is not open
// This will be executed only when the app starts or wasn't active
// in the background
window.plugins.intent.getCordovaIntent(HandleIntent, function () {
alert("Error: Cannot handle open with file intent");
});
}, false);
An intent object, will look like :
{
"action": "android.intent.action.SEND_MULTIPLE",
"clipItems": [
{
"uri": "file:///storage/emulated/0/Download/example-document.pdf",
"type": "application/pdf",
"extension": "pdf"
},
{
"uri": "file:///storage/emulated/0/Download/example-archive.zip",
"type": "application/zip",
"extension": "zip"
}
{
"uri": "content://media/external/images/media/29",
"type": "image/jpeg",
"extension": "jpeg"
}
],
"flags": 390070273,
"type": "*/*",
"component": "ComponentInfo{com.example.droid/com.example.droid.MainActivity}",
"extras": "Bundle[mParcelledData.dataSize=596]"
}
Read more about cordova intent plugin in the official repository here.
Build your app , then you'll see your app listed on the open with menu and you'll be able to do something like open the file with your app with the given information, have fun !