Ionic app does not work properly on android device - android

I am new to ionic 1. I have been making an app where I have used SQLite. The app runs perfectly on browser but works partially on device. There is a button that does not work. The code that contains this button is given below. The button function name is charge. Here's my code:
angular.module('app.cartCtrl', ['ngCordova'])
.controller('cartCtrl', ['$scope', '$stateParams', '$state', '$cordovaSQLite', '$ionicHistory', '$ionicPopup',// The following is the constructor function for this page's controller. See https://docs.angularjs.org/guide/controller
$stateParams.parameterName
function ($scope, $stateParams, $state, $cordovaSQLite, $ionicHistory, $ionicPopup) {
$scope.items = [];
$scope.grandTotal = 0;
$scope.receiptnumber = 0;
$scope.receiptnumber = $scope.receiptnumber + 1;
$scope.items = [];
$scope.item = {};
$scope.grandTotal = null;
var query2 = "SELECT * FROM items WHERE quantity!='' ";
console.log(query2);
$cordovaSQLite.execute(db, query2, []).then(function (res) {
if (res.rows.length > 0) {
for (var i = 0; i < res.rows.length; i++) {
$scope.items.push({
itemname: res.rows.item(i).itemname,
price: res.rows.item(i).price,
quantity: res.rows.item(i).quantity,
});
$scope.items = $scope.items;
}
} else {
console.log("No results found");
}
}, function (err) {
console.error("error=>" + err);
});
$ionicHistory.clearCache();
$ionicHistory.clearHistory();
var query = "SELECT SUM(total) FROM items";
$cordovaSQLite.execute(db, query, []).then(function (res) {
$scope.grandTotal = res.rows[0]['SUM(total)'];
//$scope.grandtotal = parseFloat(res.rows[0]['SUM(total)']);
// console.log("Grand total is" + res.rows[0]['SUM(total)']);
}, function (err) {
console.error("error=>" + err);
});
$scope.myGoBack = function () {
$state.go("menu.sales");
};
$scope.charge = function () {
$state.go('transactionsuccess');
}
}])
I am in doubt with below piece of code. Will it work on device or emulator:
res.rows[0]['SUM(total)']

Try with this updated query and check the post the log what ur getting
var query2 = "SELECT * FROM items WHERE quantity!='' ";
console.log(query2);
$cordovaSQLite.execute(db, query2, [5]).then(function (res) {
if (res.rows.length > 0) {
for (var i = 0; i < res.rows.length; i++) {
$scope.items.push({
itemname: res.rows.item(i).itemname,
price: res.rows.item(i).price,
quantity: res.rows.item(i).quantity,
});
$scope.items = $scope.items;
}
} else {
console.log("No results found");
}
}, function (err) {
console.error("error=>" + err);
});
$ionicHistory.clearCache();
$ionicHistory.clearHistory();
var query = "SELECT SUM(total) total FROM items";
$cordovaSQLite.execute(db, query, []).then(function (res) {
console.log('Result: ', res);
$scope.grandTotal = res.rows[0].total;
//$scope.grandtotal = parseFloat(res.rows[0]['SUM(total)']);
// console.log("Grand total is" + res.rows[0]['SUM(total)']);
}, function (err) {
console.error("error=>" + err);
});

Related

React native search for documents(.pdf, .doc, .xlsx) in device

