googlearchive / firebase-jobdispatcher-android

DEPRECATED please see the README.md below for details.
Apache License 2.0
1.79k stars 208 forks source link

java.lang.ArrayIndexOutOfBoundsException: length=0; index=-1 #276

Closed Mudasar2016 closed 4 years ago

Mudasar2016 commented 5 years ago

12-30 20:27:41.733 26641-26641/com.example.mudasar.ubercloneapp E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.mudasar.ubercloneapp, PID: 26641 java.lang.ArrayIndexOutOfBoundsException: length=0; index=-1 at java.util.ArrayList.get(ArrayList.java:310) at com.example.mudasar.ubercloneapp.Welcome$4.onResponse(Welcome.java:309) at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:70) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:158) at android.app.ActivityThread.main(ActivityThread.java:7224) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)****

Mudasar2016 commented 5 years ago

package com.example.mudasar.ubercloneapp;

import android.Manifest; import android.animation.ValueAnimator; import android.content.pm.PackageManager; import android.graphics.Color; import android.location.Location; /import android.location.LocationListener;/ import android.os.Handler; import android.os.SystemClock; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.design.widget.Snackbar; import android.support.v4.app.ActivityCompat; import android.support.v4.app.FragmentActivity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import android.widget.Button; import android.widget.EditText; import android.widget.Toast;

import com.example.mudasar.ubercloneapp.Common.Common; import com.example.mudasar.ubercloneapp.Remote.IGoogleAPI; import com.google.android.gms.maps.CameraUpdate; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.location.LocationListener; import com.firebase.geofire.GeoFire; import com.firebase.geofire.GeoLocation; import com.github.glomadrian.materialanimatedswitch.MaterialAnimatedSwitch; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; import com.google.android.gms.common.api.GoogleApi; import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.location.FusedLocationProviderClient; import com.google.android.gms.location.LocationRequest; import com.google.android.gms.location.LocationServices; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.BitmapDescriptor; import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.CameraPosition; import com.google.android.gms.maps.model.JointType; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; import com.google.android.gms.maps.model.Polyline; import com.google.android.gms.maps.model.PolylineOptions; import com.google.android.gms.maps.model.SquareCap; import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.database.DatabaseError; import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase;

import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject;

import java.net.URLEncoder; import java.util.ArrayList; import java.util.List;

import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response;

public class Welcome extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener, GoogleMap.OnMapLongClickListener

{

private GoogleMap mMap;

//Play Services
private static final int MY_PERMISSION_REQUEST_CODE = 7000;
private static final int PLAY_SERVICE_RES_REQUEST = 7001;

private LocationRequest mLocationRequest;
private GoogleApiClient mGoogleApiClient;
private Location mLastLocation;

private static int UPDATE_INTERVAL = 5000;
private static int FASTST_INTERVAL = 3000;
private static int DISPLACEMENT = 10;

DatabaseReference drivers;
GeoFire geoFire;

Marker mCurrent;

MaterialAnimatedSwitch location_switch;
SupportMapFragment mapFragment;

//Car animation
private List<LatLng> polyLineList;
private Marker carMarker;
private float v;
private double lat,lng;
private Handler handler;
private LatLng startPosition, endPosition, currentPosition;
private int index,next;
private Button btnGo;
private EditText edtPlace;
private String destination;
private PolylineOptions polylineOptions, blackPolylineOptions;
private Polyline blackPolyline, greyPolyline;

private IGoogleAPI mService;

Runnable drawPathRunnable = new Runnable() {
    @Override
    public void run() {
        if (index < polyLineList.size()-1)
        {
            index++;
            next = index+1;
        }
        if(index < polyLineList.size()-1)
        {
            startPosition = polyLineList.get(index);
            endPosition = polyLineList.get(next);
        }

        final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0,1);
        valueAnimator.setDuration(3000);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {

                v = valueAnimator.getAnimatedFraction();
                lng = v*endPosition.longitude+(1-v)*startPosition.longitude;
                lat = v*endPosition.latitude+(1-v)*startPosition.latitude;
                LatLng newPos = new LatLng(lat,lng);
                carMarker.setPosition(newPos);
                carMarker.setAnchor(0.5f,0.5f);
                carMarker.setRotation(getBearing(startPosition,newPos));
                mMap.moveCamera(CameraUpdateFactory.newCameraPosition(
                        new CameraPosition.Builder()
                        .target(newPos)
                        .zoom(15.5f)
                        .build()

                ));
            }
        });

        valueAnimator.start();
        handler.postDelayed(this,3000);
    }
};

