Memory leak warnings in electron - reactjs

I'm getting memory leak warning in the console for my Electron app, i don't know what to do to increase limit. It's causing it everytime i run the app.
Does the error is linked to uiohook? Or did i miss something here?
How can i use emitter.setMaxListeners() in my case? I have no clue of how to fix it, and hwo to increase the memory leak.
[3452:1014/104426.056:ERROR:service_worker_storage.cc(1904)] Failed to delete the database: Database IO error
(node:21792) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 terminate-timer listeners added to [EventEmitter]. Use emitter.setMaxListeners() to increase limit
(Use `electron --trace-warnings ...` to show where the warning was created)
(node:21792) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 set-activity listeners added to [EventEmitter]. Use emitter.setMaxListeners() to increase limit
Electron
const electron = require('electron');
const BrowserWindow = electron.BrowserWindow;
const dialog = electron.dialog;
const desktopCapturer = electron.desktopCapturer;
const idle = electron.powerMonitor;
const remote = electron.remote;
const notification = electron.Notification;
const globalShortcut = electron.globalShortcut;
const screen = electron.screen;
const ipcMain = electron.ipcMain;
const app = electron.app;
const isDev = require('electron-is-dev');
const path = require('path');
const activeWindows = require('electron-active-window');
const activeWindowPage = require('active-win');
const BMParser = require('bookmark-parser');
const axios = require('axios');
const uiohook = require('uiohook-napi');
const { autoUpdater } = require("electron-updater");
const debug = require('debug')('Franz:ipcApi:autoUpdate');
const dns = require("dns");
const activity = { is_mouse: 0, is_keyboard: 0 };
const headers = {
'Content-Type': 'application/json;charset=UTF-8',
"Access-Control-Allow-Headers": "*",
"Access-Control-Allow-Origin": "*",
"Accept": "application/json"
}
const sessionUser = null;
let updateInterval = null;
app.disableHardwareAcceleration();
electron.powerSaveBlocker.start('prevent-app-suspension');
//electron.commandLine.appendSwitch ("disable-http-cache");
// Change App Name on Windows
if (process.platform === 'win32')
{
app.setAppUserModelId('Rubii');
}
let apiEndpoint = "http://creaz:81/xorix/api"; // Brian
let frameUrl = 'http://localhost:3000'; // Brian
//if (isDev) { // or if(process.env.NODE_ENV)
// apiEndpoint = "http://creaz:81/xorix/api";
// frameUrl = 'http://localhost:3000';
//}
var internetAvailable = require("internet-available");
let isConnected = false;
let counterInternet = 0;
let allowSendInternetNotification = 1;
async function liveInternetCheck() {
var userSessionCheck = await getSessionUser();
// Most easy way
internetAvailable({
domainName: "rubii.com",
// Provide maximum execution time for the verification
timeout: 10000,
// If it tries 10 times and it fails, then it will throw no internet
retries: 10
}).then(() => {
// Available Internet
isConnected = true;
counterInternet++;
if(counterInternet > 3 && allowSendInternetNotification == 0) {
allowSendInternetNotification = 1;
}
}).catch(() => {
// Not available internet
isConnected = false;
if(isConnected == false && userSessionCheck && allowSendInternetNotification == 1) {
var message = 'Your internet has been disconnected! Please login again';
new notification({ title: 'Ooops', body: message }).show();
// Logout the user in the other end
win.webContents.send("terminate-timer", "hello");
allowSendInternetNotification = 0;
counterInternet = 0;
}
});
}
autoUpdater.on("update-available", (_event, releaseNotes, releaseName) => {
const dialogOpts = {
type: 'info',
buttons: ['Ok'],
title: 'Update Available',
message: process.platform === 'win32' ? releaseNotes : releaseName,
detail: 'A new version download started. The app will be restarted to install the update.'
};
dialog.showMessageBox(dialogOpts);
updateInterval = null;
});
autoUpdater.on("update-downloaded", (_event, releaseNotes, releaseName) => {
const dialogOpts = {
type: 'info',
buttons: ['Restart'],
title: 'Application Update',
message: process.platform === 'win32' ? releaseNotes : releaseName,
detail: 'A new version has been downloaded. Restart the application to apply the updates.'
};
dialog.showMessageBox(dialogOpts).then((returnValue) => {
if (returnValue.response === 0) autoUpdater.quitAndInstall()
});
});
function checkUpdate() {
updateInterval = setInterval(() => autoUpdater.checkForUpdates(), 600000);
}
let win;
ipcMain.on('close-me', (evt, arg) => {
new notification({ title: 'Ooops', body: 'We hope to see you again!' }).show();
app.quit()
});
function determineScreenShotSize() {
var screenSize = screen.getPrimaryDisplay().workAreaSize
return {
width: screenSize.width,
height: screenSize.height
}
}
async function takeScreenshot() {
var user = await getSessionUser();
var timer = await getSessionTimer();
if (user && timer) {
if (timer.timer == 1) {
//console.log('Gathering screens...');
//console.log(app.getPath('pictures'));
const thumbSize = determineScreenShotSize();
const workaroundTimestamp = Date.now();
const options = {
types: ['screen'],
thumbnailSize: { ...thumbSize, workaroundTimestamp }
};
desktopCapturer.getSources(options).then((sources) => {
console.log('Sources received:' + sources.length);
sources.forEach(function (source) {
const sourceName = source.name.toLowerCase();
//console.log(sourceName);
if (['entire screen', 'screen 1'].includes(sourceName)) {
var the_screenshot = source.thumbnail.toPNG();
var data = {
user_id: user.id,
company_id: timer.company_id,
image: the_screenshot.toString('base64')
}
axios.post(apiEndpoint + "/desktop/save_screenshots", data, {
headers: headers
})
.then((response) => {
// console.log(response);
})
.catch((error) => {
//console.log(error);
})
}
})
}).catch(console.error);
}
}
}
function saveSoftware() {
(async () => {
var options = [];
var software = await activeWindowPage();
var user = await getSessionUser();
var timer = await getSessionTimer();
if (user && timer) {
if (timer.timer == 1) {
software.user = user;
software.timer = timer;
axios.post(apiEndpoint + "/desktop/save_app", software, {
headers: headers
})
.then((response) => {
//console.log(response);
})
.catch((error) => {
//console.log(error);
})
}
}
})();
}
function getSessionUser() {
return win.webContents.executeJavaScript('sessionStorage.getItem("user");', true)
.then(result => {
if (result) {
return JSON.parse(result);
}
});
}
function getSessionTimer() {
return win.webContents.executeJavaScript('sessionStorage.getItem("timer");', true)
.then(result => {
if (result) {
return JSON.parse(result);
}
});
}
async function generateActivity() {
win.webContents.send("set-activity", activity);
// We reset after we send it
activity.is_mouse = activity.is_keyboard = 0;
}
function secondsToHms(d) {
d = Number(d);
var h = Math.floor(d / 3600);
var m = Math.floor(d % 3600 / 60);
var s = Math.floor(d % 3600 % 60);
var hDisplay = h > 0 ? h + (h == 1 ? " hour, " : " hours, ") : "";
var mDisplay = m > 0 ? m + (m == 1 ? " minute, " : " minutes, ") : "";
var sDisplay = s > 0 ? s + (s == 1 ? " second" : " seconds") : "";
return hDisplay + mDisplay + sDisplay;
}
function createWindow() {
win = new BrowserWindow({
width: 1200,
height: 900,
frame: true,
webPreferences: {
webSecurity: false,
nodeIntegration: true,
enableRemoteModule: true,
contextIsolation: false,
backgroundThrottling: false
}
});
//win.loadURL('https://desktop.rubii.com');
win.loadURL(frameUrl, { "extraHeaders": "pragma: no-cache\n" });
// http://localhost:3000
//win.webContents.openDevTools();
//win.removeMenu(); // Brian
// or set the Menu to null
//win.setMenu(null); // Brian
// Reload cache
win.webContents.reloadIgnoringCache();
// Keyboard activity
uiohook.uIOhook.on('keydown', (e) => {
//console.log('Keyboard!')
activity.is_keyboard = 1;
})
// Mouse activity
uiohook.uIOhook.on('mousemove', (e) => {
//console.log('mouse');
activity.is_mouse = 1;
})
// Start listener for keyboard and mouse
uiohook.uIOhook.start();
win.on('close', function () {
win = null;
})
}
app.whenReady().then(createWindow).then(checkUpdate);
app.on('window-all-closed', function () {
app.quit();
});
app.on('activate', function () {
if (win == null) {
createWindow();
}
})
setInterval(takeScreenshot, 10 * 60 * 1000); // 10 minutes
setInterval(saveSoftware, 5 * 1000); // 5 seconds
setInterval(generateActivity, 1 * 1000);
setInterval(function() { liveInternetCheck(); }, 10 * 1000); // 10 seconds
Render
ipcRenderer.on("terminate-timer", function (event, data) {
// Logout if there is no internet connection
handleLogout();
});
// Set activity if there were any keyboard, mouse
ipcRenderer.on("set-activity", function (event, data) {
// If the timer is on
if(timer) {
setActivity(data);
}
});

