ngCordova cdvfile URLs and ng-src not rendering image - android

I've been struggling with this for days now. I have an Ionic 1.3.0 application using ngCordova#0.1.26-alpha
I am using $cordovaFile.writeFile() to store images in cordova.file.applicationStorageDirectory. I've tried every storage location with the same result. The file is good, I can view it in a file manager app. I would like to use the file as an ng-src for an <img>. On Android, this might look something like: cdvfile://localhost/sdcard/Android/data/com.example.mobile/img-49444.jpg
So in my page, I bind the URL to the <img> and stick a sanity check <pre> in there to see that record.image_url has a valid URL:
<img ng-src="{{record.image_url}}">
<pre>{{record.image_url}}</pre>
While the URL looks good to me, the image simply doesn't render and it seems no amount of effort will convince it. I've tried file:///, cdvfile://, and http:// URLs, using entry.toURL(), entry.toInternalURL(), etc., from the response objects from $cordovaFile.writeFile(). All approaches fail with either a broken image icon or an empty <img> element rendering.
I've tried adding this CSP tag to index.html (and dozens of other attempts)
<meta http-equiv="Content-Security-Policy" content="img-src 'self' data: blob: filesystem: cdvfile://*;">
And I've tried messing around with $compileProvider, like:
$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|cdvfile):|data:image\//);
And throwing everything I can at config.xml Cordova whitelists
<plugin name="cordova-plugin-whitelist" spec="~1.2.1">
<access origin="*"/>
<access origin="cdvfile://*"/>
<access origin="file://*"/>
<access origin="file:///*"/>
<allow-intent href="cdvfile://*"/>
<allow-intent href="file://*"/>
<allow-intent href="file:///*"/>
<allow-navigation href="cdvfile://*"/>
<allow-navigation href="file://*"/>
<allow-navigation href="file:///*"/>
</plugin>
Nothing works. I don't think this is a white list plugin issue - my assumption is that when the image is rejected due to the white list, the image is displayed as a broken link, whereas the <img> element is instead empty and takes up no space when the white list is not rejecting it. This behavior is consistent on Android 4.4.4 and 6.0.1.
Any help would be greatly appreciated.

So as to not mislead others that come across this answer, I managed to get cdvfile:// URLs to work even in livereload mode without issue in a new app. Simply:
config.xml
<access origin="*"/>
<access origin="tel:*" launch-external="yes"/>
<access origin="geo:*" launch-external="yes"/>
<access origin="mailto:*" launch-external="yes"/>
<access origin="sms:*" launch-external="yes"/>
<access origin="market:*" launch-external="yes"/>
<access origin="cdvfile:*"/>
<plugin name="cordova-plugin-whitelist" spec="~1.2.2"/>
Note that <access> rules are NOT supposed to be nested under <plugin>. The documentation doesn't explicitly call that out.
app.js
.config(function ($stateProvider, $urlRouterProvider, $compileProvider) {
$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|file|blob|cdvfile|content|tel|geo|mailto|sms|market):|data:image\//);
I do not have a Content-Security-Policy meta tag declared in index.html
And all is well.

So it turns out I can use file:///* paths for ng-src if I deploy the built .apk to the device instead of using the Ionic livereload server (ionic run android -cls). It should be obvious that hardware-level functions won't work through something like the browser-based ionic serve, but it was less obvious that testing on actual hardware would fail like this based on the livereload server. I incorrectly assumed that the livereload server was just a file monitoring approach where it would stream assets onto the device as they change and maybe notify the app to reload. Instead it seems they are just hosting a web server directly on your host. $cordovaFile correctly reads/write files on the device even in livereload, but the web views in the app don't have native access to the files on the device in that mode. I could read the file contents with $cordovaFile.readAsText() and that would still work even on livereload, but when it comes to the web views in the app reaching files, well, it just doesn't have any access to native device URLs.
If anyone else runs into this issue, here's how I'm writing the file and capturing the URL so that it works in a view.
$ionicPlatform.ready(function () {
var targetDir = cordova.file.externalApplicationStorageDirectory + "files/";
$cordovaFile.writeFile(targetDir, name, imageData, true)
.then(function (info) {
console.log("File created", info.target.localURL, JSON.stringify(info));
$cordovaFile.checkFile(targetDir, name).then(function (entry) {
console.log("Got file entry", entry.toURL());
q.resolve(entry.toURL());
});
}, function (e) {
q.reject(e);
});
});
return q.promise;
}
On android this would return a URL like:
file:///storage/emulated/0/Android/data/com.example/files/<name>
I've found that cordova-plugin-whitelist can be empty in config.xml - we don't need any whitelist directives for file:///. Also, no $compileProvider.imgSrcSanitizationWhitelist() changes are necessary - the default whitelist should work.
I never did get cdvfile:// URLs to work, regardless of whitelist settings, Content-Security-Policy directives, or app.config tweaks.

