I am trying to use webintents with a cordova app to be able to send images from another app to mine.
I am using cordova 5.1.1 and added the following plugins to my android platform project:
com.virtualartifacts.webintent 1.0.0 "WebIntent"
cordova-plugin-camera 1.1.0 "Camera"
cordova-plugin-console 1.0.0 "Console"
cordova-plugin-device 1.0.0 "Device"
cordova-plugin-file 2.0.0 "File"
cordova-plugin-file-transfer 1.1.0 "File Transfer"
cordova-plugin-whitelist 1.0.0 "Whitelist"
The index.html file for the project looks like:
<!DOCTYPE html>
<html>
<head>
<title>WebIntent Test</title>
<meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'">
<script src="cordova.js"></script>
<script src="js/webintent.js"></script>
<script>
function init() {
document.addEventListener("deviceready",deviceReady,false);
}
function deviceReady() {
console.log("App started. Device ready");
window.plugins.webintent.getExtra(window.plugins.webintent.EXTRA_STREAM,
function(data) {
console.log(data); // which never gets called
}, function(e) {
console.log(e);
// I simply get the message "Error"
});
}
</script>
</head>
<body onload="init()">
<h1>Demo WebIntent</h1>
</body>
</html>
so nothing really special here.
after searching the net for a while I found some information about the webintent plugin being buggy (as mentioned here on SO. So i found the patched version and double checked that the right code is in the WebIntent.java file, which is.
I also added the intent-filter tags in the AndroidManifest.xml file like so:
<intent-filter>
<action android:name="android.intent.action.SEND" />
<data android:mimeType="image/*" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
When i installed the app on the device and try to share an Image my app shows up in the list of apps that are able to handle this sharing, and i also get the "App started..." text, so I know it gets called.
But no matter what kind of image i try i always reach the "error" part of the getExtra method and my console.log only shows "Error". Debugging is done directly on the device via GapDebug.
Is there anything I am missing or has anyone an idea on making my app getting images from other apps to work with?
Thanks in advance!
There is a bug in that Cordova plugin, use this fork instead
https://github.com/florentvaldelievre/virtualartifacts-webintent
so just remove the old one
cordova plugin rm com.virtualartifacts.webintent
and add the new one
cordova plugin add https://github.com/florentvaldelievre/virtualartifacts-webIntent.git
that should be it, although I'm didn't need to run js\webintent.js to get it to work.
This works when selecting a single image, arrays of streams doesn't seem to work yet.
Related
I am needing to have my cordova wrapped html show a picture and run a video file located off the root of the external SD. There did not seem to be a place to ask these questions on the git hub for the cordova-plugin-file.
A) I am not sure I understand what path to use in 2 B&C below in order to accomplish this if the files are in those two sub directories off the root?
B) Are ALL those values in 3 B necessary if all I need is access to the ext SD?
Here is what I know from the documentation so far ... but obviously I don't have it all correct because I get the error (see below)
1) Set up environment from CMD line
cordova create MyApp
cd /MyApp
cordova platform add android#latest
cordova plugin add cordova-plugin-whitelist
cordova plugin add cordova-plugin-file
corddova build android (after step 3 below)
2) Add these to index.html
A) cdvfile: scheme to Content-Security-Policy meta tag of the index page, e.g.:
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap:cdvfile:https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src
B) <img src="cdvfile:///img/logo.png" />
C) <p>Play video</p>
3) Add these to config.xml
A) <access origin="cdvfile://*" />
B) <preference name="AndroidExtraFilesystems" value="files,files-external,documents,sdcard,cache,cache-external,assets,root" />
The error I get on the Android when clicking on the video link is ...
net::ERR_UNKNOWN_URL_SCHEME (cdvfile:video/0001_a1.mp4)
===========
EDIT #1
Now trying recommendation by #DaveAlden ... using plugin called [cordova.plugins.diagnostic][2] with this configuration to locate root path on ExtSD to play video BUT get the error (see below) ...
config.xml
<preference name="android-minSdkVersion" value="14" />
<preference name="android-targetSdkVersion" value="14" />
<preference name="android-maxSdkVersion" value="25" />
<plugin name="cordova-plugin-whitelist" spec="1" />
<plugin name="cordova.plugins.diagnostic" />
Index.html
<body>
<!-- Set up path to ExtSD on Android -->
<script>
function getSdRefAndEmbed(){
cordova.plugins.diagnostic.getExternalSdCardDetails(function(details){
details.forEach(function(detail){
if(detail.type === "root"){
cordova.file.externalSdCardRoot = detail.filePath;
embedMedia();
}
});
}, function(error){
console.error(error);
});
}
function embedMedia(){
$('.extSdVideo').each(function(){
$(this).attr('href', cordova.file.externalSdCardRoot + $(this).attr('href'));
});
}
$(document).on('deviceready', getSdRefAndEmbed);
$(document).on('pageinit', embedMedia);
</script>
<!-- Play video file -->
<a class="extSdVideo" href="video/0001_a1.mp4" id="0001_a1"> a1 </a>
</body>
Application Error
net::ERR_FILE_NOT_FOUND (file:///android_assest/www/HHR/hhr-cm_cameroon-cm1-fra-spa/hhr/hhr-cm_cameroon-cm1-fra-spa/video/0001_a1.mp4
Tried placing the 0001_a1.mp4 in either of these two directories...
extSDRoot/video/0001_a1.mp4
and/or
extSDRoot/www/HHR/hhr-cm_cameroon-cm1-fra-spa/hhr/hhr-cm_cameroon-cm1-fra-spa/video/0001_a1.mp4
=================== EDIT #2
#DaveAlden Suggested trying these three things...
1) Put console.dir(details) inside of getExternalSdCardDetails() to see what native paths the plugin is finding.
RESULT: it gives the same path in the error message
Application Error
net::ERR_FILE_NOT_FOUND
(file:///android_asset/www/hhr/cm_cameroon-cm1-fra-spa/0001_a1.mp4)
2) Try the example project (https://github.com/dpa99c/cordova-diagnostic-plugin-example) on the same device to see if the ext SD example works.
RESULT 1: The build for the example project failed...
BUILD FAILED Total time: 47.426 secs Error: cmd: Command failed with exit code 1 Error output: F:\DIAGNOSTIC_WORKING\cordova-diagnostic-plugin-example\platforms\android\build\ intermediates\res\merged\debug\values-v24\values-v24.xml:3: AAPT: Error retrievi ng parent for item: No resource found that matches the given name 'android:TextA ppearance.Material.Widget.Button.Borderless.Colored'.
#DaveAlden response to the Build Fail...
You have missing/outdated Android SDK components in your build
environment and/or are using an outdated version of cordova-android
platform. See documentation
(https://github.com/dpa99c/cordova-diagnostic-plugin#building-for-android)
and this issue
(https://github.com/dpa99c/cordova-diagnostic-plugin/issues/161).
My Actions:
I checked the Android SDK Manager to see that all API levels were on the same level for the required products by running this command
C:> Android -v
Android SDK Tool 25.2.5
SDK platform 25
Android Support Repository 46
Google Play services 39
Google Repository 45
I ran this command...
cordova platform check android
Got this result...
F:\DIAGNOSTIC_WORKING\cordova-diagnostic-plugin-example>cordova platform check android
Subproject Path: CordovaLib
android # 6.1.2; current did not install, and thus its version cannot be determined
Why do I get this "current did not install"? Could this be the issue why the diagnostic plugin is not finding the correct path for the extSD?
I ran this command...
cordova platform rm android && cordova platform add android#latest && cordova build android
Now the Build Succeeded for Example Project!
See screen shot of the example diagnostic app showing path to the extSD. This path looks very different from the path I am getting when I run the diagnostic plugin in my app.
Note the button "Write External SD File" did not write anything when pressed. I checked with my file manager.
The path given for the Example Project is very different for the path that the diagnostic plugin gives for my app (see mine below). These results were from the same Galaxy S7.
net::ERR_FILE_NOT_FOUND (file:///android_assest/www/HHR/hhr-cm_cameroon-cm1-fra-spa/hhr/hhr-cm_cameroon-cm1-fra-spa/video/0001_a1.mp4
I ran this command for my app but no change ...
cordova platform rm android && cordova platform add android#latest && cordova build android
3) #DaveAlden suggested running a debug using Chrome... I'll do that next.
Found this...
============= EDIT 3 SUCCESSFULLY played video from extSD using cordova-diagnostic-plugin
Here's how...
The final hurdle was that because I have an Android 6+ phone I had to also add a function to check for run time permission to read the extSD. The code kept bombing with the error show in Edit #2 (see above) like it was trying to see an internal path. Once I added the function to check for run time permission it finally gave the correct external path. Hint ... it is not enough to just provide the permission in the manifest. You can read about it here. Thanks #DaveAlden for your example project!
https://github.com/dpa99c/cordova-diagnostic-plugin-android-runtime-example
Android runtime permissions
Android 6 / API 23 introduces the concept of runtime permissions. Similar to >iOS, certain "dangerous" permissions must be requested at runtime in addition >to being listed in the Android manifest.
Runtime permissions only apply if the device/emulator the app is running on has >Android 6.0 or above AND the app is built using API 23 or higher. For Cordova, >this means using the Cordova Android platform version 5.0.0 or above. If the >app is built with version 4.x or below (API 22 or below), runtime permissions >do not apply - all permissions are granted at installation time.
Add to Config.xml
<access origin="*" />
<plugin name="cordova-plugin-whitelist" version="*" />
<plugin name="cordova.plugins.diagnostic" version="*" />
<plugin name="cordova-plugin-file" version="*" />
<preference name="android-minSdkVersion" value="21" />
<preference name="android-targetSdkVersion" value="23" />
<config-file target="AndroidManifest.xml" parent="/*">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Thanks to #DaveAlden for this code... I only added the function to check the run time read permission. Dave you should just add this code for reading media files from the extSD to your project example so you don't have to help the next person as much as you did me. :)
Add to Index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="default-src * gap://ready file:; style-src 'self' 'unsafe-inline'; img-src * 'self' data:; script-src * 'unsafe-inline' 'unsafe-eval'">
<meta name="format-detection" content="telephone=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/jquery-2.1.3.min.js"></script>
<script type="text/javascript" src="js/index.js"></script>
<h3>Play video and img file</h3>
<img class="extSdImg" src="img/image1.png"/>
<img class="extSdImg" src="img/image2.png"/>
<p>
<a class="extSdVideo" href="video/video1.mp4">Play video</a>
</p>
<p>
<a class="extSdVideo" href="video/video2.mp4">Play video</a>
</p>
</body>
</html>
Add to Index.js
function authorizerequestExtSD() {
cordova.plugins.diagnostic.requestExternalStorageAuthorization(function(status){
console.log("Successfully requested external storage authorization: authorization was " + status);
checkState();
getSdRefAndEmbed();
}, function(error){
console.error(error);
});
}
function getSdRefAndEmbed(){
cordova.plugins.diagnostic.getExternalSdCardDetails(function(details){
details.forEach(function(detail){
if(detail.type === "root"){
cordova.file.externalSdCardRoot = detail.filePath;
embedMedia();
}
});
}, function(error){
console.error(error);
});
}
function embedMedia(){
$('.extSdImg').each(function(){
$(this).attr('src', cordova.file.externalSdCardRoot + $(this).attr('src'));
});
$('.extSdVideo').each(function(){
$(this).attr('href', cordova.file.externalSdCardRoot + $(this).attr('href'));
});
}
$(document).on('deviceready', authorizerequestExtSD);
$(document).on('pageinit', embedMedia);
Add local file copy of jQuery (found one in this project https://github.com/dpa99c/cordova-diagnostic-plugin-example):
jquery-2.1.3.min.js
Your approach is not going to work: cdvfile:// is an internal pseudo-protocol defined by cordova where the first part of the path defines an internal reference point (cdvfile://localhost/persistent|temporary|another-fs-root*/path/to/file) whereas 2B and 2C are defining paths as if relative to the root of the external SD card root.
Note that cordova-plugin-media will not help you, since it's only for playing audio and does not itself resolve file locations.
If your media files are on an external removable SD card (e.g. in Samsung Galaxy devices), cordova-plugin-file does not provide a reference to access this location. The "external" references used by cordova-plugin-file (e.g. cordova.file.externalRootDirectory) actually point to an internal memory location - /scard/. This is because not all devices have removable external SD cards (e.g. Google Nexus) so /sdcard is an "emulated" storage location which is guaranteed to exist on all Android devices.
If you wish to read files from the external removable SD card, you can do so using cordova-diagnostic-plugin to obtain a valid filepath reference to the external SD card root. Note that this will need to by done dynamically in JS as opposed to hardcoding static paths in HTML:
index.html
<body>
<img class="extSdImg" src="img/image1.png"/>
<img class="extSdImg" src="img/image2.png"/>
<p><a class="extSdVideo" href="video/video1.mp4">Play video</a></p>
<p><a class="extSdVideo" href="video/video2.mp4">Play video</a></p>
</body>
index.js
function getSdRefAndEmbed(){
cordova.plugins.diagnostic.getExternalSdCardDetails(function(details){
details.forEach(function(detail){
if(detail.type === "root"){
cordova.file.externalSdCardRoot = detail.filePath;
embedMedia();
}
});
}, function(error){
console.error(error);
});
}
function embedMedia(){
$('.extSdImg').each(function(){
$(this).attr('src', cordova.file.externalSdCardRoot + $(this).attr('src'));
});
$('.extSdVideo').each(function(){
$(this).attr('href', cordova.file.externalSdCardRoot + $(this).attr('href'));
});
}
$(document).on('deviceready', getSdRefAndEmbed);
$(document).on('pageinit', embedMedia);
I have a fiori app that has an embedded IFRAME that makes XMLHttpRequest. The IFRAME src is pointing to "https://myserver:port/some/path/iframe.html" and the request within the page is made to the same server - "https://myserver:port/some/path/request_uri" (POST request).
This works fine in desktop/mobile browser and Fiori app for iOS but it fails for Android app with "404 Not Found (from cache)". I'm not sure why it load the page fine (https://myserver:port/some/path/iframe.html) but fails the request.
Some research seems to indicate that this is caused by Cordova and that I need to add the cordova plugin whitelist - GitHub - apache/cordova-plugin-whitelist: Mirror of Apache Cordova plugin whitelist.
It looks like the request should work fine with the following in the config.xml
<access origin="*" />
But it's not working. I've even tried adding very loosely configured CSP meta tag in the iframe page as well as the LaunchPad page:
<meta http-equiv="Content-Security-Policy" content="default-src *; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">
But the request still seems to be blocked and returns "404 Not Found (from cache)".
Does any one have any idea how to fix this issue?
You could perhaps try adding allow-navigation to the config.xml.
<allow-navigation href="myserver:port/*/*" />
https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-whitelist/
You might also try using the the logcat tool for Android. It might be possible to pinpoint the problem using it.
When I run my application either in the Android emulator or on my Android device, I get he following error on all AJAX requests:
Failed to load resource: the server responded with a status of 404 (Not Found)
I have tried all the following steps to solve this problem, but it persists.
Installed the whitelist plugin to the project using npm.
Added <plugin name="cordova-plugin-whitelist" version="1" /> to
config.xml.
Added <uses-permission android:name="android.permission.INTERNET" />
to platforms\android\AndroidManifest.xml.
Added <meta http-equiv="Content-Security-Policy" content="default-src * 'unsafe-inline';"> and <meta http-equiv="X-XSS-Protection" content="0"> to the <head> of www/index.html file.
Added <access origin="*" />, <allow-navigation href="*" /> and
<allow-intent href="*" /> to the config.xml file.
Regardless I still get the same errors. Any ideas?
The project compiles fine. I'm on Windows 7, using Cordova 5.4.0, Android 5.1.1
Removing the whole Android part of the application with:
cordova platform remove android
and adding it again with:
cordova platform add android
solved the problem, which is still a mystery to me.
Perhaps there was something wrong left from the earlier versions of Cordova that wasn't getting on well with the current Cordova version.
I think the problem's with your Content Security Policy meta tag - try adding * to the default-src to open up Ajax requests to anywhere. You could also add a connect-src clause specifically for Ajax requests and list the hosts and protocols you want to be able to access. For example:
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; connect-src http://myhost.mydomain.com">
Would allow Ajax requests to http://myhost.mydomain.com
I wrote a blog post addressing this topic that you may find helpful, it can be read here.
Update Android
cordova platform update android#5.1.1
I had the problem for me connect to a php page on my server and I made an update to android
I recently upgraded to Cordova 5.0 (and Cordova Android 4.0) and, since then, my app can no longer access external resources.
I still have <access origin="*" /> in config.xml (as before), and I still have <uses-permission android:name="android.permission.INTERNET" /> in AndroidManifest.xml (as before), but ajax calls are rejected with no explanation (the "textStatus" param is "error", the "errorThrown" param is null, and xhr.state() returns "rejected").
I've verified that no request is hitting the server, so it appears it is being stopped by Android, but the log doesn't give any explanation as to why...
I can access the URL in question fine from the Android browser, just not from the app.
The ajax request is made via a call to Backbone.sync() of Backbone.js, which ultimately calls jquery's $.ajax(). I haven't changed anything about how the call is made... just upgraded cordova.
Are there new requirements/setup for network requests, in Cordova 5.0, or anything I need to do differently from previous Cordova versions?
Does anyone know of a way I can get more information as to why Android and/or Cordova is rejecting the request?
I tracked the culprit down to the android#4.0.0 cordova platform. It now requires the new cordova-plugin-whitelist plugin.
It can be installed with
cordova plugin add cordova-plugin-whitelist
or by adding
<plugin name="cordova-plugin-whitelist" spec="1" />
to config.xml, and then it is configured with
<allow-navigation href="*" />
in place of the old, <access origin="*" /> tag.
It's a little annoying that the log doesn't spit out the "whitelist rejection" error messages anymore when a problem like this comes up (that would have saved me a ton a time), but maybe that'll come later.
In Cordova 6.X you need to remove the builtin whitelist plugin and reinstall the new version of plugin.
cordova plugin remove cordova-plugin-whitelist
and re install the plugin
cordova plugin add cordova-plugin-whitelist
and then replace <allow-navigation href="*" /> to config.xml file instead of <access origin="*" />
in my case this trick worked.
Two things
Ensure the ajax url you are using allows cross origin requests
Are you passing relevant headers while making cross origin requests
To Read
http://enable-cors.org/
How to enable CORS in AngularJs
http://backbonetutorials.com/cross-domain-sessions/
if you are using cordova 6.x.x u need to uninstall builtin cordova-plugin-whitelist using
cordova plugin remove cordova-plugin-whitelist
and reinstall it by using
cordova plugin add cordova-plugin-whitelist
even if the issue persists relaunch command prompt and try it.
For me it started working after I removed from html file mata tag:
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
I'm using Cordova for create an App in Android and iOS, in iOS I did not have any problem, and the app is now in the App Store.
I have some questions for Android, because I am desperate...
I created the Project using cordova platform add android, and the project created fine. I can load and compile, and all works fine, except the plugins... I have added the plugins correctly and works fine in iOS using the command cordova plugins add org.cordova...
Can someone tell me how I need to use the plugins in Android? Do I need include any .js (of course Cordova.js is include, but I don't know how exactly is my project using it, like a charm...).
I just can see an error in LogCat that say:
error adding plugin org.apache.cordova.inappbrowse
The app works, but the alerts is showing the typical alert of a browser and the links is open inside my App, I use it with this code:
$('a[target=_blank]').on('click', function(e) {
e.preventDefault();
window.open($(this).attr('href'), '_system');
return false;
});
And for the notifications:
navigator.notification.alert("Hello!", null, "Title", "Close");
Can someone show me a way to solve the problem? An example?
Just for information... I have tried this very simple example (Link) in a new separate project and App and I have the some error... Maybe the error is in the Config.xml? How I need to use it for Android?
Thank you so much!!
Run it and watch console. If you get a "Refused to execute inline event handler" type message then add 'unsafe-inline' to your default source in the content security policy of your config.xml file.
<meta http-equiv="Content-Security-Policy" content="default-src 'self'
data: gap: https://ssl.gstatic.com 'unsafe-inline'
'unsafe-eval'; style-src 'self'; media-src *;">
Details on the policies are available at https://developer.chrome.com/extensions/contentSecurityPolicy .
Hope this helps. Healy in Tampa.
Uninstall all plugins and reinstalling them again solved my problem.