1

I have written a for loop to add multiple geofences on a Google Map, but it is giving me IndexOutOfBoundsException: Invalid index 3, size is 3. But it is impossible to have this issue since my condition is saying radius< list.size(), which is 3. But when I put in Log and check line by line, I found that inside onSuccess method, radius is returning a value of 3, which cause this problem.

Code:

        int permission = ContextCompat.checkSelfPermission(getContext(),
            Manifest.permission.ACCESS_FINE_LOCATION);
    if (permission == PackageManager.PERMISSION_GRANTED) {
        for(count = 0; count < id_list.size(); count++) {
            Log.d(TAG, "init: " + count);
            LatLng latlng = new LatLng(lat_list.get(count), lng_list.get(count));
            latlng_list.add(latlng);
        }
        Log.d(TAG, "latlng_list size: "+ latlng_list.size());

        for(radius=0; radius<latlng_list.size(); radius++) {

        // Add geofence
        // passing all the data inside the list into GeofenceHelper class for process
        Geofence geofence = geofenceHelper.getGeofence(id_list.get(radius), lat_list.get(radius), lng_list.get(radius), radius_list.get(radius), Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_DWELL | Geofence.GEOFENCE_TRANSITION_EXIT);
        GeofencingRequest request = geofenceHelper.getGeofencingRequest(geofence);
        PendingIntent pendingIntent = geofenceHelper.getPendingIntent();
        Log.e("middle", String.valueOf(radius));
        geofencingClient.addGeofences(request, pendingIntent)
                .addOnSuccessListener(new OnSuccessListener<Void>() {
                    @Override
                    public void onSuccess(Void aVoid) {
                        // Here is returning 3
                        Log.d(TAG, "onSuccess: " + radius);

                        addCircle(latlng_list.get(radius), radius_list.get(radius));
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        String errorMessage = geofenceHelper.getErrorString(e);
                        Toast.makeText(getContext(), errorMessage, Toast.LENGTH_SHORT).show();
                    }
                });

            Log.d("TAG", "here");
        }
    }

