From be2f69ae95e7b4a4710e3feb46c3d4dfb4ad147f Mon Sep 17 00:00:00 2001 From: John Borges Date: Sat, 12 Jun 2021 10:24:02 -0400 Subject: [PATCH 01/11] feat(crashes): add hasCrashedInLastSession --- appcenter-crashes/CHANGELOG.md | 5 +++++ .../ios/Plugin/AppCenterCrashesBase.swift | 4 ++++ .../ios/Plugin/AppCenterCrashesPlugin.m | 1 + .../ios/Plugin/AppCenterCrashesPlugin.swift | 5 +++++ appcenter-crashes/package.json | 2 +- appcenter-crashes/src/definitions.ts | 12 +++++++++++- appcenter-crashes/src/web.ts | 3 +++ example/src/components/app-crashes/app-crashes.tsx | 8 +++++++- 8 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 appcenter-crashes/CHANGELOG.md diff --git a/appcenter-crashes/CHANGELOG.md b/appcenter-crashes/CHANGELOG.md new file mode 100644 index 0000000..75e2a81 --- /dev/null +++ b/appcenter-crashes/CHANGELOG.md @@ -0,0 +1,5 @@ +# Change Log + +## Features + +* Add hasCrashedInLastSession api diff --git a/appcenter-crashes/ios/Plugin/AppCenterCrashesBase.swift b/appcenter-crashes/ios/Plugin/AppCenterCrashesBase.swift index 634d426..dd649da 100644 --- a/appcenter-crashes/ios/Plugin/AppCenterCrashesBase.swift +++ b/appcenter-crashes/ios/Plugin/AppCenterCrashesBase.swift @@ -24,4 +24,8 @@ import AppCenterCrashes public func hasReceivedMemoryWarningInLastSession() -> Bool { return Crashes.hasReceivedMemoryWarningInLastSession } + + public func hasCrashedInLastSession() -> Bool { + return Crashes.hasCrashedInLastSession + } } diff --git a/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.m b/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.m index a6d75c6..1f7d2b2 100644 --- a/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.m +++ b/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.m @@ -8,4 +8,5 @@ CAP_PLUGIN_METHOD(isEnabled, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(generateTestCrash, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(hasReceivedMemoryWarningInLastSession, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(hasCrashedInLastSession, CAPPluginReturnPromise); ) diff --git a/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.swift b/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.swift index c7a57b0..aebf9f8 100644 --- a/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.swift +++ b/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.swift @@ -40,4 +40,9 @@ public class CrashesPlugin: CAPPlugin { @objc func hasReceivedMemoryWarningInLastSession(_ call: CAPPluginCall) { call.resolve(["value": implementation.hasReceivedMemoryWarningInLastSession()]) } + + @objc func hasCrashedInLastSession(_ call: CAPPluginCall) { + call.resolve(["value": implementation.hasCrashedInLastSession()]) + } + } diff --git a/appcenter-crashes/package.json b/appcenter-crashes/package.json index 2753f60..90f2154 100644 --- a/appcenter-crashes/package.json +++ b/appcenter-crashes/package.json @@ -1,6 +1,6 @@ { "name": "@capacitor-community/appcenter-crashes", - "version": "0.2.0", + "version": "0.3.0", "description": "Capacitor plugin for Microsoft AppCenter Crashes.", "main": "dist/plugin.cjs.js", "module": "dist/esm/index.js", diff --git a/appcenter-crashes/src/definitions.ts b/appcenter-crashes/src/definitions.ts index 6272369..c432378 100644 --- a/appcenter-crashes/src/definitions.ts +++ b/appcenter-crashes/src/definitions.ts @@ -103,10 +103,20 @@ export interface CrashesPlugin { * const { value: gotMemWarning } = await Crashes.hasReceivedMemoryWarningInLastSession(); */ hasReceivedMemoryWarningInLastSession(): Promise<{value: boolean}>; + + /** + * Check if the app has crashed in the last session. + * @returns {Promise<{value: boolean}>} + * @since 0.3.0 + * @example + * import Crashes from '@capacitor-community/appcenter-crashes'; + * + * const { value: hasCrashed } = await Crashes.hasCrashedInLastSession(); + */ + hasCrashedInLastSession(): Promise<{ value: boolean}>; } // convert -// export function hasCrashedInLastSession(): Promise; // export function lastSessionCrashReport(): Promise; // export function notifyUserConfirmation(userConfirmation: UserConfirmation): void; // export function setListener(crashesListener: CrashesListener): Promise; diff --git a/appcenter-crashes/src/web.ts b/appcenter-crashes/src/web.ts index e810c76..aa2348b 100644 --- a/appcenter-crashes/src/web.ts +++ b/appcenter-crashes/src/web.ts @@ -5,6 +5,9 @@ import type { CrashesPlugin } from './definitions'; export class CrashesWeb extends WebPlugin implements CrashesPlugin { + hasCrashedInLastSession(): Promise<{ value: boolean; }> { + throw this.unimplemented('Not supported on web.'); + } hasReceivedMemoryWarningInLastSession(): Promise<{ value: boolean; }> { throw this.unimplemented('Not supported on web.'); } diff --git a/example/src/components/app-crashes/app-crashes.tsx b/example/src/components/app-crashes/app-crashes.tsx index 206d87f..0211d75 100644 --- a/example/src/components/app-crashes/app-crashes.tsx +++ b/example/src/components/app-crashes/app-crashes.tsx @@ -10,6 +10,7 @@ export class AppCrashes { /* Flag to toggle entire Crashes service */ @State() enabled: boolean = false @State() memoryWarning: boolean = false + @State() hasCrashed: boolean = false constructor() { this.toggleCrashes = this.toggleCrashes.bind(this); @@ -20,10 +21,11 @@ export class AppCrashes { try { const { value: crashesEnabled } = await Crashes.isEnabled(); const { value: memoryWarning } = await Crashes.hasReceivedMemoryWarningInLastSession(); + const { value: hasCrashed } = await Crashes.hasCrashedInLastSession(); this.enabled = crashesEnabled this.memoryWarning = memoryWarning - console.debug(`got mem warning: ${this.memoryWarning}`) + this.hasCrashed = hasCrashed } catch (error) { console.error(error) } @@ -71,6 +73,10 @@ export class AppCrashes { Memory Warning {this.memoryWarning.toString()} + + Crashed Before + {this.hasCrashed.toString()} +
From d7254dbd88129366fb57bef6da7d8b1ca704f5db Mon Sep 17 00:00:00 2001 From: John Borges Date: Mon, 14 Jun 2021 21:42:09 -0400 Subject: [PATCH 02/11] feat(crashes): add lastSessionCrashReport --- appcenter-crashes/CHANGELOG.md | 1 + appcenter-crashes/README.md | 73 +++++++++++++++++++ .../ios/Plugin/AppCenterCrashesBase.swift | 4 + .../ios/Plugin/AppCenterCrashesPlugin.m | 2 + .../ios/Plugin/AppCenterCrashesPlugin.swift | 11 +++ appcenter-crashes/src/definitions.ts | 52 ++++++++++--- appcenter-crashes/src/web.ts | 5 +- 7 files changed, 138 insertions(+), 10 deletions(-) diff --git a/appcenter-crashes/CHANGELOG.md b/appcenter-crashes/CHANGELOG.md index 75e2a81..e5378a1 100644 --- a/appcenter-crashes/CHANGELOG.md +++ b/appcenter-crashes/CHANGELOG.md @@ -3,3 +3,4 @@ ## Features * Add hasCrashedInLastSession api +* Add lastSessionCrashReport api diff --git a/appcenter-crashes/README.md b/appcenter-crashes/README.md index 3fc9179..441bb96 100644 --- a/appcenter-crashes/README.md +++ b/appcenter-crashes/README.md @@ -17,6 +17,9 @@ npx cap sync * [`setEnabled(...)`](#setenabled) * [`generateTestCrash()`](#generatetestcrash) * [`hasReceivedMemoryWarningInLastSession()`](#hasreceivedmemorywarninginlastsession) +* [`hasCrashedInLastSession()`](#hascrashedinlastsession) +* [`lastSessionCrashReport()`](#lastsessioncrashreport) +* [Interfaces](#interfaces) @@ -87,4 +90,74 @@ Check if app recieved memory warning in the last session. -------------------- + +### hasCrashedInLastSession() + +```typescript +hasCrashedInLastSession() => any +``` + +Check if the app has crashed in the last session. + +**Returns:** any + +**Since:** 0.3.0 + +-------------------- + + +### lastSessionCrashReport() + +```typescript +lastSessionCrashReport() => any +``` + +Provides details about the crash that occurred in the last app session. + +**Returns:** any + +**Since:** 0.3.0 + +-------------------- + + +### Interfaces + + +#### ErrorReport + +| Prop | Type | +| -------------------------- | ----------------------------------------- | +| **`id`** | string | +| **`threadName`** | string | +| **`appErrorTime`** | string \| number | +| **`appStartTime`** | string \| number | +| **`exceptionName`** | string | +| **`exceptionReason`** | string | +| **`device`** | Device | +| **`signal`** | string | +| **`appProcessIdentifier`** | number | + + +#### Device + +| Prop | Type | +| -------------------- | ------------------- | +| **`sdkName`** | string | +| **`sdkVersion`** | string | +| **`model`** | string | +| **`oemName`** | string | +| **`osName`** | string | +| **`osVersion`** | string | +| **`osBuild`** | string | +| **`osApiLevel`** | number | +| **`locale`** | string | +| **`timeZoneOffset`** | number | +| **`screenSize`** | string | +| **`appVersion`** | string | +| **`carrierName`** | string | +| **`carrierCountry`** | string | +| **`appBuild`** | string | +| **`appNamespace`** | string | + diff --git a/appcenter-crashes/ios/Plugin/AppCenterCrashesBase.swift b/appcenter-crashes/ios/Plugin/AppCenterCrashesBase.swift index dd649da..6b87df4 100644 --- a/appcenter-crashes/ios/Plugin/AppCenterCrashesBase.swift +++ b/appcenter-crashes/ios/Plugin/AppCenterCrashesBase.swift @@ -28,4 +28,8 @@ import AppCenterCrashes public func hasCrashedInLastSession() -> Bool { return Crashes.hasCrashedInLastSession } + + public func lastSessionCrashReport() -> Dictionary? { + return CrashesUtil.convertReportToJs(report: Crashes.lastSessionCrashReport) + } } diff --git a/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.m b/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.m index 1f7d2b2..8d5d3d6 100644 --- a/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.m +++ b/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.m @@ -9,4 +9,6 @@ CAP_PLUGIN_METHOD(generateTestCrash, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(hasReceivedMemoryWarningInLastSession, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(hasCrashedInLastSession, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(lastSessionCrashReport, CAPPluginReturnPromise); + ) diff --git a/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.swift b/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.swift index aebf9f8..879132e 100644 --- a/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.swift +++ b/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.swift @@ -19,6 +19,7 @@ public class CrashesPlugin: CAPPlugin { let alwaysSendCrashes = config["CrashesAlwaysSend"] as? Bool if AppCenterCapacitorShared.isSdkConfigured() { + print("[CrashesPlugin] starting") implementation.start() } } @@ -44,5 +45,15 @@ public class CrashesPlugin: CAPPlugin { @objc func hasCrashedInLastSession(_ call: CAPPluginCall) { call.resolve(["value": implementation.hasCrashedInLastSession()]) } + + @objc func lastSessionCrashReport(_ call: CAPPluginCall) { + + guard let report = implementation.lastSessionCrashReport() else { + call.reject("No crash report available") + return + } + + call.resolve(["value": report]) + } } diff --git a/appcenter-crashes/src/definitions.ts b/appcenter-crashes/src/definitions.ts index c432378..d4b064e 100644 --- a/appcenter-crashes/src/definitions.ts +++ b/appcenter-crashes/src/definitions.ts @@ -5,34 +5,58 @@ export enum UserConfirmation { } export interface Device { + /* Name of the SDK. Consists of the name of the SDK and the platform, e.g. "appcenter.ios", "appcenter.android" */ sdkName: string; + /* Version of the SDK in semver format, e.g. "1.2.0" or "0.12.3-alpha.1". */ sdkVersion: string; + /* Device model (example: iPad2,3). */ model: string; + /* Device manufacturer (example: HTC). */ oemName: string; + /* OS name (example: iOS). */ osName: string; + /* OS version (example: 9.3.0). */ osVersion: string; - osBuild: string; + /* OS build code (example: LMY47X). */ + osBuild?: string; + /* API level when applicable like in Android (example: 15). */ osApiLevel?: number; + /* Language code (example: en_US). */ locale: string; + /* The offset in minutes from UTC for the device time zone, including daylight savings time. */ timeZoneOffset: number; - screenSize?: string; + /* Screen size of the device in pixels (example: 640x480). */ + screenSize: string; + /* Application version name, e.g. 1.1.0 */ appVersion: string; + /* Carrier name (for mobile devices). */ carrierName?: string; + /* Carrier country code (for mobile devices). */ carrierCountry?: string; + /* The app's build number, e.g. 42. */ appBuild: string; - appNamespace: string; + /* The bundle identifier, package identifier, or namespace, depending on what the individual plattforms use, .e.g com.microsoft.example. */ + appNamespace?: string; } export interface ErrorReport { + /* UUID for the crash report. */ id: string; threadName?: string; - appErrorTime: string | number; - appStartTime: string | number; - exception?: string; + /* Date and time the error occurred. */ + appErrorTime?: string | number; + /* Date and time the app started. */ + appStartTime?: string | number; + /* Exception name that triggered the crash. */ + exceptionName?: string; + /* Exception reason. */ exceptionReason?: string; + /* Device information of the app when it crashed. */ device: Device; - signal?: string; - appProcessIdentifier?: number; + /* Signal that caused the crash. */ + signal: string; + /* Identifier of the app process that crashed. */ + appProcessIdentifier: number; } export interface CrashesListener { @@ -114,9 +138,19 @@ export interface CrashesPlugin { * const { value: hasCrashed } = await Crashes.hasCrashedInLastSession(); */ hasCrashedInLastSession(): Promise<{ value: boolean}>; + + /** + * Provides details about the crash that occurred in the last app session. + * @returns {Promise<{value: ErrorReport}>} + * @since 0.3.0 + * @example + * import Crashes from '@capacitor-community/appcenter-crashes'; + * + * const { value: crashReport } = await Crashes.lastSessionCrashReport(); + */ + lastSessionCrashReport(): Promise<{value: ErrorReport}>; } // convert -// export function lastSessionCrashReport(): Promise; // export function notifyUserConfirmation(userConfirmation: UserConfirmation): void; // export function setListener(crashesListener: CrashesListener): Promise; diff --git a/appcenter-crashes/src/web.ts b/appcenter-crashes/src/web.ts index aa2348b..ed0cce5 100644 --- a/appcenter-crashes/src/web.ts +++ b/appcenter-crashes/src/web.ts @@ -1,10 +1,13 @@ import { WebPlugin } from '@capacitor/core'; -import type { CrashesPlugin } from './definitions'; +import { CrashesPlugin, ErrorReport } from './definitions'; export class CrashesWeb extends WebPlugin implements CrashesPlugin { + lastSessionCrashReport(): Promise<{ value: ErrorReport; }> { + throw new Error('Method not implemented.'); + } hasCrashedInLastSession(): Promise<{ value: boolean; }> { throw this.unimplemented('Not supported on web.'); } From a7cd59fb7290b7309d07a71cbdeb1a38b095672e Mon Sep 17 00:00:00 2001 From: John Borges Date: Mon, 14 Jun 2021 21:43:03 -0400 Subject: [PATCH 03/11] refactor(crashes): checking optionals --- .../ios/Plugin/AppCenterCrashesUtil.swift | 198 ++++++++---------- 1 file changed, 82 insertions(+), 116 deletions(-) diff --git a/appcenter-crashes/ios/Plugin/AppCenterCrashesUtil.swift b/appcenter-crashes/ios/Plugin/AppCenterCrashesUtil.swift index 7f8bee7..e0e49db 100644 --- a/appcenter-crashes/ios/Plugin/AppCenterCrashesUtil.swift +++ b/appcenter-crashes/ios/Plugin/AppCenterCrashesUtil.swift @@ -2,142 +2,108 @@ import Foundation import AppCenterCrashes /** - Utility class containing helpers for converting App Center objects. + Utility class containing helpers for converting App Center objects. */ public class CrashesUtil { - static let kMSSdkName: String = "sdkName"; - static let kMSSdkVersion: String = "sdkVersion"; - static let kMSModel: String = "model"; - static let kMSOemName: String = "oemName"; - static let kMSOsName: String = "osName"; - static let kMSOsVersion: String = "osVersion"; - static let kMSOsBuild: String = "osBuild"; - static let kMSOsApiLevel: String = "osApiLevel"; - static let kMSLocale: String = "locale"; - static let kMSTimeZoneOffset: String = "timeZoneOffset"; - static let kMSScreenSize: String = "screenSize"; - static let kMSAppVersion: String = "appVersion"; - static let kMSCarrierName: String = "carrierName"; - static let kMSCarrierCountry: String = "carrierCountry"; - static let kMSAppBuild: String = "appBuild"; - static let kMSAppNamespace: String = "appNamespace"; + static let kMSSdkName: String = "sdkName"; + static let kMSSdkVersion: String = "sdkVersion"; + static let kMSModel: String = "model"; + static let kMSOemName: String = "oemName"; + static let kMSOsName: String = "osName"; + static let kMSOsVersion: String = "osVersion"; + static let kMSOsBuild: String = "osBuild"; + static let kMSOsApiLevel: String = "osApiLevel"; + static let kMSLocale: String = "locale"; + static let kMSTimeZoneOffset: String = "timeZoneOffset"; + static let kMSScreenSize: String = "screenSize"; + static let kMSAppVersion: String = "appVersion"; + static let kMSCarrierName: String = "carrierName"; + static let kMSCarrierCountry: String = "carrierCountry"; + static let kMSAppBuild: String = "appBuild"; + static let kMSAppNamespace: String = "appNamespace"; - /** - Serializes App Center Device properties to Dictionary - - Parameter device: App Center Device - - Returns Device Dictionary + /** + Serializes App Center Device properties to Dictionary + - Parameter device: App Center Device + - Returns Device Dictionary */ - public func serializeDeviceToDictionary(device: Device) -> Dictionary { - var dict = [String: Any]() + public static func serializeDeviceToDictionary(device: Device) -> Dictionary { + var dict = [String: Any]() - if !device.sdkName.isEmpty { - dict[CrashesUtil.kMSSdkName] = device.sdkName; - } - if !device.sdkName.isEmpty { - dict[CrashesUtil.kMSSdkVersion] = device.sdkVersion; - } - if !device.model.isEmpty { - dict[CrashesUtil.kMSModel] = device.model; - } - if !device.oemName.isEmpty { - dict[CrashesUtil.kMSOemName] = device.oemName; - } - if !device.osName.isEmpty { - dict[CrashesUtil.kMSOsName] = device.osName; - } - if !device.osVersion.isEmpty { - dict[CrashesUtil.kMSOsVersion] = device.osVersion; - } - if !device.osBuild.isEmpty { - dict[CrashesUtil.kMSOsBuild] = device.osBuild; - } - if device.osApiLevel != nil { - dict[CrashesUtil.kMSOsApiLevel] = device.osApiLevel!; - } - if !device.locale.isEmpty { - dict[CrashesUtil.kMSLocale] = device.locale; - } - if device.timeZoneOffset != nil { - dict[CrashesUtil.kMSTimeZoneOffset] = device.timeZoneOffset!; - } - if !device.screenSize.isEmpty { - dict[CrashesUtil.kMSScreenSize] = device.screenSize; - } - if !device.appVersion.isEmpty { - dict[CrashesUtil.kMSAppVersion] = device.appVersion; - } - if !device.carrierName.isEmpty { - dict[CrashesUtil.kMSCarrierName] = device.carrierName; - } - if !device.carrierCountry.isEmpty { - dict[CrashesUtil.kMSCarrierCountry] = device.carrierCountry; - } - if !device.appBuild.isEmpty { - dict[CrashesUtil.kMSAppBuild] = device.appBuild; - } - if !device.appNamespace.isEmpty { - dict[CrashesUtil.kMSAppNamespace] = device.appNamespace; - } - return dict; - } + dict[CrashesUtil.kMSSdkName] = device.sdkName; + dict[CrashesUtil.kMSSdkVersion] = device.sdkVersion; + dict[CrashesUtil.kMSModel] = device.model; + dict[CrashesUtil.kMSOemName] = device.oemName; + dict[CrashesUtil.kMSOsName] = device.osName; + dict[CrashesUtil.kMSOsVersion] = device.osVersion; + + if device.osBuild != nil { + dict[CrashesUtil.kMSOsBuild] = device.osBuild!; + } + if device.osApiLevel != nil { + dict[CrashesUtil.kMSOsApiLevel] = device.osApiLevel!; + } + + dict[CrashesUtil.kMSLocale] = device.locale; + dict[CrashesUtil.kMSTimeZoneOffset] = device.timeZoneOffset; + dict[CrashesUtil.kMSScreenSize] = device.screenSize; + dict[CrashesUtil.kMSAppVersion] = device.appVersion; + + if device.carrierName != nil { + dict[CrashesUtil.kMSCarrierName] = device.carrierName!; + } + if device.carrierCountry != nil { + dict[CrashesUtil.kMSCarrierCountry] = device.carrierCountry!; + } + + dict[CrashesUtil.kMSAppBuild] = device.appBuild; + + if device.appNamespace != nil { + dict[CrashesUtil.kMSAppNamespace] = device.appNamespace!; + } + + return dict; + } /** Converts App Center ErrorReport to Dictionary - Parameter report: App Center ErrorReport - Returns JS optional Dictionary */ - public func convertReportToJs(report: ErrorReport?) -> Dictionary? { + public static func convertReportToJs(report: ErrorReport?) -> Dictionary? { - guard let actualReport = report else { - return nil - } + guard let actualReport = report else { + return nil + } - var dict = [String: Any]() - - let identifier: String = actualReport.incidentIdentifier - if !identifier.isEmpty { - dict["id"] = identifier - } - - let processIdentifier: UInt = actualReport.appProcessIdentifier - dict["appProcessIdentifier"] = String(processIdentifier) - - let startTime: Date? = actualReport.appStartTime - if startTime != nil { - dict["appStartTime"] = String(startTime!.timeIntervalSince1970) - } - - let errTime: Date? = actualReport.appErrorTime - if errTime != nil { - dict["appErrorTime"] = errTime!.timeIntervalSince1970 - } - - let exceptionName: String = actualReport.exceptionName - if !exceptionName.isEmpty { - dict["exceptionName"] = exceptionName - } - - let exceptionReason: String = actualReport.exceptionReason - if !exceptionReason.isEmpty { - dict["exceptionReason"] = exceptionReason - } - - let signal: String = actualReport.signal - if !signal.isEmpty { - dict["signal"] = signal - } - - dict["device"] = serializeDeviceToDictionary(device: actualReport.device) + var dict = [String: Any]() - return dict + dict["id"] = actualReport.incidentIdentifier + dict["signal"] = actualReport.signal + if let exceptionName = actualReport.exceptionName { + dict["exceptionName"] = exceptionName + } + if let exceptionReason = actualReport.exceptionReason { + dict["exceptionReason"] = exceptionReason + } + if let startTime = actualReport.appStartTime { + dict["appStartTime"] = String(startTime.timeIntervalSince1970) + } + if let errTime = actualReport.appErrorTime { + dict["appErrorTime"] = String(errTime.timeIntervalSince1970) + } + dict["device"] = serializeDeviceToDictionary(device: actualReport.device) + dict["appProcessIdentifier"] = actualReport.appProcessIdentifier + + return dict } /** - Converts arrat of App Center ErrorReports to a Dictionary + Converts array of App Center ErrorReports to a Dictionary - Parameter reports: App Center ErrorReport - Returns Array of Dictionaries */ - public func convertReportsToJS (reports: [ErrorReport]) -> [[String: Any]] { + public static func convertReportsToJS (reports: [ErrorReport]) -> [[String: Any]] { var jsReadyReports = [[String: Any]]() for (index, value) in reports.enumerated() { guard let convertedReport = convertReportToJs(report: value) else { From ea21cabea2f7cd7e11525ebcf066c6332b9682f8 Mon Sep 17 00:00:00 2001 From: John Borges Date: Mon, 14 Jun 2021 21:43:12 -0400 Subject: [PATCH 04/11] docs: cleanup --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 10bfc21..0d66b18 100644 --- a/README.md +++ b/README.md @@ -43,21 +43,21 @@ Example: - + AppSecret {APP_SECRET_VALUE} LogLevel - 2 - AnalyticsEnableInJs - + 2 + AnalyticsEnableInJs + AnalyticsTransmissionInterval - 3 + 3 CrashesEnableInJs - + CrashesAlwaysSend - - + + ``` From 17896661cbaffcfcb1d3b7a31033dc1a5d90017b Mon Sep 17 00:00:00 2001 From: John Borges Date: Mon, 14 Jun 2021 21:43:31 -0400 Subject: [PATCH 05/11] chore(example): using latest plugins --- example/ios/App/App/AppCenter-Config.plist | 2 +- .../components/app-crashes/app-crashes.tsx | 33 ++++++++++++++----- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/example/ios/App/App/AppCenter-Config.plist b/example/ios/App/App/AppCenter-Config.plist index 236aaa8..e6f5a4f 100644 --- a/example/ios/App/App/AppCenter-Config.plist +++ b/example/ios/App/App/AppCenter-Config.plist @@ -5,7 +5,7 @@ AnalyticsTransmissionInterval 10 AnalyticsEnableInJs - + AppSecret fb3a28d5-1ed9-401c-b06a-0379f66c8650 LogLevel diff --git a/example/src/components/app-crashes/app-crashes.tsx b/example/src/components/app-crashes/app-crashes.tsx index 0211d75..f0d835b 100644 --- a/example/src/components/app-crashes/app-crashes.tsx +++ b/example/src/components/app-crashes/app-crashes.tsx @@ -1,6 +1,6 @@ import { Component, State, h } from '@stencil/core'; import { ToggleChangeEventDetail } from '@ionic/core'; -import Crashes from '@capacitor-community/appcenter-crashes'; +import Crashes, { ErrorReport } from '@capacitor-community/appcenter-crashes'; @Component({ tag: 'app-crashes', @@ -11,6 +11,7 @@ export class AppCrashes { @State() enabled: boolean = false @State() memoryWarning: boolean = false @State() hasCrashed: boolean = false + crashReport: ErrorReport constructor() { this.toggleCrashes = this.toggleCrashes.bind(this); @@ -22,10 +23,13 @@ export class AppCrashes { const { value: crashesEnabled } = await Crashes.isEnabled(); const { value: memoryWarning } = await Crashes.hasReceivedMemoryWarningInLastSession(); const { value: hasCrashed } = await Crashes.hasCrashedInLastSession(); + const { value: crashReport } = await Crashes.lastSessionCrashReport(); this.enabled = crashesEnabled this.memoryWarning = memoryWarning this.hasCrashed = hasCrashed + console.debug(crashReport) + } catch (error) { console.error(error) } @@ -56,19 +60,18 @@ export class AppCrashes { - Crashes , +

