Capawesome May 2025 Update¶
The Capawesome May update is here! This update includes new features and improvements for Capawesome Cloud and our Plugins. Let's take a look at the most important changes.
Blog¶
Check out our latest blog post How to Securely Store Credentials with Capacitor to learn how to securely store credentials and authenticate users using the Biometrics and Secure Preferences plugins. It's a cross-platform solution that works on both Android and iOS, and it provides a secure way to store sensitive information such as passwords, tokens, or other credentials.
CLI¶
The Capawesome CLI has been updated with several new commands and improvements this month.
New apps:channels:get
command¶
The new apps:channels:get
command allows you to retrieve information about a specific channel in your app. You can use this command to get details such as the channel's ID, name, and metadata. In combination with the --json
option, you can easily integrate this command into your scripts or workflows to automate tasks related to your app's channels.
For example, the following command retrieves the information about a specific channel in JSON format and extracts the channel ID using jq:
New apps:channels:list
command¶
The new apps:channels:list
command allows you to list all channels in your app. You can use this command to get an overview of all channels and their metadata. Again, you can use the --json
option to get the output in JSON format, which makes it easy to integrate into your scripts or workflows. Thanks to the --limit
and --offset
options, you can also paginate through the list of channels.
New apps:channels:update
command¶
The new apps:channels:update
command allows you to update the name or bundle limit of a specific channel in your app.
npx capawesome apps:channels:update --app-id my-app-id --channel-id my-channel-id --name "New Channel Name" --bundle-limit 100
Cloud¶
New Logs page¶
We have introduced a new Logs page in the Capawesome Cloud Console. This page allows you to view and filter logs for your app, making it easier to debug your implementation when getting started. View detailed information on requests and responses, including status and body, to help you identify issues before they become critical. Read more about the new Logs page in the docs.
Plugins¶
Audio Recorder¶
The Audio Recorder plugin got several new features and improvements this month.
New bitRate
property¶
The StartRecordingOptions
now includes a new bitRate
property. This property allows you to specify the audio encoding bit rate in bits per second (bps) for the recorded audio. This gives you more control over the audio quality and file size of the recording.
import { AudioRecorder } from '@capawesome-team/capacitor-audio-recorder';
const startRecording = async () => {
await AudioRecorder.startRecording({
bitRate: 128000, // 128 kbps
});
};
New duration
property¶
The StopRecordingResult
and RecordingStoppedEvent
now include a new duration
property. This property provides the duration of the recorded audio in milliseconds, allowing you to easily access the length of the recording.
import { AudioRecorder } from '@capawesome-team/capacitor-audio-recorder';
const stopRecording = async () => {
const { blob, duration, uri } = await AudioRecorder.stopRecording();
console.log(`Recording duration: ${duration} ms`);
};
New sampleRate
property¶
The StartRecordingOptions
now includes a new sampleRate
property. This property allows you to specify the sample rate for the recorded audio. Just like the bitRate
property, this gives you more control over the audio quality and file size of the recording. The sample rate is specified in Hertz (Hz) and can be set to common values such as 44100 Hz or 48000 Hz.
import { AudioRecorder } from '@capawesome-team/capacitor-audio-recorder';
const startRecording = async () => {
await AudioRecorder.startRecording({
sampleRate: 44100,
});
};
This property is optional and defaults to 44100 if not specified.
New recordingPaused
event¶
In order to handle audio interruptions, the plugin now emits a new recordingPaused
event. This event is triggered when the recording is paused, allowing you to handle any necessary actions in your app.
import { AudioRecorder } from '@capawesome-team/capacitor-audio-recorder';
AudioRecorder.addListener('recordingPaused', () => {
console.log('Recording paused');
});
Biometrics¶
We have published a new Biometrics plugin. This plugin allows you to use biometric authentication (such as fingerprint or face recognition) in your Capacitor app. The plugin provides a simple API for authenticating users and checking if biometric authentication is available on the device. The plugin is available on Android and iOS.
import { Biometrics, ErrorCode } from '@capawesome-team/capacitor-biometrics';
const authenticate = async () => {
try {
await Biometrics.authenticate({
title: 'Authentication Required',
subtitle: 'Please authenticate to continue',
cancelButtonText: 'Cancel',
iosFallbackButtonText: 'Use Passcode',
});
} catch (error) {
if (error.code === ErrorCode.USER_CANCELED) {
console.log('User canceled the authentication.');
} else if (error.code === ErrorCode.NOT_ENROLLED) {
console.log('No biometric authentication enrolled.');
} else if (error.code === ErrorCode.NOT_AVAILABLE) {
console.log('Biometric authentication not available.');
} else {
console.log('Another error occurred:', error);
}
}
};
Check out the announcement post for more details.
Contacts¶
The Contacts plugin has received several new features and improvements this month.
New displayContactById(...)
method¶
The displayContactById(...)
method allows you to display a contact in the system's default contacts app. This is useful for apps that need to show contact details without having to implement a custom UI.
import { Contacts } from '@capawesome-team/capacitor-contacts';
const displayContact = async (id: string) => {
await Contacts.displayContactById({
id,
});
};
You just need to pass the contact ID of the contact you want to display. The system will then open the default contacts app and show the contact details.
New updateContactById(...)
and displayUpdateContactById(...)
methods¶
The updateContactById(...)
method allows you to update an existing contact by its ID. This is useful for apps that need to modify contact details without having to create a new contact.
import { Contacts } from '@capawesome-team/capacitor-contacts';
const updateContactById = async (id: string) => {
await Contacts.updateContactById({
id,
contact: {
givenName: 'John',
familyName: 'Doe'
}
});
};
It's important to note that all fields are required to be provided when updating a contact, even if you only want to change one field. Fields that are not provided will be removed from the contact. This behavior will be improved in a future release to allow partial updates.
In addition, the displayUpdateContactById(...)
method allows you to display a contact in the system's default contacts app with the option to update it.
import { Contacts } from '@capawesome-team/capacitor-contacts';
const displayUpdateContact = async (id: string) => {
await Contacts.displayUpdateContactById({
id,
});
};
This way, you don't have to implement a custom UI for updating contacts, and you can leverage the system's default contacts app for this purpose.
New countContacts(...)
method¶
The countContacts(...)
method allows you to count the number of contacts in the device's contacts database. This allows you to show the number of contacts in your app without having to fetch all contacts.
import { Contacts } from '@capawesome-team/capacitor-contacts';
const countContacts = async () => {
const { count } = await Contacts.countContacts();
console.log(`Number of contacts: ${count}`);
};
Accounts and Groups support¶
The plugin now supports Android accounts and iOS groups. This allows you to manage contacts that are associated with specific accounts or groups, making it easier to organize and access contacts in your app.
For example, on Android, you can retrieve the accounts associated with the device using the getAccounts(...)
method:
import { Contacts } from "@capawesome-team/capacitor-contacts";
const getAccounts = async () => {
const { accounts } = await Contacts.getAccounts();
return accounts;
};
You can then create a contact and associate it with an account using the account
property of the Contact
object:
import { Contacts } from "@capawesome-team/capacitor-contacts";
const createContact = async () => {
return Contacts.createContact({
contact: {
account: {
name: 'john@doe.tld',
type: 'com.google'
},
givenName: 'John',
familyName: 'Doe'
},
});
};
On iOS, you can retrieve the groups associated with the device using the getGroups(...)
method:
import { Contacts } from "@capawesome-team/capacitor-contacts";
const getGroups = async () => {
const { groups } = await Contacts.getGroups();
return groups;
};
Just like with accounts, you can create a contact and associate it with one (or more) group(s) using the groupIds
property of the Contact
object:
import { Contacts } from "@capawesome-team/capacitor-contacts";
const createContact = async () => {
return Contacts.createContact({
contact: {
groupIds: ['904DE809-D144-4562-8552-DFEB91F0E4BD:ABGroup'],
givenName: 'John',
familyName: 'Doe'
},
});
};
You can even create a new group using the createGroup(...)
method:
import { Contacts } from "@capawesome-team/capacitor-contacts";
const createGroup = async () => {
return Contacts.createGroup({
group: {
name: 'Friends'
}
});
};
Pagination support¶
That's not all! The plugin now supports pagination for fetching contacts. This allows you to fetch contacts in smaller chunks, which can improve performance and reduce memory usage, especially when dealing with a large number of contacts.
import { Contacts } from '@capawesome-team/capacitor-contacts';
const getContacts = async () => {
const { contacts } = await Contacts.getContacts({
limit: 10, // Fetch 10 contacts at a time
offset: 0, // Start from the first contact
});
console.log(contacts);
};
Secure Preferences¶
We have published a new Secure Preferences plugin. This plugin is a drop-in replacement for the Capacitor Preferences plugin and and allows you to securely store key/value pairs such as passwords, tokens or other sensitive information.
import { SecurePreferences } from '@capawesome-team/capacitor-secure-preferences';
const set = async () => {
await SecurePreferences.set({
key: 'password',
value: '123456',
});
};
const get = async () => {
const { value } = await SecurePreferences.get({
key: 'password',
});
console.log(value);
};
Check out the announcement post for more details.
Wifi¶
New addNetwork(...)
method¶
The Wifi plugin now includes a new addNetwork(...)
method. This method displays a system dialog that allows the user to add a new Wi-Fi network with predefined credentials. This is useful for apps that require the user to connect to a specific Wi-Fi network.
import { Wifi } from '@capawesome-team/capacitor-wifi';
const addNetwork = async () => {
await Wifi.addNetwork({
ssid: 'MyNetwork',
password: 'MyPassword',
});
}
Here is a short video demonstrating how this looks like in practice on Android: