This error occurs seldom in the app when it loads (Not all the time). The index.js is the main file ,selected in package.json, and the script.js is the file connected to main html file of the electron app.
index.js
const {app, BrowserWindow} = require('electron');
const path = require('path');
const url = require('url');
let window;
var APP_DIR = '/app/';
var IMG_DIR = '/images/';
function createWindow() {
window = new BrowserWindow({
webPreferences: { nodeIntegration: true },
width:610,
height:679,
icon: path.join(__dirname, APP_DIR, IMG_DIR, 'icon.png'),
frame: false,
resizable: false,
fullscreenable: false
});
window.loadURL(url.format({
pathname: path.join(__dirname, APP_DIR, 'index.html'),
protocol: 'file:',
slashes: true
}));
}
app.on('ready', createWindow);
script.js (where the error occurs)
var {BrowserWindow} = require('electron').remote;
BrowserWindow.getFocusedWindow().on('blur', function() {
windowBlurHandler(); //a function
});
How can I fix it?
Function BrowserWindow.getFocusedWindow() returns null when all windows are blurred. You are getting the error because listeners cannot be registered on null.
Try something like this instead:
const mainWindow = require('electron').remote.getCurrentWindow()
mainWindow.on('blur', function() {
windowBlurHandler()
})
Related
I'm building an app with electron react and MySQL, I'm stuck in preload script where i want to make my db instance available in render-er process, i got the following error
Error: module not found: ./config/db in console.
this happening when i try to require a module inside preload script.
const { app, BrowserWindow } = require("electron");
const path = require("path");
const isDev = require("electron-is-dev");
const dotenv = require("dotenv");
//load .env
dotenv.config();
function createWindow() {
// Create the browser window.
const mainWindow = new BrowserWindow({
title: "Electron",
minWidth: 800,
minHeight: 600,
webPreferences: {
preload: path.join(__dirname, "preload.js"),
devTools: isDev,
},
});
//get url dependig on envirement (dev/prod)
const url = isDev
? `http://localhost:${process.env.PORT}/`
: `file://${path.join(__dirname, "../../dist/react/index.html")}`;
// load the url
mainWindow.loadURL(url);
// Open the DevTools.
isDev && mainWindow.webContents.openDevTools();
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
createWindow();
app.on("activate", function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on("window-all-closed", function () {
if (process.platform !== "darwin") app.quit();
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
require("./handlers");
preload
const { contextBridge, ipcRenderer } = require("electron");
const { db } = require("./config/db");
contextBridge.exposeInMainWorld("mainApi", {
db,
});
Since Electron v20.0.0, the sandbox parameter defaults to true (according to the list of Breaking Changes)
One of the side effects of the sandbox attribute is that it can only require a few things:
A require function similar to Node's require module is exposed, but can only import a subset of Electron and Node's built-in modules:
electron (only renderer process modules)
events
timers
url
To disable sandboxing, just add sandbox: false to your webPreferences on window creation:
// ...
// Create the browser window.
const mainWindow = new BrowserWindow({
title: "Electron",
minWidth: 800,
minHeight: 600,
webPreferences: {
preload: path.join(__dirname, "preload.js"),
devTools: isDev,
sandbox: false, // fixes require() in preloader
},
});
// ...
I am trying to execute a binary file in linux when an electron app is started. In development mode, everything is working properly, but when I build the app binary file (which is part of the app) is not executed.
Here is the code where I`m executing the binary file:
const { spawn, exec } = require('child_process');
const startServer = () => {
const ls = exec('./binary');
ls.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
ls.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});
};
function createWindow() {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
icon: './electronJs.png',
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
});
mainWindow.loadURL(
url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true,
})
);
}
app.whenReady().then(() => {
createWindow();
startServer();
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
Directory path ./ is relative to generated executable file once packaged.
You should use __dirname to fully qualify your binary path and make it relative to the calling file.
const path = require('path')
const myexefilepath = path.join(__dirname, 'binary')
...
const ls = exec(myexefilepath);
If you use asar file format to package your app, previous solution won't work.
Your options then are:
Copy binary to the same folder where the generated executable file is.
Use app.getPath( name ) to get a path to a special directory where you can put your binary. My choice being name: userData
I'm trying to implement speech recognition into the electron application. The solution works in chrome browser, but does not work in electron. The application stops listening immediately - it probably has no microphone permission. How to grant permissions?
index.js
const electron = require('electron');
const url = require('url');
const path = require('path');
const { app, BrowserWindow, ipcMain } = electron;
let mainWindow;
ipcMain.on('close-me', (evt, arg) => {
app.quit()
})
app.on('ready', () => {
mainWindow = new BrowserWindow({
transparent: true,
frame: false,
webPreferences: {
nodeIntegration: true,
webviewTag: true
}
});
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'web/index.html'),
protocol: 'file',
slashes: true
}));
mainWindow.webContents.openDevTools();
mainWindow.setFullScreen(true);
});
index.html
<!doctype html>
<html lang="en">
<head>
<title></title>
<link rel="stylesheet" href="styles/style.css">
</head>
<body>
<div class="container">
<button id="rec"> rec</button>
<button id="endrec"> end</button>
</div>
<script src="scripts/speech.js"></script>
</body>
</html>
speech.js
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
const recognition = new SpeechRecognition();
recognition.lang = 'pl-PL';
const rec = document.querySelector('#rec');
const endrec = document.querySelector('#endrec');
recognition.onstart = function () {
console.log('I started');
}
recognition.onend = function () {
console.log('I finished');
}
recognition.onresult = function () {
console.log('Take what I recorded');
console.log(event);
const current = event.resultIndex;
const transcript = event.results[current][0].transcript;
console.log(transcript);
}
rec.addEventListener('click', () => {
recognition.start();
console.log('You clicked me');
})
endrec.addEventListener('click', () => {
recognition.stop();
})
I've also tried solutions with
webview.addEventListener('permissionrequest', function (e) {
if (e.permission === 'media') {
e.request.allow();
}
});
and
navigator.webkitGetUserMedia({ audio: true })
UPDATE
I found a reason to stop recognizing - error - network
I think you'll want to use the setPermissionRequestHandler on your session, like this:
const electron = require('electron');
const url = require('url');
const path = require('path');
const {
app,
BrowserWindow,
ipcMain,
session
} = electron;
let mainWindow;
ipcMain.on('close-me', (evt, arg) => {
app.quit()
})
app.on('ready', () => {
mainWindow = new BrowserWindow({
transparent: true,
frame: false,
webPreferences: {
nodeIntegration: true,
webviewTag: true
}
});
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'web/index.html'),
protocol: 'file',
slashes: true
}));
mainWindow.webContents.openDevTools();
mainWindow.setFullScreen(true);
session.fromPartition("default").setPermissionRequestHandler((webContents, permission, callback) => {
let allowedPermissions = ["audioCapture"]; // Full list here: https://developer.chrome.com/extensions/declare_permissions#manifest
if (allowedPermissions.includes(permission)) {
callback(true); // Approve permission request
} else {
console.error(
`The application tried to request permission for '${permission}'. This permission was not whitelisted and has been blocked.`
);
callback(false); // Deny
}
});
});
I've faced similar problem myself and found out that google doesn't provide speechAPI for CLI based apps like electron. Your best bet is to use either Google Cloud Speech API or any third-party API like Microsoft Cognitive Service.
Are you testing on MacOS? I faced a similar issue in my MBP, and below check solved the issue -
systemPreferences.askForMediaAccess(microphone)
See the Electron doc reference for additional details.
I am building an electron app. The app runs without any errors but does not open. I am running windows 7 on a 32 bit machine. My main.js file looks like this:
const {app, BrowserWindow} = require('electron');
const path = require('path');
const url = require('url');
// Initialize window
let win;
function createWindow() {
win = new BrowserWindow({
width: 800,
height: 600,
icon: __dirnaname+ '/assets/images/icon.jpg'
});
// Load Window
win.loadUrl(url.format({
pathname: path.join(__dirname, './index.html'),
protocol: 'file',
slashes: true
}));
// Close window
win.on('closed', () =>{
win = null;
});
//Run Create Window Function
win.on('ready', createWindow);
//Check Mac OS platform
app.on('all-window-closed', () => {
if(process.platform !== 'darwin') {
app.quit();
}
});
};
This line is wrong
win.on('ready', createWindow);
you meant
app.on('ready', createWindow);
outside of createWindow's scope. Like this:
function createWindow() {
...
};
app.on('all-window-closed', () => {
...
});
app.on('ready', createWindow);
I had the same problem after I upgraded electron from v3.x to v8.x it started working
I'm trying to receive the name of a new file from the front-end using ipcRenderer, sending it to electron and using ipcMain to listen to this event and load a new view for the window. However, the loadURL re-renders the same view. I've checked and made sure that the correct name is sent back back and that the path to the file is correct.
Here is a code snippet of the two method calls:
let win
const createWindow = () => {
win = new BrowserWindow({width: 800, height: 600})
win.loadURL(url.format({
pathname: path.join(__dirname, '/src/index.ejs'),
protocol: 'file:',
slashes: true
}));
};
app.on('ready', createWindow);
ipcMain.on('redirectToView', (event, metadata) => {
const pathToView = `${__dirname}/src/views/${metadata.viewName}.ejs`;
const URL = url.format({
pathname: pathToView,
protocol: 'file:',
slashes: true
})
win.loadURL(URL);
})