How to resolve java.lang.StringIndexOutOfBoundsException? - android

I am getting an error, while calculating on String,
java.lang.StringIndexOutOfBoundsException: length=4; regionStart=5; regionLength=2
My implementation is below.
private void initializeMyPLsAllotted() {
int theMonthWhenICame = Integer.parseInt(myDateHired.substring(5, 7)); //This line is showing the error
int theYearWhenICame = Integer.parseInt(myDateHired.substring(0,4));
int theCurrentMonth = Integer.parseInt(todaysDate.substring(5, 7));
int theCurrentYear = Integer.parseInt(todaysDate.substring(0, 4));
int myTotalMonths = (theCurrentYear - theYearWhenICame)*12 + theCurrentMonth - theMonthWhenICame;
if (myTotalMonths > 6) {
numberOfPLsAllotted = 2;
} else {
numberOfPLsAllotted = 0;
}
myPLs = numberOfPLsAllotted;
}

java.lang.StringIndexOutOfBoundsException: length=4; regionStart=5; regionLength=2
it clearly says that length of your string is 4 and you are trying to fetch sub-string from index 5. make sure your string is valid
you can check something like that to avoid crashing your app
private void initializeMyPLsAllotted() {
if(myDateHired.length() > 7 && todaysDate.length() > 7){
int theMonthWhenICame = Integer.parseInt(myDateHired.substring(5, 7));
int theYearWhenICame = Integer.parseInt(myDateHired.substring(0,4));
int theCurrentMonth = Integer.parseInt(todaysDate.substring(5, 7));
int theCurrentYear = Integer.parseInt(todaysDate.substring(0, 4));
int myTotalMonths = (theCurrentYear - theYearWhenICame)*12 + theCurrentMonth - theMonthWhenICame;
if(myTotalMonths>6) {
numberOfPLsAllotted = 2;
} else {
numberOfPLsAllotted = 0;
}
myPLs = numberOfPLsAllotted;
} else {
// print some error message
}
}

StringIndexOutOfBoundsException means that the section you're trying to substring is outside of the string length.
Example
String test = "123";
String testSubstringOne = test.substring(0, 1);
//testSubstringOne -> "1"
String testSubstringTwo = test.substring(0, 5);
//testSubstringTwo -> java.lang.StringIndexOutOfBoundsException
Make sure your myDateHired has the value you expect.
Tip from the coach
You say that those values are from a server... Maybe you should look into returning data in a more friendly format such as json.

As doc says, the IndexOutOfBoundsException will be throwed when:
if the beginIndex is negative, or endIndex is larger than the length
of this String object, or beginIndex is larger than endIndex
so check myDateHired before using it.

Related

How to Set AlignSpan Style on current cursor paragraph?

