Changeset View
Changeset View
Standalone View
Standalone View
app/src/main/java/it/reyboz/bustorino/fragments/MainScreenFragment.java
Show First 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | |||||
import it.reyboz.bustorino.middleware.AppLocationManager; | import it.reyboz.bustorino.middleware.AppLocationManager; | ||||
import it.reyboz.bustorino.middleware.AsyncArrivalsSearcher; | import it.reyboz.bustorino.middleware.AsyncArrivalsSearcher; | ||||
import it.reyboz.bustorino.middleware.AsyncStopsSearcher; | import it.reyboz.bustorino.middleware.AsyncStopsSearcher; | ||||
import it.reyboz.bustorino.middleware.BarcodeScanContract; | import it.reyboz.bustorino.middleware.BarcodeScanContract; | ||||
import it.reyboz.bustorino.middleware.BarcodeScanOptions; | import it.reyboz.bustorino.middleware.BarcodeScanOptions; | ||||
import it.reyboz.bustorino.middleware.BarcodeScanUtils; | import it.reyboz.bustorino.middleware.BarcodeScanUtils; | ||||
import it.reyboz.bustorino.util.LocationCriteria; | import it.reyboz.bustorino.util.LocationCriteria; | ||||
import it.reyboz.bustorino.util.Permissions; | import it.reyboz.bustorino.util.Permissions; | ||||
import org.jetbrains.annotations.NotNull; | |||||
import static it.reyboz.bustorino.backend.utils.getBusStopIDFromUri; | import static it.reyboz.bustorino.backend.utils.getBusStopIDFromUri; | ||||
import static it.reyboz.bustorino.util.Permissions.LOCATION_PERMISSIONS; | import static it.reyboz.bustorino.util.Permissions.LOCATION_PERMISSIONS; | ||||
/** | /** | ||||
* A simple {@link Fragment} subclass. | * A simple {@link Fragment} subclass. | ||||
* Use the {@link MainScreenFragment#newInstance} factory method to | * Use the {@link MainScreenFragment#newInstance} factory method to | ||||
Show All 23 Lines | public class MainScreenFragment extends ScreenBaseFragment implements FragmentListenerMain{ | ||||
private boolean setupOnStart = true; | private boolean setupOnStart = true; | ||||
private boolean suppressArrivalsReload = false; | private boolean suppressArrivalsReload = false; | ||||
//private Snackbar snackbar; | //private Snackbar snackbar; | ||||
/* | /* | ||||
* Search mode | * Search mode | ||||
*/ | */ | ||||
private static final int SEARCH_BY_NAME = 0; | private static final int SEARCH_BY_NAME = 0; | ||||
private static final int SEARCH_BY_ID = 1; | private static final int SEARCH_BY_ID = 1; | ||||
private static final int SEARCH_BY_ROUTE = 2; // TODO: implement this -- https://gitpull.it/T12 | //private static final int SEARCH_BY_ROUTE = 2; // implement this -- DONE! | ||||
private int searchMode; | private int searchMode; | ||||
//private ImageButton addToFavorites; | //private ImageButton addToFavorites; | ||||
//// HIDDEN BUT IMPORTANT ELEMENTS //// | //// HIDDEN BUT IMPORTANT ELEMENTS //// | ||||
FragmentManager fragMan; | FragmentManager childFragMan; | ||||
Handler mainHandler; | Handler mainHandler; | ||||
private final Runnable refreshStop = new Runnable() { | private final Runnable refreshStop = new Runnable() { | ||||
public void run() { | public void run() { | ||||
if(getContext() == null) return; | if(getContext() == null) return; | ||||
List<ArrivalsFetcher> fetcherList = utils.getDefaultArrivalsFetchers(getContext()); | List<ArrivalsFetcher> fetcherList = utils.getDefaultArrivalsFetchers(getContext()); | ||||
ArrivalsFetcher[] arrivalsFetchers = new ArrivalsFetcher[fetcherList.size()]; | ArrivalsFetcher[] arrivalsFetchers = new ArrivalsFetcher[fetcherList.size()]; | ||||
arrivalsFetchers = fetcherList.toArray(arrivalsFetchers); | arrivalsFetchers = fetcherList.toArray(arrivalsFetchers); | ||||
if (fragMan.findFragmentById(R.id.resultFrame) instanceof ArrivalsFragment) { | if (childFragMan.findFragmentById(R.id.resultFrame) instanceof ArrivalsFragment) { | ||||
ArrivalsFragment fragment = (ArrivalsFragment) fragMan.findFragmentById(R.id.resultFrame); | ArrivalsFragment fragment = (ArrivalsFragment) childFragMan.findFragmentById(R.id.resultFrame); | ||||
if (fragment == null){ | if (fragment == null){ | ||||
//we create a new fragment, which is WRONG | //we create a new fragment, which is WRONG | ||||
Log.e("BusTO-RefreshStop", "Asking for refresh when there is no fragment"); | Log.e("BusTO-RefreshStop", "Asking for refresh when there is no fragment"); | ||||
// AsyncDataDownload(fragmentHelper, arrivalsFetchers,getContext()).execute(); | // AsyncDataDownload(fragmentHelper, arrivalsFetchers,getContext()).execute(); | ||||
} else{ | } else{ | ||||
String stopName = fragment.getStopID(); | String stopName = fragment.getStopID(); | ||||
new AsyncArrivalsSearcher(fragmentHelper, fragment.getCurrentFetchersAsArray(), getContext()).execute(stopName); | new AsyncArrivalsSearcher(fragmentHelper, fragment.getCurrentFetchersAsArray(), getContext()).execute(stopName); | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | private final ActivityResultLauncher<String[]> requestPermissionLauncher = | ||||
if(result==null) return; | if(result==null) return; | ||||
if(result.get(Manifest.permission.ACCESS_COARSE_LOCATION) == null || | if(result.get(Manifest.permission.ACCESS_COARSE_LOCATION) == null || | ||||
result.get(Manifest.permission.ACCESS_FINE_LOCATION) == null) | result.get(Manifest.permission.ACCESS_FINE_LOCATION) == null) | ||||
return; | return; | ||||
Log.d(DEBUG_TAG, "Permissions for location are: "+result); | Log.d(DEBUG_TAG, "Permissions for location are: "+result); | ||||
if(Boolean.TRUE.equals(result.get(Manifest.permission.ACCESS_COARSE_LOCATION)) | if(Boolean.TRUE.equals(result.get(Manifest.permission.ACCESS_COARSE_LOCATION)) | ||||
&& Boolean.TRUE.equals(result.get(Manifest.permission.ACCESS_FINE_LOCATION))){ | || Boolean.TRUE.equals(result.get(Manifest.permission.ACCESS_FINE_LOCATION))){ | ||||
locationPermissionGranted = true; | locationPermissionGranted = true; | ||||
Log.w(DEBUG_TAG, "Starting position"); | Log.w(DEBUG_TAG, "Starting position"); | ||||
if (mListener!= null && getContext()!=null){ | if (mListener!= null && getContext()!=null){ | ||||
if (locationManager==null) | if (locationManager==null) | ||||
locationManager = AppLocationManager.getInstance(getContext()); | locationManager = AppLocationManager.getInstance(getContext()); | ||||
locationManager.addLocationRequestFor(requester); | locationManager.addLocationRequestFor(requester); | ||||
} | } | ||||
// show nearby fragment | // show nearby fragment | ||||
//showNearbyStopsFragment(); | //showNearbyStopsFragment(); | ||||
Log.d(DEBUG_TAG, "We have location permission"); | Log.d(DEBUG_TAG, "We have location permission"); | ||||
if(pendingNearbyStopsFragmentRequest){ | if(pendingNearbyStopsFragmentRequest){ | ||||
showNearbyFragmentIfNeeded(cr); | showNearbyFragmentIfPossible(); | ||||
pendingNearbyStopsFragmentRequest = false; | pendingNearbyStopsFragmentRequest = false; | ||||
} | } | ||||
} | } | ||||
if(pendingNearbyStopsFragmentRequest) pendingNearbyStopsFragmentRequest =false; | if(pendingNearbyStopsFragmentRequest) pendingNearbyStopsFragmentRequest =false; | ||||
} | } | ||||
}); | }); | ||||
private final LocationCriteria cr = new LocationCriteria(2000, 10000); | private final LocationCriteria cr = new LocationCriteria(2000, 10000); | ||||
//Location | //Location | ||||
private AppLocationManager.LocationRequester requester = new AppLocationManager.LocationRequester() { | private AppLocationManager.LocationRequester requester = new AppLocationManager.LocationRequester() { | ||||
@Override | @Override | ||||
public void onLocationChanged(Location loc) { | public void onLocationChanged(Location loc) { | ||||
} | } | ||||
@Override | @Override | ||||
public void onLocationStatusChanged(int status) { | public void onLocationStatusChanged(int status) { | ||||
if(status == AppLocationManager.LOCATION_GPS_AVAILABLE && !isNearbyFragmentShown() && checkLocationPermission()){ | if(status == AppLocationManager.LOCATION_GPS_AVAILABLE && !isNearbyFragmentShown() && checkLocationPermission()){ | ||||
//request Stops | //request Stops | ||||
//pendingNearbyStopsRequest = false; | //pendingNearbyStopsRequest = false; | ||||
if (getContext()!= null && !isNearbyFragmentShown()) | if (getContext()!= null && !isNearbyFragmentShown()) | ||||
//mainHandler.post(new NearbyStopsRequester(getContext(), cr)); | //mainHandler.post(new NearbyStopsRequester(getContext(), cr)); | ||||
showNearbyFragmentIfNeeded(cr); | showNearbyFragmentIfPossible(); | ||||
} | } | ||||
} | } | ||||
@Override | @Override | ||||
public long getLastUpdateTimeMillis() { | public long getLastUpdateTimeMillis() { | ||||
return 50; | return 50; | ||||
} | } | ||||
@Override | @Override | ||||
public LocationCriteria getLocationCriteria() { | public LocationCriteria getLocationCriteria() { | ||||
return cr; | return cr; | ||||
} | } | ||||
@Override | @Override | ||||
public void onLocationProviderAvailable() { | public void onLocationProviderAvailable() { | ||||
//Log.w(DEBUG_TAG, "pendingNearbyStopRequest: "+pendingNearbyStopsRequest); | //Log.w(DEBUG_TAG, "pendingNearbyStopRequest: "+pendingNearbyStopsRequest); | ||||
if(!isNearbyFragmentShown() && getContext()!=null){ | if(!isNearbyFragmentShown() && getContext()!=null){ | ||||
// we should have the location permission | // we should have the location permission | ||||
if(!checkLocationPermission()) | if(!checkLocationPermission()) | ||||
Log.e(DEBUG_TAG, "Asking to show nearbystopfragment when " + | Log.e(DEBUG_TAG, "Asking to show nearbystopfragment when " + | ||||
"we have no location permission"); | "we have no location permission"); | ||||
pendingNearbyStopsFragmentRequest = true; | pendingNearbyStopsFragmentRequest = true; | ||||
//mainHandler.post(new NearbyStopsRequester(getContext(), cr)); | //mainHandler.post(new NearbyStopsRequester(getContext(), cr)); | ||||
showNearbyFragmentIfNeeded(cr); | showNearbyFragmentIfPossible(); | ||||
} | } | ||||
} | } | ||||
@Override | @Override | ||||
public void onLocationDisabled() { | public void onLocationDisabled() { | ||||
} | } | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | public View onCreateView(LayoutInflater inflater, ViewGroup container, | ||||
AppCompatImageButton qrButton = root.findViewById(R.id.QRButton); | AppCompatImageButton qrButton = root.findViewById(R.id.QRButton); | ||||
qrButton.setOnClickListener(this::onQRButtonClick); | qrButton.setOnClickListener(this::onQRButtonClick); | ||||
AppCompatImageButton searchButton = root.findViewById(R.id.searchButton); | AppCompatImageButton searchButton = root.findViewById(R.id.searchButton); | ||||
searchButton.setOnClickListener(this::onSearchClick); | searchButton.setOnClickListener(this::onSearchClick); | ||||
// Fragment stuff | // Fragment stuff | ||||
fragMan = getChildFragmentManager(); | childFragMan = getChildFragmentManager(); | ||||
fragMan.addOnBackStackChangedListener(() -> Log.d("BusTO Main Fragment", "BACK STACK CHANGED")); | childFragMan.addOnBackStackChangedListener(() -> Log.d("BusTO Main Fragment", "BACK STACK CHANGED")); | ||||
fragmentHelper = new FragmentHelper(this, getChildFragmentManager(), getContext(), R.id.resultFrame); | fragmentHelper = new FragmentHelper(this, getChildFragmentManager(), getContext(), R.id.resultFrame); | ||||
setSearchModeBusStopID(); | setSearchModeBusStopID(); | ||||
cr.setAccuracy(Criteria.ACCURACY_FINE); | cr.setAccuracy(Criteria.ACCURACY_FINE); | ||||
cr.setAltitudeRequired(false); | cr.setAltitudeRequired(false); | ||||
▲ Show 20 Lines • Show All 99 Lines • ▼ Show 20 Lines | public void onStart() { | ||||
if(PreferencesHolder.hasIntroFinishedOneShot(requireContext())){ | if(PreferencesHolder.hasIntroFinishedOneShot(requireContext())){ | ||||
Log.d(DEBUG_TAG, "Showing nearby stops"); | Log.d(DEBUG_TAG, "Showing nearby stops"); | ||||
if(!checkLocationPermission()){ | if(!checkLocationPermission()){ | ||||
requestLocationPermission(); | requestLocationPermission(); | ||||
pendingNearbyStopsFragmentRequest = true; | pendingNearbyStopsFragmentRequest = true; | ||||
} | } | ||||
else { | else { | ||||
showNearbyFragmentIfNeeded(cr); | showNearbyFragmentIfPossible(); | ||||
} | } | ||||
} else { | } else { | ||||
//The Introductory Activity is about to be started, hence pause the request and show later | //The Introductory Activity is about to be started, hence pause the request and show later | ||||
pendingIntroRun = true; | pendingIntroRun = true; | ||||
} | } | ||||
} | } | ||||
else{ | else{ | ||||
Show All 15 Lines | public void onResume() { | ||||
//recheck the introduction activity has been run | //recheck the introduction activity has been run | ||||
if(pendingIntroRun && PreferencesHolder.hasIntroFinishedOneShot(con)){ | if(pendingIntroRun && PreferencesHolder.hasIntroFinishedOneShot(con)){ | ||||
//request position permission if needed | //request position permission if needed | ||||
if(!checkLocationPermission()){ | if(!checkLocationPermission()){ | ||||
requestLocationPermission(); | requestLocationPermission(); | ||||
pendingNearbyStopsFragmentRequest = true; | pendingNearbyStopsFragmentRequest = true; | ||||
} | } | ||||
else { | else { | ||||
showNearbyFragmentIfNeeded(cr); | showNearbyFragmentIfPossible(); | ||||
} | } | ||||
//deactivate flag | //deactivate flag | ||||
pendingIntroRun = false; | pendingIntroRun = false; | ||||
} | } | ||||
if(Permissions.bothLocationPermissionsGranted(con)){ | if(Permissions.bothLocationPermissionsGranted(con)){ | ||||
Log.d(DEBUG_TAG, "Location permission OK"); | Log.d(DEBUG_TAG, "Location permission OK"); | ||||
if(!locationManager.isRequesterRegistered(requester)) | if(!locationManager.isRequesterRegistered(requester)) | ||||
locationManager.addLocationRequestFor(requester); | locationManager.addLocationRequestFor(requester); | ||||
} //don't request permission | } //don't request permission | ||||
// if we have a pending stopID request, do it | // if we have a pending stopID request, do it | ||||
Log.d(DEBUG_TAG, "Pending stop ID for arrivals: "+pendingStopID); | Log.d(DEBUG_TAG, "Pending stop ID for arrivals: "+pendingStopID); | ||||
//this is the second time we are attaching this fragment | //this is the second time we are attaching this fragment -> | ||||
Log.d(DEBUG_TAG, "Waiting for new stop request: "+ suppressArrivalsReload); | Log.d(DEBUG_TAG, "Waiting for new stop request: "+ suppressArrivalsReload); | ||||
//TODO: if we come back to this from another fragment, and the user has given again the permission | |||||
// for the Location, we should show the Nearby Stops | |||||
if(!suppressArrivalsReload && pendingStopID==null){ | |||||
//none of the following cases are true | |||||
// check if we are showing any fragment | |||||
final Fragment fragment = getChildFragmentManager().findFragmentById(R.id.resultFrame); | |||||
if(fragment==null || swipeRefreshLayout.getVisibility() != View.VISIBLE){ | |||||
//we are not showing anything | |||||
if(Permissions.anyLocationPermissionsGranted(getContext())){ | |||||
showNearbyFragmentIfPossible(); | |||||
} | |||||
} | |||||
} | |||||
if (suppressArrivalsReload){ | if (suppressArrivalsReload){ | ||||
// we have to suppress the reloading of the (possible) ArrivalsFragment | // we have to suppress the reloading of the (possible) ArrivalsFragment | ||||
Fragment fragment = getChildFragmentManager().findFragmentById(R.id.resultFrame); | Fragment fragment = getChildFragmentManager().findFragmentById(R.id.resultFrame); | ||||
if (fragment instanceof ArrivalsFragment){ | if (fragment instanceof ArrivalsFragment){ | ||||
ArrivalsFragment frag = (ArrivalsFragment) fragment; | ArrivalsFragment frag = (ArrivalsFragment) fragment; | ||||
frag.setReloadOnResume(false); | frag.setReloadOnResume(false); | ||||
} | } | ||||
//deactivate | //deactivate | ||||
▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | private void setSearchModeBusStopName() { | ||||
searchMode = SEARCH_BY_NAME; | searchMode = SEARCH_BY_NAME; | ||||
busStopSearchByIDEditText.setVisibility(View.GONE); | busStopSearchByIDEditText.setVisibility(View.GONE); | ||||
busStopSearchByIDEditText.setText(""); | busStopSearchByIDEditText.setText(""); | ||||
busStopSearchByNameEditText.setVisibility(View.VISIBLE); | busStopSearchByNameEditText.setVisibility(View.VISIBLE); | ||||
floatingActionButton.setImageResource(R.drawable.numeric); | floatingActionButton.setImageResource(R.drawable.numeric); | ||||
} | } | ||||
protected boolean isNearbyFragmentShown(){ | protected boolean isNearbyFragmentShown(){ | ||||
Fragment fragment = getChildFragmentManager().findFragmentByTag(NearbyStopsFragment.FRAGMENT_TAG); | Fragment fragment = getChildFragmentManager().findFragmentByTag(NearbyStopsFragment.FRAGMENT_TAG); | ||||
return (fragment!= null && fragment.isVisible()); | return (fragment!= null && fragment.isResumed()); | ||||
} | } | ||||
/** | /** | ||||
* Having that cursor at the left of the edit text makes me cancer. | * Having that cursor at the left of the edit text makes me cancer. | ||||
* | * | ||||
* @param busStopID bus stop ID | * @param busStopID bus stop ID | ||||
*/ | */ | ||||
private void setBusStopSearchByIDEditText(String busStopID) { | private void setBusStopSearchByIDEditText(String busStopID) { | ||||
Show All 30 Lines | public class MainScreenFragment extends ScreenBaseFragment implements FragmentListenerMain{ | ||||
private void prepareGUIForBusStops() { | private void prepareGUIForBusStops() { | ||||
swipeRefreshLayout.setEnabled(false); | swipeRefreshLayout.setEnabled(false); | ||||
swipeRefreshLayout.setVisibility(View.VISIBLE); | swipeRefreshLayout.setVisibility(View.VISIBLE); | ||||
//actionHelpMenuItem.setVisible(false); | //actionHelpMenuItem.setVisible(false); | ||||
} | } | ||||
private void actuallyShowNearbyStopsFragment(){ | private void actuallyShowNearbyStopsFragment(){ | ||||
swipeRefreshLayout.setVisibility(View.VISIBLE); | swipeRefreshLayout.setVisibility(View.VISIBLE); | ||||
final Fragment existingFrag = fragMan.findFragmentById(R.id.resultFrame); | final Fragment existingFrag = childFragMan.findFragmentById(R.id.resultFrame); | ||||
// fragment; | // fragment; | ||||
if (!(existingFrag instanceof NearbyStopsFragment)){ | if (!(existingFrag instanceof NearbyStopsFragment)){ | ||||
Log.d(DEBUG_TAG, "actually showing Nearby Stops Fragment"); | Log.d(DEBUG_TAG, "actually showing Nearby Stops Fragment"); | ||||
//there is no fragment showing | //there is no fragment showing | ||||
final NearbyStopsFragment fragment = NearbyStopsFragment.newInstance(NearbyStopsFragment.FragType.STOPS); | final NearbyStopsFragment fragment = NearbyStopsFragment.newInstance(NearbyStopsFragment.FragType.STOPS); | ||||
FragmentTransaction ft = fragMan.beginTransaction(); | FragmentTransaction ft = childFragMan.beginTransaction(); | ||||
ft.replace(R.id.resultFrame, fragment, NearbyStopsFragment.FRAGMENT_TAG); | ft.replace(R.id.resultFrame, fragment, NearbyStopsFragment.FRAGMENT_TAG); | ||||
if (getActivity()!=null && !getActivity().isFinishing()) | if (getActivity()!=null && !getActivity().isFinishing()) | ||||
ft.commit(); | ft.commit(); | ||||
else Log.e(DEBUG_TAG, "Not showing nearby fragment because activity null or is finishing"); | else Log.e(DEBUG_TAG, "Not showing nearby fragment because activity null or is finishing"); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 103 Lines • ▼ Show 20 Lines | private boolean checkLocationPermission(){ | ||||
return isOldVersion || !noPermission; | return isOldVersion || !noPermission; | ||||
} | } | ||||
private void requestLocationPermission(){ | private void requestLocationPermission(){ | ||||
requestPermissionLauncher.launch(LOCATION_PERMISSIONS); | requestPermissionLauncher.launch(LOCATION_PERMISSIONS); | ||||
} | } | ||||
private void showNearbyFragmentIfNeeded(Criteria cr){ | private void showNearbyFragmentIfPossible() { | ||||
if(isNearbyFragmentShown()) { | if (isNearbyFragmentShown()) { | ||||
//nothing to do | //nothing to do | ||||
Log.w(DEBUG_TAG, "launched nearby fragment request but we already are showing"); | Log.w(DEBUG_TAG, "Asked to show nearby fragment but we already are showing it"); | ||||
return; | return; | ||||
} | } | ||||
if(getContext()==null){ | if (getContext() == null) { | ||||
Log.e(DEBUG_TAG, "Wanting to show nearby fragment but context is null"); | Log.e(DEBUG_TAG, "Wanting to show nearby fragment but context is null"); | ||||
return; | return; | ||||
} | } | ||||
AppLocationManager appLocationManager = AppLocationManager.getInstance(getContext()); | if (fragmentHelper.getLastSuccessfullySearchedBusStop() == null | ||||
final boolean haveProviders = appLocationManager.anyLocationProviderMatchesCriteria(cr); | && !childFragMan.isDestroyed()) { | ||||
if (haveProviders | |||||
&& fragmentHelper.getLastSuccessfullySearchedBusStop() == null | |||||
&& !fragMan.isDestroyed()) { | |||||
//Go ahead with the request | //Go ahead with the request | ||||
actuallyShowNearbyStopsFragment(); | actuallyShowNearbyStopsFragment(); | ||||
pendingNearbyStopsFragmentRequest = false; | pendingNearbyStopsFragmentRequest = false; | ||||
} else if(!haveProviders){ | |||||
Log.e(DEBUG_TAG, "NO PROVIDERS FOR POSITION"); | |||||
} | } | ||||
} | } | ||||
/////////// LOCATION METHODS ////////// | /////////// LOCATION METHODS ////////// | ||||
/* | /* | ||||
private void startStopRequest(String provider) { | private void startStopRequest(String provider) { | ||||
Log.d(DEBUG_TAG, "Provider " + provider + " got enabled"); | Log.d(DEBUG_TAG, "Provider " + provider + " got enabled"); | ||||
if (locmgr != null && mainHandler != null && pendingNearbyStopsRequest && locmgr.getProvider(provider).meetsCriteria(cr)) { | if (locmgr != null && mainHandler != null && pendingNearbyStopsRequest && locmgr.getProvider(provider).meetsCriteria(cr)) { | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | class NearbyStopsRequester implements Runnable { | ||||
} | } | ||||
} | } | ||||
} | } | ||||
*/ | */ | ||||
} | } | ||||
No newline at end of file | No newline at end of file |
Public contents are in Creative Commons Attribution-ShareAlike 4.0 (CC-BY-SA) or GNU Free Documentation License (at your option) unless otherwise noted. · Contact / Register