Pdf make not creating pdf using File Plugin on android device. But able to create and download on web.
global packages:
Cordova CLI : 7.1.0
local packages:
#ionic/app-scripts : 2.1.4
Cordova Platforms : android 6.3.0
Ionic Framework : ionic-angular 3.6.0
packages.json
"#ionic-native/file": "^4.20.0",
"#ionic-native/file-opener": "^5.0.0"
Here is the code below
print() {
this.createPdf();
if (this.plt.is('cordova')) {
this.pdfObj.getBuffer(function (buffer) {
let utf8 = new Uint8Array(buffer);
let binaryArray = utf8.buffer;
var filename = this.formname + new Date().toDateString();
this.file.writeFile(this.file.documentsDirectory, filename+'.pdf', binaryArray, { replace: true }).then(fileEntry => {
const toast = this.toastCtrl.create({
message: 'File saved to your device',
duration: 3000,
position: 'top'
});
toast.present();
this.fileOpener.open(this.file.documentsDirectory + filename+'.pdf', 'application/pdf');
})
});
} else {
this.pdfObj.download();
}
}
createPdf() {
for (let item of this.columns) {
this.columnRelDataForPdf.push(this.formData[item.columnDef])
}
console.log("Inside create pdf");
console.log(this.columnDataForPdf);
console.log(this.columnRelDataForPdf);
var bodyData = [];
var dataRowHeader = [];
dataRowHeader.push(this.formName)
dataRowHeader.push('')
bodyData.push(dataRowHeader);
for (let item of this.columns) {
var dataRow = [];
dataRow.push(item.header);
dataRow.push(this.formdata[item.columnDef] == undefined ? "" : this.formdata[item.columnDef]);
bodyData.push(dataRow)
}
var docDefinition = {
content: [
{
layout: 'lightHorizontalLines',
table: {
headerRows: 1,
widths: ['*', '*'],
body: bodyData
}
}
], styles: {
header: {
bold: true,
fontSize: 20,
alignment: 'right'
}
}
};
this.pdfObj = pdfMake.createPdf(docDefinition);
}
I tried externalDataDirectory and other options as well but no luck with the pdf file creation. Please let me know where am i doing wrong.
Thank you.
Do:
File.writeFile(File.externalRootDirectory, filename+'.pdf', binaryArray, { replace: true }).then(fileEntry =>
instead of:
this.file.writeFile(this.file.documentsDirectory, filename+'.pdf', binaryArray, { replace: true }).then(fileEntry =>
Related
When loading a webpage that has the stripe javascript on it the InAppWebView is just a blank page, onLoadStop reports the URI: https://m.stripe.network/inner.html?url=\*\*&title=\*\*&referrer=\*\*&muid=NA&sid=NA&version=6&preview=false
The flutter app is a simple InAppWebView that mirrors a laravel website using the cashier/stripe subscription combination. The page works in a browser and when launched using url_launcher, but this requires the user to re-login and navigate back to where they were.
Is there any way to allow this page to load in flutter_inappwebview? Or, create the card-element element without the JavaScript include (https://js.stripe.com/v3)?
JavaScript code:
<script src="https://js.stripe.com/v3/"></script> -- this is the culprit
<script>
var stripe = Stripe('{{ env('STRIPE_KEY') }}');
var elements = stripe.elements();
var style = {
base: {
color: '#32325d',
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: '#aab7c4'
}
},
invalid: {
color: '#fa755a',
iconColor: '#fa755a'
}
};
var card = elements.create('card', {
hidePostalCode: true,
style: style
});
card.mount('#card-element');
card.addEventListener('change', function(event) {
var displayError = document.getElementById('card-errors');
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
});
const cardHolderName = document.getElementById('card-holder-name');
const cardButton = document.getElementById('card-button');
const clientSecret = cardButton.dataset.secret;
cardButton.addEventListener('click', async (e) => {
console.log("attempting");
const { setupIntent, error } = await stripe.confirmCardSetup(
clientSecret, {
payment_method: {
card: card,
billing_details: { name: cardHolderName.value }
}
});
if (error) {
var errorElement = document.getElementById('card-errors');
errorElement.textContent = error.message;
} else {
paymentMethodHandler(setupIntent.payment_method);
}
});
function paymentMethodHandler(payment_method) {
var form = document.getElementById('subscribe-form');
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'payment_method');
hiddenInput.setAttribute('value', payment_method);
form.appendChild(hiddenInput);
form.submit();
}
</script>
Solved.
Stripe doesn't like custom headers, so if you add a header to the request it will block it.
I've gotten this menu to work without filtering it, but now I'm doing an ajax request to filter out menu items the user isn't supposed to see, and I'm having some trouble to figure out how to set the resulting menu data, the line that is not working is commented below:
<script>
import { ref } from 'vue';
import axios from 'axios';
var currentSelected = 'device_access';
var menuData = [
{
text: 'Device Access',
id: 'device_access',
children: [
{
text: 'Interactive',
link: '/connection_center'
},{
text: 'Reservation',
link: '/reserve_probe'
}, {
text: 'Reservation Vue',
link: '/reservation.html'
}
]
}, {
text: 'Automation',
id: 'automation',
show: ['is_mxadmin', 'can_schedule_scripts'],
children: [
{
text: 'Builder',
link: '/builder',
},{
text: 'Execution Results',
link: '/test_suite_execution_results'
},
]
}
];
function hasMatch(props, list) {
var match = false;
for (var i=0; i < list.length && !match; i++) {
match = props[list[i]];
}
return match;
}
export default {
name: 'Header',
setup() {
const cursorPosition = ref('0px');
const cursorWidth = ref('0px');
const cursorVisible = ref('visible');
//the menu is zero length until I get the data:
const menu = ref([]);
return {
menu,
cursorPosition,
cursorWidth,
cursorVisible
}
},
created() {
let that = this;
axios.get('navigation_props')
.then(function(res) {
var data = res.data;
var result = [];
menuData.forEach(function(item) {
if (!item.show || hasMatch(data, item.show)) {
var children = [];
item.children.forEach(function (child) {
if (!child.show || hasMatch(data, child.show)) {
children.push({ text: child.text, link: child.link });
}
});
if (children.length > 0) {
result.push({ text: item.text,
children: children, lengthClass: "length_" + children.length });
}
}
});
//continues after comment
this is probably the only thing wrong, I've run this in the debugger and I'm getting the
correct data:
that.$refs.menu = result;
since the menu is not being rebuilt, then this fails:
//this.restoreCursor();
})
.catch(error => {
console.log(error)
// Manage errors if found any
});
},
this.$refs is for template refs, which are not the same as the refs from setup().
And the data fetching in created() should probably be moved to onMounted() in setup(), where the axios.get() callback sets menu.value with the results:
import { onMounted, ref } from 'vue'
export default {
setup() {
const menu = ref([])
onMounted(() => {
axios.get(/*...*/).then(res => {
const results = /* massage res.data */
menu.value = results
})
})
return {
menu
}
}
}
I finally figured out the problem.
This code above will probably work with:
that.menu = result;
You don't need: that.$refs.menu
You can't do it in setup because for some reason "that" is not yet defined.
In my working code I added a new method:
methods: {
setMenuData: function() {
this.menu = filterMenu();
},
}
And "this" is properly defined inside them.
I have an ionic 3 app who shown markers on a map. But now I have a new request for the app to port it to wereable devices (Android wear and Apple watch). Show the markers in a map on the watch and some info...
After a lot of search and any questions on forums, I get a android wear plugin https://github.com/tgardner/cordova-androidwear but it is a cordova plugin.
The code in cordova is:
function watch(handle) {
var self = this;
AndroidWear.onDataReceived(handle, function(e) {
self.dataReceived(e.data);
});
self.handle = handle;
}
watch.prototype = {
dataReceived: function(data) {
app.logEvent("AndroidWear message received: " + data);
},
sendMessage: function(message) {
AndroidWear.sendData(this.handle, message);
app.logEvent("AndroidWear message sent!");
}
};
var app = {
watch: null,
initialize: function() {
this.bindEvents();
},
bindEvents: function() {
var self = this;
document.addEventListener('deviceready', function() {
self.onDeviceReady();
}, false);
},
onDeviceReady: function() {
var self = this;
self.receivedEvent('deviceready');
if(AndroidWear) {
AndroidWear.onConnect(function(e) {
self.logEvent("AndroidWear connection established");
self.watch = new watch(e.handle);
});
}
var sendButton = document.getElementById("sendMessage");
sendButton.addEventListener("click", function() {
if(self.watch) {
self.watch.sendMessage("Mensaje");
}
});
},
receivedEvent: function(id) {
var parentElement = document.getElementById(id);
var listeningElement = parentElement.querySelector('.listening');
var receivedElement = parentElement.querySelector('.received');
listeningElement.setAttribute('style', 'display:none;');
receivedElement.setAttribute('style', 'display:block;');
this.logEvent('Received Event: ' + id);
},
logEvent: function(message) {
var events = document.getElementById("events");
var el = document.createElement("li");
el.innerHTML = message;
events.appendChild(el);
}
};
But I need to translate the cordova code to ionic code.
I try that:
(<any>window).AndroidWear.onConnect(() =>{
console.log("Androidwear : CONECTADO " );
})
(<any>window).AndroidWear.onDataReceived((data) =>{
console.log("Plugin: " + data);
})
But I received an execution error like this
[INFO:CONSOLE(13355)] "Didn't set nav root: TypeError: window.AndroidWear.onConnect(...) is not a function", source: file:///android_asset/www/build/main.js (13355)
I never translate the Cordova code into ionic 3, so maybe I've had stupid mistakes.
How can I translate that code to use the android-wear plugin on ionic 3 app?
Thanks you.
I am using floatinghotpot plugin to show ads
cordova plugin add https://github.com/floatinghotpot/cordova-plugin-admob.git
This is my code for admob
$ionicPlatform.ready(function($location) {
var adMobId = {
admob_banner_key: 'ca-app-pub-3378914045953959/7363511027'
};
var options = {
interstitialAdId: 'ca-app-pub-3940256099942544/1033173712',
autoShow: true
};
var adMobPosition = {
BOTTOM_CENTER: 8
};
$scope.showBannerAd = function() {
try {
console.log('Show Banner Ad');
$cordovaAdMob.createBannerView({
adId: adMobId.admob_banner_key,
position: adMobPosition.BOTTOM_CENTER,
isTesting: true,
autoShow: true
});
} catch (e) {
alert(e);
}
}
$scope.showInterstitialAd = function(st) {
try {
console.log('Show Interstitial Ad');
$cordovaAdMob.createInterstitialView(options, function() {
admob.requestInterstitialAd({
'isTesting': true
},
function() {
admob.showAd(true);
},
function(error) {
console.log('failed to request ad ' + error);
}
);
},
function() {
console.log('failed to create Interstitial view');
});
} catch (e) {
alert("ALAS");
}
}
});
But when I call showBannerAd() using ng-init="showBannerAd()" it does not show ads and show this error message. How can I solve this problem? Am I missing anythinh important?
TypeError: Cannot read property 'AdMob' of undefined
This is the lists of installed plugins
com.google.admobsdk 6.12.2 "AdMob SDK for Android, iOS and WP8"
cordova-plugin-admob 2.10.0 "AdMob Plugin Pro"
cordova-plugin-console 1.0.2 "Console"
cordova-plugin-device 1.1.0 "Device"
cordova-plugin-extension 1.2.3 "Cordova Plugin Extension"
cordova-plugin-googleplayservices 19.0.3 "Google Play Services for Android"
cordova-plugin-inappbrowser 1.1.1 "InAppBrowser"
cordova-plugin-network-information 1.1.0 "Network Information"
cordova-plugin-splashscreen 3.0.0 "Splashscreen"
cordova-plugin-statusbar 2.0.0 "StatusBar"
cordova-plugin-whitelist 1.2.0 "Whitelist"
ionic-plugin-keyboard 1.0.8 "Keyboard"
I have created a JS File as below
var admobid = {};
// TODO: replace the following ad units with your own
if( /(android)/i.test(navigator.userAgent) ) {
//console.log("android");
admobid = { // for Android
banner: 'ca-app-pub-123123/123123',
interstitial: 'ca-app-pub-123123/123123'
};
} else if(/(ipod|iphone|ipad)/i.test(navigator.userAgent)) {
admobid = { // for iOS
banner: 'ca-app-pub-123123/123123',
interstitial: 'ca-app-pub-123123/4123123'
};
} else {
admobid = { // for Windows Phone
banner: 'ca-app-pub-123123/123123',
interstitial: 'ca-app-pub-123123/123123'
};
}
function initApp() {
if (! AdMob ) { alert( 'admob plugin not ready' ); return; }
// this will create a banner on startup
AdMob.createBanner( {
adId: admobid.banner,
position: AdMob.AD_POSITION.BOTTOM_CENTER,
isTesting: false, // TODO: remove this line when release
overlap: false,
offsetTopBar: false,
bgColor: 'black'
} );
// this will load a full screen ad on startup
AdMob.prepareInterstitial({
adId: admobid.interstitial,
isTesting: false, // TODO: remove this line when release
autoShow: false
});
}
if(( /(ipad|iphone|ipod|android|windows phone)/i.test(navigator.userAgent) )) {
document.addEventListener('deviceready', initApp, false);
} else {
initApp();
}
and included this js file into the index.html which is starter page of the application
Hope this may help you.
I have found with Apache Cordova that I have to put a setTimeout (aka sleep) and only execute my AdMob code after 1, 2 or 3 seconds.
Eg:
$ionicPlatform.ready(function($location) {
setTimeout(function()
{
var adMobId = {
admob_banner_key: 'ca-app-pub-3378914045953959/7363511027'
};
var options = {
interstitialAdId: 'ca-app-pub-3940256099942544/1033173712',
autoShow: true
};
...
...
...
etc...
}, 3000);
});
I'm using Backbone, Require and Underscore Bundled with Phonegap or Cordova.
I tried using the childbrowser plugin but it wont work. I followed the instructions here.
http://blog.digitalbackcountry.com/2012/03/installing-the-childbrowser-plugin-for-ios-with-phonegapcordova-1-5/
define([
'jquery',
'backbone',
'underscore',
'base64',
'mobile',
'const',
'child',
'text!template/login/login.tpl.html'
],function($, Backbone, _, base64, Mobile, Const, ChildBrowser, template){
var EncodeAuth = function(user,pass)
{
var _tok = user + ':' + pass;
var _hash = Base64.encode(_tok);
return "Basic "+ _hash;
}
var LoginView = Backbone.View.extend({
events:{
"click .login-btn" : "Login",
"click .connection-btn" : "OpenSite"
},
initialize: function(){
},
Login: function(){
Const.USERNAME = $("#username").val();
Const.PASSWORD = $("#password").val();
if(!Const.USERNAME || !Const.PASSWORD)
{
navigator.notification.alert("Invalid Username/Password!");
$("input").val("");
}else{
var auth = EncodeAuth(Const.USERNAME,Const.PASSWORD);
var sendAuthorization = function (xhr) {
xhr.setRequestHeader('Authorization', auth)
};
this.model.save(this.model, {
beforeSend : sendAuthorization,
success: function(model,result){
if(result.ErrorMessage === null)
{
alert(JSON.stringify(result.Message));
$("input").val("");
}
else
{
alert(JSON.stringify(result.ErrorMessage));
$("input").val("");
}
},
error: function(model,result){
alert("Remote server returned an error. Not Found");
$("input").val("");
}
});
}
},
OpenSite: function(){
window.plugins.ChildBrowser.showWebPage("http://www.google.com");
}
});
return LoginView;
});
Any ideas?