It's time to abandon the database copy on the Android application. While it's hard to judge from Googles reporting how many crashes there have been, I've gotten a report (and a one-star rating) from someone using a Milestone, so I can't be thinking it's only on the HTC desire. So, I have a couple of options. Either I can build the DB from scratch, which I think would be fine, or I can download it from the internet. Because the latter is a quicker fix, I'm going to give that a shot first. If that fails, then I'll go for the building the DB from scratch. So, let's fire up the old Eclipse and see where we're at with this. I had been trying to add a debugging library with little success. Well, how tough would it be to just convert it to one application? That would save me all these headaches I've been having with multiple apps and dependent libraries. Ok, the code which checks the licensing is keeping me from getting in. So, if it's the free version, it shouldn't be checking the licensing. Let's see what it defaults to. It default to free based on strings.xml. Ok, so let's look at questions. Ok,
if (Utils.isFree(this))
{ // noop } else
{ if (false == SharedPreferencesUtil.getLicensed(appState))
{ finish(); }
}
Somehow, I could make prettier, but anyway. Ok, the main issue now is having a separate quiz start and end for each of the levels. But we can still use the same pair of start and ending quiz numbers as in app state. All we have to do is check the level when saving and restoring, and add the level to the prefs key. How does this look?
prefEditor.putInt(InitUtils.QUIZ_START_NUM + appState.jlptLevel, appState.quizStartNum); prefEditor.putInt(InitUtils.QUIZ_END_NUM + appState.jlptLevel, appState.quizEndNum);
// We need the save to accomodate browse vs. SRS mode
prefEditor.putInt(InitUtils.SAVE_QUIZ_START_NUM + appState.jlptLevel, appState.saveQuizStartNum); prefEditor.putInt(InitUtils.SAVE_QUIZ_END_NUM + + appState.jlptLevel, appState.saveQuizEndNum);
Ok, and we'll do the same thing with the restore of state. Ok, now, let's unprotect the jlpt level field in the settings view... Ok; and enable broadcast of the change. But, there's a problem. When I switch to level 4, it should download the data. Somehow it's bypassing the check - ok, I will just add the check to the start quiz button... Well, it started it but it didn't get anywhere - what happened? Just a little question on why it's not finding the sound file initially, and why it's not display the progress dialog.
D/PlaySoundUtil(10296): file notfound: /mnt/sdcard/Android/data/com.jlptquiz.app/cache/data/.com.kanjisoft.jlpt/aud5/5_455.mp3, 5 なる to become
Ah, I see - the question screen kind of is overshadowing it. Yowch. I need to make sure I know how to make these downloads modal - otherwise we could be trying to access and incomplete db!
Ok, it works if I handle on the level change. The problem on level change is similar to the one we had on changing the mode earlier. That is, once you change level, everything else should freeze - and once you change quiz number, start or finish, you shouldn't be able to change level. Sigh. It's complicated. The reason is, if you change level, you want it to go and get the correct quiz numbers. What we'll do is on a level change, freeze the quiz number changes - and vice versa. This example looks helpful (from SO)
textMessage.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s)
{ i++; tv.setText(String.valueOf(i) + " / " + String.valueOf(charCounts)); }
public void beforeTextChanged(CharSequence s, int start, int count, int after){}
public void onTextChanged(CharSequence s, int start, int before, int count){}
});
And here it is:
this.mLevel.addTextChangedListener(new TextWatcher(){
public void afterTextChanged(Editable s) {
SettingsActivity.this.mQuizStartNum.setEnabled(false);
SettingsActivity.this.mQuizEndNum.setEnabled(false); }
(same for quiz start and end)
Ok, let's try running this. Nice. It visually disables the fields, so the user will know. I like that. But - it's not good enough. It just saves the start and end quiz anyway. What I want to happen is for it to go into the retrieve routine on a change of level, and get whatever the start/end quiz numbers are for that level. So why not just do that? Ok, but the thick plottens still.
Because, now I need to update the app state with the new level - which means I have to validate it! Oy, vey. And, I think it's coming back to freeze the level input due to the change to the start and end quiz numbers. Holy double-twisted validation logic, Batman!
Ok, the problem is I'm trying to do too much. As soon as the level is updated, I'll just make sure it's valid, and then finish. Back at the start activity, it should re-initialize based on the new level in app state. Also, it needs to broadcast it back so the level display can be changed, and more importantly, the level stored and the revised app state retrieved. This code seems to do the trick:
this.mLevel.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
int inputLevel = SettingsActivity.this
.getEnteredValueAsInt(R.id.level_in);
if ((inputLevel < 1) || (inputLevel > 5)) // on Success
{
// pop up ERROR message
Toast.makeText(getBaseContext(),
"Level must be between 1 and 5", Toast.LENGTH_LONG)
.show();
} else {
/* retrieve app state */
AppState appState = ((AppState) getApplicationContext());
appState.jlptLevel = inputLevel;
// need to update shared prefs with level on return
Intent intent = new Intent("level.updated");
getApplicationContext().sendBroadcast(intent);
finish();
}
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
});
And - that's a wrap.
Hi Gaurav,
ReplyDeleteThanks so much for your nice comment. Actually, this change turned out really well. It reduced the overhead of trying to manage this app. Having a project for each level, free and paid, made 10 projects - 11 if you count the "core" project. Now on a change, I only have to upload a couple of apks - what a relief!
Better yet, since I'm downloading the DB from the web (since Monday), I have received no crash reports out of about 100 downloads. This is a huge problem solved.
- Mark