Related

Cordova Android 10 - Trouble to assign the root path

As breautek wonderfully explain here , with Android 10 Platform (the mximum platform available at the moment on Cordova and the minimum platform required to publish on playstore) "XHR not CORS request" and "file://" not working if I don't set on my config.xml
<preference name="hostname" value="localhost" />
<preference name="AndroidInsecureFileModeEnabled" value="true" />
I'm pretty sure that this solution is useful... but temporary. I'm sure the PlayStore will impose a new restriction shortly and this solution will be in vain.
So I decided to not use them and carry on... I have solved my problem about XHR CORS request but I have no solution about how to set the root path... for example to assign it an image path
At the moment I get it as:
var urlRootMobile=cordova.file.applicationDirectory+'www/';
var img1 = urlRootMobile."/img/1.png";
var img2 = urlRootMobile."/img/2.png";
var img3 = urlRootMobile."/img/3.png";
Obviously don't work on my app because the path is : " file:///android_asset/www/img/1.png"
I tried to use "https://localhost/www"
I tried to use "https://localhost"
I tried to use "/"
But nothing...
I there some other command or trick ???
You need to use cordova-plugin-file to read these files.
If you just need to read images from www then the path is simply '/img/1.png'

Google map is showing on browser but not in real device android

I am new to ionic platform. I am trying to implement Google map in my app.Map is displaying when I am testing on browser but when running on real device on Android it is just displaying white screen. I have tried different number of things as recommended in different threads. I have applied changes in config file as mentioned in below link
https://github.com/driftyco/ionic-starter-maps/issues/10
but no luck and have applied changes using different number of meta tags individually as describes in other threads but no luck. In console I can see the error as 'Uncaught ReferenceError: google is not defined'. For this I have tried different thread as mentioned below
Uncaught ReferenceError: google is not defined
but still getting the same error. I am not able to figure this error out.What else I am missing below is the code I am sharing used in my app.Index page code is
This is my controller code
.controller('MapCtrl', function($scope, $ionicLoading) {
google.maps.event.addDomListener(window, 'load', function() {
var myLatlng = new google.maps.LatLng(37.3000, -120.4833);
var mapOptions = {
center: myLatlng,
zoom: 16,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var myDiv=document.getElementById("map");
var map = new google.maps.Map(myDiv, mapOptions);
});
})
and below are the lines I have added in config file as recommended in different threads
<access origin="*"/>
<access origin="http://maps.google.com"/>
<access origin="https://maps.google.com"/>
<access origin="http://*.googleapis.com"/>
<access origin="https://*.googleapis.com"/>
Any help
It seems that you haven't well imported Google Maps in the file index.html.
The issue is the line :
<script src="//maps.google.com/maps/api/..."></script>
On a browser it will load this script : http://maps.google.com/maps/api/... since you are serving the file through http.
But on a device, you are serving the file through file:// so it will try to load this script : file://maps.google.com/maps/api/...
That is not available.
So you need to specify https like this :
<script src="https://maps.google.com/maps/api/..."></script>

jquery mobile loader not working on android

I am developing an hybrid application for android and iOS. This is not my first app, but I don't consider myself an expert either. At the moment I'm targeting Android 4.4 or later. For iOS I got an iPhone 4S to test, not supporting anything below iOS 9.2. To make this app I'm currently using Phonegap Build, which outputs version=cli-5.2.0 and using jQuery Mobile 1.4.5 as the framework to handle the UI, navigation and so on. The Javascript is being loaded locally - from the device.
Considering some server interaction takes some time to load, I was thinking to show a loading gif while the server interaction processes. For this matter I'm using a loader widget from jQuery Mobile. The code for the ajax request calls has the following code:
$.serviceCall = function(web_method, web_root, params){
var ajax_response;
var request_url = 'http:/some.url.com/' + web_root + '/' + web_method;
$.mobile.loading( "show", {
text: "loading",
textVisible: false,
theme: "z",
html: ""
});
$.ajax({
type: 'get',
contentType: 'application/json; charset=utf-8',
async: false,
dataType: 'json',
url: request_url,
data: params,
}).done(function(data){
ajax_response = data
ajax_response.callback = 'done';
$.mobile.loading("hide");
}).fail(function(jqXHR, textStatus, errorThrown){
var failure_details = {
status: jqXHR.status,
text_status: textStatus,
error_thrown: errorThrown
};
ajax_response = failure_details;
ajax_response.callback = 'fail';
$.mobile.loading("hide");
});
return ajax_response;
};
Which works perfectly fine when accessing from a desktop browser or from ripple emulator to simulate the actual device.Once the request starts, the loader shows, hides as soon as the request ends and makes the page transition.
However, on android doesn't work. Whenever the request starts the loader doesn't show up no matter how long the request takes. Is there any trick for mobile OS that I need to apply in order to make it work?
check this guide on how to inspect the App.
I suggest taking out $.mobile.loading("hide"); so you can keep the loader running to see whats happening. might be a z-index issue or an error in the console
You have made a common mistake. You need to apply the whitelist system. It is required as of Cordova Tools 5.0.0 (April 21, 2015). For Phonegap Build, that means since cli-5.1.1 (16 Jun 2015)
Add this to your config.xml
<plugin name="cordova-plugin-whitelist" source="npm" spec="1.1.0" />
<allow-navigation href="*" />
<allow-intent href="*" />
<access origin="*" /> <!-- Required for iOS9 -->
NOTE YOUR APP IS NOW INSECURE. IT IS UP TO YOU TO SECURE YOUR APP.
Add the following to your index.html
<meta http-equiv="Content-Security-Policy"
content="default-src *;
style-src * 'self' 'unsafe-inline' 'unsafe-eval';
script-src * 'self' 'unsafe-inline' 'unsafe-eval';">
This whitelist worksheet should help.
HOW TO apply the Cordova/Phonegap the whitelist system
If it is not this, then there may be a JQuery Mobile setting which I may not be familiar with.

PhoneGap and WhatsApp

I hope you'll can help me to find an issue to my problem.
I'm developping an application who should use WhatsApp. This application is using HTML5, CSS3 and Javascript. I am using this link to send an message with WhatsApp :
<a href="whatsapp://send?text=Test 1">
This link work perfectly when you use directly a browser but when I use PhoneGap I have a error like this :
net::ERR_UNKNOWN_URL_SCHEME
I have tested some issues but doesn't work. I have also checked the Documentation but nothing...
Can you help me please ?
Thanks
EDIT
Here is the solution to my problem (thanks to #jcesarmobile):
<access origin="whatsapp:*" launch-external="yes" />
Many thanks :)
Edit for newer cordova versions:
Use <allow-intent href="whatsapp:*" />
Old answer:
Add this line to your config.xml
<access origin="whatsapp:*" launch-external="yes" />
Or use the social sharing plugin
https://github.com/EddyVerbruggen/SocialSharing-PhoneGap-Plugin
<button onclick="window.plugins.socialsharing.shareViaWhatsApp('Message via WhatsApp', null /* img */, null /* url */, function() {console.log('share ok')}, function(errormsg){alert(errormsg)})">msg via WhatsApp (with errcallback)</button>
First and more important, add this line to your config.xml
<allow-intent href="whatsapp:*" />
after use the code:
Hello, world!
window.location.href = 'whatsapp://send?text=hello world';
this worked for phonegap IOS
window.open("'whatsapp://send?text=hello world'", "_system");
for android.

$.get not working with phonegap cordovaExample

I have a problem with phonegap and $.get (jQuery). It's actually only a webapp which exists already but I want to bring it on my Android Smartphone.
So my $.get is working and I have this settings:
In res/xml/config.xml:
<access origin="*"/>
In AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
But it's not working :(
Edit 1 (17.11.2013 15:23):
alert("getData: "+searchTerm+" in "+language);
$.get("http://mysite.de/search.php", {art: searchTerm, lang: language}).done(function(data){
alert("daten: "+data);
}, "html");
alert("ready");
Only the first and the third alert is working.
The problem is
XMLHttpRequest cannot load http://mysite.de/search.php. Origin http://localhost is not allowed by Access-Control-Allow-Origin.
You need to allow access to http://mysite.de/search.php from any domain
Allow it by adding code to your php page:
header("Access-Control-Allow-Origin: *");

Categories

Resources