Related

how to Open electron app from browser in both windows and mac

const { app, BrowserWindow, ipcMain, dialog, screen,Tray } = require('electron');
try {
require('electron-reloader')(module)
} catch (_) { }
const path = require('path')
let deeplinkingUrl;
let mainWindow;
const createWindow = () => {
let { width, height } = screen.getPrimaryDisplay().size
// Create the browser window.
mainWindow = new BrowserWindow({
width: width,
height: height,
minWidth: width,
minHeight: height,
productName: "abc",
copyright: "Copyright © 2022 ${author}",
// mac: {
// icon: "./img/abc_256x256px.ico"
// },
icon: __dirname + "/img/icon.ico",
// icon: "./img/abc_256x256px.ico",
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
nodeIntegration: true,
contextIsolation: false,
devTools: false,
}
})
mainWindow.setClosable(false);
mainWindow.setMenuBarVisibility(false);
mainWindow.maximize();
mainWindow.setMovable(false);
mainWindow.setResizable(false);
if (process.platform == 'win32') {
// Keep only command line / deep linked arguments
deeplinkingUrl = process.argv.slice(1)
}
logEverywhere("createWindow# " + deeplinkingUrl)
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
//tray
let tray = null;
mainWindow.on('minimize', function (event) {
event.preventDefault();
mainWindow.hide();
tray = createTray();
});
mainWindow.on('restore', function (event) {
mainWindow.maximize();
mainWindow.show();
tray.destroy();
});
function createTray() {
let appIcon = new Tray(path.join(__dirname + "/img/icon.ico"));
appIcon.on('click', function (event) {
mainWindow.show();
});
appIcon.setToolTip('abc');
return appIcon;
}
}
app.whenReady().then(() => {
createWindow()
if (isDev && process.platform === 'win32') {
// Set the path of electron.exe and your app.
// These two additional parameters are only available on windows.
// Setting this is required to get this working in dev mode.
app.setAsDefaultProtocolClient('pro', process.execPath, [
resolve(process.argv[1])
]);
} else {
app.setAsDefaultProtocolClient('pro');
}
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
app.on('open-url', function (event, url) {
event.preventDefault();
deeplinkingUrl = url;})
})
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
return;
} else {
app.on('second-instance', (e, argv) => {
if (process.platform !== 'darwin') {
// Find the arg that is our custom protocol url and store it
deeplinkingUrl = argv.find((arg) => arg.startsWith('custom://'));
}
if (myWindow) {
if (myWindow.isMinimized()) myWindow.restore();
myWindow.focus();
}
});
}
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
function logEverywhere(s) {
console.log(s)
if (mainWindow && mainWindow.webContents) {
mainWindow.webContents.executeJavaScript(`console.log("${s}")`)
}
}
//to allow self signed certificate
app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
// Verification logic.
event.preventDefault()
callback(true)
})
ipcMain.handle('download', async (someArgument) => {
const result = await download(someArgument)
return result;
})
const download = async (data) => {
let value = 100;
console.log(data.name)
dialog.showSaveDialog({
title: 'Select the File Path to save',
defaultPath: path.join(__dirname, data.name + '.p12'),
buttonLabel: 'Save',
filters: [
{
name: 'Personal Information Exchnage',
extensions: ['.p12']
}
],
properties: []
}).then((path) => {
value = 1;
console.log('success')
mainWindow.webContents.send('success', path);
}).catch((value) => {
value = 2;
mainWindow.webContents.send('failed', path);
console.log('error')
});
return value;
}
This code throws some error when I type 'pro://something' in the browser.
Erorr description: Error launching app, unable to find Electron app at C:\Windows\system32\pro:\something
I have also tried some other code which opens my app but in a different window.
I want to open the App but in the existing window of my app.