private float getBearing(LatLng startPosition, LatLng endPosition) {

    double lat = Math.abs(startPosition.latitude - endPosition.latitude);
    double lng = Math.abs(startPosition.longitude - endPosition.longitude);

    if(startPosition.latitude < endPosition.latitude && startPosition.longitude < endPosition.longitude)
        return (float)(Math.toDegrees(Math.atan(lng/lat)));
    else
        if(startPosition.latitude >= endPosition.latitude && startPosition.longitude < endPosition.longitude)
            return (float)((90-Math.toDegrees(Math.atan(lng/lat)))+90);
    else
        if(startPosition.latitude >= endPosition.latitude && startPosition.longitude >= endPosition.longitude)
            return (float)(Math.toDegrees(Math.atan(lng/lat))+180);
    else
        if(startPosition.latitude < endPosition.latitude && startPosition.longitude >= endPosition.longitude)
            return (float)((90-Math.toDegrees(Math.atan(lng/lat)))+270);

    return -1;
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_welcome);
    // Obtain the SupportMapFragment and get notified when the map is ready to be used.
    mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);

    //Init View
    location_switch = (MaterialAnimatedSwitch)findViewById(R.id.location_switch);
    location_switch.setOnCheckedChangeListener(new MaterialAnimatedSwitch.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(boolean isOnline) {

            if(isOnline)
            {
                startLocationUpdates();
                displayLocation();
                Snackbar.make(mapFragment.getView(),"Your are online",Snackbar.LENGTH_SHORT)
                        .show();
            }
            else {
                stopLocationUpdates();
                mCurrent.remove();

                mMap.clear();
                handler.removeCallbacks(drawPathRunnable);
                Snackbar.make(mapFragment.getView(),"Your are offline",Snackbar.LENGTH_SHORT)
                        .show();
            }

        }
    });

    polyLineList = new ArrayList<>();
    btnGo = (Button)findViewById(R.id.btnGo);
    edtPlace =(EditText)findViewById(R.id.edtPlace);

    btnGo.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            destination = edtPlace.getText().toString();
            destination = destination.replace("","+"); // Replace space with + for fetch data
            Log.d("EDMTDEV",destination);

            getDirection();
        }
    });

    //Geo Fire
    drivers = FirebaseDatabase.getInstance().getReference("Drivers");
    geoFire = new GeoFire(drivers);

    setUpLocation();

    mService = Common.getGoogleAPI();
}

