Show PDF downloaded from API in Ionic / Angular - android

I need to hit an API endpoint, which returns a pdf file (not a url to a pdf, but the actual data), then somehow display this pdf in my ionic application. Ideally, I'd like to just give it to some other application like the phone's mobile web browser but I'd be open to trying to embed it within my app as well. On iOS, I just use $window.open(url) and mobile safari knows to download and display the pdf that is returned. However, Android tries to download the file then tells me that it can't be opened when I try to open it.
I've also tried embedding it in the app with <embed> but nothing gets embedded. However, a similar method works with images in <img ng-src="url">.
I've also tried messing around with cordova FileOpener2 but am having a lot of trouble getting anything to work in that. If that's the right way to do this, I'd be open to re-visiting that method.
The closest I've gotten is definitely just sending it to the devices mobile browser as that works perfectly on iOS.

I solved it using filetransfer and fileopener2. My code is below. The main issues I ran into was not having <access origin="cdvfile://*" /> in my config.xml file and not having ngCordova installed correctly.
if (ionic.Platform.isIOS())
$window.open(APIUrl, '_blank', 'location=no');
else if (ionic.Platform.isAndroid()) {
var fileExtension = filename.substr(filename.lastIndexOf('.')+1);
//I have a dictionary with this somewhere else
var MIMEType = extToMime[fileExtension];
var uri = encodeURI(APIurl);
var fileURL = "cdvfile://localhost/persistent/file."+fileExtension;
$cordovaFileTransfer.download(uri, fileURL, {}, true)
.then(function(result) {
$cordovaFileOpener2.open(
fileURL,
MIMEType
).then(function() {
console.log("SUCCESS");
}, function(e) {
console.log("ERROR");
console.log(JSON.stringify(e));
});
}, function(e) {
console.log("Error: " + JSON.stringify(e));
});
}

Related

Download Word .docx as Blob file from Angular on mobile devices