I know for set a style into spannable, we can use setSpan(Object classOfStyle, int start, int end, int flags).
I wanna set alignspan into a current paragraph. Current paragraph detected by current cursor position. It`s possible? May i can get start-position and end-position of paragraph?
Edit :
A paragraph is a group of sentences. One of paragraph will be ended by "Enter Character".
I've written a small helper class (optimized for speed) that will do exactly what you want. You pass a Spannable object which will be parsed to find all paragraphs:
public class Layout {
private static final Pattern LINEBREAK_PATTERN = Pattern.compile("\\r\\n|\\r|\\n");
private int mNrOfLines = 0;
private ArrayList<Selection> mSelection = new ArrayList<Selection>();
public Layout(Spannable spannable) {
String s = spannable.toString();
// remove the trailing line feeds
int len = s.length();
char c = len > 0 ? s.charAt(len - 1) : '-';
while (len > 0 && (c == '\n' || c == '\r')) {
len--;
c = s.charAt(len - 1);
}
// now find the line breaks and the according lines / paragraphs
mNrOfLines = 1;
Matcher m = LINEBREAK_PATTERN.matcher(s.substring(0, len));
int groupStart = 0;
while (m.find()) {
mSelection.add( new Selection(groupStart, m.end()) );
groupStart = m.end();
mNrOfLines++;
}
if (groupStart < len) {
mSelection.add( new Selection(groupStart, len) );
}
}
public List<Selection> getParagraphs() {
return mSelection;
}
public int getLineForOffset(int offset) {
int lineNr = 0;
while(lineNr < mNrOfLines && offset >= mSelection.get(lineNr).end()) {
lineNr++;
}
return Math.min(Math.max(0, lineNr), mSelection.size() - 1);
}
public int getLineStart(int line) {
return mNrOfLines == 0 || line < 0 ? 0 :
line<mNrOfLines ? mSelection.get(line).start() :
mSelection.get(mNrOfLines-1).end()-1;
}
public int getLineEnd(int line) {
return mNrOfLines == 0 || line < 0 ? 0 :
line<mNrOfLines ? mSelection.get(line).end() :
mSelection.get(mNrOfLines-1).end()-1;
}
}
The three methods getLineForOffset, getLineStart and getLineEnd can be used to find the paragraphs for the current Selection. The Selection can be either the current cursor position (which is basically a Selection with start==end) or the selected text. The following code will return the selected paragraphs for the current selection:
Selection getParagraphs(EditText editor) {
Layout layout = new Layout( editor.getEditableText() );
int selStart = editor.getSelectionStart();
int selEnd = editor.getSelectionEnd();
int firstLine = layout.getLineForOffset(selStart);
int end = selStart == selEnd ? selEnd : selEnd - 1;
int lastLine = layout.getLineForOffset(end);
return new Selection(layout.getLineStart(firstLine), layout.getLineEnd(lastLine));
}
If e.g. your text is:
line 1
l[ine 2
line ]3
line 4
with everything between the [] selected, getParagraphs() would return the second and third line (it basically expands the selected text to include all (even partially) selected paragraphs.
I Write some method for get first position of paragraph and last position of paragraph.
I don`t know, which one is better performance. Please correct me if its wrong.
public static int getFirstPositionOfParagraph(String paragraph, int cursorPosition) {
StringBuffer buffer = new StringBuffer(paragraph);
List pos = new ArrayList();
for (String breaker : LINE_BREAK){
pos.add(buffer.lastIndexOf(breaker, cursorPosition));
}
int firstPosition = Collections.max(pos);
return firstPosition
public static int getLastPositionOfParagraph(String paragraph, int cursorPosition) {
StringBuffer buffer = new StringBuffer(paragraph);
List pos = new ArrayList();
for (String breaker : LINE_BREAK){
int breakerPos = buffer.indexOf(breaker, cursorPosition);
if (breakerPos > 0)
pos.add(breakerPos);
}
return pos.size() > 0 ? Collections.min(pos) + 1 : paragraph.length();
}

Need help generating a unique request code for alarm

My app structure is like, there are 1000 masjids/mosques and each masjid has been given a unique id like 1,2,3,4 ..... 1000 . Now each mosque has seven alarms associated with it , I wish to generate a unique request code number for each alarm so that they don't overlap each other,
Following is the code:
//note integer NamazType has range 0 to 5
public int generateRequestCodeForAlarm(int MasjidID,int NamazType )
{
return (MasjidID *(10)) + (namazType);
}
Will this code work?
you can simply concatenate masjidID and namaztype( or specifically namaz ID). This will always return unique.
public int generateRequestCodeForAlarm(int MasjidID,int NamazType )
{
return Integer.ParseInt(String.valueOf(MasjidID)+""+NamazType)
}
Use Random class:
Try out like this:
//note integer NamazType has range 0 to 5
public int generateRequestCodeForAlarm(int MasjidID, int NamazType)
{
return (MasjidID * (Math.abs(new Random().nextInt()))) + (namazType);
}
It will work for sure.
public int generateRequestCodeForAlarm(int MasjidID,int NamazType )
{
return (MasjidID*(10)) + (NamazType );
}
Output:
Have a look at this
If MasjidID and NamazType are unique, then
Integer.parseInt( MasjidID + "" + NamazType );
would be enough to do the trick!
Example:
Masjid ID = 96, Namaz type = 1, Unique no = 961
MasjidId = 960, Namaz type = 1, Unique no = 9601
MasjidID = 999, Namaz type = 6, Unique no = 9996
I don't find any way in which it would get repeated. However, it is very similar to
(MasjidID * 10) + NamazType
Irrespective of MasjidID and NamazType, if a random number needs to be generated, this can be used.
public class NoRepeatRandom {
private int[] number = null;
private int N = -1;
private int size = 0;
public NoRepeatRandom(int minVal, int maxVal)
{
N = (maxVal - minVal) + 1;
number = new int[N];
int n = minVal;
for(int i = 0; i < N; i++)
number[i] = n++;
size = N;
}
public void Reset() { size = N; }
// Returns -1 if none left
public int GetRandom()
{
if(size <= 0) return -1;
int index = (int) (size * Math.random());
int randNum = number[index];
// Swap current value with current last, so we don't actually
// have to remove anything, and our list still contains everything
// if we want to reset
number[index] = number[size-1];
number[--size] = randNum;
return randNum;
}
}

Android : Remove last paragraph tag generated by Html.toHtml

I'm editing content that may be html in an EditText. Just before saving the result, I use Html.toHtml to convert the input into a string to be sent to the server. However this method call seems to be generating paragraph tags which I dont need. Eg -
Test edited
seems to get converted to
<p dir="ltr">Test edited</p>
I would like to strip out the last paragraph tag before saving the content. If there are other paragraph tags, I would like to keep those. I have this regex that matches all p tags
"(<p.*>)(.*)(</p>)";
but I'm not sure how to match just the last paragraph and remove just the tags for it.
public static void handleOneParagraph(SpannableStringBuilder text) {
int start = 0;
int end = text.length();
String chars1 = "<p";
if (end < 2)
return;
while (start < end ) {
String seq = text.toString().substring(start, start + 2);
if (seq.equalsIgnoreCase(chars1))
break;
start++;
}
if (text.toString().substring(start, start + 2).equalsIgnoreCase(chars1) ) {
int start2 = start + 1;
String chars2 = ">";
while (start2 < end && !text.subSequence(start2, start2+1).toString().equalsIgnoreCase(chars2) ) {
start2++;
}
if (start2 >= end)
return;
text.replace(start, start2+1, "");
end = text.length();
start = end;
String chars3 = "</p>";
while (start > start2 + 4) {
String last_p = text.subSequence(start - 4, start).toString();
if (last_p.equalsIgnoreCase(chars3) ) {
text.replace(start - 4, start, "");
break;
}
start--;
}
}
}
And now, you can use it like this...
SpannableStringBuilder cleaned_text = new SpannableStringBuilder(Html.toHtml(your_text));
handleOneParagraph(cleaned_text);

Android: Int stays the same

i feel dumb for asking this but i have been fighting with this for a day now and i can't seem to get it working.
So my problem is I want to keep adding 1 to and integer and make it go like ;
1+1=2
2+1=3
That it keeps updating the Integer I have this now;
int val = 1;
int g = 1;
val = g + val;
But it keeps saying its 2 how come?
Thanks.
I'm guessing you put all of your code in your click handler. Instead, put the variable declaration/initialization in the class level and only your addition code in your click handler. Rough code as follows:
public YourActivity extends Activity {
int val = 1;
int g = 1;
#Override
protected void onCreate (Bundle savedInstanceState) {
... //find button in here
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
val = g + val;
}
});
}
}
Because you keep setting it to 1. Initialize it outside the loop.
int val = 1;
int g = 1;
The next line:
val = g + val;
is therefore equivalent to
val = 1 + 1;
which is equivalent to
val = 2;
Not sure what you would expect here...
int val = 1; int g = 1; val = g + val;
Will always evaluate to 2. Because what happens is you take the value in g which is 1 and the value in val which is 1. This produces the sum of 2. You then take 2 and assign it to the variable val (which previously was initialized to 1).
1+1 will always be 2 (in Integer mathematics)
So my problem is I want to keep adding 1 to and integer and make it go like ;
1+1=2
2+1=3
I'm guessing you want to do something like this, to produce your output a given number of times.
int timesToLoop = 10;
int summedUp = 0;
for (int i=0; i < timesToLoop; i++)
{
summedUp = i + 1;
System.out.println(i + " + " + "1 = " + summedUp);
}