private void getDirection() {

    currentPosition = new LatLng(mLastLocation.getLatitude(),mLastLocation.getLongitude());
    String requestApi = null;

    try {
        requestApi="https://maps.googleapis.com/maps/api/directions/json?"+
                "mode=driving&"+
                "transit_routing_preference=less_driving&"+
                "origin="+currentPosition.latitude+","+currentPosition.longitude+"&"+
                "destination="+destination+"&"+
                "key="+getResources().getString(R.string.google_direction_api);
                /*"destination=" + URLEncoder.encode(destination, "UTF-8") + "&"+*/
        Log.d("EDMTDEV",requestApi); // Print URL for debug
        mService.getPath(requestApi)
                .enqueue(new Callback<String>() {
                    @Override
                    public void onResponse(Call<String> call, Response<String> response) {

                        try{
                            JSONObject jsonObject = new JSONObject(response.body().toString());
                            JSONArray jsonArray = jsonObject.getJSONArray("routes");
                            for (int i=0; i<jsonArray.length(); i++)
                            {
                                JSONObject route = jsonArray.getJSONObject(i);
                                JSONObject poly = route.getJSONObject("overview_polyline");
                                String polyline = poly.getString("points");
                                polyLineList = decodePoly(polyline);
                            }

                            //Adjusting Bounds

                            if (!polyLineList.isEmpty()) {
                                //Adjusting bounds
                                LatLngBounds.Builder builder = new LatLngBounds.Builder();
                                for (LatLng latLng : polyLineList)
                                    builder.include(latLng);
                                LatLngBounds bounds = builder.build();
                                CameraUpdate mCameraUpdate = CameraUpdateFactory.newLatLngBounds(bounds, 2);
                                mMap.animateCamera(mCameraUpdate);
                            }

                           /* LatLngBounds.Builder builder = new LatLngBounds.Builder();
                            for (LatLng latLng:polyLineList)
                                builder.include(latLng);
                            LatLngBounds bounds = builder.build();
                            CameraUpdate mCameraUpdate = CameraUpdateFactory.newLatLngBounds(bounds,2);
                            mMap.animateCamera(mCameraUpdate);*/

                            polylineOptions = new PolylineOptions();
                            polylineOptions.color(Color.GRAY);
                            polylineOptions.width(5);
                            polylineOptions.startCap(new SquareCap());
                            polylineOptions.endCap(new SquareCap());
                            polylineOptions.jointType(JointType.ROUND);
                            polylineOptions.addAll(polyLineList);
                            greyPolyline = mMap.addPolyline(polylineOptions);

                            blackPolylineOptions = new PolylineOptions();
                            blackPolylineOptions.color(Color.BLACK);
                            blackPolylineOptions.width(5);
                            blackPolylineOptions.startCap(new SquareCap());
                            blackPolylineOptions.endCap(new SquareCap());
                            blackPolylineOptions.jointType(JointType.ROUND);
                            blackPolyline = mMap.addPolyline(blackPolylineOptions);

                            mMap.addMarker(new MarkerOptions()
                                    .position(polyLineList.get(polyLineList.size()-1))  **(Welcome.java:309)**
                                    .title("Pickup Location"));

                            //Animation
                            ValueAnimator polyLineAnimator = ValueAnimator.ofInt(0,100);
                            polyLineAnimator.setDuration(2000);
                            polyLineAnimator.setInterpolator(new LinearInterpolator());
                            polyLineAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                                @Override
                                public void onAnimationUpdate(ValueAnimator animation) {
                                    List<LatLng> points = greyPolyline.getPoints();
                                    int percentValue = (int)animation.getAnimatedValue();
                                    int size = points.size();
                                    int newPoints = (int) (size * (percentValue/100.0f));
                                    List<LatLng> p = points.subList(0,newPoints);
                                    blackPolyline.setPoints(p);
                                }
                            });
                            polyLineAnimator.start();

                            carMarker = mMap.addMarker(new MarkerOptions().position(currentPosition)
                            .flat(true)
                            .icon(BitmapDescriptorFactory.fromResource(R.drawable.car)));

                            handler = new Handler();
                            index=-1;
                            next=1;
                            handler.postDelayed(drawPathRunnable,3000);

                        }catch (JSONException e)
                        {
                            e.printStackTrace();
                        }
                    }

                    @Override
                    public void onFailure(Call<String> call, Throwable t) {
                        Toast.makeText(Welcome.this,""+t.getMessage(),Toast.LENGTH_SHORT).show();
                    }
                });

    }catch (Exception e)
    {
        e.printStackTrace();
    }

}

private List decodePoly(String encoded) {

    List poly = new ArrayList();
    int index = 0, len = encoded.length();
    int lat = 0, lng = 0;

    while (index < len) {
        int b, shift = 0, result = 0;
        do {
            b = encoded.charAt(index++) - 63;
            result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);
        int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
        lat += dlat;

        shift = 0;
        result = 0;
        do {
            b = encoded.charAt(index++) - 63;
            result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);
        int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
        lng += dlng;
        LatLng p = new LatLng((((double) lat / 1E5)),
                (((double) lng / 1E5)));
        poly.add(p);

        /*poly.add(((double) lat / 1E5, (double) lng / 1E5));*/
    }

    return poly;
}

// Press Ctrl + O
//Because we request runtime permission , we need override OnRequestPermissionResult method

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode)
    {
        case MY_PERMISSION_REQUEST_CODE:
            if(grantResults.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
            {
                if (checkPlayServices())
                {
                    buildGoogleApiClient();
                    createLocationRequest();
                    if (location_switch.isChecked())
                        displayLocation();
                }
            }
    }
}

private void stopLocationUpdates() {

    if(ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
    {
        return;
    }
    LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient,this);
}

private void displayLocation() {
    if(ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
    {
        return;
    }
    mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);

    if(mLastLocation !=null)
    {
        if(location_switch.isChecked())
        {
            final double latitude = mLastLocation.getLatitude();
            final double longitude = mLastLocation.getLongitude();

            //Update To Firebase
            geoFire.setLocation(FirebaseAuth.getInstance().getCurrentUser().getUid(), new GeoLocation(latitude, longitude), new GeoFire.CompletionListener() {
                @Override
                public void onComplete(String key, DatabaseError error) {

                    //Add Marker
                    if (mCurrent != null)
                         mCurrent.remove();
                    mCurrent = mMap.addMarker(new MarkerOptions()
                                                    .position(new LatLng(latitude,longitude))
                                                    .title("Your Location"));

                    //Move camera to this position
                    mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(latitude,longitude),15.0f));

                    // Draw animation rotate marker
                    //rotateMarker(mCurrent,-360,mMap);
                }
            });

        }
    }
    else {
        Log.d("ERROR", "Cannot get your location");
    }
}