I am trying to download .docx file from REST API (.NET Core FileContentResult) in Angular application. Everything is working fine on PC, but there is problem with downloading .docx files in VMware Workspace ONE Web browser (didn't try standard browsers like Chrome or Safari, it looks like there is just Android WebView). It is company application and this browser is the only one allowed.
The problem is only with .docx files. Files like PDF, .doc and .xlsx (created by ClosedXML) are working fine.
REST API call (also tried with 'arraybuffer' instead of 'blob' and created Blob object in client, but problem persists)
this.httpClient.get(requestUrl, {
responseType: 'blob',
observe: 'response'
});
Then I save response body with FileSaver.
generateDocument(file: string | Blob, name: string): void {
FileSaver.saveAs(file, name);
}
I also tried approach that creates link and click on it (it does not work).
Solution with using window.open(blobUrl) is not working.
EDIT:
I got information that it is not working at all in iOS with same browser. Users get error message "Link is invalid."
Can someone help me with this issue? Thanks.
If you can retrieve obtain an ArrayBuffer, this could be used to initiate the download with those bytes:
Test here: https://batman.dev/static/70085191/
async function downloadUrl(url) {
downloadBuffer(
await (await fetch(url)).arrayBuffer()
)
}
function downloadBuffer(arrayBuffer) {
const a = document.createElement('a')
a.href = URL.createObjectURL(new Blob(
[ arrayBuffer ],
{ type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }
))
a.download = 'my-file.docx'
a.click()
}

Cordova - Continously taking and uploading pictures

I'm doing a bit of feasability R&D on a project I've been thinking about, the problem is that I'm unfamiliar with the limitations of the Camera API or the OS itself.
I want to write a cordova app which when opened (and authorized), will take a picture every nth second and upload it to a FTP site. Consider it something like a CCTV function, where my site will continuously render the latest image to the user.
Some pseudo code:
while (true) {
var img = api.takePicture(args);
uploadImage(img);
thread.sleep(1000);
}
So my question is, can I access the camera and instruct it to take a picture without user intervention (again, after camera access is authorized)?
Examples or direction for any API call to accomplish it would be really appreciated. I saw this article, and the answer looks promising, but the OP has android and I'd to know if it behaves the same on iOS.
On a side note, how do I test my cordova application on my iPhone without buying an app store license? I only want to run it on my own device.
Solved using CameraPictureBackground plugin:
function success(imgurl) { console.log("Imgurl = " + imgurl); //here I added my function to upload the saved pictures //on my internet server using file-tranfer plugin }
function onFail(message) {
alert('Failed because: ' + message); }
function CaptureBCK() {
var options = {
name: "Image", //image suffix
dirName: "CameraPictureBackground", //foldername
orientation: "portrait", //or landscape
type: "back" //or front
};
window.plugins.CameraPictureBackground.takePicture(success, onFail, options); }
<button onclick="CaptureBCK();">Capture Photo</button> <br>
You will find your pictures under CameraPictureBackground directory in your device acrhive. I used also file-transfer plugin in order to directly upload the pictures on my server over the internet.

Hybrid app with remote html and local cordova.js

I have a website that I want to enhance on mobiles with a hybrid app. Ideally the app would load the remote site over http but load the platform specific code locally. I've tried to set up a Cordova project to do this but am having lots of trouble. Cordova 4.3.1, Cordova Android 3.7.2 on a Nexus 7 Android 4.4.4 has been my environment. (The google maps plugin is for Cordova Android < 4.)
If I try to load file:///android_assets/www/cordova.js from an http site, chromium says Not allowed to load local resource. I tried to set up a local URL scheme but don't know what android-specific code to put where.
Is this the right way to make a hybrid app? Is there a cordova plugin to allow loading file: from http:?
I also tried using an iframe and passing messages to indicate cordova is enabled and which plugins are installed, but I don't want to deal with having the http server re-serve the same js files that are already available locally.
I also thought to download the website and access it over file: but I imagine I will have the same problem trying to access http resources.
I am able to load local cordova.js on remote html using cordova-plugin-file (cdvfile://) plugin .
Add cordova-plugin-file plugin to your cordova project
https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/
Confirm cdvfile URI for cordova.js using below sample code(Android example)
checkCordovaJSPath('file:///android_asset/www/cordova.js');
function checkCordovaJSPath(jsUri) {
window.resolveLocalFileSystemURL(jsUri, function success(fileEntry){
console.log("got cordova.js file: " + fileEntry.fullPath);
console.log('cordova.js cdvfile URI: ' + fileEntry.toInternalURL());
});
}
Load cordova.js using cdvfile://localhost on remote html.
<script type="text/javascript" src="cdvfile://localhost/assets/www/cordova.js"/>
I don't know if this is the right way to make a hybrid app, but I got it working by serving assets over http with https://github.com/floatinghotpot/cordova-httpd .
On the local page bundled with the app I have added:
<script type="text/javascript">
document.addEventListener("deviceready", function () {
var httpd = cordova.plugins.CorHttpd;
httpd.startServer({
'www_root': '',
'port': 8080,
'localhost_only': false
}, function (url) {
// if server is up, it will return the url of http://<server ip>:port/
// the ip is the active network connection
// if no wifi or no cell, "127.0.0.1" will be returned.
document.getElementById('url').innerHTML = "server is started: <a href='" + url + "' target='_blank'>" + url + "</a>";
location.replace('http://192.168.0.134:9090/homechooser/beta/#' + JSON.stringify({'cordova.js': url + '/cordova.js'}));
}, function (error) {
document.getElementById('url').innerHTML = 'failed to start server: ' + error;
});
}, false);
</script>
<div id="url"></div>
Then on the remote webpage I have added:
(function () {
var hash;
if (location && location.hash)
try {
hash = JSON.parse(location.hash.substring(1));
} catch (e) {
}
if (hash && hash['cordova.js'])
$.getScript(hash['cordova.js'], function () {
alert("Running cordova.js");
});
})();
now to see if cordova can actually be used this way...
The cdvfile solution will not work for active content (js files) because of the mixed content policy. Here is how to make it work:
For android: Disable mixed content policy by putting the following code inside the pluginInitialize method of your cordova plugin:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
final WebSettings settings = ((WebView)this.webView.getView()).getSettings();
settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
https://developer.android.com/reference/android/webkit/WebSettings.html#MIXED_CONTENT_ALWAYS_ALLOW)
Then include local cordova.js using:
<script src="cdvfile://localhost/assets/www/cordova.js"></script>
For ios: I submitted a PR to the file plugin which solves the mixed content problem on ios: apache/cordova-plugin-file#296 The fixed version is available at: https://github.com/guylando/cordova-plugin-file If you load a remote site https://example.com on the webview then it allows to access local files using the url: https://example.com/cdvfile/bundle/www/cordova.js instead of cdvfile://localhost/bundle/www/cordova.js And by this solves the mixed content problems
Include local cordova.js using:
<script src="/cdvfile/bundle/www/cordova.js"></script>
Thing is your are trying to load a web-url on the local hosted app, imagine doing the same thing on Native Android App, what would you do? you will place a web-client or a web-browser in your app. But Cordova/Phonegap already uses Web-Browser to render your pages. So its like a using web-browser inside a web browser.
You need to install InAppBrowser which will give you the ability to load 3rd party hosted web pages.
Sample Code
document.addEventListener("deviceready", onDeviceReady, false);
// device APIs are available
//
function onDeviceReady() {
var ref = window.open('http://yourWebPage.com', '_blank', 'location=yes');
ref.addEventListener('loadstart', function(event) { alert('start: ' + event.url); });
ref.addEventListener('loadstop', function(event) { alert('stop: ' + event.url); });
ref.addEventListener('loaderror', function(event) { alert('error: ' + event.message); });
ref.addEventListener('exit', function(event) { alert(event.type); });
}

Best way to display a Images and Doc files from base64-string - Android and Blackberry

I am trying to display image,docs from base64-string for Android and IOS. I am using inapp browser plugin to display image and doc files in app.
For IOS i am able to display images using below code.But facing issue with Android and Blackberry.
window.open(urlData, "_blank", "location=no,enableviewportscale=yes");
I am passing urlData parameter as base-64 string. Android and Blackberry nothing is displaying. After searching i found this post.
Alternative: just store that whole data string in your database. Then when you render your tag you can simply dump it into the src
attribute:>" />
After inserting above code i am able to display image but how to close the image ? How to open image in popup ? So user can close the image.
Thanks
First, window.open probably isn't working because all URLs have to be granted access specifically, for security. You can try to bypass it with this in your config.xml -- I don't know if it will work for data: URLs.
<access origin="*" subdomains="true"/>
<preference name="WebSecurity" value="disable"/>
If this doesn't work, how to show an image in a pop-up comes down to the design of your app. If you're using something like Ionic Framework, Bootstrap, jQueryUI, or Ratchet, they each have components for Modals or Dialogs you could potentially use. If you're not using a UI framework, you'll have to design your own pop-up div to contain the image tag, that is hidden again when you tap or dismiss it. Finding information on Google about how to do this is not very hard.
Good luck!
I am able to solve this issue in BlackBerry using below steps.
1)Remove webWorks.js from index.html
2)Replace below script inside index.html
<script src="worklight/cordova.js"></script> to <script src="../../cordova.js"></script>
3) Add below code inside js file. Need to pass urlData as Base64 string and filename.
requestFileSystem(LocalFileSystem.PERSISTENT, 7 * 1024 * 1024, function (fs) {
var ft = new FileTransfer(),
localPath = fs.root.toURL() + fileName;
ft.download(urlData, localPath, function (entry) {
entry.file(function (file) { console.log(file.size); });
window.open(localPath, "_blank", "location=yes,closebuttoncaption=Close,enableViewportScale=yes");
}, function (e) { console.log('download error'); console.log(e); });
});

