Friday, July 22, 2011

Accommodating SRS, linkify and android.app.IntentReceiverLeaked

Putting a spaced repetition system into the app has some broader implication. For example, the autoplay function, which plays audio at random from the specified range, should not be taking into account the review schedule and all the SRS stuff. It should just play from the minimum to the maximum range in random order. So, it needs to use the old input statement. Also, it can't update the SRS. Since it's going through same logic path as the regular questions, we need to prevent the SRS module from updating the schedule if it's in autoplay mode.

The other function will be to provide a "non-SRS" mode. This will work the same was they app did before SRS was put in. There is a hitch with that, though. I would have to preserve the SRS start and finish numbers so if they went back to SRS mode, it would start at there old settings. I wonder if I should even do that? I probably will. It's just that much more complicated, though.

Well, for now, let's get the timer piece working. That's certainly a must. Did I comment out the "old" statement? I did. Well, let's do a comparison on svn

Ok, that was quick - now I have logic like this:

// Non-SRS

if (this.autoPlay) {

initQuizSequenceForAutoplay(context, startNum, endNum);
} else {
// SRS

initQuizSequenceForSRS(context, startNum, endNum);
}


Ok. If Im going to do the "quiz" vs. "srs", it become more than just a toggle. Now, there would be three modes. Don't like. The other thing is I would have to preserve the start and finis numbers. Again, not really in love with the concept. And there is the problem of explaining the difference between the quiz and srs modes. I dunno. I'm thinking, forget it. It's too confusing.

Ok. So, where does that leave us?

I wanted to put a link to my website somewhere in there.

Also, there are the ads, but that has to wait until I publish this one.

Well, I want to put a link up to my web site in the first page at least.

I'll use Linkify, which is more of a hassle than it ought to be. How did I do it for the other ones?


Ok, it takes the compiled pattern as the url, then adds the third part of the addlinks to it, and then linkify's the whole text field, at least the way I have it.

So, this works:


// add reference to softypapa

TextView kanjisoftView = (TextView) findViewById(R.id.kanjisoft);

String text = "Developed by KanjiSoft Systems";

kanjisoftView.setText(text);

// pattern we want to match and turn into a clickable link
Pattern pattern = Pattern.compile("");

// prefix our pattern with http://
Linkify.addLinks(kanjisoftView, pattern,
"http://www.kanjisoft.com/");


I should put an add there, like "Learn Kanji with KanjiCan" - maybe in the free version. Or maybe in this version, if I change my mind.

Ok, I just noticed I'm getting this error in the logcat:

ctivityThread( 5135): android.app.IntentReceiverLeaked: Activity com.jlptquiz.app.StartActivity has leaked IntentReceiver com.jlptquiz.app.StartActivity$3@405a09c0 that was originally registered here. Are you missing a call to unregisterReceiver()?
E/A

I think it expects me to unregister it somewhere along the line. This would have to be on returning from the settings display.

The first thing I'll do is move the receiver method into the onClick which gets into the activity.

/**
* This receives a broadcast from settings activity when level is
* changed. It updates the level showing on this activity's display.
*/

if (null == receiver) {
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("my.db.updated")) {
setupJlptLevelDisplay();
}
}
};
registerReceiver(receiver, new IntentFilter("my.db.updated"));

}

Ok. then I can unregister it in setupJlptLevelDisplay. First, let's make sure it's still working...

Yup. Now, just change setupJlptLevelDisplay...


/**
* @param appState
*/
private void setupJlptLevelDisplay(BroadcastReceiver br) {
/* display the current level */

AppState appState = (AppState) this.getApplication();
mJlptLevel = (TextView) this.findViewById(R.id.level);
mJlptLevel.setText(new Integer(appState.jlptLevel).toString());

this.unregisterReceiver(br);
}

Ok. I also want to support multiple levels in single app. This is more for demo purposes, since i plan to sell them separately by app. There are two change that are needed. The first is to add level to SRS select statement. That will be simple. The second one involves adding level to the start and end values. That's a little more complex. For now, I'm just going to add level to the select statement.

Well, happy day - level's already in there:

Cursor cursor = this.myDataBase
.query(DataBaseHelper.VIEW_WORD_SCHEDULE_JOIN,
new String[] { "_id", "level", "number", "kanji",
"hiragana", "english", "level_freq_sequence",
"next_review_date" },
"level = ? and (next_review_date is null or next_review_date <=?)",
new String[] { strLevel, date_YYYY_MM_DD }, null, null,
null);


Ok, that's a wrap for now!

No comments:

Post a Comment