Reactjs Websocket connection is not stable

I'm new to Reactjs. I have a code written in Reactjs. The code below is to get a response from server by using Websocket. Every 10 secs, under the componentDidUpdate it will run the retrieveServerData to get the latest information.
I have 3 enquiries that I need to send to server, for each enquiry i will open a new socket inside ws.onmessage() . This works well, data can be retrieved correctly with no any connection error.
class Subject extends React.Component {
componentDidUpdate = (prevProps, prevState) => {
setTimeout(() => {
this.setState({
//set some state
}, () => {
this.interval = setInterval(() => this.retrieveServerData(), 5000);
});
}, 10000);
}
retrieveServerData = () => {
let statusEn = "enabled";
let enquiry = ["data1", "data2", "data3"];
for (let i = 0; i < 2; i++) {
let dataMethod = {
Name: "AAA",
Subject: "Math",
Day: "Thursday",
Parameters: { Data: enquiry[0] }
};
let ws = new WebSocket("ws://localhost:XXX");
let dataMethodInString = JSON.stringify(dataMethod);
ws.onopen = () => {
ws.send(dataMethodInString);
};
ws.onmessage = (event) => {
if (event.data !== "Socket server connected") {
if (!event.data.includes("Error")) {
let myArray = ProcessElement(event.data);
console.log("myArray 0: ", commands[0], myArray);
//2nd
let ws = new WebSocket("ws://localhost:XXX");
let dataMethodCopy = JSON.parse(JSON.stringify(dataMethod));
dataMethodCopy["Parameters"] = { Data: commands[1] };
let dataMethodInString = JSON.stringify(dataMethodCopy);
ws.onopen = () => {
ws.send(dataMethodInString);
};
ws.onmessage = (event) => {
if (event.data !== "Socket server connected") {
if (event.data.includes("Error") === false) {
let myArray = ProcessElement(event.data);
console.log("myArray 1: ", myArray);
let ws = new WebSocket("ws://localhost:XXX");
let dataMethodCopy = JSON.parse(JSON.stringify(dataMethod));
dataMethodCopy["Parameters"] = { Data: commands[2] };
let dataMethodInString = JSON.stringify(dataMethodCopy);
ws.onopen = function () {
ws.send(dataMethodInString);
};
ws.onmessage = (event) => {
if (event.data !== "Socket server connected") {
if (event.data.includes("Error") === false) {
let myArray = ProcessElement(event.data);
console.log("myArray 2: ", myArray);
} else {
console.log("myArray 2 error ");
}
ws.close(1000, "request 2 fetch completed");
}
};
} else {
console.log("myArray 1 error ");
}
ws.close(1000, "request 1 fetch completed");
}
};
} else {
console.log("myArray 0 error ");
}
ws.close(1000, "request 0 fetch completed");
}
};
}
};
}
I tried to simplify the code above, instead of opening 1 connection for each enquiry, I want to have 1 connection and send 3 enquiries.
retrieveServerData = () => {
let statusEn = "enabled";
let commands = ["data1", "data2", "data3"];
for (let i = 0; i < 2; i++) {
let commandResponse = [];
const getDataMethod = (command) => {
return JSON.stringify({
Name: "AAA",
Subject: "Math",
Day: "Thursday",
Parameters: { Data: command }
});
};
let ws = new WebSocket("ws://localhost:XXX");
ws.onopen = () => {
commands.forEach((command) => {
setTimeout(() => {
ws.send(getDataMethod(command));
}, 500);
});
};
ws.onmessage = (event) => {
if (event.data !== "Socket server connected") {
if (!event.data.includes("Error")) {
let myArray = ProcessElement(event.data);
console.log(myArray);
if (myArray.length > 0) commandResponse.push(myArray);
if (commandResponse.length === commands.length) {
console.log(commandResponse);
}
}
}
};
ws.onerror = (e) => {
console.log(`${i}: `, e);
};
}
};
Data can be retrieved, but I will get some error connections in between (err connection is refused / err connection is reset).
WebSocket is already in CLOSING or CLOSED state.
failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED
failed: Error during WebSocket handshake: net::ERR_CONNECTION_RESET
Can i get some direction on how to fix it? Thank you

