---
title: Capawesome December 2024 Update
description: The Capawesome December update is here! This update includes new features and improvements for Capawesome Cloud and our Plugins.
date: 
  created: 2024-12-31
  updated: 2026-07-08
authors:
  - robingenz
categories:
  - Updates
---

# Capawesome December 2024 Update

The Capawesome December update is here! This update includes new features and improvements for [Capawesome Cloud](../../cloud/index.md) and our [Plugins](../../sdks/capacitor/index.md). There are also some news from the community. Let's take a look at the most important changes.

<!-- more -->

<div class="capawesome-z29o10a">
  <a href="/" target="_blank">
    <img alt="Deliver Live Updates to your Capacitor app with Capawesome Cloud" src="https://capawesome.io/assets/banners/cloud-build-and-deploy-capacitor-apps.png?t=1" />
  </a>
</div>

In case you missed it, check out the [November 2024 update](./2024-november-update.md) to catch up on what shipped last month.

## CLI

### `login` command no longer creates tokens

Until now, the `login` command created a new token every time you logged in using email and password.
However, tokens were originally only intended for the API and CI/CD. 
To avoid confusion, the `login` command no longer creates tokens. 
Instead, a session is created, which is automatically deleted after 30 days of inactivity.

## Cloud

### Unsubscribe from notifications