I am working on an app to get all documents like .pdf .doc .docx .ppt .pptx .xls .txt .xlsx. ihave tried rn-fetch-blob and react-native-fs but there are giving only directory status.
useEffect(() => {
const fetchdocuments = async () => {
RNFetchBlob.fs.lstat(RNFetchBlob.fs.dirs.SDCardDir).then((data) => {
data.forEach(element => {
console.log(element)
});
}).catch((error) => {
console.log(error)
})
}
fetchdocuments()
},[])
I also tried this library react-native-get-music-files but it returns only the mediastore file API for android but don't know how to implement this in react-native. any help will be really appreciated.
here I have created a native module for this. code is given below
package com.dconverter;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.provider.Settings;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.facebook.react.ReactActivity;
import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeArray;
import com.facebook.react.bridge.WritableNativeMap;
import java.util.Objects;
public class CustomerMediaStore extends ReactContextBaseJavaModule implements ActivityEventListener {
private final ReactApplicationContext reactContext;
private int version = Build.VERSION.SDK_INT;
#Override
public String getName() {
return "CustomerMediaStore";
}
public CustomerMediaStore(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
reactContext.addActivityEventListener(this);
}
#ReactMethod
public void GetFiles(final Callback successCallback, final Callback errorCallback){
if(version <= 19){
getSongs( successCallback, errorCallback);
}else{
Thread bgThread = new Thread(null, new Runnable() {
#Override
public void run() {
getSongs(successCallback, errorCallback);
}
}, "asyncTask", 1024);
bgThread.start();
}
}
private void getSongs (final Callback successCallback, final Callback errorCallback) {
ContentResolver musicResolver = reactContext.getApplicationContext().getContentResolver();
Uri uri = MediaStore.Files.getContentUri("external");
try {
WritableArray jsonArray = new WritableNativeArray();
String[] projection = {
MediaStore.Files.FileColumns._ID,
MediaStore.Files.FileColumns.MIME_TYPE,
MediaStore.Files.FileColumns.DATE_ADDED,
MediaStore.Files.FileColumns.DATE_MODIFIED,
MediaStore.Files.FileColumns.DISPLAY_NAME,
MediaStore.Files.FileColumns.DATA,
MediaStore.Files.FileColumns.TITLE,
MediaStore.Files.FileColumns.SIZE,
};
String mimeType = "application/pdf";
String selection = MediaStore.Files.FileColumns.MIME_TYPE + " IN ('" + mimeType + "')"
+ " OR " + MediaStore.Files.FileColumns.MIME_TYPE + " LIKE 'application/vnd%'" // .docx , .xlsx , .pptx .xls
+ " OR " + MediaStore.Files.FileColumns.MIME_TYPE + " LIKE '%application/msword'" // .doc
+ " OR " + MediaStore.Files.FileColumns.MIME_TYPE + " LIKE 'application/mspowerpoint'" // .ppt
+ " OR " + MediaStore.Files.FileColumns.MIME_TYPE + " LIKE 'text/plain'" // .txt
// + " OR " + MediaStore.Files.FileColumns.MIME_TYPE + " LIKE '%/%'" // all type of douments audio/vidoe/ evey thing
+ " OR " + MediaStore.Files.FileColumns.MIME_TYPE + " LIKE 'application/rtf'" // wordpad
+ " OR " + MediaStore.Files.FileColumns.MIME_TYPE + " LIKE 'font/otf'" // .otf
+ " OR " + MediaStore.Files.FileColumns.MIME_TYPE + " LIKE 'application/vnd.oasis.opendocument.spreadsheet'" // .ods
+ " OR " + MediaStore.Files.FileColumns.MIME_TYPE + " LIKE 'application/vnd.oasis.opendocument.text'" // .otd
;
String orderBy = MediaStore.Files.FileColumns.DATE_ADDED;
Cursor cursor = musicResolver.query(uri, projection, selection,null,orderBy);
if (cursor != null && cursor.getCount() > 0) {
Log.e("Musica", String.valueOf(cursor.getCount()));
cursor.moveToFirst();
do {
WritableMap item = new WritableNativeMap();
item.putString("id", String.valueOf(cursor.getString(0)));
item.putString("minetype", String.valueOf(cursor.getString(1)));
item.putString("dateadded", String.valueOf(cursor.getString(2)));
item.putString("datemodified", String.valueOf(cursor.getString(3)));
item.putString("displayname", String.valueOf(cursor.getString(4)));
item.putString("uri",String.valueOf(cursor.getString(5)));
item.putString("title", String.valueOf(cursor.getString(6)));
item.putString("size", String.valueOf(cursor.getString(7)));
jsonArray.pushMap(item);
} while (cursor.moveToNext());
} else {
String msg = "cursor is either null or empty ";
Log.e("Musica", String.valueOf(cursor.getCount()));
}
cursor.close();
successCallback.invoke(jsonArray);
}catch (Exception e) {
errorCallback.invoke(e.getMessage());
Log.e("Musica", e.getMessage());
}
}
#RequiresApi(api = Build.VERSION_CODES.R)
#ReactMethod private void checkStorgePermision(Promise promise){
}
#RequiresApi(api = Build.VERSION_CODES.R)
#ReactMethod private void checkStorgaePermission(Promise promise){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
promise.resolve(Environment.isExternalStorageManager());
}
}
#ReactMethod
private void askforscopestoragepermission(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if(!Environment.isExternalStorageManager())
{
askAndroid11StoragePermission(reactContext);
}
}
}
#RequiresApi(Build.VERSION_CODES.R)
private void askAndroid11StoragePermission(Context context )
{
try {
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
intent.addCategory("android.intent.category.DEFAULT");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("data",Uri.parse(String.format("package:%s",context.getApplicationContext().getPackageName())));
getReactApplicationContext().startActivityForResult(intent,2296, null);
}
catch (Exception e){
Intent intent = new Intent();
intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getReactApplicationContext().startActivityForResult(intent,2296, null);
}
}
// #Override
// protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
// super.onActivityResult(requestCode, resultCode, data);
// if (requestCode == 2296) {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// if (Environment.isExternalStorageManager()) {
// // perform action when allow permission success
// } else {
//
// }
// }
// }
// }
#Override
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
Log.e("Musics", String.valueOf(requestCode + requestCode));
}
#Override
public void onNewIntent(Intent intent) {
}
}
Here is the usage example
import React, { useEffect, useState } from 'react';
import {
SafeAreaView,
PermissionsAndroid,
StatusBar,
StyleSheet,
Text,
View,
FlatList,
NativeModules,Platform, addons
} from 'react-native';
const {CustomerMediaStore} = NativeModules;
const calculateSize = (bytes, decimals = 2) => {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
const Item = ({ title, dateadded, datemodified, size }) => {
let dateModified = (new Date(datemodified*1000));
let dateAdded = new Date(dateadded*1000)
return (
<View style={styles.item}>
<Text style={styles.title}>Name: {title}</Text>
<Text>Date Modified: {('0' + dateModified.getUTCDate()).slice(-2) + '-' + ('0' + dateModified.getUTCMonth()).slice(-2) + '-' + dateModified.getUTCFullYear() }</Text>
<Text>Date Added: {('0' + dateAdded.getUTCDate()).slice(-2) + '-' + ('0' + dateAdded.getUTCMonth()).slice(-2) + '-' + dateAdded.getUTCFullYear() }</Text>
<Text>Size: {calculateSize(size*1)}</Text>
</View>
)}
const App = () => {
const [data, setData] = useState([])
useEffect(() => {
requestCameraPermission()
},[])
const requestCameraPermission = async () => {
if(Platform.OS === "android"){
if(Platform.Version >= "29"){
CustomerMediaStore.checkStorgaePermission().then( async(data) => {
if(!data){
CustomerMediaStore.askforscopestoragepermission();
}else{
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
{
title: "Document Reader App Storage Permission",
message:
"Cool Photo App needs access to your Storage" +
"so you can take awesome pictures.",
buttonNeutral: "Ask Me Later",
buttonNegative: "Cancel",
buttonPositive: "OK"
}
);
console.log(granted)
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
try {
myGetFiles().then((data) => {
console.log(data.length,"length")
setData(data)
}).catch((err) => {
console.log(err,"error")
})
}
catch (err) {
console.log(err)
}
} else {
console.log("Storage Permission is required permission denied");
}
} catch (err) {
console.warn(err);
}
}
})
}else {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
{
title: "Document Reader App Storage Permission",
message:
"Cool Photo App needs access to your Storage" +
"so you can take awesome pictures.",
buttonNeutral: "Ask Me Later",
buttonNegative: "Cancel",
buttonPositive: "OK"
}
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
try {
myGetFiles().then((data) => {
console.log(data.length)
setData(data)
}).catch((err) => {
console.log(err,"error")
})
}
catch (err) {
console.log(err)
}
} else {
console.log("Storage Permission is required permission denied");
}
} catch (err) {
console.warn(err);
}
}
}else {
console.log("ios Setting here");
}
};
const myGetFiles = () => {
return new Promise((resolve, reject) => {
if (Platform.OS === "android") {
CustomerMediaStore.GetFiles(
tracks => {
resolve(tracks);
},
error => {
reject(error);
}
);
}
});
}
const renderItem = ({ item }) => {
return (
<Item title={item.displayname} dateadded={item.dateadded} datemodified={item.datemodified} size={item.size} />
)
}
return (
<SafeAreaView style={styles.container}>
<FlatList
data={[...data]}
renderItem={renderItem}
keyExtractor={item => `${item.id}${+ new Date(item.id*1)}`}
/>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: StatusBar.currentHeight || 0,
},
item: {
backgroundColor: '#f9c2ff',
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
},
title: {
fontSize: 15,
},
});
export default App;