Using PhoneGap, can't load local .html file using Ajax on Android only

I'm using PhoneGap (latest), Jquery 1.7. I'm having troubles getting some html loaded via AJAX into a div. My problem is simple, I have an index.html file in the www/ directory. And a js file that does this:
$.ajax({
type:"GET",
timeout:10000,
dataType: "html",
async: false,
cache: false,
url: "file:///android_asset/www/_liqui-cult.html",
success: function(data) {
$('#data_details .description').html(data); // never runs
},
error: function(xhr,msg){
alert(xhr.status + ", " + msg);
if(xhr.status == 0 || xhr.status == "0"){
alert(xhr.responseText); // always blank, if runs
}
}
});
Having spent the day Googling this error, I've tried numerous things, but the AJAX call never succeeds. I've tried changing the url to simply, _liqui-cult.html (without the file:// -based url). I've also tried /_liqui-cult.html.
I started out trying with the JQuery $.load, and that wasn't working, so I switched to the more verbose $.ajax call.
No matter what I do, I either get a 404 as the status, or, if I change the url to http://_liqui-cult.html, I get a status of 0, but nothing in the responseText.
So, I took JQuery out of the equation, and tried a simple XMLHttpRequest, as so:
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && (xmlhttp.status==200 || xmlhttp.status==0))
{
$('#data_details .description').html(xmlhttp.responseText);
$.mobile.changePage('#screen_detail');
}
}
xmlhttp.open("GET","_liqui-cult.html", true);
xmlhttp.send(null);
Again, I've tried every conceivable url pattern to map to the html file. And still, the best I can get is xmlhttp.responseText is blank.
So how about cross-origin issues? Here is what I've tried:
<access origin=".*"/>
<access origin="file://*"/>
<access origin="*"/>
Again, I've tried all ways of mapping to the html file, with those different access origin settings, and I still cannot load the html file.
Any ideas?
Changing the name of the html file that gets AJAX-loaded from "_liqui-cult.html" to the same name without the underscore "liqui-cult.html" fixed the problem.
Seems something else is wrong in your project. The following gist have some of the files from my test application and it works without any issue in Android.
https://gist.github.com/2873186

Categories

Resources