private void setUpLocation() {

    if(ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
    {
        //Request Runtime Permission
        ActivityCompat.requestPermissions(this,new String[]{
                Manifest.permission.ACCESS_COARSE_LOCATION,
                Manifest.permission.ACCESS_FINE_LOCATION,
        },MY_PERMISSION_REQUEST_CODE);
    }
    else {
        if (checkPlayServices())
        {
            buildGoogleApiClient();
            createLocationRequest();
            if (location_switch.isChecked())
                displayLocation();
        }
    }
}

private void createLocationRequest() {
    mLocationRequest = new LocationRequest();
    mLocationRequest.setInterval(UPDATE_INTERVAL);
    mLocationRequest.setFastestInterval(FASTST_INTERVAL);
    mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    mLocationRequest.setSmallestDisplacement(DISPLACEMENT);
}

private void buildGoogleApiClient() {
    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();
    mGoogleApiClient.connect();
}

private boolean checkPlayServices() {
    int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
    if(resultCode != ConnectionResult.SUCCESS)
    {
        if(GooglePlayServicesUtil.isUserRecoverableError(resultCode))
            GooglePlayServicesUtil.getErrorDialog(resultCode,this, PLAY_SERVICE_RES_REQUEST).show();
        else {
            Toast.makeText(this, "This device is not supported", Toast.LENGTH_SHORT).show();
            finish();
        }
        return false;
    }
    return true;
}

private void rotateMarker(final Marker mCurrent, final float i, GoogleMap mMap) {
    final Handler handler = new Handler();
    final long start = SystemClock.uptimeMillis();
    final float startRotation = mCurrent.getRotation();
    final long duration = 1500;

    final Interpolator interpolator = new LinearInterpolator();

    handler.post(new Runnable() {
        @Override
        public void run() {
            long elapsed = SystemClock.uptimeMillis() - start;
            float t = interpolator.getInterpolation((float)elapsed/duration);
            float rot = t*i+(1-t)*startRotation;
            mCurrent.setRotation(-rot > 180?rot/2:rot);

            if(t<1.0)
            {
                handler.postDelayed(this,16);
            }
        }
    });

}

private void startLocationUpdates() {

    if(ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)
    {
        return;
    }

    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest, this);
}

@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    mMap.setOnMapLongClickListener(this);

    mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
    mMap.setTrafficEnabled(false);
    mMap.setIndoorEnabled(false);
    mMap.setBuildingsEnabled(false);
    mMap.getUiSettings().setZoomControlsEnabled(true);
   /* // Add a marker in Sydney and move the camera
    LatLng sydney = new LatLng(-34, 151);
    mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
    mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));*/
}

@Override
public void onLocationChanged(Location location) {
    mLastLocation = location;
    displayLocation();
}

/* @Override public void onStatusChanged(String provider, int status, Bundle extras) {

}

@Override
public void onProviderEnabled(String provider) {

}

@Override
public void onProviderDisabled(String provider) {

}*/

@Override
public void onConnected(@Nullable Bundle bundle) {

        displayLocation();
        startLocationUpdates();
}

@Override
public void onConnectionSuspended(int i) {
    mGoogleApiClient.connect();

}

@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

}

public void onMapLongClick(LatLng point) {
    if(mMap != null){
        mMap.addMarker(new MarkerOptions()
                .position(point)
                .title("You are here")
                .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
    }
}

@Override
public void onPointerCaptureChanged(boolean hasCapture) {

}

}

samtstern commented 4 years ago

In April 2019 we announced that Firebase Job Dispatcher would be deprecated today, April 7th 2020. For this reason we are going to close all open issues and archive the repository. We will also stop supporting FJD for new app installations (such as those targeting sdk versions greater than Android Q). Existing apps that rely on FJD should continue to function as usual.

While we will no longer work on FJD, we encourage you to migrate to Work Manager which is a superior tool and fully supported by the Android team.

Thank you for taking the time to try the library and provide this feedback. We sincerely appreciate your effort and we apologize for not addressing it in time.