how can we display the PDF from base 64 string in Cordova.inappbrowser in Android

My requirement is to display the pdf base64 string in cordova.InAppBrowser it's not displaying in Android
But it's displaying in iOS application.
I am using the below code to display the PDF in InAppBrowser
$scope.urlString = "data:application/pdf;base64,"+encodeURI($scope.PdfString);
var ref = cordova.InAppBrowser.open($scope.urlString, '_blank', 'toolbarposition=bottom');
Does anybody know how I can display the PDF base64 string in Cordova InAppBrowser? or is there any alternative way to display.
Finally got the solution
We need to have the cordova-file-plugin in our project
cordova plugin add cordova-plugin-file
var myBase64 = "JVBERi0xLjcKCjEgMCBvYmogICUgZW50cnkgcG9pbnQKPDwKICAvVHlwZSAvQ2F0YWxvZwogIC9QYWdlcyAyIDAgUgo+PgplbmRvYmoKCjIgMCBvYmoKPDwKICAvVHlwZSAvUGFnZXMKICAvTWVkaWFCb3ggWyAwIDAgMjAwIDIwMCBdCiAgL0NvdW50IDEKICAvS2lkcyBbIDMgMCBSIF0KPj4KZW5kb2JqCgozIDAgb2JqCjw8CiAgL1R5cGUgL1BhZ2UKICAvUGFyZW50IDIgMCBSCiAgL1Jlc291cmNlcyA8PAogICAgL0ZvbnQgPDwKICAgICAgL0YxIDQgMCBSIAogICAgPj4KICA+PgogIC9Db250ZW50cyA1IDAgUgo+PgplbmRvYmoKCjQgMCBvYmoKPDwKICAvVHlwZSAvRm9udAogIC9TdWJ0eXBlIC9UeXBlMQogIC9CYXNlRm9udCAvVGltZXMtUm9tYW4KPj4KZW5kb2JqCgo1IDAgb2JqICAlIHBhZ2UgY29udGVudAo8PAogIC9MZW5ndGggNDQKPj4Kc3RyZWFtCkJUCjcwIDUwIFRECi9GMSAxMiBUZgooSGVsbG8sIHdvcmxkISkgVGoKRVQKZW5kc3RyZWFtCmVuZG9iagoKeHJlZgowIDYKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDEwIDAwMDAwIG4gCjAwMDAwMDAwNzkgMDAwMDAgbiAKMDAwMDAwMDE3MyAwMDAwMCBuIAowMDAwMDAwMzAxIDAwMDAwIG4gCjAwMDAwMDAzODAgMDAwMDAgbiAKdHJhaWxlcgo8PAogIC9TaXplIDYKICAvUm9vdCAxIDAgUgo+PgpzdGFydHhyZWYKNDkyCiUlRU9G";
// To define the type of the Blob
var contentType = "application/pdf";
// if cordova.file is not available use instead :
// var folderpath = "file:///storage/emulated/0/";
var folderpath = cordova.file.externalRootDirectory;
var filename = "helloWorld.pdf";
savebase64AsPDF(folderpath,filename,$scope.PdfString,contentType);
function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, {type: contentType});
return blob;
}
function savebase64AsPDF(folderpath,filename,content,contentType){
// Convert the base64 string in a Blob
var DataBlob = b64toBlob(content,contentType);
console.log("Starting to write the file :3");
window.resolveLocalFileSystemURL(folderpath, function(dir) {
console.log("Access to the directory granted succesfully");
dir.getFile(filename, {create:true}, function(file) {
console.log("File created succesfully.");
file.createWriter(function(fileWriter) {
console.log("Writing content to file");
fileWriter.write(DataBlob);
console.log("Folder Path"+folderpath+filename);
var finalPath = folderpath+filename;
window.open(finalPath, '_system');
}, function(){
alert('Unable to save file in path '+ folderpath);
});
});
});
}
just to complement the solution of #Byka we should install this in ionic 3
ionic cordova plugin add cordova-plugin-file
npm install --save #ionic-native/file
ionic cordova plugin add cordova-plugin-file-opener2
npm install --save #ionic-native/file-opener
Important for some reason the writeFile from file does not work so edit your index.html
you should included before your cordova.js
<script src="build/polyfills.js"></script>
add the plugins to your app's module
import { File } from '#ionic-native/file'
import { FileOpener } from '#ionic-native/file-opener'
added in providers as well
providers: [
.....
File,
FileOpener
]
import { Component } from '#angular/core'
import { NavController, NavParams, Platform } from 'ionic-angular'
import { InAppBrowser } from '#ionic-native/in-app-browser'
import { File } from '#ionic-native/file'
import { FileOpener } from '#ionic-native/file-opener'
#Component({
selector: 'page-pantalla-mi-promenal-consultas',
templateUrl: 'pantalla-mi-promenal-consultas.html'
})
export class YourPage {
constructor(
public navCtrl: NavController,
public navParams: NavParams,
private platform: Platform,
private file: File,
private fileOpener: FileOpener
) {}
getUserDataSheet() {
const blob = this.b64toBlob(pdfString, 'application/pdf', 512)
let pathFile = ''
const fileName = 'myPdf.pdf'
const contentFile = blob
if (this.platform.is('ios')) {
pathFile = this.file.documentsDirectory
} else {
pathFile = this.file.externalRootDirectory
}
this.file
.writeFile(pathFile, fileName, contentFile, { replace: true })
.then(success => {
this.fileOpener
.open(pathFile + fileName, 'application/pdf')
.then(data => {
this.inAppBrowser.create(data, '_system')
})
.catch(e => console.log('Error opening file', e))
})
.catch(e => console.log('Error writing file', e))
}
}
b64toBlob(b64Data, contentType, sliceSize = 512) {
contentType = contentType || ''
sliceSize = sliceSize || 512
b64Data = b64Data.replace(/^[^,]+,/, '')
b64Data = b64Data.replace(/\s/g, '')
var byteCharacters = atob(b64Data)
var byteArrays = []
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize)
var byteNumbers = new Array(slice.length)
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i)
}
var byteArray = new Uint8Array(byteNumbers)
byteArrays.push(byteArray)
}
var blob = new Blob(byteArrays, {
type: contentType
})
// return byteCharacters;
return blob
}
}
In my case the Byka's answer worked only for Android.
I edited it and now it works like charms also in iOS.
My app downloads a pdf base64 encoded, converts and opens it.
The problem was open the file in iOS, solved adding the file opener2 plugin
function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, { type: contentType });
return blob;
}
function savebase64AsPDF(folderpath, filename, content, contentType) {
// Convert the base64 string in a Blob
var DataBlob = b64toBlob(content, contentType);
window.resolveLocalFileSystemURL(folderpath, function (dir) {
dir.getFile(filename, { create: true }, function (file) {
file.createWriter(function (fileWriter) {
fileWriter.write(DataBlob);
var finalPath = folderpath + filename;
//window.open(finalPath, '_system');
cordova.plugins.fileOpener2.open(finalPath, 'application/pdf'
//,
//{
// error: function (e) {
// alert('Error status: ' + e.status + ' - Error message: ' + e.message);
// },
// success: function () {
// alert('file opened successfully');
// }
//}
);
}, function () {
alert("err");
});
});
}
function PrintFile(id) {
jQuery("#large-indicator").css("display", "inline");
$.ajax({
type: "POST",
contentType: "application/json",
dataType: "json",
url: "myurl",
data: JSON.stringify({
"id": id
}),
success: function (Response) {
jQuery("#large-indicator").css("display", "none");
var contentType = "application/pdf";
var folderpath = cordova.file.externalRootDirectory;
if (folderpath == null)
folderpath = cordova.file.dataDirectory
var filename = id + ".pdf";
savebase64AsPDF(folderpath, filename, Response.value, contentType);
},
error: function (Response) {
jQuery("#large-indicator").css("display", "none");
var mex = Response["responseText"];
alert(mex);
}
});
}
This is how i achieved for Android & IOS. Cheers!!
Use this plugins
<plugin name="cordova-plugin-inappbrowser" />
<plugin name="cordova-plugin-file"/>
<plugin name="cordova-plugin-file-transfer"/>
<plugin spec="https://github.com/tectronik/cordova-plugin-file-opener2-tectronik.git"/>
Working code for you.
var blob = b64toBlob("base64 string here", 'application/pdf');
var pathFile = "";
var fileName ='PdfName.pdf';
var contentFile = blob;
if (ionic.Platform.isIOS()) {
var pathFile = cordova.file.documentsDirectory
} else {
var pathFile = cordova.file.externalRootDirectory
}
$cordovaFile.writeFile(pathFile, fileName, contentFile, true)
.then(function(success) {
$scope.filePath=pathFile + fileName;
// console.log("File saved on internal storage location," + pathFile + fileName);
if (ionic.Platform.isAndroid()) {
$cordovaFileOpener2.open($scope.filePath,
'application/pdf'
).then(function() {
// file opened successfully
// alert(' file opened successfully')
}, function(err) {
alert('An error occurred '+err);
});
}else{
var ref = cordova.InAppBrowser.open(data, '_blank',
'location=no,toolbar=yes');
}
}, function(error) {
});
function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
b64Data = b64Data.replace(/^[^,]+,/, '');
b64Data = b64Data.replace(/\s/g, '');
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, {
type: contentType
});
// return byteCharacters;
return blob;
}

