Capacitor Network Bug? Problem? Help Me

HI my name is Cristian

Problem Description

Hi my name is Cristian,I am developing an application using Capacitor on macOS. I am using Vite as the web development framework and Android Studio to deploy the app to an Android device. While everything works perfectly in the Vite environment, I am encountering issues when running the app on an Android device through Android Studio, specifically with module resolution, Android permissions, and the @capacitor/network plugin listeners.


Errors Encountered

  1. Module Resolution Error for @capacitor/core:

In the Android Studio Logcat console, the following error appears:

TypeError: Failed to resolve module specifier ā€œ@capacitor/coreā€. Relative references must start with either ā€œ/ā€, ā€œ./ā€, or ā€œā€¦/ā€.

This error indicates that the @capacitor/core module is not being resolved correctly in the Android native environment. The module works perfectly in the Vite environment.

  1. Listener Registration Error for networkStatusChange:

Even though I implemented a listener for the networkStatusChange event in the @capacitor/network plugin, the following message appears in Logcat:

Notifying listeners for event networkStatusChange
No listeners found for event networkStatusChange

This suggests that the plugin attempts to notify changes in network status but does not recognize any registered listeners, even though the listener is configured in the code.

  1. Potential Issue with Android Permissions:

I have reviewed the Capacitor documentation and followed tutorials to ensure all required Android permissions for the @capacitor/network plugin are set up. Despite this, the issue persists, suggesting that I might have missed something critical in the configuration.


Development Environment

  • Operating System: macOS
  • Web Framework: Vite
  • IDE: Android Studio
  • Test Platform: Physical Android Device
  • Capacitor:
    • @capacitor/cli: 6.2.0
    • @capacitor/core: 6.2.0
    • @capacitor/network: 6.0.3

Code Implementation

Listener Registration:

import { Network } from '@capacitor/network';

const initializeApp = async () => {
  // Register the listener for network status changes
  Network.addListener('networkStatusChange', (status) => {
    console.log('Network status changed:', status);
  });

  // Get the current network status
  const status = await Network.getStatus();
  console.log('Current network status:', status);
};

// Call the initialization function
initializeApp();

Steps Taken

  1. Early Listener Registration:

    • Ensured that the listener is registered during the initialization of the app.
    • Verified that the listener remains active during application lifecycle changes (pause, resume, etc.).
  2. Full Synchronization:

    • Ran npx cap sync to ensure the plugins are correctly synced with the native platforms.
  3. Route Validation:

    • Verified that the import paths (@capacitor/core, @capacitor/network) are correct and work perfectly in the Vite environment.
  4. Capacitor Configuration:

    • capacitor.config.json file:
{
  "appId": "com.testCapacitor.app",
  "appName": "app-nativa",
  "webDir": "www",
  "bundledWebRuntime": false
}
  1. Android Permissions:
    • Added the following permissions to the AndroidManifest.xml file:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
  • Verified that the permissions are declared correctly, but the issue persists.
  1. Additional Testing:
    • Tried setting "bundledWebRuntime": true, but it did not resolve the listener issue.
    • Updated Capacitor and all plugins to their latest versions.

Expectation

I am seeking guidance on the following:

  1. Why the @capacitor/core module is not resolving correctly on Android.
  2. Why the @capacitor/network plugin does not recognize the registered listeners.
  3. Whether there are additional configurations needed to make Capacitor compatible with Vite and Android Studio.
  4. If there are any specific Android permissions or configuration steps I might have missed.
  5. If there are any known issues with the current versions of Capacitor or the @capacitor/network plugin.

Appreciation

Thank you in advance for any guidance or solutions you can provide to resolve these issues. I am happy to share further details or perform additional testing if necessary.

I would focus on fixing the errors with @capacitor/core first. My guess is that fixing that will fix registering the listeners.

I am little confused though. You say Vite is the web framework you are using but Vite isnā€™t a web framework. It is just a build tool. Are you using a JS framework like Vue/React or are you just using plain JS?

