Dear Paul,
How did you create the jar wrappers for Fabric and Crashlytics ?
And How did you created a Podfile with those two pods listed, installed them, and then manually added the frameworks to your xcode project ?
How did you use IOSUncaughtExceptionHandler?
Help me, please!
I generated the jars for the pods using the documented method here:
https://doc.multi-os-engine.org/multi-os-engine/5_using_thirdparty/2_wrap_android/2_toxcode/3_UsingCocoapods/cocoapods.html?highlight=cocoapods
Getting the project to link to the framework was a bit annoying, as it didnāt appear that the project was discovering the frameworks embedded in the jar files. I ended up just creating a dummy XCode project to install the pods, copying the framework files over, then manually adding them to the libgdx generated xcode project. I think I read somewhere that all this is changing in MOE 1.3?
As for actually using the IOSUncaughtExceptionHandler, I added the following to my main IOSLauncher class:
@Override
public boolean applicationDidFinishLaunchingWithOptions(UIApplication application, NSDictionary<?, ?> launchOptions) {
boolean retVal = super.applicationDidFinishLaunchingWithOptions(application, launchOptions);
if (retVal) {
NSMutableArray array = NSMutableArray.alloc().init();
array.add(Crashlytics.class_objc_static());
Fabric.with(array);
Thread.setDefaultUncaughtExceptionHandler(new IOSUncaughtExceptionHandler());
}
return retVal;
}
Hope that helps. Good luck.
I was also looking at this and wonder if you had a chance to update this to MOE 1.3-beta-2 yet? There is a new tool to generate java bindings.
On a side note, for Crashlytics, does it have to be a native wrapper? Or it would work to just use Crashlytics runtime for Java?
Hi Eugene,
Recently I have successfully connected Fabric and Crashlytics using the new Java Binding Generator. Itās working correctly, I have just one small issue with the Crashlytics raport - @PaulS custom ExceptionHandler is not working for me.
Iāve used the iOS native Fabric and Crashlytics pods:
- Install CocoaPods on your computer
sudo gem install cocoapods
- In terminal proceed to the xcode project directory and create new pod file
pod init
- Edit Podfile - use frameworks and set target to 9.0. Then save the file.
vim Podfile
platform :ios, 9.0
use_frameworks!
target 'MyTarget' do
# Pods for MyTarget
pod 'Fabric'
pod 'Crashlytics'
end
- Force remove the xcode configurations for your targets
Project navigator > Project > Info > Configurations
Set all to āNoneā
More on: http://stackoverflow.com/questions/26287103/cocoapods-warning-cocoapods-did-not-set-the-base-configuration-of-your-project/33509278#33509278
5) Quit xcode!
6) Ensure that xcode is not running!
Note: Running xcode will cause problems during pod installing. If you had your xcode running and you are having problems - try repeating this tutorial after removing all files modified by pod install.
- Install all pods from the Podfile - go to Podfile dir in terminal and type:
pod install
- Change build settings in xcode
Project navigator > Targets > MyTarget > Build Phases > Link Binary With Libraries
- Link your new pods. If you cannot find them try:
New > Add Other > ios > xcode > Pods > Fabric > iOS > Fabric.framework
-
Some libraries are needed extra for Fabric and Crashlytics (if you wonāt have them you will get later an error and then find the needed libraries in some StackOverflow answers ):
-
Add your API key (after creating a Fabric account you will find it here: https://fabric.io/kits/ios/crashlytics/install)
Remember to do all steps from Add a Run Script Build Phase and Add Your API Key. -
Add
-ObjC
to your linker flags:
Project > Targets > MyTarget > Build settings > Linking > Other Linker Flags
Double click and add new flag -ObjC
- If building through xcode is passing then proceed to Android Studio. Right click on project and do
MOE Actions > Create New Bindings
- Create .nbc file and proceed to form. In new window select
Header
and fill the form as below:
Name: <YOUR_POD_NAME>
Header path: xcode/Pods/<YOUR_POD_NAME>/<YOUR_POD_NAME>
(or another path to pod headers)
Base package name: com.yourapp.ios.pods.<YOUR_POD_NAME>
Import headers:
#import "<YOUR_POD_HEADER_FILE>.h"
(same as the objc import added in native pod usage)
-
Click on gear icon and click Generate bindings. The IDE will now freeze (@kisg ;)) and after a while it should generate Java classes in
com.yourapp.ios.pods.<YOUR_POD_NAME>
-
In your main class make sure that you initialize them correctly:
@Override
public boolean applicationDidFinishLaunchingWithOptions(UIApplication application, NSDictionary launchOptions) {
Fabric.with(NSArray.arrayWithObject(Crashlytics.class_objc_static()));
return true;
}
The only issue I have is that all my reports is grouped in a single one:
Which have different exceptions inside:
Iām not sure why the @PaulS custom exception handler is not working here.
Let me know if I can help you with any more issues!
Thank you Mateusz. It will take me some time to process all that. Great stuff.
Just one thing Iām still confused about. What you gaining by hooking up iOS version of Crashlytics vs. using Java one under MOEā¦ Is it just to get the native stack traces?
To be honest - I thought that the only way to make Crashlytics work with iOS is to use the native version. As far as I know, there is no clean-java version of Crashlytics, there is only the Android version, which wouldnāt work with iOS - it requires a lot of Android dependencies:
Native iOS stack traces are also not so valuable if most of your code is in Java.
Make sense. Havenāt thought Fabric would have those dependenciesā¦ Though seeing Answers stats it is probably unavoidable.
Hi Mateusz!
Great guide, thank you. It is good to know that someone else figured out how to use binding generation despite the somewhat ālimitedā documentation.
I get the hint about the freezing IDE. In the next release (beta3 or final 1.3) we will also have a Gradle task to run the generation.
Best Regards,
Gergely
We have a few options here:
-
MOE 2.0 will have native stack traces that include mangled, but easily decipherable Java class / method names like
Class_methodname
because of the new LLVM backend. We really just need to clean the code up a bit to release an alpha. -
If there would be a crash reporting tool that had an open-source Android SDK, it could be ported to MOE relatively painlessly. HockeyAppās SDK is open source for example. The main entry point for all such crash reporters is the standard Java UncaughtExceptionHandler that is also present in MOE.
-
I donāt know how much Fabric is using from Android. The screenshot only shows a handful of classes. If one of you would create a Hello World APK with only the Fabric / Crashlytics SDK initialized and uploaded it to the Migeran Analyzer, we would have a detailed report on what exactly is missing from MOE to get it running. Then the missing functionality could be stubbed out / reimplemented on top of the iOS APIs.
Hey guys, just wanted to drop and note that I have been using Fabric / Crashlytics successfully since posting the above. The reports Iām getting out of it are very helpful for my purposes. As my game is itself in beta now, I have not tried to update to newer versions of MOE, in an effort to maintain stability as we approach release.
The monkey wrench we should all keep our eyes on though is the fact that apparently Google has acquired Fabric, and we can expect Fabric and Firebase to merge in the near future. Details here:
https://fabric.io/blog/fabric-joins-google?utm_campaign=fabric-marketing&utm_medium=natural
Name: <YOUR_POD_NAME>
Header path: xcode/Pods/<YOUR_POD_NAME>/<YOUR_POD_NAME>
(or another path to pod headers)
Base package name: com.yourapp.ios.pods.<YOUR_POD_NAME>
Import headers:
#import "<YOUR_POD_HEADER_FILE>.h"
(same as the objc import added in native pod usage)
On step 15) , do we have to create .nbc file manually like that ? Is there a tool to scan through Pods/ folder and create the .nbc for us ?
For now you have to do it manually. .nbc files has been introduced quite recently and I donāt really think that this kind of tool would be available.
Wow, LLVM based, this does not sound like āAndroid AOT portā.
Any chance to see in action ?
Can you run my Collection Performance on it ?
(I can make a dedicated project for that if you can)
Hi Kirill,
sure, please share the project, and we will run the test.
It is actually still based on Android ART, but we developed a new backend for ARTās optimizing compiler, so it does not output machine code with its custom assembler, but generates LLVM IR / bitcode.
Best Regards,
Gergely
Dear @matis11,
In this post , step 17 you use class_objc_static()
method of Crashlytics
but in MOE 2.x this method has been removed.
I use Crashlytics.alloc().init()
in my project and its worked.
Regards,
Saeed.
Great, thank you for sharing it here
Is this still the recommended way to implement crashlytics with moe 1.3?
I saw some mentions in 1.3 about pregenerated bindings but havenāt found much documentation on how to use them. Do I simply copy files from the example projects at https://github.com/multi-os-engine/moe-bindings ?
Iāve followed the steps in post 10 above and the pod generation appeared to work. However, when I run it on my device I get a crash during launch.
2017-09-24 19:35:10.145714+0930 hoplite[522:155195] [DYMTLInitPlatform] platform initialization successful
art I 522 155010 /Volumes/SSD/Android/moe-final/aosp/art/runtime/parsed_options.cc:449] setting boot class path to /var/containers/Bundle/Application/6BB6EAB3-FAE2-4C32-B3C7-90E032DB92E8/hoplite.app/application.jar:/var/containers/Bundle/Application/6BB6EAB3-FAE2-4C32-B3C7-90E032DB92E8/hoplite.app
/Volumes/SSD/Android/moe-final/moe/natj/natj/src/main/native/natj/NatJ.cpp:353 DEBUG: Method 'boolean java.lang.reflect.Method.isDefault()' is not accessible.
2017-09-24 19:35:10.619832+0930 hoplite[522:155010] [Crashlytics] Version 3.8.6 (124)
SQLiteLog 6 (1) no such table: cfurl_cache_response
SQLiteLog 6 (1) no such table: cfurl_cache_response
2017-09-24 19:35:10.685349+0930 hoplite[522:155010] refreshPreferences: HangTracerEnabled: 0
2017-09-24 19:35:10.685596+0930 hoplite[522:155010] refreshPreferences: HangTracerDuration: 500
2017-09-24 19:35:10.685843+0930 hoplite[522:155010] refreshPreferences: ActivationLoggingEnabled: 0 ActivationLoggingTaskedOffByDA:0
2017-09-24 19:35:10.686853+0930 hoplite[522:155010] *** Terminating app due to uncaught exception 'java.lang.NullPointerException', reason: 'java.lang.NullPointerException: Attempt to invoke virtual method 'void com.badlogic.gdx.backends.iosmoe.IOSApplication.didBecomeActive(apple.uikit.UIApplication)' on a null object reference
at com.badlogic.gdx.backends.iosmoe.IOSApplication$Delegate.applicationDidBecomeActive(IOSApplication.java:79)
at apple.uikit.c.UIKit.UIApplicationMain(Native Method)
at com.magmafortress.hoplite.IOSMoeLauncher.main(IOSMoeLauncher.java:56)
'
First throw call stack:
(0x1862afd38 0x1857c4528 0x10a236b78 0x10a23c66c 0x10a260e38 0x10a24c1b4 0x18f7406cc 0x190099a5c 0x19022efc8 0x190099870 0x18fe83850 0x18fd28bd8 0x18895221c 0x10aa5d45c 0x10aa69b74 0x188985a04 0x1889856a8 0x188985c44 0x186258358 0x1862582d8 0x186257b60 0x186255738 0x1861762d8 0x188007f84 0x18f722880 0x10a24c044 0x10a2606c0 0x10a23e084 0x10a23df24 0x10a23efe8 0x10a260e38 0x10a24c1b4 0x111199cf4 0x109f56dc0 0x109f9d8c4 0x109f9d604 0x10a04a954 0x109d31fa8 0x10a0edc4c 0x109d30284 0x104cd32ac 0x185c9a56c)
libc++abi.dylib: terminating with uncaught exception of type ObjCException
Iām initialising crashlytics as done in step 17 and not doing anything with didBecomeActive or applicationDidBecomeActive in my code.
Has anyone come across this issue or know how I might get around it?
Does anyone have an example how to call org.moe.binding.crashlytics.c.Crashlytics.CLSLog(@Mapped(value=ObjCStringMapper.class) String format, Objectā¦ varargs) and its variants CLSNSLog and CLSLogv methods from Java?
MagmaFortress, Iām pretty sure you can just declare those bingings as your gradle dependencies - org.multi-os-engine.binding.ios:crashlytics:3.8.3
and you still need pod 'Crashlytics', '3.8.6'
in your Podfile to get frameworks into your app as explained above. Iām initializing Crashlytics in my main app class in applicationDidFinishLaunchingWithOptions(..)
method:
Fabric.with(NSArray.arrayWithObjects( //
Crashlytics.class_objc_static(), //
Answers.class_objc_static(), //
null));