@capgo/capacitor-android-usagestatsmanager 8.0.32 → 8.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -76,7 +76,7 @@ npx cap sync
76
76
  * [`queryAndAggregateUsageStats(...)`](#queryandaggregateusagestats)
77
77
  * [`isUsageStatsPermissionGranted()`](#isusagestatspermissiongranted)
78
78
  * [`openUsageStatsSettings()`](#openusagestatssettings)
79
- * [`queryAllPackages()`](#queryallpackages)
79
+ * [`queryAllPackages(...)`](#queryallpackages)
80
80
  * [`getPluginVersion()`](#getpluginversion)
81
81
  * [Interfaces](#interfaces)
82
82
  * [Type Aliases](#type-aliases)
@@ -137,15 +137,19 @@ This will always open the settings screen, even if the permission is already gra
137
137
  --------------------
138
138
 
139
139
 
140
- ### queryAllPackages()
140
+ ### queryAllPackages(...)
141
141
 
142
142
  ```typescript
143
- queryAllPackages() => Promise<{ packages: PackageInfo[]; }>
143
+ queryAllPackages(options?: QueryAllPackagesOptions | undefined) => Promise<{ packages: PackageInfo[]; }>
144
144
  ```
145
145
 
146
146
  Queries all installed packages on the device.
147
147
  Requires the QUERY_ALL_PACKAGES permission.
148
148
 
149
+ | Param | Type | Description |
150
+ | ------------- | --------------------------------------------------------------------------- | ------------------------- |
151
+ | **`options`** | <code><a href="#queryallpackagesoptions">QueryAllPackagesOptions</a></code> | - Optional query settings |
152
+
149
153
  **Returns:** <code>Promise&lt;{ packages: PackageInfo[]; }&gt;</code>
150
154
 
151
155
  **Since:** 1.2.0
@@ -211,14 +215,25 @@ Result of a usage stats permission check.
211
215
 
212
216
  Represents basic information about an installed package.
213
217
 
214
- | Prop | Type | Description |
215
- | ---------------------- | ------------------- | ---------------------------------------------- |
216
- | **`packageName`** | <code>string</code> | Package name |
217
- | **`appName`** | <code>string</code> | App display name |
218
- | **`versionName`** | <code>string</code> | Version name string |
219
- | **`versionCode`** | <code>number</code> | Version code number |
220
- | **`firstInstallTime`** | <code>number</code> | First install time in milliseconds since epoch |
221
- | **`lastUpdateTime`** | <code>number</code> | Last update time in milliseconds since epoch |
218
+ | Prop | Type | Description | Since |
219
+ | ---------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ |
220
+ | **`packageName`** | <code>string</code> | Package name | |
221
+ | **`appName`** | <code>string</code> | App display name | |
222
+ | **`versionName`** | <code>string</code> | Version name string | |
223
+ | **`versionCode`** | <code>number</code> | Version code number | |
224
+ | **`firstInstallTime`** | <code>number</code> | First install time in milliseconds since epoch | |
225
+ | **`lastUpdateTime`** | <code>number</code> | Last update time in milliseconds since epoch | |
226
+ | **`category`** | <code>number</code> | Application category from `ApplicationInfo.category`. Only available on Android 8.0 (API level 26) and above. Common values: - `0` — undefined - `1` — game - `2` — audio - `3` — video - `4` — image - `5` — social - `6` — news - `7` — maps - `8` — productivity | 8.0.33 |
227
+ | **`icon`** | <code>string</code> | App icon as a base64 data URL (`data:image/png;base64,...`). Only present when `queryAllPackages({ includeIcon: true })` is used. | 8.0.33 |
228
+
229
+
230
+ #### QueryAllPackagesOptions
231
+
232
+ Options for querying installed packages.
233
+
234
+ | Prop | Type | Description | Default |
235
+ | ----------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
236
+ | **`includeIcon`** | <code>boolean</code> | When true, includes each app's launcher icon as a base64 data URL. Defaults to false because icons significantly increase the response size. | <code>false</code> |
222
237
 
223
238
 
224
239
  ### Type Aliases
@@ -8,8 +8,13 @@ import android.content.Intent;
8
8
  import android.content.pm.ApplicationInfo;
9
9
  import android.content.pm.PackageInfo;
10
10
  import android.content.pm.PackageManager;
11
+ import android.graphics.Bitmap;
12
+ import android.graphics.Canvas;
13
+ import android.graphics.drawable.BitmapDrawable;
14
+ import android.graphics.drawable.Drawable;
11
15
  import android.os.Build;
12
16
  import android.provider.Settings;
17
+ import android.util.Base64;
13
18
  import android.util.Log;
14
19
  import androidx.annotation.NonNull;
15
20
  import com.getcapacitor.JSObject;
@@ -17,6 +22,7 @@ import com.getcapacitor.Plugin;
17
22
  import com.getcapacitor.PluginCall;
18
23
  import com.getcapacitor.PluginMethod;
19
24
  import com.getcapacitor.annotation.CapacitorPlugin;
25
+ import java.io.ByteArrayOutputStream;
20
26
  import java.io.PrintWriter;
21
27
  import java.io.StringWriter;
22
28
  import java.util.List;
@@ -25,7 +31,7 @@ import java.util.Map;
25
31
  @CapacitorPlugin(name = "CapacitorUsageStatsManager")
26
32
  public class CapacitorUsageStatsManagerPlugin extends Plugin {
27
33
 
28
- private final String pluginVersion = "8.0.32";
34
+ private final String pluginVersion = "8.1.1";
29
35
 
30
36
  @PluginMethod
31
37
  public void queryAndAggregateUsageStats(final PluginCall call) {
@@ -100,6 +106,7 @@ public class CapacitorUsageStatsManagerPlugin extends Plugin {
100
106
 
101
107
  @PluginMethod
102
108
  public void queryAllPackages(final PluginCall call) {
109
+ final boolean includeIcon = Boolean.TRUE.equals(call.getBoolean("includeIcon", false));
103
110
  PackageManager pm = getContext().getPackageManager();
104
111
  List<PackageInfo> packages = pm.getInstalledPackages(0);
105
112
  JSObject result = new JSObject();
@@ -108,12 +115,27 @@ public class CapacitorUsageStatsManagerPlugin extends Plugin {
108
115
  for (PackageInfo packageInfo : packages) {
109
116
  JSObject packageJS = new JSObject();
110
117
  packageJS.put("packageName", packageInfo.packageName);
118
+ ApplicationInfo appInfo = null;
111
119
  try {
112
- ApplicationInfo appInfo = pm.getApplicationInfo(packageInfo.packageName, 0);
120
+ appInfo = pm.getApplicationInfo(packageInfo.packageName, 0);
113
121
  packageJS.put("appName", pm.getApplicationLabel(appInfo).toString());
114
122
  } catch (PackageManager.NameNotFoundException e) {
115
123
  packageJS.put("appName", packageInfo.packageName);
116
124
  }
125
+ if (appInfo != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
126
+ packageJS.put("category", appInfo.category);
127
+ }
128
+ if (includeIcon && appInfo != null) {
129
+ try {
130
+ Drawable icon = pm.getApplicationIcon(appInfo);
131
+ String iconDataUrl = drawableToBase64DataUrl(icon);
132
+ if (iconDataUrl != null) {
133
+ packageJS.put("icon", iconDataUrl);
134
+ }
135
+ } catch (Exception e) {
136
+ Log.w("CapacitorUsageStatsManager", "Failed to load icon for " + packageInfo.packageName, e);
137
+ }
138
+ }
117
139
  packageJS.put("versionName", packageInfo.versionName);
118
140
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
119
141
  packageJS.put("versionCode", packageInfo.getLongVersionCode());
@@ -130,6 +152,34 @@ public class CapacitorUsageStatsManagerPlugin extends Plugin {
130
152
  call.resolve(result);
131
153
  }
132
154
 
155
+ private static String drawableToBase64DataUrl(Drawable drawable) {
156
+ if (drawable == null) {
157
+ return null;
158
+ }
159
+
160
+ Bitmap bitmap;
161
+ if (drawable instanceof BitmapDrawable) {
162
+ bitmap = ((BitmapDrawable) drawable).getBitmap();
163
+ if (bitmap == null) {
164
+ return null;
165
+ }
166
+ } else {
167
+ int width = drawable.getIntrinsicWidth() > 0 ? drawable.getIntrinsicWidth() : 1;
168
+ int height = drawable.getIntrinsicHeight() > 0 ? drawable.getIntrinsicHeight() : 1;
169
+ bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
170
+ Canvas canvas = new Canvas(bitmap);
171
+ drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
172
+ drawable.draw(canvas);
173
+ }
174
+
175
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
176
+ if (!bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream)) {
177
+ return null;
178
+ }
179
+
180
+ return "data:image/png;base64," + Base64.encodeToString(stream.toByteArray(), Base64.NO_WRAP);
181
+ }
182
+
133
183
  @NonNull
134
184
  private static JSObject getJsObject(Map.Entry<String, UsageStats> stat) {
135
185
  final UsageStats value = stat.getValue();
package/dist/docs.json CHANGED
@@ -109,10 +109,20 @@
109
109
  },
110
110
  {
111
111
  "name": "queryAllPackages",
112
- "signature": "() => Promise<{ packages: PackageInfo[]; }>",
113
- "parameters": [],
112
+ "signature": "(options?: QueryAllPackagesOptions | undefined) => Promise<{ packages: PackageInfo[]; }>",
113
+ "parameters": [
114
+ {
115
+ "name": "options",
116
+ "docs": "- Optional query settings",
117
+ "type": "QueryAllPackagesOptions | undefined"
118
+ }
119
+ ],
114
120
  "returns": "Promise<{ packages: PackageInfo[]; }>",
115
121
  "tags": [
122
+ {
123
+ "name": "param",
124
+ "text": "options - Optional query settings"
125
+ },
116
126
  {
117
127
  "name": "returns",
118
128
  "text": "Promise that resolves with an array of package information"
@@ -127,12 +137,13 @@
127
137
  },
128
138
  {
129
139
  "name": "example",
130
- "text": "```typescript\nconst { packages } = await UsageStatsManager.queryAllPackages();\npackages.forEach(pkg => {\n console.log(`${pkg.appName} (${pkg.packageName}): v${pkg.versionName}`);\n});\n```"
140
+ "text": "```typescript\nconst { packages } = await UsageStatsManager.queryAllPackages({ includeIcon: true });\npackages.forEach(pkg => {\n console.log(`${pkg.appName} (${pkg.packageName}): category=${pkg.category}`);\n});\n```"
131
141
  }
132
142
  ],
133
143
  "docs": "Queries all installed packages on the device.\nRequires the QUERY_ALL_PACKAGES permission.",
134
144
  "complexTypes": [
135
- "PackageInfo"
145
+ "PackageInfo",
146
+ "QueryAllPackagesOptions"
136
147
  ],
137
148
  "slug": "queryallpackages"
138
149
  },
@@ -346,6 +357,56 @@
346
357
  "docs": "Last update time in milliseconds since epoch",
347
358
  "complexTypes": [],
348
359
  "type": "number"
360
+ },
361
+ {
362
+ "name": "category",
363
+ "tags": [
364
+ {
365
+ "text": "8.0.33",
366
+ "name": "since"
367
+ }
368
+ ],
369
+ "docs": "Application category from `ApplicationInfo.category`.\nOnly available on Android 8.0 (API level 26) and above.\n\nCommon values:\n- `0` — undefined\n- `1` — game\n- `2` — audio\n- `3` — video\n- `4` — image\n- `5` — social\n- `6` — news\n- `7` — maps\n- `8` — productivity",
370
+ "complexTypes": [],
371
+ "type": "number | undefined"
372
+ },
373
+ {
374
+ "name": "icon",
375
+ "tags": [
376
+ {
377
+ "text": "8.0.33",
378
+ "name": "since"
379
+ }
380
+ ],
381
+ "docs": "App icon as a base64 data URL (`data:image/png;base64,...`).\nOnly present when `queryAllPackages({ includeIcon: true })` is used.",
382
+ "complexTypes": [],
383
+ "type": "string | undefined"
384
+ }
385
+ ]
386
+ },
387
+ {
388
+ "name": "QueryAllPackagesOptions",
389
+ "slug": "queryallpackagesoptions",
390
+ "docs": "Options for querying installed packages.",
391
+ "tags": [
392
+ {
393
+ "text": "8.0.33",
394
+ "name": "since"
395
+ }
396
+ ],
397
+ "methods": [],
398
+ "properties": [
399
+ {
400
+ "name": "includeIcon",
401
+ "tags": [
402
+ {
403
+ "text": "false",
404
+ "name": "default"
405
+ }
406
+ ],
407
+ "docs": "When true, includes each app's launcher icon as a base64 data URL.\nDefaults to false because icons significantly increase the response size.",
408
+ "complexTypes": [],
409
+ "type": "boolean | undefined"
349
410
  }
350
411
  ]
351
412
  }
@@ -134,18 +134,19 @@ export interface CapacitorUsageStatsManagerPlugin {
134
134
  * Queries all installed packages on the device.
135
135
  * Requires the QUERY_ALL_PACKAGES permission.
136
136
  *
137
+ * @param options - Optional query settings
137
138
  * @returns Promise that resolves with an array of package information
138
139
  * @throws Error if the permission is not granted or query fails
139
140
  * @since 1.2.0
140
141
  * @example
141
142
  * ```typescript
142
- * const { packages } = await UsageStatsManager.queryAllPackages();
143
+ * const { packages } = await UsageStatsManager.queryAllPackages({ includeIcon: true });
143
144
  * packages.forEach(pkg => {
144
- * console.log(`${pkg.appName} (${pkg.packageName}): v${pkg.versionName}`);
145
+ * console.log(`${pkg.appName} (${pkg.packageName}): category=${pkg.category}`);
145
146
  * });
146
147
  * ```
147
148
  */
148
- queryAllPackages(): Promise<{
149
+ queryAllPackages(options?: QueryAllPackagesOptions): Promise<{
149
150
  packages: PackageInfo[];
150
151
  }>;
151
152
  /**
@@ -193,6 +194,20 @@ export interface UsageEvent {
193
194
  /** Task root class name (requires API 31+) */
194
195
  taskRootClassName?: string;
195
196
  }
197
+ /**
198
+ * Options for querying installed packages.
199
+ *
200
+ * @since 8.0.33
201
+ */
202
+ export interface QueryAllPackagesOptions {
203
+ /**
204
+ * When true, includes each app's launcher icon as a base64 data URL.
205
+ * Defaults to false because icons significantly increase the response size.
206
+ *
207
+ * @default false
208
+ */
209
+ includeIcon?: boolean;
210
+ }
196
211
  /**
197
212
  * Represents basic information about an installed package.
198
213
  *
@@ -211,4 +226,29 @@ export interface PackageInfo {
211
226
  firstInstallTime: number;
212
227
  /** Last update time in milliseconds since epoch */
213
228
  lastUpdateTime: number;
229
+ /**
230
+ * Application category from `ApplicationInfo.category`.
231
+ * Only available on Android 8.0 (API level 26) and above.
232
+ *
233
+ * Common values:
234
+ * - `0` — undefined
235
+ * - `1` — game
236
+ * - `2` — audio
237
+ * - `3` — video
238
+ * - `4` — image
239
+ * - `5` — social
240
+ * - `6` — news
241
+ * - `7` — maps
242
+ * - `8` — productivity
243
+ *
244
+ * @since 8.0.33
245
+ */
246
+ category?: number;
247
+ /**
248
+ * App icon as a base64 data URL (`data:image/png;base64,...`).
249
+ * Only present when `queryAllPackages({ includeIcon: true })` is used.
250
+ *
251
+ * @since 8.0.33
252
+ */
253
+ icon?: string;
214
254
  }
@@ -1 +1 @@
1
- {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Usage statistics for an Android app.\n *\n * @since 1.0.0\n */\nexport interface UsageStats {\n /**\n * The first timestamp of the usage stats.\n */\n firstTimeStamp: number;\n /**\n * The last timestamp of the usage stats.\n */\n lastTimeStamp: number;\n /**\n * Only available on Android Q (API level 29) and above.\n * Will be undefined on lower Android versions.\n */\n lastTimeForegroundServiceUsed?: number;\n /**\n * The last time the app was used.\n */\n lastTimeUsed: number;\n /**\n * Only available on Android Q (API level 29) and above.\n * Will be undefined on lower Android versions.\n */\n lastTimeVisible?: number;\n /**\n * The name of the package.\n */\n packageName: string;\n /**\n * Only available on Android Q (API level 29) and above.\n * Will be undefined on lower Android versions.\n */\n totalForegroundServiceUsed?: number;\n /**\n * The total time the app was in the foreground.\n */\n totalTimeInForeground: number;\n /**\n * Only available on Android Q (API level 29) and above.\n * Will be undefined on lower Android versions.\n */\n totalTimeVisible?: number;\n}\n\n/**\n * Options for querying usage statistics.\n *\n * @since 1.0.0\n */\nexport interface UsageStatsOptions {\n /**\n * The inclusive beginning of the range of stats to include in the results.\n * Defined in terms of \"Unix time\"\n */\n beginTime: number;\n\n /**\n * The exclusive end of the range of stats to include in the results.\n * Defined in terms of \"Unix time\"\n */\n endTime: number;\n}\n\n/**\n * Result of a usage stats permission check.\n *\n * @since 1.0.0\n */\nexport interface UsageStatsPermissionResult {\n /**\n * Whether the usage stats permission is granted.\n */\n granted: boolean;\n}\n\n/**\n * Capacitor plugin for accessing Android UsageStatsManager API.\n *\n * @since 1.0.0\n */\nexport interface CapacitorUsageStatsManagerPlugin {\n /**\n * Queries and aggregates usage stats for the given time range.\n *\n * @param options - The time range options for the query\n * @returns Promise that resolves to a record of package names and their corresponding usage stats\n * @throws Error if the permission is not granted or query fails\n * @since 1.0.0\n * @example\n * ```typescript\n * const oneDayAgo = Date.now() - 24 * 60 * 60 * 1000;\n * const now = Date.now();\n * const stats = await UsageStatsManager.queryAndAggregateUsageStats({\n * beginTime: oneDayAgo,\n * endTime: now\n * });\n *\n * for (const [packageName, usageData] of Object.entries(stats)) {\n * console.log(`${packageName}: ${usageData.totalTimeInForeground}ms`);\n * }\n * ```\n */\n queryAndAggregateUsageStats(options: UsageStatsOptions): Promise<Record<string, UsageStats>>;\n\n /**\n * Checks if the usage stats permission is granted.\n *\n * @returns Promise that resolves to a permission result object\n * @throws Error if checking permission fails\n * @since 1.0.0\n * @example\n * ```typescript\n * const { granted } = await UsageStatsManager.isUsageStatsPermissionGranted();\n * if (!granted) {\n * await UsageStatsManager.openUsageStatsSettings();\n * }\n * ```\n */\n isUsageStatsPermissionGranted(): Promise<UsageStatsPermissionResult>;\n\n /**\n * Open the usage stats settings screen.\n * This will open the usage stats settings screen, which allows the user to grant the usage stats permission.\n * This will always open the settings screen, even if the permission is already granted.\n *\n * @returns Promise that resolves when the settings screen is opened\n * @throws Error if opening settings fails\n * @since 1.0.0\n * @example\n * ```typescript\n * await UsageStatsManager.openUsageStatsSettings();\n * ```\n */\n openUsageStatsSettings(): Promise<void>;\n\n /**\n * Queries all installed packages on the device.\n * Requires the QUERY_ALL_PACKAGES permission.\n *\n * @returns Promise that resolves with an array of package information\n * @throws Error if the permission is not granted or query fails\n * @since 1.2.0\n * @example\n * ```typescript\n * const { packages } = await UsageStatsManager.queryAllPackages();\n * packages.forEach(pkg => {\n * console.log(`${pkg.appName} (${pkg.packageName}): v${pkg.versionName}`);\n * });\n * ```\n */\n queryAllPackages(): Promise<{ packages: PackageInfo[] }>;\n\n /**\n * Get the native Capacitor plugin version.\n *\n * @returns Promise that resolves with the plugin version\n * @throws Error if getting the version fails\n * @since 1.0.0\n * @example\n * ```typescript\n * const { version } = await UsageStatsManager.getPluginVersion();\n * console.log('Plugin version:', version);\n * ```\n */\n getPluginVersion(): Promise<{ version: string }>;\n}\n\n/**\n * Represents a single usage event.\n *\n * @since 1.0.0\n */\nexport interface UsageEvent {\n /** Package name of the app */\n packageName: string;\n /** Class name (might be null) */\n className?: string;\n /** Timestamp in milliseconds since epoch */\n timeStamp: number;\n /** Event type constant (e.g., MOVE_TO_FOREGROUND, MOVE_TO_BACKGROUND) */\n eventType: number;\n /** Configuration object (requires API 28+) */\n configuration?: any;\n /** Shortcut ID (requires API 28+) */\n shortcutId?: string;\n /** App standby bucket (requires API 28+) */\n standbyBucket?: number;\n /** Notification channel ID (requires API 29+) */\n notificationChannelId?: string;\n /** Instance ID (requires API 30+) */\n instanceId?: number;\n /** Task root package name (requires API 31+) */\n taskRootPackageName?: string;\n /** Task root class name (requires API 31+) */\n taskRootClassName?: string;\n}\n\n/**\n * Represents basic information about an installed package.\n *\n * @since 1.0.0\n */\nexport interface PackageInfo {\n /** Package name */\n packageName: string;\n /** App display name */\n appName: string;\n /** Version name string */\n versionName: string;\n /** Version code number */\n versionCode: number;\n /** First install time in milliseconds since epoch */\n firstInstallTime: number;\n /** Last update time in milliseconds since epoch */\n lastUpdateTime: number;\n}\n"]}
1
+ {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Usage statistics for an Android app.\n *\n * @since 1.0.0\n */\nexport interface UsageStats {\n /**\n * The first timestamp of the usage stats.\n */\n firstTimeStamp: number;\n /**\n * The last timestamp of the usage stats.\n */\n lastTimeStamp: number;\n /**\n * Only available on Android Q (API level 29) and above.\n * Will be undefined on lower Android versions.\n */\n lastTimeForegroundServiceUsed?: number;\n /**\n * The last time the app was used.\n */\n lastTimeUsed: number;\n /**\n * Only available on Android Q (API level 29) and above.\n * Will be undefined on lower Android versions.\n */\n lastTimeVisible?: number;\n /**\n * The name of the package.\n */\n packageName: string;\n /**\n * Only available on Android Q (API level 29) and above.\n * Will be undefined on lower Android versions.\n */\n totalForegroundServiceUsed?: number;\n /**\n * The total time the app was in the foreground.\n */\n totalTimeInForeground: number;\n /**\n * Only available on Android Q (API level 29) and above.\n * Will be undefined on lower Android versions.\n */\n totalTimeVisible?: number;\n}\n\n/**\n * Options for querying usage statistics.\n *\n * @since 1.0.0\n */\nexport interface UsageStatsOptions {\n /**\n * The inclusive beginning of the range of stats to include in the results.\n * Defined in terms of \"Unix time\"\n */\n beginTime: number;\n\n /**\n * The exclusive end of the range of stats to include in the results.\n * Defined in terms of \"Unix time\"\n */\n endTime: number;\n}\n\n/**\n * Result of a usage stats permission check.\n *\n * @since 1.0.0\n */\nexport interface UsageStatsPermissionResult {\n /**\n * Whether the usage stats permission is granted.\n */\n granted: boolean;\n}\n\n/**\n * Capacitor plugin for accessing Android UsageStatsManager API.\n *\n * @since 1.0.0\n */\nexport interface CapacitorUsageStatsManagerPlugin {\n /**\n * Queries and aggregates usage stats for the given time range.\n *\n * @param options - The time range options for the query\n * @returns Promise that resolves to a record of package names and their corresponding usage stats\n * @throws Error if the permission is not granted or query fails\n * @since 1.0.0\n * @example\n * ```typescript\n * const oneDayAgo = Date.now() - 24 * 60 * 60 * 1000;\n * const now = Date.now();\n * const stats = await UsageStatsManager.queryAndAggregateUsageStats({\n * beginTime: oneDayAgo,\n * endTime: now\n * });\n *\n * for (const [packageName, usageData] of Object.entries(stats)) {\n * console.log(`${packageName}: ${usageData.totalTimeInForeground}ms`);\n * }\n * ```\n */\n queryAndAggregateUsageStats(options: UsageStatsOptions): Promise<Record<string, UsageStats>>;\n\n /**\n * Checks if the usage stats permission is granted.\n *\n * @returns Promise that resolves to a permission result object\n * @throws Error if checking permission fails\n * @since 1.0.0\n * @example\n * ```typescript\n * const { granted } = await UsageStatsManager.isUsageStatsPermissionGranted();\n * if (!granted) {\n * await UsageStatsManager.openUsageStatsSettings();\n * }\n * ```\n */\n isUsageStatsPermissionGranted(): Promise<UsageStatsPermissionResult>;\n\n /**\n * Open the usage stats settings screen.\n * This will open the usage stats settings screen, which allows the user to grant the usage stats permission.\n * This will always open the settings screen, even if the permission is already granted.\n *\n * @returns Promise that resolves when the settings screen is opened\n * @throws Error if opening settings fails\n * @since 1.0.0\n * @example\n * ```typescript\n * await UsageStatsManager.openUsageStatsSettings();\n * ```\n */\n openUsageStatsSettings(): Promise<void>;\n\n /**\n * Queries all installed packages on the device.\n * Requires the QUERY_ALL_PACKAGES permission.\n *\n * @param options - Optional query settings\n * @returns Promise that resolves with an array of package information\n * @throws Error if the permission is not granted or query fails\n * @since 1.2.0\n * @example\n * ```typescript\n * const { packages } = await UsageStatsManager.queryAllPackages({ includeIcon: true });\n * packages.forEach(pkg => {\n * console.log(`${pkg.appName} (${pkg.packageName}): category=${pkg.category}`);\n * });\n * ```\n */\n queryAllPackages(options?: QueryAllPackagesOptions): Promise<{ packages: PackageInfo[] }>;\n\n /**\n * Get the native Capacitor plugin version.\n *\n * @returns Promise that resolves with the plugin version\n * @throws Error if getting the version fails\n * @since 1.0.0\n * @example\n * ```typescript\n * const { version } = await UsageStatsManager.getPluginVersion();\n * console.log('Plugin version:', version);\n * ```\n */\n getPluginVersion(): Promise<{ version: string }>;\n}\n\n/**\n * Represents a single usage event.\n *\n * @since 1.0.0\n */\nexport interface UsageEvent {\n /** Package name of the app */\n packageName: string;\n /** Class name (might be null) */\n className?: string;\n /** Timestamp in milliseconds since epoch */\n timeStamp: number;\n /** Event type constant (e.g., MOVE_TO_FOREGROUND, MOVE_TO_BACKGROUND) */\n eventType: number;\n /** Configuration object (requires API 28+) */\n configuration?: any;\n /** Shortcut ID (requires API 28+) */\n shortcutId?: string;\n /** App standby bucket (requires API 28+) */\n standbyBucket?: number;\n /** Notification channel ID (requires API 29+) */\n notificationChannelId?: string;\n /** Instance ID (requires API 30+) */\n instanceId?: number;\n /** Task root package name (requires API 31+) */\n taskRootPackageName?: string;\n /** Task root class name (requires API 31+) */\n taskRootClassName?: string;\n}\n\n/**\n * Options for querying installed packages.\n *\n * @since 8.0.33\n */\nexport interface QueryAllPackagesOptions {\n /**\n * When true, includes each app's launcher icon as a base64 data URL.\n * Defaults to false because icons significantly increase the response size.\n *\n * @default false\n */\n includeIcon?: boolean;\n}\n\n/**\n * Represents basic information about an installed package.\n *\n * @since 1.0.0\n */\nexport interface PackageInfo {\n /** Package name */\n packageName: string;\n /** App display name */\n appName: string;\n /** Version name string */\n versionName: string;\n /** Version code number */\n versionCode: number;\n /** First install time in milliseconds since epoch */\n firstInstallTime: number;\n /** Last update time in milliseconds since epoch */\n lastUpdateTime: number;\n /**\n * Application category from `ApplicationInfo.category`.\n * Only available on Android 8.0 (API level 26) and above.\n *\n * Common values:\n * - `0` — undefined\n * - `1` — game\n * - `2` — audio\n * - `3` — video\n * - `4` — image\n * - `5` — social\n * - `6` — news\n * - `7` — maps\n * - `8` — productivity\n *\n * @since 8.0.33\n */\n category?: number;\n /**\n * App icon as a base64 data URL (`data:image/png;base64,...`).\n * Only present when `queryAllPackages({ includeIcon: true })` is used.\n *\n * @since 8.0.33\n */\n icon?: string;\n}\n"]}
package/dist/esm/web.d.ts CHANGED
@@ -4,7 +4,9 @@ export declare class CapacitorUsageStatsManagerWeb extends WebPlugin implements
4
4
  isUsageStatsPermissionGranted(): Promise<any>;
5
5
  openUsageStatsSettings(): Promise<void>;
6
6
  queryAndAggregateUsageStats(_options: any): Promise<Record<string, any>>;
7
- queryAllPackages(): Promise<{
7
+ queryAllPackages(_options?: {
8
+ includeIcon?: boolean;
9
+ }): Promise<{
8
10
  packages: PackageInfo[];
9
11
  }>;
10
12
  getPluginVersion(): Promise<{
package/dist/esm/web.js CHANGED
@@ -9,7 +9,7 @@ export class CapacitorUsageStatsManagerWeb extends WebPlugin {
9
9
  queryAndAggregateUsageStats(_options) {
10
10
  throw new Error('Method not implemented.');
11
11
  }
12
- queryAllPackages() {
12
+ queryAllPackages(_options) {
13
13
  throw new Error('Method not implemented.');
14
14
  }
15
15
  async getPluginVersion() {
@@ -1 +1 @@
1
- {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,MAAM,OAAO,6BAA8B,SAAQ,SAAS;IAC1D,6BAA6B;QAC3B,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IACD,sBAAsB;QACpB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IACD,2BAA2B,CAAC,QAAa;QACvC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IACD,gBAAgB;QACd,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5B,CAAC;CACF","sourcesContent":["import { WebPlugin } from '@capacitor/core';\n\nimport type { CapacitorUsageStatsManagerPlugin, PackageInfo } from './definitions';\n\nexport class CapacitorUsageStatsManagerWeb extends WebPlugin implements CapacitorUsageStatsManagerPlugin {\n isUsageStatsPermissionGranted(): Promise<any> {\n throw new Error('Method not implemented.');\n }\n openUsageStatsSettings(): Promise<void> {\n throw new Error('Method not implemented.');\n }\n queryAndAggregateUsageStats(_options: any): Promise<Record<string, any>> {\n throw new Error('Method not implemented.');\n }\n queryAllPackages(): Promise<{ packages: PackageInfo[] }> {\n throw new Error('Method not implemented.');\n }\n\n async getPluginVersion(): Promise<{ version: string }> {\n return { version: 'web' };\n }\n}\n"]}
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,MAAM,OAAO,6BAA8B,SAAQ,SAAS;IAC1D,6BAA6B;QAC3B,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IACD,sBAAsB;QACpB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IACD,2BAA2B,CAAC,QAAa;QACvC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IACD,gBAAgB,CAAC,QAAoC;QACnD,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5B,CAAC;CACF","sourcesContent":["import { WebPlugin } from '@capacitor/core';\n\nimport type { CapacitorUsageStatsManagerPlugin, PackageInfo } from './definitions';\n\nexport class CapacitorUsageStatsManagerWeb extends WebPlugin implements CapacitorUsageStatsManagerPlugin {\n isUsageStatsPermissionGranted(): Promise<any> {\n throw new Error('Method not implemented.');\n }\n openUsageStatsSettings(): Promise<void> {\n throw new Error('Method not implemented.');\n }\n queryAndAggregateUsageStats(_options: any): Promise<Record<string, any>> {\n throw new Error('Method not implemented.');\n }\n queryAllPackages(_options?: { includeIcon?: boolean }): Promise<{ packages: PackageInfo[] }> {\n throw new Error('Method not implemented.');\n }\n\n async getPluginVersion(): Promise<{ version: string }> {\n return { version: 'web' };\n }\n}\n"]}
@@ -16,7 +16,7 @@ class CapacitorUsageStatsManagerWeb extends core.WebPlugin {
16
16
  queryAndAggregateUsageStats(_options) {
17
17
  throw new Error('Method not implemented.');
18
18
  }
19
- queryAllPackages() {
19
+ queryAllPackages(_options) {
20
20
  throw new Error('Method not implemented.');
21
21
  }
22
22
  async getPluginVersion() {
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst CapacitorUsageStatsManager = registerPlugin('CapacitorUsageStatsManager', {\n web: () => import('./web').then((m) => new m.CapacitorUsageStatsManagerWeb()),\n});\nexport * from './definitions';\nexport { CapacitorUsageStatsManager };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class CapacitorUsageStatsManagerWeb extends WebPlugin {\n isUsageStatsPermissionGranted() {\n throw new Error('Method not implemented.');\n }\n openUsageStatsSettings() {\n throw new Error('Method not implemented.');\n }\n queryAndAggregateUsageStats(_options) {\n throw new Error('Method not implemented.');\n }\n queryAllPackages() {\n throw new Error('Method not implemented.');\n }\n async getPluginVersion() {\n return { version: 'web' };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,0BAA0B,GAAGA,mBAAc,CAAC,4BAA4B,EAAE;AAChF,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,6BAA6B,EAAE,CAAC;AACjF,CAAC;;ACFM,MAAM,6BAA6B,SAASC,cAAS,CAAC;AAC7D,IAAI,6BAA6B,GAAG;AACpC,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;AAClD,IAAI;AACJ,IAAI,sBAAsB,GAAG;AAC7B,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;AAClD,IAAI;AACJ,IAAI,2BAA2B,CAAC,QAAQ,EAAE;AAC1C,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;AAClD,IAAI;AACJ,IAAI,gBAAgB,GAAG;AACvB,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;AAClD,IAAI;AACJ,IAAI,MAAM,gBAAgB,GAAG;AAC7B,QAAQ,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE;AACjC,IAAI;AACJ;;;;;;;;;"}
1
+ {"version":3,"file":"plugin.cjs.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst CapacitorUsageStatsManager = registerPlugin('CapacitorUsageStatsManager', {\n web: () => import('./web').then((m) => new m.CapacitorUsageStatsManagerWeb()),\n});\nexport * from './definitions';\nexport { CapacitorUsageStatsManager };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class CapacitorUsageStatsManagerWeb extends WebPlugin {\n isUsageStatsPermissionGranted() {\n throw new Error('Method not implemented.');\n }\n openUsageStatsSettings() {\n throw new Error('Method not implemented.');\n }\n queryAndAggregateUsageStats(_options) {\n throw new Error('Method not implemented.');\n }\n queryAllPackages(_options) {\n throw new Error('Method not implemented.');\n }\n async getPluginVersion() {\n return { version: 'web' };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;;AACK,MAAC,0BAA0B,GAAGA,mBAAc,CAAC,4BAA4B,EAAE;AAChF,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,6BAA6B,EAAE,CAAC;AACjF,CAAC;;ACFM,MAAM,6BAA6B,SAASC,cAAS,CAAC;AAC7D,IAAI,6BAA6B,GAAG;AACpC,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;AAClD,IAAI;AACJ,IAAI,sBAAsB,GAAG;AAC7B,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;AAClD,IAAI;AACJ,IAAI,2BAA2B,CAAC,QAAQ,EAAE;AAC1C,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;AAClD,IAAI;AACJ,IAAI,gBAAgB,CAAC,QAAQ,EAAE;AAC/B,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;AAClD,IAAI;AACJ,IAAI,MAAM,gBAAgB,GAAG;AAC7B,QAAQ,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE;AACjC,IAAI;AACJ;;;;;;;;;"}
package/dist/plugin.js CHANGED
@@ -15,7 +15,7 @@ var capacitorCapacitorUsageStatsManager = (function (exports, core) {
15
15
  queryAndAggregateUsageStats(_options) {
16
16
  throw new Error('Method not implemented.');
17
17
  }
18
- queryAllPackages() {
18
+ queryAllPackages(_options) {
19
19
  throw new Error('Method not implemented.');
20
20
  }
21
21
  async getPluginVersion() {
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst CapacitorUsageStatsManager = registerPlugin('CapacitorUsageStatsManager', {\n web: () => import('./web').then((m) => new m.CapacitorUsageStatsManagerWeb()),\n});\nexport * from './definitions';\nexport { CapacitorUsageStatsManager };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class CapacitorUsageStatsManagerWeb extends WebPlugin {\n isUsageStatsPermissionGranted() {\n throw new Error('Method not implemented.');\n }\n openUsageStatsSettings() {\n throw new Error('Method not implemented.');\n }\n queryAndAggregateUsageStats(_options) {\n throw new Error('Method not implemented.');\n }\n queryAllPackages() {\n throw new Error('Method not implemented.');\n }\n async getPluginVersion() {\n return { version: 'web' };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,0BAA0B,GAAGA,mBAAc,CAAC,4BAA4B,EAAE;IAChF,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,6BAA6B,EAAE,CAAC;IACjF,CAAC;;ICFM,MAAM,6BAA6B,SAASC,cAAS,CAAC;IAC7D,IAAI,6BAA6B,GAAG;IACpC,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;IAClD,IAAI;IACJ,IAAI,sBAAsB,GAAG;IAC7B,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;IAClD,IAAI;IACJ,IAAI,2BAA2B,CAAC,QAAQ,EAAE;IAC1C,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;IAClD,IAAI;IACJ,IAAI,gBAAgB,GAAG;IACvB,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;IAClD,IAAI;IACJ,IAAI,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE;IACjC,IAAI;IACJ;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst CapacitorUsageStatsManager = registerPlugin('CapacitorUsageStatsManager', {\n web: () => import('./web').then((m) => new m.CapacitorUsageStatsManagerWeb()),\n});\nexport * from './definitions';\nexport { CapacitorUsageStatsManager };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class CapacitorUsageStatsManagerWeb extends WebPlugin {\n isUsageStatsPermissionGranted() {\n throw new Error('Method not implemented.');\n }\n openUsageStatsSettings() {\n throw new Error('Method not implemented.');\n }\n queryAndAggregateUsageStats(_options) {\n throw new Error('Method not implemented.');\n }\n queryAllPackages(_options) {\n throw new Error('Method not implemented.');\n }\n async getPluginVersion() {\n return { version: 'web' };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,0BAA0B,GAAGA,mBAAc,CAAC,4BAA4B,EAAE;IAChF,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,6BAA6B,EAAE,CAAC;IACjF,CAAC;;ICFM,MAAM,6BAA6B,SAASC,cAAS,CAAC;IAC7D,IAAI,6BAA6B,GAAG;IACpC,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;IAClD,IAAI;IACJ,IAAI,sBAAsB,GAAG;IAC7B,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;IAClD,IAAI;IACJ,IAAI,2BAA2B,CAAC,QAAQ,EAAE;IAC1C,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;IAClD,IAAI;IACJ,IAAI,gBAAgB,CAAC,QAAQ,EAAE;IAC/B,QAAQ,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC;IAClD,IAAI;IACJ,IAAI,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE;IACjC,IAAI;IACJ;;;;;;;;;;;;;;;"}
@@ -7,7 +7,7 @@ import Capacitor
7
7
  */
8
8
  @objc(CapacitorUsageStatsManagerPlugin)
9
9
  public class CapacitorUsageStatsManagerPlugin: CAPPlugin, CAPBridgedPlugin {
10
- private let pluginVersion: String = "8.0.32"
10
+ private let pluginVersion: String = "8.1.1"
11
11
  public let identifier = "CapacitorUsageStatsManagerPlugin"
12
12
  public let jsName = "CapacitorUsageStatsManager"
13
13
  public let pluginMethods: [CAPPluginMethod] = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-android-usagestatsmanager",
3
- "version": "8.0.32",
3
+ "version": "8.1.1",
4
4
  "description": "Exposes the Android's UsageStatsManager SDK to Capacitor",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",
@@ -47,7 +47,8 @@
47
47
  "prepublishOnly": "bun run build",
48
48
  "check:wiring": "node scripts/check-capacitor-plugin-wiring.mjs",
49
49
  "example:install": "cd example-app && bun install --frozen-lockfile",
50
- "example:build": "bun run build && cd example-app && bun install --frozen-lockfile && bun run build"
50
+ "example:build": "bun run build && cd example-app && bun install --frozen-lockfile && bun run build",
51
+ "changelog:ai": "node scripts/generate-ai-changelog.mjs"
51
52
  },
52
53
  "devDependencies": {
53
54
  "@capacitor/android": "^8.0.0",