Logcat:`

11-18 12:15:45.157 1282-1282/com.example.assignment E/id_list: 3
11-18 12:15:45.157 1282-1282/com.example.assignment E/lat_list: 3
11-18 12:15:45.157 1282-1282/com.example.assignment E/lng_list: 3
11-18 12:15:45.157 1282-1282/com.example.assignment E/radius_list: 3
11-18 12:15:45.157 1282-1282/com.example.assignment D/MapsFragment: init: 0
11-18 12:15:45.157 1282-1282/com.example.assignment D/MapsFragment: init: 1
11-18 12:15:45.157 1282-1282/com.example.assignment D/MapsFragment: init: 2
11-18 12:15:45.157 1282-1282/com.example.assignment D/MapsFragment: latlng_list size: 3
11-18 12:15:45.158 1282-1282/com.example.assignment E/b4: 0
11-18 12:15:45.160 1282-1282/com.example.assignment E/middle: 0
11-18 12:15:45.168 1282-1282/com.example.assignment D/TAG: here
11-18 12:15:45.168 1282-1282/com.example.assignment E/b4: 1
11-18 12:15:45.168 1282-1282/com.example.assignment E/middle: 1
11-18 12:15:45.168 1282-1282/com.example.assignment D/TAG: here
11-18 12:15:45.168 1282-1282/com.example.assignment E/b4: 2
11-18 12:15:45.168 1282-1282/com.example.assignment E/middle: 2
11-18 12:15:45.169 1282-1282/com.example.assignment D/TAG: here
11-18 12:15:45.182 1282-1282/com.example.assignment D/MapsFragment: onSuccess: 3

Error code:

11-18 12:15:45.187 1282-1282/com.example.assignment E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.assignment, PID: 1282
java.lang.IndexOutOfBoundsException: Invalid index 3, size is 3
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at com.example.assignment.fragments.MapsFragment$6.onSuccess(MapsFragment.java:429)
at com.example.assignment.fragments.MapsFragment$6.onSuccess(MapsFragment.java:424)
at com.google.android.gms.tasks.zzm.run(com.google.android.gms:play-services-tasks@@17.0.2:4)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at com.google.android.gms.internal.tasks.zzb.dispatchMessage(com.google.android.gms:play- 
services-tasks@@17.0.2:6)
at android.os.Looper.loop(Looper.java:179)
at android.app.ActivityThread.main(ActivityThread.java:5650)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:681)
David Kroukamp
  • 36,155
  • 13
  • 81
  • 138
SY L
  • 25
  • 6
  • Does this answer your question? [What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?](https://stackoverflow.com/questions/5554734/what-causes-a-java-lang-arrayindexoutofboundsexception-and-how-do-i-prevent-it) – Zain Nov 18 '20 at 04:38
  • Please check the size of 'id_list' and 'radius_list' if both are different then this is causing issue. – Haseeb Mirza Nov 18 '20 at 04:41
  • @Zain Hmm, I don't think so, I'm doing the same as what the accepted answer said – SY L Nov 18 '20 at 04:43
  • @HaseebMirza Hi, I have edited my Logcat, after all the size of list is equal to 3 only this code will be called. – SY L Nov 18 '20 at 04:47
  • Log the both arraylist sizes. or Debug code to see. otherwise can not figure out – Haseeb Mirza Nov 18 '20 at 04:47
  • @SY L onSuccess code only called once why? explain – Haseeb Mirza Nov 18 '20 at 04:55
  • @HaseebMirza exactly, suppose it will be called three times, but when the first time it being called, the value is already 3, which cause the application crash due to IndexOutOfBoundsException. If it starts like normal from 0 to 2, it will be called 3 times – SY L Nov 18 '20 at 04:59
  • Yes I understand. When loop is executed all iteration. then radius value became 3. When geofence comes onSuccess function and try to read the value of radius (3). This is causing problem. Try to save value in temp variable then access addCircle(latlng_list.get(temp), radius_list.get(temp)); – Haseeb Mirza Nov 18 '20 at 05:00
  • @HaseebMirza I think I get what you mean, but since the onSuccess method will be called after the loop finish, that means the temp var cannot simply be an integer right? What I think I can do is store the radius value inside a list, then access addCircle(latlng_list.get(temp_list.get(i))) from another new for loop??? – SY L Nov 18 '20 at 05:11
  • Or is there any more efficient way to do that? – SY L Nov 18 '20 at 05:11
  • I don't understand your full scenario. But first you implement above logic you explained earlier. Then you can make code more efficient after it. – Haseeb Mirza Nov 18 '20 at 05:15
  • Before calling `geofencingClient.addGeofences`, declare a new radius variable like this `final int newRadius = radius;` and use `newRadius` inside the `OnSuccessListener` instead of `radius`. – David Kroukamp Nov 18 '20 at 05:21
  • Also I think it should be `radius < latlng_list.size() - 1` as if the size is 3, then when radius is at 2 (meaning its iterated 3 times already starting from 0), it would read 2 < 3 and it will iterate a 4th time. – David Kroukamp Nov 18 '20 at 05:30
  • @DavidKroukamp WOW! this is actually working, I tried my own approach which has explained earlier and its also working, but this seems to be more efficient. Could you explain abit why this is working, cuz at first I thought it will gonna be same, since after the loop finish, the newRadius value will be 3, and then when onSuccess method get called, it will only read the value 3 – SY L Nov 18 '20 at 05:33
  • @DavidKroukamp but in fact it was not, inside onSuccess method, it is reading one by one, how? – SY L Nov 18 '20 at 05:34
  • 1
    @HaseebMirza Also a big thank you to you Mr. HaseebMirza for pointing out the right direction on how to solve this problem. – SY L Nov 18 '20 at 05:37
  • Great Pleasure for me. – Haseeb Mirza Nov 18 '20 at 05:41
  • @DavidKroukamp For this, I don't think so, because I want to get all 3 items inside my list, which is get(0), get(1), get(2). So 2<3 is the last time the loop runs. – SY L Nov 18 '20 at 05:41
  • If anyone of you would like to post the answer, I am more than happy to accept it. – SY L Nov 18 '20 at 05:42
  • Yeah but 2<3 is true then it executes radius++ which then should make the radius == 3 and radius should never be 3. It should be 2. So yeah just make sure of that. Or maybe it's early in the morning for me. Also the final variable basically ensures that the integer once declared cannot change where as radius will keep being updated and because onSuccess gets called back whenever it is ready radius would have been incremented more then once already hence your issue. – David Kroukamp Nov 18 '20 at 05:46

1 Answers1

1

As per my comments: Before calling geofencingClient.addGeofences, declare a new radius variable like this final int newRadius = radius; and use newRadius inside the OnSuccessListener instead of radius. The final variable basically ensures that the integer once declared cannot be changed where as radius will keep being updated by the for loop and because onSuccess gets called back whenever it is ready radius might have been incremented more then once already hence your issue.

David Kroukamp
  • 36,155
  • 13
  • 81
  • 138