How wait a "Array for each" function?

I got a little problem with synchronous/asynchronous system in the function "Array.foreach".
I don't know how to force my code to wait its end.
I tried to use await/async system but my code did not wait the code in "async responseDB =>".
This is my class:
...
let responsesDTO = [];
await Array.prototype.forEach.call(await searchResponsesByQuestionAndUserId(questions[cpt].idquestion, idUser), async responseDB => {
if(responseDB !== undefined){
const responseDTO = {
response_id:0,
response_text:"",
response_type:""
}
const responseEntity = await searchResponseByResponseId(responseDB.response_id);
responseDTO.response_id = responseDB.response_id;
responseDTO.response_text= responseEntity.text;
responseDTO.response_type= responseDB.type;
responsesDTO.push(responseDTO);
}
});
questionResponse.responses=responsesDTO;
questionResponses[cpt]=questionResponse;
}
Could you help me please? Thanks in advance.
I had to mock your async functions. However, the relevant part is to use for..of instead of forEach
async function searchResponsesByQuestionAndUserId() {
let responsesDB = [];
for (let i = 0; i < 10; i++) {
responsesDB.push({
response_id: parseInt(1000 * Math.random(), 10),
type: 'whatever ' + i
});
}
return new Promise((res) => {
window.setTimeout(() => {
res(responsesDB);
}, 1500);
});
}
async function searchResponseByResponseId(response_id) {
return new Promise((res) => {
window.setTimeout(() => {
res({
text: 'text for response ' + response_id
});
}, 300);
});
}
async function getResponsesDTO() {
let responsesDTO = [],
responsesDB = await searchResponsesByQuestionAndUserId();
for (let responseDB of responsesDB) {
if (responseDB === undefined) {
continue;
}
let responseDTO = {
response_id: 0,
response_text: "",
response_type: ""
},
responseEntity = await searchResponseByResponseId(responseDB.response_id);
responseDTO.response_id = responseDB.response_id;
responseDTO.response_text = responseEntity.text;
responseDTO.response_type = responseDB.type;
responsesDTO.push(responseDTO);
console.log({responseDTO});
}
return responsesDTO;
}
getResponsesDTO().then(responsesDTO => {
console.log(responsesDTO);
});