App Center Crashes

+

App Center Crashes will automatically generate a crash log every time your app crashes.

+ - Enable Analytics + Enable Crashes this.toggleCrashes(e)} /> - - Previous Crash Info - Memory Warning {this.memoryWarning.toString()} @@ -78,11 +81,25 @@ export class AppCrashes { {this.hasCrashed.toString()} -
+
-
Generate Test Crash
+
Generate a Test Crash
Let app crash
+ + + + Crash Report + + + { this.crashReport ? Object.keys(this.crashReport).map(key => { + + {key} + + }) : null} + + +
, ]; } From 477eb22f45ce1df9cc47563069ad1d3f18fdc014 Mon Sep 17 00:00:00 2001 From: John Borges Date: Tue, 15 Jun 2021 18:17:17 -0400 Subject: [PATCH 06/11] chore(crashes): add missing licence file --- appcenter-crashes/LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 appcenter-crashes/LICENSE diff --git a/appcenter-crashes/LICENSE b/appcenter-crashes/LICENSE new file mode 100644 index 0000000..9c5a1fa --- /dev/null +++ b/appcenter-crashes/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) COPYRIGHT_YEAR COPYRIGHT_HOLDER + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file From 9aebeab965d3129aea0e385d20e973c51a1137e1 Mon Sep 17 00:00:00 2001 From: John Borges Date: Tue, 15 Jun 2021 18:20:01 -0400 Subject: [PATCH 07/11] docs(crashes): fix broken links and missing info --- appcenter-crashes/README.md | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/appcenter-crashes/README.md b/appcenter-crashes/README.md index 441bb96..cc5e34e 100644 --- a/appcenter-crashes/README.md +++ b/appcenter-crashes/README.md @@ -1,6 +1,35 @@ -# @capacitor-community/appcenter-crashes - -App Center Crashes will automatically generate a crash log every time your app crashes. The log is first written to the device's storage and when the user starts the app again, the crash report will be sent to App Center. Collecting crashes works for both beta and live apps, i.e. those submitted to the App Store. Crash logs contain valuable information for you to help fix the crash. +


