Wednesday, August 24, 2011

Android and the dreaded fragmentation problem

As I try desperately to get untracked onto my IOS version of my Japanese Quiz app, I'm getting inexorably sucked into the vortex of Android support - exactly what I had hoped to avoid and feared I wouldn't be able to.

It seems I'm getting some exception in the wild still based on SQLlite exceptions. As you can see from previous posts, I've made several attempts - two at least - to resolve this. But it still keep on coming. Googling reveals the multiple developers have had this problem, and the only clear fix presented, which was effective for some, hasn't worked for me.

Some of the developers who've been skilled or fortunate enough to establish contacts with the users involved have determined that the problem may be isolated to some version of the HTC Desire. Googles crash reports don't give that level of detail, lumping most phones into the "other' category.

As a shot in the dark, and based on a slightly related post in that the problem appeared on a similar phone in a similar file copy of a database situation, I could try removing the "readonly" parameter from the open database command. I needs an integer, so I could try readwrite. But, I'm not sure that would help.

Another option would be to install this library (ACRA):

http://code.google.com/p/acra/wiki/BasicSetup

Acra is a library that apparently does a far better job reporting on crashes than Google's solution. It would be nice to know if it's limited to a particular phone, for example. I also had a couple of other crashes - one where it couldn't instantiate the font, and another where a class wasn't defined or something.

The problem is my phone's recharger isn't working, so I'm unable to test on it until the new recharger arrives. For some reason, it never works on my emulator either. Maybe now would be a good time to try to get that working.

One problem I would love to figure out is why this uhhgly compile warning, or more precisely, how to get rid of it?