Can you share your Vite config file?

Thank you for your response. I might be confused about a system and may have explained it incorrectly.

Vite is the build tool I use to view the page as a server in a WebView. The code is written in plain JavaScript since I come from Noodl.

When I run tests with Vite, both the code and the plugin work perfectly. However, when testing on Android using the same code from VS Code and then syncing with npx cap sync android, issues arise.

This app is connected to my Android mobile device, and when I check the logs in Logcat, it shows an error related to the listeners in the code.

Also, how did you install Capacitor? Assuming you followed the guide - Installing Capacitor | Capacitor Documentation

Hereā€™s the revised version including the additional context:


I configured everything as outlined in the Capacitor documentation, including the Vite configuration. Iā€™ve tested it both with and without the Vite setup. Note that the output folder is the same as the input folder, but I havenā€™t exported anything yet since I havenā€™t reached that step. So far, Iā€™ve only been running tests in development mode, and these have been successful when I run npm run dev.

If thereā€™s text in Spanish, itā€™s because Iā€™m in Chile and speak Spanish.

import { defineConfig } from ā€˜viteā€™;

export default defineConfig({
root: ā€˜./wwwā€™, // Establece ā€˜wwwā€™ como la raĆ­z del proyecto
build: {
outDir: ā€˜./wwwā€™, // Carpeta de salida para la app exportada de Noodl
},
server: {
port: 3000, // Puerto para el servidor de desarrollo
},
});

To confirm, you have a www build folder within your root www folder (after you run npx vite build)?

Can you screenshot your folder structure from the root of your project?

Itā€™s looking like your folder structure/config is incorrect. In your Capacitor config, you set webDir to www but itā€™s probably www/www. Not certain without seeing your entire folder structure.

My guess is that your build is out-of-date or Capacitor is not copying the right files when you run npx cap sync. Before you run that command, you do need to do a production build of your app by running npx vite build.

If you donā€™t want to have to do a production build every time to test on Android, you can run in livereload mode by running in one terminal npm run dev and then in another terminal npx cap run android -l (see cap run).

Iā€™ve tested the build folder in two ways: as www and as dist. However, this creates an issue because, originally, I believe the folder that Android listens to is www. I could be mistaken, but thatā€™s why I havenā€™t run npm run build yetā€”Iā€™ve only been using npm run dev to work with the live version.

The issue arises when I send the app using npm run dev with Vite, where it works perfectly. However, when I build the app for Android, sync it using npx cap sync android, and then open it on the device, it doesnā€™t appear in Logcat as ā€œCapacitor Network,ā€ and the listeners donā€™t seem to work.

You might be right, and the problem could lie in the build process. Iā€™ll try this tomorrow. Thank you very muchā€”Iā€™ll keep you updated.

I personally would change Vite back to using defaults which is the dist folder by removing root and build.outDir then change your Capacitor config setting webDir to dist.

Android doesnā€™t listen to the www or dist folder. When you run npx cap sync Capacitor copies the build files from dist (assuming you configured dist instead of www :slight_smile:) to android/app/src/main/assets/public for Android. So, if you donā€™t build your project npx vite build before running npx cap sync, the most up-to-date files arenā€™t going to be copied to Android and thus not do what you expect.

Thank you very much! I will test this idea right now and review the folder configuration.

1 Like

I followed your advice, and now two things are happening: if I set www in the Capacitor config, the app shows up, but it doesnā€™t recognize the plugin. If I set dist, the plugin detects something, but the app doesnā€™t show up.

Hereā€™s my Capacitor config:

json

Copiar cĆ³digo

{
  "appId": "com.testCapacitor.app",
  "appName": "app-nativa",
  "webDir": "dist",
  "bundledWebRuntime": false
}

However, if I remove the routes in the Vite config, the app doesnā€™t show up in the web version. Iā€™ve tried setting the output path to ./dist, ../dist, and dist, but all of them cause issues.