+ +

App Center Crashes

+

@capacitor-community/appcenter-crashes

+

+ App Center Crashes will automatically generate a crash log every time your app crashes. The log is first written to the device's storage and when the user starts the app again, the crash report will be sent to App Center. Collecting crashes works for both beta and live apps, i.e. those submitted to the App Store. Crash logs contain valuable information for you to help fix the crash. +

+ +

+ + + +
+ + + + + +

+ +## Maintainers + +| Maintainer | GitHub | Social | +| -----------| -------| -------| +| John Borges | [johnborges](https://github.com/johnborges) | [@johnborges](https://twitter.com/johnborges) | + +## Features + +- Generate test crashes +- Get more information about a previous crash +- Customize how crashes are processed +- Enable or disable App Center Crashes at runtime ## Install From a6f63ecda3b28f8da76ab38ed3c6c8bc6da56bde Mon Sep 17 00:00:00 2001 From: John Borges Date: Tue, 15 Jun 2021 18:21:11 -0400 Subject: [PATCH 08/11] fix(crashes): use void return method type --- appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.m b/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.m index 8d5d3d6..afdc5dd 100644 --- a/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.m +++ b/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.m @@ -6,7 +6,7 @@ CAP_PLUGIN(CrashesPlugin, "Crashes", CAP_PLUGIN_METHOD(setEnabled, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(isEnabled, CAPPluginReturnPromise); - CAP_PLUGIN_METHOD(generateTestCrash, CAPPluginReturnPromise); + CAP_PLUGIN_METHOD(generateTestCrash, CAPPluginReturnNone); CAP_PLUGIN_METHOD(hasReceivedMemoryWarningInLastSession, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(hasCrashedInLastSession, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(lastSessionCrashReport, CAPPluginReturnPromise); From aeb681798cd99d2551b9a932ac0b8a4f795c84b4 Mon Sep 17 00:00:00 2001 From: John Borges Date: Tue, 15 Jun 2021 18:21:56 -0400 Subject: [PATCH 09/11] refactor(crashes): use DispatchQueue --- .../ios/Plugin/AppCenterCrashesPlugin.swift | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.swift b/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.swift index 879132e..1ee60c0 100644 --- a/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.swift +++ b/appcenter-crashes/ios/Plugin/AppCenterCrashesPlugin.swift @@ -39,21 +39,26 @@ public class CrashesPlugin: CAPPlugin { } @objc func hasReceivedMemoryWarningInLastSession(_ call: CAPPluginCall) { - call.resolve(["value": implementation.hasReceivedMemoryWarningInLastSession()]) + DispatchQueue.main.async { + call.resolve(["value": self.implementation.hasReceivedMemoryWarningInLastSession()]) + } } @objc func hasCrashedInLastSession(_ call: CAPPluginCall) { - call.resolve(["value": implementation.hasCrashedInLastSession()]) + DispatchQueue.main.async { + call.resolve(["value": self.implementation.hasCrashedInLastSession()]) + } } @objc func lastSessionCrashReport(_ call: CAPPluginCall) { - - guard let report = implementation.lastSessionCrashReport() else { - call.reject("No crash report available") - return + DispatchQueue.main.async { + guard let report = self.implementation.lastSessionCrashReport() else { + call.reject("No crash report available") + return + } + + call.resolve(["value": report]) } - - call.resolve(["value": report]) } } From 774f7918ff89b6c0b7ba77117b57f8e046f89861 Mon Sep 17 00:00:00 2001 From: John Borges Date: Tue, 15 Jun 2021 18:22:14 -0400 Subject: [PATCH 10/11] chore(example): cleanup --- example/src/components/app-crashes/app-crashes.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/src/components/app-crashes/app-crashes.tsx b/example/src/components/app-crashes/app-crashes.tsx index f0d835b..0ff5608 100644 --- a/example/src/components/app-crashes/app-crashes.tsx +++ b/example/src/components/app-crashes/app-crashes.tsx @@ -11,7 +11,7 @@ export class AppCrashes { @State() enabled: boolean = false @State() memoryWarning: boolean = false @State() hasCrashed: boolean = false - crashReport: ErrorReport + @State() crashReport: ErrorReport constructor() { this.toggleCrashes = this.toggleCrashes.bind(this); @@ -77,7 +77,7 @@ export class AppCrashes { {this.memoryWarning.toString()} - Crashed Before + Crashed Prior {this.hasCrashed.toString()} From d1cf295ff9704afa623f66b9f24aac33dc482d6f Mon Sep 17 00:00:00 2001 From: John Borges Date: Tue, 15 Jun 2021 20:39:14 -0400 Subject: [PATCH 11/11] chore(crashes): updating changelog --- appcenter-crashes/CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/appcenter-crashes/CHANGELOG.md b/appcenter-crashes/CHANGELOG.md index e5378a1..326b499 100644 --- a/appcenter-crashes/CHANGELOG.md +++ b/appcenter-crashes/CHANGELOG.md @@ -1,6 +1,8 @@ # Change Log -## Features +## 0.3.0 + +### Features * Add hasCrashedInLastSession api * Add lastSessionCrashReport api