0

I have made the below function to break String into Hindi Chars. But It behaves differently android API 29 and API 30. In Android 29 Hindi word चक्की is broken into च क् की But in Android 30 it is correctly broken into च क्की.

public List<String> breakIntoHindiChar(String textAnswer) {
    List<String> ansCharList = new ArrayList<String>();
    Locale hindi = new Locale("hi", "IN");
    BreakIterator breaker = BreakIterator.getCharacterInstance(hindi);
    breaker.setText(textAnswer);
    int start = breaker.first();
    for (int end = breaker.next();
         end != BreakIterator.DONE;
         start = end, end = breaker.next()) {

        ansCharList.add(textAnswer.substring(start, end));

    }
    return ansCharList;

}

How can I solve this problem?

halfer
  • 19,824
  • 17
  • 99
  • 186
Prashanth
  • 993
  • 8
  • 18

2 Answers2

1

Android implementation of BreakIterator was not able to interpret Bharatiya scripts (abiguda type) accurately. See this bug - https://code.google.com/p/android/issues/detail?id=230832

Looks like it has been fixed for API 30 and has not been backported for previous versions.

Vinod Singh
  • 138
  • 2
  • 5
  • So what is the solution? – Stephen C Aug 05 '21 at 06:38
  • @StephenC There is no viable solution other than to wait for Android 11 to become widely available on mobile devices. Recently I built a word search game in dictionary app for https://xn--l1b6a9di5a0j.xn--h2brj9c/ and due to BreakIterator bug, I had disabled game on devices having this bug. – Vinod Singh Aug 10 '21 at 04:14
  • Apart from the possible solutions I suggested ... of course :-) – Stephen C Aug 10 '21 at 04:18
1

How can I solve this problem?

As you noted in your question, the behavior in Android 29 is incorrect, and the behavior in Android 30 is correct.

So it depends on what you think the problem is:

  • If you think that it is that they fixed the behavior in Android 30 at that has "broken" your app on later versions, then a solution would be for you to copy the Android 29 BreakIterator into your app (with a different name) and use it.

  • If you think that it is that they didn't fix the behavior in Android 29 (and earlier) and you want your app to behave correctly on older Android, then a solution would be for you to copy the Android 30 BreakIterator into your app (with a different name) and use it.

Note that what you would be doing is to implement either forwards or backwards compatible behavior for BreakIterator, albeit not in the standard class.

(There may be a more elegant solution, but I don't have my own local copy of the Android master repo to dig through the history.)

Note: If you can't replace all of your app's use of BreakIterator with an alternative version of the class, then (AFAIK) there won't be a way to make the behavior consistent. You cannot patch the Android platform. And note that while you could use android.icu.text.BreakIterator instead of android.text.BreakIterator in your own code, that wouldn't fix the problem for other code that your app depends on.


But if you think the problem is that BreakIterator behaves differently in Android 29 vs 30 ... there is no solution to that. It is a fact. Yes ... it does behave differently ... and even Google can't make it not behave differently in Android 30 ... now.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • It is not as simple as copying just one class named BreakIterator. BreakIterator is supported by lots classes. Bundling ICU implementation of BreakIterator with the app would be a better solution though it will increase app size significantly hence not recommended. – Vinod Singh Aug 05 '21 at 06:00
  • It >will< fix the example in the OP's question. And if it doesn't fix the problem in the OP's app, then there probably isn't any solution. (Bundling ICU wouldn't solve it either.) – Stephen C Aug 05 '21 at 06:27