[2011-08-25 00:17:26 - JlptQuiz5Full] Dx
UNEXPECTED TOP-LEVEL EXCEPTION:
java.lang.IllegalArgumentException: already added: Lcom/mobfox/R$attr;
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at com.android.dx.dex.file.ClassDefsSection.add(ClassDefsSection.java:123)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at com.android.dx.dex.file.DexFile.add(DexFile.java:143)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at com.android.dx.command.dexer.Main.processClass(Main.java:372)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at com.android.dx.command.dexer.Main.processFileBytes(Main.java:346)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at com.android.dx.command.dexer.Main.access$400(Main.java:59)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:294)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:244)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:130)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:108)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at com.android.dx.command.dexer.Main.processOne(Main.java:313)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at com.android.dx.command.dexer.Main.processAllFiles(Main.java:233)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at com.android.dx.command.dexer.Main.run(Main.java:185)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at sun.reflect.GeneratedMethodAccessor8.invoke(Unknown Source)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at java.lang.reflect.Method.invoke(Method.java:597)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at com.android.ide.eclipse.adt.internal.build.DexWrapper.run(DexWrapper.java:179)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at com.android.ide.eclipse.adt.internal.build.BuildHelper.executeDx(BuildHelper.java:585)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at com.android.ide.eclipse.adt.internal.build.builders.PostCompilerBuilder.build(PostCompilerBuilder.java:490)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at org.eclipse.core.internal.events.BuildManager$2.run(BuildManager.java:629)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:172)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:203)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at org.eclipse.core.internal.events.BuildManager$1.run(BuildManager.java:255)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:258)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at org.eclipse.core.internal.events.BuildManager.basicBuildLoop(BuildManager.java:311)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at org.eclipse.core.internal.events.BuildManager.build(BuildManager.java:343)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at org.eclipse.core.internal.events.AutoBuildJob.doBuild(AutoBuildJob.java:144)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at org.eclipse.core.internal.events.AutoBuildJob.run(AutoBuildJob.java:242)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)
[2011-08-25 00:17:26 - JlptQuiz5Full] Dx 1 error; aborting
[2011-08-25 00:17:26 - JlptQuiz5Full] Conversion to Dalvik format failed with error 1
[2011



So, if I comment out the update, will it work?

Yes. So, I can test this change. Perfect. I'll figure out later why I can't update, it's not a concern right now.

Ok, let's take a look at ACRA. This is a better alternative for reporting errors.

http://code.google.com/p/acra/wiki/BasicSetup#Introduction

Introduction
All ACRA bug reports should be filed in the Issues Tracker. You can also post your questions or suggestions to the Discussion Group.

ACRA allows your Android application to send Crash Reports to various destinations:

a Google Docs spreadsheet (default and original behavior)
an email (new in 4.0)
your own server-side HTTP POST script (parameter names changed in 4.0)
any other possible destination by implementing your own report sender (new in 4.0)
When a crash occurs, you can choose and configure 3 different ways of interacting with the user:

Silent (default): ACRA actions are not visible. The crash report is sent and then the default android crash system does its job (Force Close dialog)
Toast: When the crash occurs, ACRA displays a toast and simultaneously sends the report.
Notification: An optional toast is displayed on application crash, but the report is not sent immediately. A status bar notification is published warning the user that he should send a report. When selected, the notification displays a dialog asking for the authorization to send the report, with an optional user comment.
This tutorial will guide you through installing ACRA in your application project.
If you have any question or comment regarding ACRA, post a message




So far, so good.

Next:

Setting-up your project

Step by step installation of the ACRA library in an existing application project, with the simplest settings:

Get http://acra.googlecode.com/files/acra-4.2.3.zip and open the archive

// ok, looks like a source and class jar, some docs and a csv file.


Login to your Google Docs account

// check.

Import the CrashReports-template.csv contained in the archive (acra-4.2.3/CrashReport/doc), with conversion enabled
// upload, actually

Open the imported document
// ok

Rename it as you like

// Dropped the suffix

In the Google Docs menu, click on Tools / Form / Create a form
// Ok

Add anything in the form description just to enable the Save button

// ok

If you are using a private Google Apps domain, make sure to uncheck the option "Require yourdomain.com sign-in to view this form."

// I don't see anything, pretty sure I'm not using Google Apps domain

Save the form

// Consider it done, Sire.

Copy the formkey value displayed in the link at the bottom of the form creation page

// That must be this: https://docs.google.com/spreadsheet/viewform?formkey=dGhjOUczdThjRFlrWmV4QnZKV3J2aVE6MQ

Open your Eclipse project

// Which one - core or dependent? Here we go again.

Create a lib folder

// I'll do it in the core and hope to he.ll it works.

Add the acra-4.2.3.jar from the archive (acra-4.2.3/build) in the lib folder

// copied

Right-click on the jar file / add to build path

// Good, seems to work.

Create a new class in your package root If your app already contains an Application subclass, add ACRA to this class.

// I think I need to add Acra to this, since I'm extending application.

Give it a name like: MyApplication, make it extend android.app.Application
Above the declaration of the MyApplication class, add the @ReportsCrashes annotation with your Google Docs formKey as a parameter

import org.acra.*;
import org.acra.annotation.*;

@ReportsCrashes(formKey = "dGVacG0ydVHnaNHjRjVTUTEtb3FPWGc6MQ")
public class MyApplication extends Application {
}

// all added

In the MyApplication class, override the onCreate() method to add the ACRA init statement

@Override
public void onCreate() {
// The following line triggers the initialization of ACRA
ACRA.init(this);
super.onCreate();
}

// Ok, done. Next?

Open the android manifest editor (AndroidManifest.xml)
In the Application tab, click on the Browse button next to the Name field
Select your newly created Application class (MyApplication).

This adds an android:name attribute to your application element like this (put the full name with package if the application class package is not the same as manifest root element declared pakage):

android:name="MyApplication">

// done

In the Permissions tab, add a Uses Permission object with value android.permission.INTERNET.

This adds the following element as a child of the manifest element:

// done


THE END - next time your application crashes, it adds a line to your Google Docs spreadsheet :-).

// Great - lets's try it.

Nope. Dependent project issues again. I've got to figure this one out. It's constantly nipping at my heels.



No comments:

Post a Comment