Skip to content

Commit

Permalink
Merge pull request #98 from xing/add_hockey_and_autoupdate
Browse files Browse the repository at this point in the history
Enable HockeyApp and AutoUpdate
  • Loading branch information
JoeSSS authored Nov 9, 2017
2 parents 48e215a + 6528fa2 commit c86658a
Show file tree
Hide file tree
Showing 211 changed files with 3,500 additions and 1 deletion.
20 changes: 20 additions & 0 deletions Calabash Launcher.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
ED85D2F01F950A9400E5E2D8 /* LanguageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED85D2EF1F950A9400E5E2D8 /* LanguageViewController.swift */; };
ED9472941E365F9D00FE2982 /* ElementConstructorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED9472931E365F9C00FE2982 /* ElementConstructorViewController.swift */; };
ED9472961E37BD3E00FE2982 /* get_uniq_elements.command in Resources */ = {isa = PBXBuildFile; fileRef = ED9472951E37BD3E00FE2982 /* get_uniq_elements.command */; };
ED99D7AC1FB334DA0077B965 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED99D7AA1FB334DA0077B965 /* Sparkle.framework */; };
ED99D7AD1FB335560077B965 /* HockeySDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED99D7A91FB334DA0077B965 /* HockeySDK.framework */; };
ED99D7AE1FB335560077B965 /* HockeySDK.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = ED99D7A91FB334DA0077B965 /* HockeySDK.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
ED99D7B01FB335560077B965 /* Sparkle.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = ED99D7AA1FB334DA0077B965 /* Sparkle.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
EDB433361DD49AF5001BABEC /* InspectorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDB433351DD49AF5001BABEC /* InspectorViewController.swift */; };
EDBC88071DFEE8A6004CB840 /* kill_process.command in Resources */ = {isa = PBXBuildFile; fileRef = EDBC88061DFEE8A6004CB840 /* kill_process.command */; };
EDC06B7C1DB40E7800379878 /* get_tags.command in Resources */ = {isa = PBXBuildFile; fileRef = EDC06B7B1DB40E7800379878 /* get_tags.command */; };
Expand All @@ -64,6 +68,8 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
ED99D7AE1FB335560077B965 /* HockeySDK.framework in Embed Frameworks */,
ED99D7B01FB335560077B965 /* Sparkle.framework in Embed Frameworks */,
ED1762E11F975B7000C84290 /* CommandsCore.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
Expand Down Expand Up @@ -106,6 +112,8 @@
ED85D2EF1F950A9400E5E2D8 /* LanguageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LanguageViewController.swift; sourceTree = "<group>"; };
ED9472931E365F9C00FE2982 /* ElementConstructorViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ElementConstructorViewController.swift; sourceTree = "<group>"; };
ED9472951E37BD3E00FE2982 /* get_uniq_elements.command */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = get_uniq_elements.command; sourceTree = "<group>"; };
ED99D7A91FB334DA0077B965 /* HockeySDK.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = HockeySDK.framework; path = Launcher/Frameworks/HockeySDK.framework; sourceTree = "<group>"; };
ED99D7AA1FB334DA0077B965 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = Launcher/Frameworks/Sparkle.framework; sourceTree = "<group>"; };
EDB433351DD49AF5001BABEC /* InspectorViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InspectorViewController.swift; sourceTree = "<group>"; };
EDBC88061DFEE8A6004CB840 /* kill_process.command */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = kill_process.command; sourceTree = "<group>"; };
EDC06B7B1DB40E7800379878 /* get_tags.command */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = get_tags.command; sourceTree = "<group>"; };
Expand All @@ -128,6 +136,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
ED99D7AD1FB335560077B965 /* HockeySDK.framework in Frameworks */,
ED99D7AC1FB334DA0077B965 /* Sparkle.framework in Frameworks */,
ED1762E01F975B7000C84290 /* CommandsCore.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -155,6 +165,7 @@
EDD303971F8F88400042E27F /* Launcher */,
EDD303931F8F869B0042E27F /* Scripts */,
ED4C14DE1DB29FB700A1190E /* Products */,
ED99D7A81FB334D90077B965 /* Frameworks */,
);
sourceTree = "<group>";
};
Expand All @@ -166,6 +177,15 @@
name = Products;
sourceTree = "<group>";
};
ED99D7A81FB334D90077B965 /* Frameworks */ = {
isa = PBXGroup;
children = (
ED99D7A91FB334DA0077B965 /* HockeySDK.framework */,
ED99D7AA1FB334DA0077B965 /* Sparkle.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
EDD303911F8F86290042E27F /* Classes */ = {
isa = PBXGroup;
children = (
Expand Down
17 changes: 17 additions & 0 deletions Launcher/Classes/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import Cocoa
import HockeySDK
import Sparkle

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {

var buildTaskNew: Process!

@IBOutlet weak var updater: SUUpdater!

@IBAction func closeTheApp(_ sender: AnyObject) {
killProcessScreenshot()
NSApplication.shared.terminate(self)
Expand Down Expand Up @@ -50,6 +54,19 @@ class AppDelegate: NSObject, NSApplicationDelegate {
return true
}

func applicationWillFinishLaunching(_ notification: Notification) {
if let hockeyID = Bundle.main.infoDictionary?["HockeyID"] as? String,
let hockeyURLString = Bundle.main.infoDictionary?["SUFeedURL"] as? String,
let hockeyURL = URL(string: hockeyURLString) {
BITHockeyManager.shared().configure(withIdentifier: hockeyID)
BITHockeyManager.shared().crashManager.isAutoSubmitCrashReport = true
BITHockeyManager.shared().start()
updater.feedURL = hockeyURL
updater.checkForUpdates(SUUpdater.self)
updater.automaticallyChecksForUpdates = true
}
}

func shouldSaveApplicationState(_ sender: NSApplication) -> Bool {
return true
}
Expand Down
1 change: 1 addition & 0 deletions Launcher/Frameworks/HockeySDK.framework/Headers
1 change: 1 addition & 0 deletions Launcher/Frameworks/HockeySDK.framework/HockeySDK
1 change: 1 addition & 0 deletions Launcher/Frameworks/HockeySDK.framework/Modules
1 change: 1 addition & 0 deletions Launcher/Frameworks/HockeySDK.framework/PrivateHeaders
1 change: 1 addition & 0 deletions Launcher/Frameworks/HockeySDK.framework/Resources
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#import <Foundation/Foundation.h>

/**
* Provides details about the crash that occured in the previous app session
*/
@interface BITCrashDetails : NSObject

/**
* UUID for the crash report
*/
@property (nonatomic, readonly, copy) NSString *incidentIdentifier;

/**
* UUID for the app installation on the device
*/
@property (nonatomic, readonly, copy) NSString *reporterKey;

/**
* Signal that caused the crash
*/
@property (nonatomic, readonly, copy) NSString *signal;

/**
* Exception name that triggered the crash, nil if the crash was not caused by an exception
*/
@property (nonatomic, readonly, copy) NSString *exceptionName;

/**
* Exception reason, nil if the crash was not caused by an exception
*/
@property (nonatomic, readonly, copy) NSString *exceptionReason;

/**
* Date and time the app started, nil if unknown
*/
@property (nonatomic, readonly, copy) NSDate *appStartTime;

/**
* Date and time the crash occured, nil if unknown
*/
@property (nonatomic, readonly, copy) NSDate *crashTime;

/**
* Operation System version string the app was running on when it crashed.
*/
@property (nonatomic, readonly, copy) NSString *osVersion;

/**
* Operation System build string the app was running on when it crashed
*
* This may be unavailable.
*/
@property (nonatomic, readonly, copy) NSString *osBuild;

/**
* CFBundleShortVersionString value of the app that crashed
*
* Can be `nil` if the crash was captured with an older version of the SDK
* or if the app doesn't set the value.
*/
@property (nonatomic, readonly, copy) NSString *appVersion;

/**
* CFBundleVersion value of the app that crashed
*/
@property (nonatomic, readonly, copy) NSString *appBuild;

/**
* Identifier of the app process that crashed
*/
@property (nonatomic, readonly, assign) NSUInteger appProcessIdentifier;

@end
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
#import <Cocoa/Cocoa.h>

/**
* `NSApplication` subclass to catch additional exceptions
*
* On OS X runtime not all uncaught exceptions do end in an custom `NSUncaughtExceptionHandler`.
* In addition "sometimes" exceptions don't even cause the app to crash, depending on where and
* when they happen.
*
* Here are the known scenarios:
*
* 1. Custom `NSUncaughtExceptionHandler` don't start working until after `NSApplication` has finished
* calling all of its delegate methods!
*
* Example:
* - (void)applicationDidFinishLaunching:(NSNotification *)note {
* ...
* [NSException raise:@"ExceptionAtStartup" format:@"This will not be recognized!"];
* ...
* }
*
*
* 2. The default `NSUncaughtExceptionHandler` in `NSApplication` only logs exceptions to the console and
* ends their processing. Resulting in exceptions that occur in the `NSApplication` "scope" not
* occurring in a registered custom `NSUncaughtExceptionHandler`.
*
* Example:
* - (void)applicationDidFinishLaunching:(NSNotification *)note {
* ...
* [self performSelector:@selector(delayedException) withObject:nil afterDelay:5];
* ...
* }
*
* - (void)delayedException {
* NSArray *array = [NSArray array];
* [array objectAtIndex:23];
* }
*
* 3. Any exceptions occurring in IBAction or other GUI does not even reach the NSApplication default
* UncaughtExceptionHandler.
*
* Example:
* - (IBAction)doExceptionCrash:(id)sender {
* NSArray *array = [NSArray array];
* [array objectAtIndex:23];
* }
*
*
* Solution A:
*
* Implement `NSExceptionHandler` and set the `ExceptionHandlingMask` to `NSLogAndHandleEveryExceptionMask`
*
* Benefits:
*
* 1. Solves all of the above scenarios
*
* 2. Clean solution using a standard Cocoa System specifically meant for this purpose.
*
* 3. Safe. Doesn't use private API.
*
* Problems:
*
* 1. To catch all exceptions the `NSExceptionHandlers` mask has to include `NSLogOtherExceptionMask` and
* `NSHandleOtherExceptionMask`. But this will result in @catch blocks to be called after the exception
* handler processed the exception and likely lets the app crash and create a crash report.
* This makes the @catch block basically not working at all.
*
* 2. If anywhere in the app a custom `NSUncaughtExceptionHandler` will be registered, e.g. in a closed source
* library the develop has to use, the complete mechanism will stop working
*
* 3. Not clear if this solves all scenarios there can be.
*
* 4. Requires to adjust PLCrashReporter not to register its `NSUncaughtExceptionHandler` which is not a good idea,
* since it would require the `NSExceptionHandler` would catch *all* exceptions and that would cause
* PLCrashReporter to stop all running threads every time an exception occurs even if will be handled right
* away, e.g. by a system framework.
*
*
* Solution B:
*
* Overwrite and extend specific methods of `NSApplication`. Can be implemented via subclassing NSApplication or
* by using a category.
*
* Benefits:
*
* 1. Solves scenarios 2 (by overwriting `reportException:`) and 3 (by overwriting `sendEvent:`)
*
* 2. Subclassing approach isn't enforcing the mechanism onto apps and let developers opt-in.
* (Category approach would enforce it and rather be a problem of this soltuion.)
*
* 3. Safe. Doesn't use private API.
*
* Problems:
*
* 1. Does not automatically solve scenario 1. Developer would have to put all that code into @try @catch blocks
*
* 2. Not a clean implementation, rather feels like a workaround.
*
* 3. Not clear if this solves all scenarios there can be.
*
*
* Chosen Solution: B via subclassing
*
* Reasons:
*
* 1. The Problems 1. and 2. of Solution A are too drastic and aren't acceptable for every developer using this SDK
* Especially Problem 1 is a big No Go for lots of developers.
*
* 2. Solution B can be used optionally, can be adopted easily into developers own `NSApplication` subclasses and
* by implementing it in a subclass instead of a category isn't enforced even though it requires additional
* steps for setup.
*
* 3. The not covered Scenario 1. can be achieved by the developer by enclosing most of the code within
* NSApplication startup delegates in @try @catch blocks or moving as much code as possible out of these
* methods and deferring their execution, e.g. using background threads. Not ideal though.
*
*
* References:
* https://developer.apple.com/library/mac/documentation/cocoa/Conceptual/Exceptions/Tasks/ControllingAppResponse.html#//apple_ref/doc/uid/20000473-BBCHGJIJ
* http://stackoverflow.com/a/4199717/474794
* http://stackoverflow.com/a/3419073/474794
* http://macdevcenter.com/pub/a/mac/2007/07/31/understanding-exceptions-and-handlers-in-cocoa.html
*
*/
@interface BITCrashExceptionApplication : NSApplication

@end
Loading

0 comments on commit c86658a

Please sign in to comment.