Erro: 404 Bad request Mongo, Express, Angular, Node

I have a problem I can not solve, my application is returning the error 400 bad request, where I can not do any post, but using the postman it works normally I can do get, post, put, delete, but in my application does not Make it possible to do the post, I have done and redid the code several times and the problem is not remedied, I need to solve this
My Controller
angular.module('primeiraApp').controller('CarCycleCtrl', [
'$scope',
'$http',
'$location',
'msgs',
'tabs',
'consts',
CarCycleController
])
function CarCycleController($scope, $http, $location, msgs, tabs, consts) {
$scope.getCarCycles = function() {
const page = parseInt($location.search().page) || 1
const url = `${consts.apiUrl}/carCycles?skip=${(page - 1) * 10}&limit=10`
$http.get(url).then(function(resp) {
$scope.carCycles = resp.data
$scope.carCycle = {}
initCarsAndOuts()
$http.get(`${consts.apiUrl}/carCycles/count`).then(function(resp) {
$scope.pages = Math.ceil(resp.data.value / 10)
tabs.show($scope, {tabList: true, tabCreate: true})
})
})
}
$scope.createCarCycle = function(){
const url = `${consts.apiUrl}/carCycles`;
$http.post(url,$scope.carCycle).then(function(response){
$scope.carCycle = {}
initCarsAndOuts()
$scope.getCarCycles()
msgs.addSuccess('Operação realizada com sucesso!')
}).catch(function(resp){
msgs.addError(resp.data.errors)
})
}
$scope.showTabUpdate = function(carCycle) {
$scope.carCycle = carCycle
initCarsAndOuts()
tabs.show($scope, {tabUpdate: true})
}
$scope.updateCarCycle = function() {
const url = `${consts.apiUrl}/carCycles/${$scope.carCycle._id}`
$http.put(url, $scope.carCycle).then(function(response) {
$scope.carCycle = {}
initCarsAndOuts()
$scope.getCarCycles()
tabs.show($scope, {tabList: true, tabCreate: true})
msgs.addSuccess('Operação realizada com sucesso!')
}).catch(function(resp) {
msgs.addError(resp.data.errors)
})
}
$scope.showTabDelete = function(carCycle) {
$scope.carCycle = carCycle
initCarsAndOuts()
tabs.show($scope, {tabDelete: true})
}
$scope.deleteCarCycle = function() {
const url = `${consts.apiUrl}/carCycles/${$scope.carCycle._id}`
$http.delete(url, $scope.carCycle).then(function(response) {
$scope.carCycle = {}
initCarsAndOuts()
$scope.getCarCycles()
tabs.show($scope, {tabList: true, tabCreate: true})
msgs.addSuccess('Operação realizada com sucesso!')
}).catch(function(resp) {
msgs.addError(resp.data)
})
}
$scope.addDebt = function(index) {
$scope.carCycle.outs.splice(index + 1, 0, {})
}
$scope.cloneDebt = function(index, {name, value, status}) {
$scope.carCycle.outs.splice(index + 1, 0, {name, value, status})
initCarsAndOuts()
}
$scope.deleteDebt = function(index) {
$scope.carCycle.outs.splice(index, 1)
initCarsAndOuts()
}
$scope.addCredit = function(index) {
$scope.carCycle.cars.splice(index + 1, 0, {name: null, value: null})
}
$scope.cloneCredit = function(index, {name, value}) {
$scope.carCycle.cars.splice(index + 1, 0, {name, value})
initCarsAndOuts()
}
$scope.deleteCredit = function(index) {
$scope.carCycle.cars.splice(index, 1)
initCarsAndOuts()
}
$scope.cancel = function() {
tabs.show($scope, {tabList: true, tabCreate: true})
$scope.carCycle = {}
initCarsAndOuts()
}
$scope.calculateValues = function() {
$scope.car = 0
$scope.out = 0
if($scope.carCycle) {
$scope.carCycle.cars.forEach(function({value}) {
$scope.car += !value || isNaN(value) ? 0 : parseFloat(value)
})
$scope.carCycle.outs.forEach(function({value}) {
$scope.out += !value || isNaN(value) ? 0 : parseFloat(value)
})
}
$scope.total = $scope.car - $scope.out
}
var initCarsAndOuts = function() {
if(!$scope.carCycle.outs || !$scope.carCycle.outs.length) {
$scope.carCycle.outs = []
$scope.carCycle.outs.push({})
}
if(!$scope.carCycle.cars || !$scope.carCycle.cars.length) {
$scope.carCycle.cars = []
$scope.carCycle.cars.push({})
}
$scope.calculateValues()
}
$scope.getCarCycles()
}
My Backend
const _ = require('lodash')
const CarCycle = require('./carCycle')
CarCycle.methods(['get', 'post', 'put', 'delete'])
CarCycle.updateOptions({new: true, runValidators: true})
CarCycle.after('post', sendErrorsOrNext).after('put', sendErrorsOrNext)
function sendErrorsOrNext(err, req, res, next) {
const bundle = res.locals.bundle
if(bundle.errors) {
var errors = parseErrors(bundle.errors)
res.status(500).json({errors})
} else {
next()
}
}
function parseErrors(nodeRestfulErrors) {
const errors = []
_.forIn(nodeRestfulErrors, error => errors.push(error.message))
return errors
}
CarCycle.route('count', function(req, res, next) {
CarCycle.count(function(error, value) {
if(error) {
res.status(500).json({errors: [error]})
} else {
res.json({value})
}
})
})
module.exports = CarCycle