import { defineConfig } from ā€˜viteā€™;

export default defineConfig({
root: ā€˜wwwā€™, // Carpeta raĆ­z de tu proyecto
build: {
outDir: ā€˜ā€¦/distā€™
},
base: ā€˜./ā€™, // Configura rutas relativas
}); import { defineConfig } from ā€˜viteā€™;

export default defineConfig({
root: ā€˜wwwā€™, // Carpeta raĆ­z de tu proyecto
build: {
outDir: ā€˜./distā€™
},
base: ā€˜./ā€™, // Configura rutas relativas
});
import { defineConfig } from ā€˜viteā€™;

export default defineConfig({
root: ā€˜wwwā€™, // Carpeta raĆ­z de tu proyecto
build: {
outDir: ā€˜/distā€™
},
base: ā€˜./ā€™, // Configura rutas relativas
});

Try the below for your Vite config - removing outDir and root altogether. root defaults to the current directory and outDir is relative to root. So without setting them explicitly, the dist folder should get created in your project root folder and Capacitor should find it when webDir is set to dist.

import { defineConfig } from 'vite'

export default defineConfig({
    server: {
        port: 3000, // Puerto para el servidor de desarrollo
    },
})

EDIT

This assumes your index.html is in the root folder of your project as well which is the standard for Vite.

Here is my workflow: I develop in Noodl, which recommends exporting to www. From there, I follow the normal route with Capacitor and Vite. Now, I implemented the code you gave me, and since itā€™s not in the root www folder, the app no longer works and cannot be deployed with npm run build. Thanks for all the help; I think weā€™re getting close.

Thanks, that screenshot is very helpful.

The problem I see with exporting to www, is that itā€™s mixed in with your source files at www/src.

If you want to keep it that way, then the following should work:

Vite Config

import { defineConfig } from 'vite'

export default defineConfig({
    root: 'www',
    build: {
        outDir: 'dist' // Should put it at www/dist since it's relative to root
    },
    server: {
        port: 3000, // Puerto para el servidor de desarrollo
    },
})

Capacitor Config

{
  "appId": "com.testCapacitor.app",
  "appName": "app-nativa",
  "webDir": "www/dist",
  "bundledWebRuntime": false
}

315s-Mac-mini:App Nativa estudio$ npx cap sync
[warn] The bundledWebRuntime configuration option has been deprecated. Can be safely deleted.
[error] Could not find the web assets directory: ./www/dist.
Please create it and make sure it has an index.html file. You can change the path of this directory in
capacitor.config.json (webDir option). You may need to compile the web assets for your app (typically npm run
build). More info: Development Workflow | Capacitor Documentation
315s-Mac-mini:App Nativa estudio$ npm run dev

Did you run npm run build (if you have this as a script) or npx vite build first? Like I said, you need the production build created first before running npx cap sync. The production build will create the www/dist folder.

Yes, but when I follow the steps, npm run build and then npx cap sync, I go to Android, run the app, and it shows a blank screen.

Sounds like progress :sweat_smile:

First, make sure you have files here android/app/src/main/assets/public. This is where cap sync copies the production build from www/dist.

A blank screen many times is due to a JS error. You can open up Chrome DevTools for the Android device by going to chrome://inspect/#devices in Chrome on your computer.

What Android device are you using? Physical or emulator? What Android version?

Yes, there is information in the path you mentioned. Now, when the Capacitor configuration was set to www, it displayed the page but didnā€™t recognize the plugin. In other words, it knew it was there but not the listener. Now itā€™s differentā€”it recognizes the listeners but not the page. Haha. Let me share it with you.


Ok, so it is a white screen due to those JS errors.

Just to confirm, you do have stuff at www/dist too?

I think you are closer or at least I hope you understand the file structure a little better :smiley:

Can you share a screenshot of whatā€™s in your www/dist and share the contents of your www/index.html file? I am not familiar with Noodl. Seems like Vite is not packaging up all the required modules/code.