Crashing inCrashing in
About /me
• Tam HANNA
– CEO, Tamoggemon
Ltd.
– Director, Tamoggemon
Holding k.s.
– Runs web sites about
mobile computing
– Writes scientific books
About /girly
• Annette BOSBACH
– Clerk to the
coordinating office,
Tamoggemon Holding
k.s.
– First GottaTxt fan
Overview
• The schedule
• Why track crashes
• Basic methods
• ACRA
Source code
• JAVA Source code is available
– Via Twitter
• Our IP: free to use
– Too low to qualify for protection
– Plus, you have to listen to us so 
The schedule
Crash first, Qt
second• 60% / 40%
– More about Qt: at our booth
• Please tweet about us
The @tamhanna show is co
GottaTxt is the best app at
#droidconnl
After listening to
@tamhanna, my app doesn‘t
crash anymore!!!
@tamhanna threw chocolate on
my head. Ouch! #droidconnl
Why trackWhy track
Market is crowded
• Bad ratings kill an application
• BUT: responding to feedback helps
– „The developer responds to ME!!!“
– I am important
– Ego issues => superhappy customer
Why track crashes?
• Isn‘t it better not to crash?
– Matthew A Brenner, UnME2
• Yes, but
– Ever-increasing number of LOC
– Fragmentation (to see /me mention that )
– Margin pressure
• TU144 / Concorde problem
Users are stupid
• What OS version do you use?
– Common question for developers
– Perceived as denigration by some users
• Send me a file from the file system!
– Common question for developers
– But for developer‘s wife or husband?
Crash vs stat
tracking• Stat tracking
– Which flows are used
– Entry/Exit path analysis
– e.g. Google Analytics
• Crash tracking
– What causes crashes
– Where do users „die“
And there‘s more
• Track „points of pain“ for users
– Rejection of user input
– Games: user death
• Fix them in the next release
– First 2min with application are critical
Private debuggerPrivate debugger
Picture: Wikimedia Commons / fluteflute
What‘s that
• Special mode of operation
– Allows developer access to internals
– ON the users phone
• Can be accessed via secret key
– Must be easy to enter, difficult to guess
– Prevent users from entering it by mistake
• Customer provides info to developer
How to implement
• By foot
• No ready made libraries available
Example
• GottaTxt
1. Open Thread
2. Enter „Secret Code“
3. Enter commands
4. Give response
Try it at our booth
FREE VODKAFREE VODKA
INCLUDED!!!INCLUDED!!!
Basic crashBasic crash
handlinghandling
Wikimedia Commons / David Monack
Really easy way
• Thread.setDefaultExceptionHandler()
• Write to file, then die
• Tell user to email file
– Can usually be accomplished
Problems
• IO is buffered
• Thread terminates before data written
• Data lost
• !!!Occurs rarely!!!
– Never saw it on Android
Non-working
solution• StackOverflow user gupta
• Fire intent from exception handler
• Hope for it to arrive
Non-working
solution - II• Doesn‘t work in practice
• Intent never arrives at application
Workable solution
• Completely override crash handling
– No Android Crash message shown
• Re-invoke application
• Example a360crash1
public ExceptionTrap(Context _context, String _filePath)
{
myContext=_context;
myFilePath=_filePath;
myHandler=Thread.getDefaultUncaughtExceptionHandler();
}
@Override
public void uncaughtException(Thread _t, Throwable _a)
{
try
{
StringWriter s=new StringWriter();
_a.printStackTrace(new PrintWriter(s));
Intent launchIntent=new Intent(ErrorReporter.INTENTSTRING);
launchIntent.putExtra("StackTrace", s.toString());
launchIntent.putExtra("FilePath", myFilePath);
PendingIntent pIntent=PendingIntent.getService(myContext, 0,
launchIntent, launchIntent.getFlags());
AlarmManager mgr = (AlarmManager)
myContext.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 2000, pIntent);
System.exit(2);
public class ErrorReporter extends IntentService
{
public static final String INTENTSTRING
="com.tamoggemon.a360crash1.intent.CALLERRORREPORTER";
public ErrorReporter()
{
super("TAG");
}
@Override
public void onCreate()
{
super.onCreate();
}
protected void onHandleIntent(Intent intent)
{//Newline, etc removed
try
{
boolean newFile=false;
File writeFile=new File(intent.getStringExtra("FilePath"));
if(writeFile.exists()==false)
{
newFile=true;
writeFile.createNewFile();
}
BufferedWriter buf = new BufferedWriter(new FileWriter(writeFile,
true));
if(newFile)
{
buf.append(android.os.Build.MODEL);
buf.append(android.os.Build.VERSION.RELEASE);
}
buf.append("-------------------CRASH-------------------")
buf.append(intent.getStringExtra("StackTrace"));
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
myTrap=new ExceptionTrap(this, "/sdcard/A360Crash.log");
Thread.setDefaultUncaughtExceptionHandler(myTrap);
setContentView(R.layout.main);
findViewById(R.id.button1).setOnClickListener(this);
}
@Override
public void onClick(View v)
{
throw new RuntimeException("Fehler erfolgreich ausgelöst!");
}
<service android:name=".ErrorReporter">
<intent-filter >
<action
android:name="com.tamoggemon.a360crash1.intent.CALLERROR
REPORTER" />
</intent-filter>
</service>
ACRAACRAWikimedia Commons / gerol
What is ACRA
• Android Crash Report for Android
• Very flexible library
• Can dump crash data to Google Docs
Set up online
• Google Account needed
• Create new form via SpreadSheet
• Export it to get FormKey
Integrate into app
@ReportsCrashes(formKey =
"dExKcElJWjVaUkpMem9WOWg3VE80SlE6MQ")
public class MyApplication extends Application
{
@Override
public void onCreate()
{
ACRA.init(this);
super.onCreate();
}
}
Custom data
• if(v==cmdStoreA)
• {
•
ErrorReporter.getInstance().putCustomData("myVariable
", "A");
• }
• if(v==cmdStoreB)
• {
•
ErrorReporter.getInstance().putCustomData("myVariable
", "B");
• }
Enable / Disable
• if(v==cmdEnable)
• {
• SharedPreferences
aPrefs=ACRA.getACRASharedPreferences();
• Editor anEditor=aPrefs.edit();
• anEditor.putBoolean("acra.enable", true);
• anEditor.commit();
• }
• if(v==cmdDisable)
• {
• SharedPreferences
aPrefs=ACRA.getACRASharedPreferences();
• Editor anEditor=aPrefs.edit();
• anEditor.putBoolean("acra.enable", false);
• anEditor.commit();
• }
Further Options
• ACRA does a LOT
– Interact with users
– Custom databases
• https://github.com/ACRA/acra/wiki/AdvancedUsage
OOP FTW
Problem of all
solutions• Integration requires manual work
– Find all classes
– Integrate logging code
• Better solution: „stub objects“
How to implement it
• By foot
• Loads of leeway for developers
– Abstract actual logging?
Example
public abstract class TMGNActivity extends Activity
{
@Override
public final void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
logThis("Creating Activity");
logThis(getClass().getName());
tmgnOnCreate(savedInstanceState);
}
public abstract void tmgnOnCreate(Bundle savedInstanceState);
Other vendors
Google Play Crash
tracking• Google Play provides crash tracking
– Rudimentary, can‘t add own data
• Better than nothing
– Check often
– Log-in freq. could (!!!) be used for ranking
Crash Trackers
• BugSense
– Specialized service
• Flurry
– Afterthought for premium analytics
• Yours?
– Tell us in Q&A
ConclusionConclusion
Crashes will happen
• Today‘s mobile apps are
– Highly complex
– Underfunded (thanks, Apple!)
• Even the OS crashes sometimes
• Users tolerate reasonable crashingUsers tolerate reasonable crashing
Work-arounds are
needed• Paid users expect frequent updates
– Let them generate their wishes themselves
• Monitoring is first step to improvement
– See what users really think
Olympic spirit
• Important:
– TRACK CRASHES
– Perform PDCA cycle on data
• Not so important
– How to track them
– Track 100% of them
?!?
tamhan@tamoggemon.com
@tamhanna

crashing in style

  • 1.
  • 2.
    About /me • TamHANNA – CEO, Tamoggemon Ltd. – Director, Tamoggemon Holding k.s. – Runs web sites about mobile computing – Writes scientific books
  • 3.
    About /girly • AnnetteBOSBACH – Clerk to the coordinating office, Tamoggemon Holding k.s. – First GottaTxt fan
  • 4.
    Overview • The schedule •Why track crashes • Basic methods • ACRA
  • 5.
    Source code • JAVASource code is available – Via Twitter • Our IP: free to use – Too low to qualify for protection – Plus, you have to listen to us so 
  • 6.
  • 7.
    Crash first, Qt second•60% / 40% – More about Qt: at our booth • Please tweet about us
  • 8.
    The @tamhanna showis co GottaTxt is the best app at #droidconnl After listening to @tamhanna, my app doesn‘t crash anymore!!! @tamhanna threw chocolate on my head. Ouch! #droidconnl
  • 9.
  • 10.
    Market is crowded •Bad ratings kill an application • BUT: responding to feedback helps – „The developer responds to ME!!!“ – I am important – Ego issues => superhappy customer
  • 11.
    Why track crashes? •Isn‘t it better not to crash? – Matthew A Brenner, UnME2 • Yes, but – Ever-increasing number of LOC – Fragmentation (to see /me mention that ) – Margin pressure • TU144 / Concorde problem
  • 12.
    Users are stupid •What OS version do you use? – Common question for developers – Perceived as denigration by some users • Send me a file from the file system! – Common question for developers – But for developer‘s wife or husband?
  • 13.
    Crash vs stat tracking•Stat tracking – Which flows are used – Entry/Exit path analysis – e.g. Google Analytics • Crash tracking – What causes crashes – Where do users „die“
  • 14.
    And there‘s more •Track „points of pain“ for users – Rejection of user input – Games: user death • Fix them in the next release – First 2min with application are critical
  • 15.
    Private debuggerPrivate debugger Picture:Wikimedia Commons / fluteflute
  • 16.
    What‘s that • Specialmode of operation – Allows developer access to internals – ON the users phone • Can be accessed via secret key – Must be easy to enter, difficult to guess – Prevent users from entering it by mistake • Customer provides info to developer
  • 17.
    How to implement •By foot • No ready made libraries available
  • 18.
    Example • GottaTxt 1. OpenThread 2. Enter „Secret Code“ 3. Enter commands 4. Give response
  • 19.
    Try it atour booth FREE VODKAFREE VODKA INCLUDED!!!INCLUDED!!!
  • 20.
  • 21.
    Really easy way •Thread.setDefaultExceptionHandler() • Write to file, then die • Tell user to email file – Can usually be accomplished
  • 22.
    Problems • IO isbuffered • Thread terminates before data written • Data lost • !!!Occurs rarely!!! – Never saw it on Android
  • 23.
    Non-working solution• StackOverflow usergupta • Fire intent from exception handler • Hope for it to arrive
  • 24.
    Non-working solution - II•Doesn‘t work in practice • Intent never arrives at application
  • 25.
    Workable solution • Completelyoverride crash handling – No Android Crash message shown • Re-invoke application • Example a360crash1
  • 26.
    public ExceptionTrap(Context _context,String _filePath) { myContext=_context; myFilePath=_filePath; myHandler=Thread.getDefaultUncaughtExceptionHandler(); }
  • 27.
    @Override public void uncaughtException(Thread_t, Throwable _a) { try { StringWriter s=new StringWriter(); _a.printStackTrace(new PrintWriter(s)); Intent launchIntent=new Intent(ErrorReporter.INTENTSTRING); launchIntent.putExtra("StackTrace", s.toString()); launchIntent.putExtra("FilePath", myFilePath); PendingIntent pIntent=PendingIntent.getService(myContext, 0, launchIntent, launchIntent.getFlags()); AlarmManager mgr = (AlarmManager) myContext.getSystemService(Context.ALARM_SERVICE); mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 2000, pIntent); System.exit(2);
  • 28.
    public class ErrorReporterextends IntentService { public static final String INTENTSTRING ="com.tamoggemon.a360crash1.intent.CALLERRORREPORTER"; public ErrorReporter() { super("TAG"); } @Override public void onCreate() { super.onCreate(); }
  • 29.
    protected void onHandleIntent(Intentintent) {//Newline, etc removed try { boolean newFile=false; File writeFile=new File(intent.getStringExtra("FilePath")); if(writeFile.exists()==false) { newFile=true; writeFile.createNewFile(); } BufferedWriter buf = new BufferedWriter(new FileWriter(writeFile, true)); if(newFile) { buf.append(android.os.Build.MODEL); buf.append(android.os.Build.VERSION.RELEASE); } buf.append("-------------------CRASH-------------------") buf.append(intent.getStringExtra("StackTrace"));
  • 30.
    public void onCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); myTrap=new ExceptionTrap(this, "/sdcard/A360Crash.log"); Thread.setDefaultUncaughtExceptionHandler(myTrap); setContentView(R.layout.main); findViewById(R.id.button1).setOnClickListener(this); } @Override public void onClick(View v) { throw new RuntimeException("Fehler erfolgreich ausgelöst!"); }
  • 31.
  • 32.
  • 33.
    What is ACRA •Android Crash Report for Android • Very flexible library • Can dump crash data to Google Docs
  • 34.
    Set up online •Google Account needed • Create new form via SpreadSheet • Export it to get FormKey
  • 35.
    Integrate into app @ReportsCrashes(formKey= "dExKcElJWjVaUkpMem9WOWg3VE80SlE6MQ") public class MyApplication extends Application { @Override public void onCreate() { ACRA.init(this); super.onCreate(); } }
  • 36.
    Custom data • if(v==cmdStoreA) •{ • ErrorReporter.getInstance().putCustomData("myVariable ", "A"); • } • if(v==cmdStoreB) • { • ErrorReporter.getInstance().putCustomData("myVariable ", "B"); • }
  • 37.
    Enable / Disable •if(v==cmdEnable) • { • SharedPreferences aPrefs=ACRA.getACRASharedPreferences(); • Editor anEditor=aPrefs.edit(); • anEditor.putBoolean("acra.enable", true); • anEditor.commit(); • } • if(v==cmdDisable) • { • SharedPreferences aPrefs=ACRA.getACRASharedPreferences(); • Editor anEditor=aPrefs.edit(); • anEditor.putBoolean("acra.enable", false); • anEditor.commit(); • }
  • 38.
    Further Options • ACRAdoes a LOT – Interact with users – Custom databases • https://github.com/ACRA/acra/wiki/AdvancedUsage
  • 39.
  • 40.
    Problem of all solutions•Integration requires manual work – Find all classes – Integrate logging code • Better solution: „stub objects“
  • 42.
    How to implementit • By foot • Loads of leeway for developers – Abstract actual logging?
  • 43.
    Example public abstract classTMGNActivity extends Activity { @Override public final void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); logThis("Creating Activity"); logThis(getClass().getName()); tmgnOnCreate(savedInstanceState); } public abstract void tmgnOnCreate(Bundle savedInstanceState);
  • 44.
  • 45.
    Google Play Crash tracking•Google Play provides crash tracking – Rudimentary, can‘t add own data • Better than nothing – Check often – Log-in freq. could (!!!) be used for ranking
  • 46.
    Crash Trackers • BugSense –Specialized service • Flurry – Afterthought for premium analytics • Yours? – Tell us in Q&A
  • 47.
  • 48.
    Crashes will happen •Today‘s mobile apps are – Highly complex – Underfunded (thanks, Apple!) • Even the OS crashes sometimes • Users tolerate reasonable crashingUsers tolerate reasonable crashing
  • 49.
    Work-arounds are needed• Paidusers expect frequent updates – Let them generate their wishes themselves • Monitoring is first step to improvement – See what users really think
  • 50.
    Olympic spirit • Important: –TRACK CRASHES – Perform PDCA cycle on data • Not so important – How to track them – Track 100% of them
  • 51.