How to upload file.mp3 to firebase storage in ionic?

I am creating an audio recording function in my ionic app. I am using media plugin:
$ ionic cordova plugin add cordova-plugin-media
$ npm install --save #ionic-native/media
I can record the audio and play it successfully like this:
constructor(private media: Media,private base64: Base64) {
this.file = this.media.create('file.mp3');
}
record_audio(){
this.file.startRecord();
}
to uplaod to firebase I cannot directly upload the file.mp3, looks like I need to convert it to Blob or base64 first so I tried doing this but it says "MediaObject cannot be assigned to string":
let filePath: string = 'this.file.mp3';
this.base64.encodeFile(filePath).then((base64File: string) => {
console.log(base64File);
}, (err) => {
console.log(err);
});
The objective is to upload the recorded audio file to firebase. to do that I need to convert this file.mp3 to base64.
startRecording() {
console.log("Started Recording");
this.recording = true;
this.file.createFile(this.file.tempDirectory, 'my_file.m4a', true).then(() => {
const audio: MediaObject = this.media.create(this.file.tempDirectory.replace(/^file:\/\//, '') + 'my_file.m4a');
console.log("Audio assigned to constant audio media object");
console.log(audio);
this.audio = audio;
console.log("Audio assigned to this.audio media object");
console.log(this.audio);
this.audio.startRecord();
this.listenToAudioEvents();
window.setTimeout(() => {
if (this.recording) this.stopRecording();
}, 10000);
});
}
listenToAudioEvents() {
this.audio.onStatusUpdate.subscribe(status => {
console.log("Status of this.audio updated");
console.log(status);
if (status == 4 && this.playingAudio) {
console.log("Time to stop playback")
this.stopPlayback();
}
});
}
stopRecording() {
this.audio.stopRecord();
console.log("Stopped Recording");
console.log(this.audio);
this.recording = false;
this.audioReady = true;
this.audio.getDuration();
console.log("Audio Duration: " + this.duration);
console.log("Audio Duration Property: " + this.audio.duration);
}
playAudio() {
console.log("Playing Audio");
this.playingAudio = true;
this.audio.play();
}
stopPlayback() {
console.log("Stopping Playback");
this.playingAudio = false;
this.audio.stop();
}
uploadAudio() {
console.log("Uploading record");
this.storeRecord().subscribe((downloadURL) => {
console.log("Finished storing record");
console.log("Download URL is " + downloadURL);
this.audioURL = downloadURL;
this.audioURLReady = true;
});
}
storeRecord() {
return Observable.create((observer) => {
console.log('Saving record');
const filePath = `${this.file.tempDirectory}my_file.m4a`;
console.log("Path to record is " + filePath);
const readFile: any = window['resolveLocalFileSystemURL'];
return readFile(filePath, (fileEntry) => {
return fileEntry.file((file) => {
const fileReader = new FileReader();
fileReader.onloadend = (result: any) => {
let arrayBuffer = result.target.result;
let blob = new Blob([new Uint8Array(arrayBuffer)], { type: 'audio/m4a' });
console.log("Blob is ");
console.log(blob);
var storageRef = firebase.storage().ref('content/' + this.firebase.user.uid + '/my-file.m4a');
console.log("Storage reference is " + storageRef);
var uploadTask = storageRef.put(blob);
console.log('Upload started:');
uploadTask.on('state_changed', (snapshot) => {
console.log("state changed");
let percent = uploadTask.snapshot.bytesTransferred / uploadTask.snapshot.totalBytes * 100;
console.log(percent + "% done");
}, (e) => {
console.error(e);
observer.error(e);
}, () => {
var downloadURL = uploadTask.snapshot.downloadURL;
console.log('Storage Download URL:' + downloadURL);
observer.next(downloadURL);
});
};
fileReader.onerror = (e: any) => {
console.error(e);
observer.error(e);
};
fileReader.readAsArrayBuffer(file);
}, (e) => {
console.error(e);
observer.error(e);
});
}, (e) => {
console.error(e);
observer.error(e);
});
});
}
downloadAudio() {
console.log("Downloading Audio")
const fileTransfer: FileTransferObject = this.fileTransfer.create();
var destPath = (cordova.file.externalDataDirectory || cordova.file.dataDirectory) + "my_file.m4a"
fileTransfer.download(this.audioURL, destPath, ).then((entry) => {
let rawAudioURI = entry.toURL();
this.audioURI = rawAudioURI.replace(/^file:\/\//, '/private');
this.audioURIReady = true;
console.log("Audio URI: " + this.audioURI);
}, (error) => {
console.error(error);
});
}
playAudioURI() {
console.log("Playing AudioURI");
let downloadedAudio: MediaObject = this.media.create(this.audioURI);
console.log("Downloaded audio: " + downloadedAudio);
downloadedAudio.play();
}
}

Resources