Array access producing unwanted result

I am getting an unusual result when attempting to place a value in an array.
I have an array table[] of a simple class result{ int score, long time, string ID}
Intention is to have a sort of leader board.
My code happily finds the correct place to insert a new score if it is in the top 10.
int ix = 0;
int jx = 10; //
while ( ix < jx )
{
if (points > sTable[ix].points)
{
// score is higher move records down
for (jx = mNumRecords - 1; jx >ix ; jx--)
{
sTable[jx] = sTable[jx -1];
}
//now add new score
sTable[ix].score = score; // all good until here
sTable[ix].time = time;
}
ix++;
}
Problem is that when I try to insert the score using sTable[ix].score = score;
The value gets written to sTable[ix].score and also sTable[ix +1].score.
It is repeatable, it occurs at any value of ix, I have single stepped through the code and as far as I can tell the command only executes once.
Has anyone seen this before?
That because you copied the object reference to the next element in the array. You should copy the values, or create a new object:
Option A:
// score is higher move records down
for (jx = mNumRecords - 1; jx >ix ; jx--)
{
sTable[jx].time = sTable[jx -1].time;
sTable[jx].score = sTable[jx -1].score;
}
//now add new score
sTable[ix].score = score; // all good until here
sTable[ix].time = time;
Option B:
for (jx = mNumRecords - 1; jx >ix ; jx--)
{
sTable[jx] = sTable[jx -1];
}
sTable[ix] = new Result(score, time, ""); // Or however you construct the object

Categories

Resources