Convert base64 string as pdf in phonegap

In my app I have received a base64 string that represents a PDF. I want the user to be able to save the base64 as a pdf to his phone. I have been looking in to the cordova-file-transfer plugin but that requires a (server)path where the file can be downloaded from, instead of converting a base64 string.
Has anybody succeeded in downloading a pdf in phonegap using a base64 string?
After some more searching and trying I found something that worked.
Converting base64 to pdf blob
//Helper function that converts base64 to blob
function b64toBlob(b64Data, contentType, sliceSize) {
var input = b64Data.replace(/\s/g, ''),
byteCharacters = atob(input),
byteArrays = [],
offset, slice, byteNumbers, i, byteArray, blob;
contentType = contentType || '';
sliceSize = sliceSize || 512;
for (offset = 0; offset < byteCharacters.length; offset += sliceSize) {
slice = byteCharacters.slice(offset, offset + sliceSize);
byteNumbers = new Array(slice.length);
for (i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
//Convert to blob.
try {
blob = new Blob(byteArrays, { type: contentType });
}
catch (e) {
// TypeError old chrome, FF and Android browser
window.BlobBuilder = window.BlobBuilder ||
window.WebKitBlobBuilder ||
window.MozBlobBuilder ||
window.MSBlobBuilder;
if (e.name == 'TypeError' && window.BlobBuilder) {
var bb = new BlobBuilder();
for (offset = 0; offset < byteArrays.length; offset += 1) {
bb.append(byteArrays[offset].buffer);
}
blob = bb.getBlob(contentType);
}
else if (e.name == "InvalidStateError") {
blob = new Blob(byteArrays, {
type: contentType
});
}
else {
return null;
}
}
return blob;
};
And then the downloading itself we need the cordova-file plugin:
var fileToSave= b64toBlob(fileData, 'application/pdf');
writeFile();
function writeFile() {
console.log("request file system");
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, onFileSystemRetrieved, onFileSystemFail);
}
function onFileSystemRetrieved(fileSystem) {
console.log("file system retrieved");
fileSystem.root.getFile(fileName, { create: true }, onFileEntryRetrieved, onFileSystemFail);
}
function onFileEntryRetrieved(fileEntry) {
console.log("file entry retrieved");
fileEntry.createWriter(gotFileWriter, onFileSystemFail);
}
function gotFileWriter(writer) {
console.log("write to file");
writer.onwrite = function (evt) {
alert('done');
}
writer.write(fileToSave);
window.open(fileName, '_blank');
}
function onFileSystemFail(error) {
console.log(error.code);
alert(error.code)
}

Add data to objects via cloud code

In Cloud code, I create a function that get the users, and another function that add specific values to that user objects.
The problem is, that in Android we get the users objects, but without the specific values that was added.
When i copy the same code to the JS file in the client side, it's works perfect. I get all the objects with all the specific values that was added to them.
I attached the code
Someone know what the problem is?
Parse.Cloud.define("getAllPeople", function (request, response) {
var currentUser = request.user;
var numberToSkip = request.params.numberToSkip || 0;
var isMale = request.params.isMale;
var latitude = request.params.latitude || 32.08; //Tel Aviv
var longitude = request.params.longitude || 34.78;
var parseGeoPoint = new Parse.GeoPoint({latitude: latitude, longitude: longitude});
var User = Parse.Object.extend("User");
var queryObject = new Parse.Query(User);
queryObject.skip(numberToSkip).limit(100)
.equalTo('isCheckIn', true)
.equalTo('isMale', isMale)
//.notEqualTo('objectId', currentUser.id)
.near('location', parseGeoPoint)
.notEqualTo('checkInPlace', null)
.include('checkInPlace')
.find({
success: function (usersInCheckIn) {
checkUserSend(currentUser, usersInCheckIn).then(function (results) {
response.success(results);
});
},
error: function (error) {
console.error("Error: " + error.code + " " + error.message);
}
});
});
function checkUserSend(currentUser, usersInCheckIn) {
var Matching = Parse.Object.extend("Matching");
var queryObject = new Parse.Query(Matching);
var promise = new Parse.Promise();
queryObject
.equalTo('sendUser', currentUser)
.include('sendUser')
.find({
success: function (results) {
for (var i = 0; i < results.length; i++) {
var current = {};
current.receivedUser = results[i].get('receivedUser');
current.isMatching = results[i].get('isMatching');
current.isRejected = results[i].get('isRejected');
for (var j = 0; j < usersInCheckIn.length; j++) {
if (usersInCheckIn[j].id == current.receivedUser.id) {
usersInCheckIn[j].sendWink = true;
usersInCheckIn[j].isMatching = current.isMatching;
usersInCheckIn[j].isRejected = current.isRejected;
}
}
}
console.log(usersInCheckIn);
promise.resolve(usersInCheckIn);
},
error: function (error) {
console.error("Error: " + error.code + " " + error.message);
}
});
return promise;
}
Remove return statement and add response.success(usersInCheckIn); on sucess of queryObject find()
function checkUserSend(currentUser, usersInCheckIn) {
var Matching = Parse.Object.extend("Matching");
var queryObject = new Parse.Query(Matching);
var promise = new Parse.Promise();
queryObject
.equalTo('sendUser', currentUser)
.include('sendUser')
.find({
success: function (results) {
for (var i = 0; i < results.length; i++) {
var current = {};
current.receivedUser = results[i].get('receivedUser');
current.isMatching = results[i].get('isMatching');
current.isRejected = results[i].get('isRejected');
for (var j = 0; j < usersInCheckIn.length; j++) {
if (usersInCheckIn[j].id == current.receivedUser.id) {
usersInCheckIn[j].sendWink = true;
usersInCheckIn[j].isMatching = current.isMatching;
usersInCheckIn[j].isRejected = current.isRejected;
}
}
}
console.log(usersInCheckIn);
// promise.resolve(usersInCheckIn);
response.success(usersInCheckIn);
},
error: function (error) {
console.error("Error: " + error.code + " " + error.message);
}
});
}

jQuery Mobile show() and hide() Don't Work in Android

I am trying to get a "Please wait..." message to display when I make an ajax call to get information. Basically, the user puts in their search term, hits Search, I want to display "Please wait..." while the page is doing the ajax call, then hide it once it is done.
I have a div on my jsp page that looks like this:
<div id="modalWindow">Please Wait...</div>
My jQuery looks like this:
jQuery('#modalWindow').css({
'text-align' : 'center',
'font-size' : '20px'
}).hide(); //this is called when the page initially loads
jQuery('#modalWindow').show(); //I call this in the function that does the Ajax call
jQuery('#modalWindow').hide(); //I call this once the Ajax is done.
This is my entire Ajax call:
jQuery.ajax(
{
url : urlContext + "/getItems.html",
data :
{
txtItemReference : txtItemReference
},
dataType : "json",
cache : false,
async : false,
timeout : 100000,
success : function(jsonResponse)
{
if ( jsonResponse instanceof Object)
{
if (jQuery.isEmptyObject(jsonResponse))
{
createLocationDisplayPanel(false);
createSimilarItemsPanel(false);
}
else if (jsonResponse['Locations'] != undefined)
{
responseArray = new Array();
arrayStart = 0;
intPage = 1;
if (jsonResponse['Locations'].length <= 20)
{
for (var x = arrayStart; x < jsonResponse['Locations'].length; x++)
{
responseArray[x] = jsonResponse['Locations'][x];
}
}
else
{
responseArray = new Array();
for (var x = arrayStart; x < (20 * intPage); x++)
{
responseArray[x] = jsonResponse['Locations'][x];
}
}
createLocationDisplayPanel(jsonResponse, responseArray, txtItemReference, urlContext, callback);
}
else
{
if (jsonResponse['Items'].length <= 20)
{
for (var x = arrayStart; x < jsonResponse['Items'].length; x++)
{
responseArray[x] = jsonResponse['Items'][x];
}
}
else
{
for (var x = arrayStart; x < (20 * intPage); x++)
{
responseArray[x] = jsonResponse['Items'][x];
}
}
createSimilarItemsPanel(jsonResponse, responseArray, txtItemReference, urlContext, callback);
}
if (callback != undefined)
{
callback();
}
}
else
{
alertLogout(document.URL);
}
},
error : function(jsonResponse)
{
if (jsonResponse.hasOwnProperty('ERROR'))
{
alertError("There was no response from the server.");
}
}
});
This works perfectly in Firefox on my desktop as well as Firefox for Android. However, on every Android browser I've tried, the "Please wait..." text never displays, and I am getting frustrated. Can anyone please tell me the workaround to get the show() and hide() functions to work in an Android browser? Thanks.
Have you checked if jQuery is loaded at that point? Write this before your script.
if (typeof jQuery == 'undefined') {
alert('jQuery is not loaded');
}
You might need to combine the scripts or find a way to ensure they are loaded in the order you need them.
I found the issue was with the async property of the Ajax call:
jQuery.ajax(
{
url : urlContext + "/getItems.html",
data :
{
txtItemReference : txtItemReference
},
dataType : "json",
cache : false,
async : true, //was false before
timeout : 100000,
success : function(jsonResponse)
{
if ( jsonResponse instanceof Object)
{
if (jQuery.isEmptyObject(jsonResponse))
{
createLocationDisplayPanel(false);
createSimilarItemsPanel(false);
}
else if (jsonResponse['Locations'] != undefined)
{
responseArray = new Array();
arrayStart = 0;
intPage = 1;
if (jsonResponse['Locations'].length <= 20)
{
for (var x = arrayStart; x < jsonResponse['Locations'].length; x++)
{
responseArray[x] = jsonResponse['Locations'][x];
}
}
else
{
responseArray = new Array();
for (var x = arrayStart; x < (20 * intPage); x++)
{
responseArray[x] = jsonResponse['Locations'][x];
}
}
createLocationDisplayPanel(jsonResponse, responseArray, txtItemReference, urlContext, callback);
}
else
{
if (jsonResponse['Items'].length <= 20)
{
for (var x = arrayStart; x < jsonResponse['Items'].length; x++)
{
responseArray[x] = jsonResponse['Items'][x];
}
}
else
{
for (var x = arrayStart; x < (20 * intPage); x++)
{
responseArray[x] = jsonResponse['Items'][x];
}
}
createSimilarItemsPanel(jsonResponse, responseArray, txtItemReference, urlContext, callback);
}
if (callback != undefined)
{
callback();
}
}
else
{
alertLogout(document.URL);
}
},
error : function(jsonResponse)
{
if (jsonResponse.hasOwnProperty('ERROR'))
{
alertError("There was no response from the server.");
}
}
});
Once I changed that, the show and hide worked in Android. Thanks for the help guys.

Categories

Resources