You can now unsubscribe from notifications via the [Capawesome Cloud Console](https://console.cloud.capawesome.io/settings/notifications){:target="_blank"}. Simply navigate to the `Notifications` page and select the notifications you want to subscribe to or unsubscribe from.

<figure>
  <video controls="true" allowfullscreen="true" autoplay="true">
    <source src="/docs/assets/videos/posts/cloud-notifications-subscriptions.mp4" type="video/mp4">
  </video>
</figure>

### Manage sessions

You can now manage your sessions via the [Capawesome Cloud Console](https://console.cloud.capawesome.io/settings/sessions){:target="_blank"}. Simply navigate to the `Sessions` page and view all your active sessions. You can also revoke sessions if needed.

<figure>
  <video controls="true" allowfullscreen="true" autoplay="true">
    <source src="/docs/assets/videos/posts/20241231_cloud-sessions.mp4" type="video/mp4">
  </video>
</figure>

## Plugins

### Android Foreground Service

The [Capacitor Android Foreground Service plugin](../../sdks/capacitor/android-foreground-service.md) now has a new `serviceType` option that allows you to specify the type of the foreground service:

```ts
import { ForegroundService, ServiceType } from '@capawesome-team/capacitor-android-foreground-service';

const startForegroundService = async () => {
  await ForegroundService.startForegroundService({
    id: 1,
    title: 'Recording',
    body: 'Recording audio in the background',
    smallIcon: 'ic_stat_icon_config_sample',
    serviceType: ServiceType.Microphone
  });
};
```

For now, only two service types are supported. Feel free to open an issue if you are missing a specific service type.

### App Shortcuts

We have published a new [Capacitor App Shortcuts plugin](../../sdks/capacitor/app-shortcuts.md) that allows you to manage app shortcuts and quick actions on Android and iOS. 
The plugin can be installed via the public npm registry:

```bash
npm install @capawesome/capacitor-app-shortcuts
```

Here is an example of how to use the plugin:

```typescript
import { AppShortcuts } from '@capawesome/capacitor-app-shortcuts';

const set = async () => {
  await AppShortcuts.set({
    shortcuts: [
      {
        id: 'feedback',
        title: 'Feedback',
      }
    ],
  });
};
```

| Android                                                                                                     | iOS                                                                                                         |
| ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| <image src="https://github.com/user-attachments/assets/58ac7272-de12-457f-a047-8f1f1e08ef52" width="324" /> | <video src="https://github.com/user-attachments/assets/6de8e629-8c31-4383-ba1a-faa921117128" width="324" /> |

### Firebase Analytics

The [Capacitor Firebase Analytics plugin](../../sdks/capacitor/firebase/analytics.md) now supports the Firebase JS SDK 11.

### Firebase App

The [Capacitor Firebase App plugin](../../sdks/capacitor/firebase/app.md) now supports the Firebase JS SDK 11.

### Firebase App Check

The [Capacitor Firebase App Check plugin](../../sdks/capacitor/firebase/app-check.md) now supports the Firebase JS SDK 11.

### Firebase Authentication

The [Capacitor Firebase Authentication plugin](../../sdks/capacitor/firebase/authentication.md) received multiple updates this month.

##### Firebase JS SDK 11

The plugin now supports the Firebase JS SDK 11.

##### Facebook iOS SDK

The [Facebook iOS SDK](https://github.com/facebook/facebook-ios-sdk){:target="_blank"} was updated to version 17.1.0.

##### New `idTokenChange` listener

The plugin now has a new `idTokenChange` listener that allows you to listen for changes to the ID token:

```ts
import { FirebaseAuthentication } from '@capacitor-firebase/authentication';

const addListener = async () => {
  FirebaseAuthentication.addListener('idTokenChange', async (event) => {
    console.log(event);
  });
};
```

##### New `verifyBeforeUpdateEmail` method

The plugin now has a new `verifyBeforeUpdateEmail` method that allows you to verify the email before updating it:

```ts
import { FirebaseAuthentication } from '@capacitor-firebase/authentication';

const verifyBeforeUpdateEmail = async () => {
  await FirebaseAuthentication.verifyBeforeUpdateEmail({
    newEmail: 'mail@example.com',
    actionCodeSettings: {
      url: 'https://www.example.com/cart?email=user@example.com&cartId=123',
      iOS: {
        bundleId: 'com.example.ios'
      },
      android: {
        packageName: 'com.example.android',
        installApp: true,
        minimumVersion: '12'
      },
      handleCodeInApp: true
    }
  });
};
```

### Firebase Cloud Firestore

The [Capacitor Firebase Cloud Firestore plugin](../../sdks/capacitor/firebase/cloud-firestore.md) now supports the Firebase JS SDK 11.

### Firebase Cloud Functions

The [Capacitor Firebase Cloud Functions plugin](../../sdks/capacitor/firebase/cloud-functions.md) received multiple updates this month.

##### Firebase JS SDK 11

The plugin now supports the Firebase JS SDK 11.

##### New `regionOrCustomDomain` option

The `UseEmulatorOptions` interface now has a new `regionOrCustomDomain` option that allows you to specify the region or custom domain for the emulator:

```ts
import { FirebaseFunctions } from '@capacitor-firebase/functions';

const useEmulator = async () => {
  await FirebaseFunctions.useEmulator({
    host: '10.0.2.2',
    port: 9001,
    regionOrCustomDomain: 'us-central1'
  });
};
```

### Firebase Cloud Messaging

The [Capacitor Firebase Cloud Messaging plugin](../../sdks/capacitor/firebase/cloud-messaging.md) now supports the Firebase JS SDK 11.

### Firebase Cloud Storage

The [Capacitor Firebase Cloud Storage plugin](../../sdks/capacitor/firebase/cloud-storage.md) now supports the Firebase JS SDK 11.

### Firebase Performance Monitoring

The [Capacitor Firebase Performance Monitoring plugin](../../sdks/capacitor/firebase/performance-monitoring.md) received multiple updates this month.

##### Firebase JS SDK 11

The plugin now supports the Firebase JS SDK 11.

##### New methods

The plugin got a few new methods that allow you to put and get attributes and metrics for a trace:

```ts
import { FirebasePerformance } from '@capacitor-firebase/performance';

const putAttribute = async () => {
  await FirebasePerformance.putAttribute({
    traceName: 'test_trace',
    attribute: 'user_id',
    value: '123',
  });
};

const getAttribute = async () => {
  const result = await FirebasePerformance.getAttribute({
    traceName: 'test_trace',
    attribute: 'user_id',
  });
  return result.attributes;
};

const getAttributes = async () => {
  const result = await FirebasePerformance.getAttributes({ traceName: 'test_trace' });
  return result.attributes;
};

const removeAttribute = async () => {
  await FirebasePerformance.removeAttribute({
    traceName: 'test_trace',
    attribute: 'user_id',
  });
};

const putMetric = async () => {
  await FirebasePerformance.putMetric({
    traceName: 'test_trace',
    metricName: 'item_cache_hit',
    num: 1,
  });
};

const getMetric = async () => {
  const result = await FirebasePerformance.getMetric({
    traceName: 'test_trace',
    metricName: 'item_cache_hit',
  });
  return result.value;
};

const record = async () => {
  await FirebasePerformance.record({
    traceName: 'test_trace',
    startTime: Date.now(),
    duration: 1000,
    options: {
      metrics: {
        item_cache_hit: 1,
      },
      attributes: {
        user_id: '123',
      },
    },
  });
};
```

### Firebase Remote Config

The [Capacitor Firebase Remote Config plugin](../../sdks/capacitor/firebase/remote-config.md) now supports the Firebase JS SDK 11.

### Live Update

The [Capacitor Live Update plugin](../../sdks/capacitor/live-update.md) received multiple updates this month.

##### New `getCurrentBundle()` and `getNextBundle()` methods

The plugin now has new [`getCurrentBundle()`](../../sdks/capacitor/live-update.md#getcurrentbundle) and [`getNextBundle()`](../../sdks/capacitor/live-update.md#getnextbundle) methods that allow you to get the current and next bundle:

```ts
import { LiveUpdate } from '@capawesome/capacitor-live-update';

/**
 * Get the bundle identifier of the current bundle. 
 * The current bundle is the bundle that is currently used by the app.
 */
const getCurrentBundle = async () => {
  const { bundleId } = await LiveUpdate.getCurrentBundle();
  return bundleId;
};

/**
 * Get the bundle identifier of the next bundle. 
 * The next bundle is the bundle that will be used after calling `reload()` or restarting the app.
 */
const getNextBundle = async () => {
  const { bundleId } = await LiveUpdate.getNextBundle();
  return bundleId;
};
```

This change deprecated the [`getBundle()`](../../sdks/capacitor/live-update.md#getbundle) method.

##### New `setNextBundle(...)` method

The plugin now has a new [`setNextBundle(...)`](../../sdks/capacitor/live-update.md#setnextbundle) method that allows you to set the next bundle:

```ts
import { LiveUpdate } from '@capawesome/capacitor-live-update';

/**
 * Set the next bundle. 
 * The next bundle is the bundle that will be used after calling `reload()` or restarting the app.
 */
const setNextBundle = async () => {
  await LiveUpdate.setNextBundle({
    bundleId: '4b678425-fe57-485d-a8ff-a08af915bd29',
  });
};
```

This change deprecated the [`setBundle(...)`](../../sdks/capacitor/live-update.md#setbundle) method.

##### New `channel` property

The [`fetchLatestBundle(...)`](../../sdks/capacitor/live-update.md#fetchlatestbundle) and [`sync(...)`](../../sdks/capacitor/live-update.md#sync) methods now have a new `channel` property that allows you to specify the name of the channel where the latest bundle is fetched from:

```ts
import { LiveUpdate } from '@capawesome/capacitor-live-update';

/**
 * Fetch the latest bundle from the specified channel.
 */
const fetchLatestBundle = async () => {
  const result = await LiveUpdate.fetchLatestBundle({
    channel: 'production-5',
  });
  return result;
};

/**
 * Sync the latest bundle from the specified channel.
 */
const sync = async () => {
  const result = await LiveUpdate.sync({
    channel: 'production-5',
  });
  return result;
};
```

##### New `FetchLatestBundleResult` properties

The [`fetchLatestBundle(...)`](../../sdks/capacitor/live-update.md#fetchlatestbundle) method now returns a `artifactType` and `downloadUrl` property:

```ts
import { LiveUpdate } from '@capawesome/capacitor-live-update';

const fetchLatestBundle = async () => {
  const result = await LiveUpdate.fetchLatestBundle();
  return {
    artifactType: result.artifactType,
    bundleId: result.bundleId,
    downloadUrl: result.downloadUrl,
  };
};
```

### NFC

The [Capacitor NFC plugin](../../sdks/capacitor/nfc.md) received multiple updates this month.

##### New `manufacturerCode` property

The plugin is now also able to read the IC Manufacturer Code for ISO15693 tags:

```ts
import { Nfc, NfcTagTechType } from '@capawesome-team/capacitor-nfc';

const readManufacturerCode = async () => {
  return new Promise((resolve) => {
    Nfc.addListener('nfcTagScanned', async (event) => {
      // Stop the NFC scan session
      await Nfc.stopScanSession();
      // Return the IC Manufacturer Code
      resolve(event.nfcTag.manufacturerCode);
    });
    // Start the NFC scan session
    void Nfc.startScanSession();
  });
};
```

##### HCE support

The plugin now supports [Host Card Emulation (HCE)](https://developer.android.com/develop/connectivity/nfc/hce){:target="_blank"} on Android. 
This allows you to emulate an NFC tag on your device and respond to commands from an NFC reader. 
Here is an example of how to use this feature:

```ts
import { Nfc } from '@capawesome-team/capacitor-nfc';

const addListener = async () => {
  Nfc.addListener('commandReceived', async (event) => {
    // Do something with the received command
    console.log(event.data);
    // Respond to the command
	  await respond({ data: [...] });
  });
};
```

##### 0x24 command support

The plugin now supports the Write Multiple Blocks command (0x24 command code), as defined in the ISO 15693-3 specification, also on iOS:

```ts
import { Nfc, NfcTagTechType } from '@capawesome-team/capacitor-nfc';

const writeMultipleBlocks = async () => {
  return new Promise((resolve) => {
    Nfc.addListener('nfcTagScanned', async (event) => {
      // Write multiple blocks to the NFC tag
      await Nfc.transceive({ 
        techType: NfcTagTechType.NfcV, 
        data: [...], 
        iso15693RequestFlags: [...], 
        iso15693CommandCode: 0x24 
      });
      // Stop the NFC scan session
      await Nfc.stopScanSession();
      resolve();
    });
    // Start the NFC scan session
    void Nfc.startScanSession();
  });
};
```

### Printer

The [Capacitor Printer plugin](../../sdks/capacitor/printer.md) now also supports the web, at least with the `printWebView` method:

```typescript
import { Printer } from '@capawesome-team/capacitor-printer';

const print = async () => {
  await Printer.printWebView({
    content: '<h1>Hello, World!</h1>',
  });
};
```

You can also use a print style sheet to customize the print output:

```css
@media print {
  h1 {
    color: red;
  }
}
```

For more information, check out the [mdn web docs](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_media_queries/Printing){:target="_blank"}.

### Speech Recognition

We have published a new [Capacitor Speech Recognition plugin](../../sdks/capacitor/speech-recognition.md) that allows you to transcribe speech to text. 
The plugin supports Android, iOS, and the web. 
It comes with a simple API that allows you to start and stop the recognition process:

```typescript
import { SpeechRecognition } from '@capawesome-team/capacitor-speech-recognition';

const startListening = async () => {
  // Print the recognized text to the console
  await SpeechRecognition.addListener('result', (event) => {
    console.log('Result:', event.result);
  });
  // Start listening for speech
  await SpeechRecognition.startListening({
    language: 'en-US',
    silenceThreshold: 2000,
  });
};
```

Besides that, there are a few special features like the ability to set a silence threshold.
The plugin is now available to all [Capawesome Insiders](../../insiders/index.md).

### Speech Synthesis

We have also published a new [Capacitor Speech Synthesis plugin](../../sdks/capacitor/speech-synthesis.md) that allows you to convert text to speech.
The plugin supports Android, iOS, and the web.
You can customize the voice, pitch, and rate of the speech.
Here is an example of how to use the plugin:

```typescript
import { SpeechSynthesis, QueueStrategy } from '@capawesome-team/capacitor-speech-synthesis';

const speak = async () => {
  // Print every spoken word to the console
  await SpeechSynthesis.addListener('boundary', (event) => {
    console.log('boundary', event);
  });
  // Speak the text
  await SpeechSynthesis.speak({
    language: 'en-US',
    pitch: 1.0,
    queueStrategy: QueueStrategy.Add,
    rate: 1.0,
    text: 'Hello, World!',
    voiceId: 'com.apple.ttsbundle.Samantha-compact',
    volume: 1.0,
  });
};
```

The plugin is now available to all [Capawesome Insiders](../../insiders/index.md).

### Torch

The [Capacitor Torch plugin](../../sdks/capacitor/torch.md) now also supports the web using the [Media Capture and Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Media_Capture_and_Streams_API){:target="_blank"}:

```typescript
import { Torch } from '@capawesome/capacitor-torch';

const enable = async () => {
  await Torch.enable();
};
```

### Wifi

The [Capacitor Wifi plugin](../../sdks/capacitor/wifi.md) got a new configuration option that allows you to force the usage of the deprecated `WifiManager` API on Android as there have been several reports that the new `WifiNetworkSpecifier` API is not yet working as expected on some devices.

You can enable the `useWifiManager` option in the Capacitor configuration file:

```json
{
  "plugins": {
    "Wifi": {
      "useWifiManager": true
    }
  }
}
```

## Community

### Build a mobile app with Qwik and Capacitor

[@srapport](https://github.com/srapport){:target="_blank"} published the official [Qwik for iOS and Android](https://qwik.dev/docs/guides/capacitor/){:target="_blank"} guide this month. The guide explains how to create a mobile app for Android and iOS with Qwik using Capacitor and highlights what you need to pay attention to. This also includes a short introduction to the Capacitor Live Update plugin from Capawesome. Check out the guide [here](https://qwik.dev/docs/guides/capacitor/){:target="_blank"}.
