Changeset View
Changeset View
Standalone View
Standalone View
src/it/reyboz/bustorino/fragments/MainScreenFragment.java
package it.reyboz.bustorino.fragments; | package it.reyboz.bustorino.fragments; | ||||
import android.Manifest; | import android.Manifest; | ||||
import android.content.Context; | import android.content.Context; | ||||
import android.content.Intent; | |||||
import android.content.pm.PackageManager; | import android.content.pm.PackageManager; | ||||
import android.location.Criteria; | import android.location.Criteria; | ||||
import android.location.Location; | import android.location.Location; | ||||
import android.net.Uri; | |||||
import android.os.Build; | import android.os.Build; | ||||
import android.os.Bundle; | import android.os.Bundle; | ||||
import androidx.activity.result.ActivityResultCallback; | import androidx.activity.result.ActivityResultCallback; | ||||
import androidx.activity.result.ActivityResultLauncher; | import androidx.activity.result.ActivityResultLauncher; | ||||
import androidx.activity.result.contract.ActivityResultContracts; | import androidx.activity.result.contract.ActivityResultContracts; | ||||
import androidx.annotation.NonNull; | import androidx.annotation.NonNull; | ||||
import androidx.annotation.Nullable; | import androidx.annotation.Nullable; | ||||
Show All 16 Lines | |||||
import android.widget.Button; | import android.widget.Button; | ||||
import android.widget.EditText; | import android.widget.EditText; | ||||
import android.widget.ImageButton; | import android.widget.ImageButton; | ||||
import android.widget.ProgressBar; | import android.widget.ProgressBar; | ||||
import android.widget.TextView; | import android.widget.TextView; | ||||
import android.widget.Toast; | import android.widget.Toast; | ||||
import com.google.android.material.floatingactionbutton.FloatingActionButton; | import com.google.android.material.floatingactionbutton.FloatingActionButton; | ||||
import com.google.zxing.integration.android.IntentIntegrator; | |||||
import java.util.Map; | import java.util.Map; | ||||
import it.reyboz.bustorino.R; | import it.reyboz.bustorino.R; | ||||
import it.reyboz.bustorino.backend.*; | import it.reyboz.bustorino.backend.*; | ||||
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.BarcodeScanOptions; | |||||
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 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; | ||||
import static it.reyboz.bustorino.util.Permissions.LOCATION_PERMISSION_GIVEN; | import static it.reyboz.bustorino.util.Permissions.LOCATION_PERMISSION_GIVEN; | ||||
/** | /** | ||||
* 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 | ||||
* create an instance of this fragment. | * create an instance of this fragment. | ||||
*/ | */ | ||||
public class MainScreenFragment extends ScreenBaseFragment implements FragmentListenerMain{ | public class MainScreenFragment extends ScreenBaseFragment implements FragmentListenerMain{ | ||||
private static final String OPTION_SHOW_LEGEND = "show_legend"; | private static final String OPTION_SHOW_LEGEND = "show_legend"; | ||||
private static final String SAVED_FRAGMENT="saved_fragment"; | private static final String SAVED_FRAGMENT="saved_fragment"; | ||||
private static final String DEBUG_TAG = "BusTO - MainFragment"; | private static final String DEBUG_TAG = "BusTO - MainFragment"; | ||||
public static final String PENDING_STOP_SEARCH="PendingStopSearch"; | |||||
public final static String FRAGMENT_TAG = "MainScreenFragment"; | public final static String FRAGMENT_TAG = "MainScreenFragment"; | ||||
/// UI ELEMENTS // | /// UI ELEMENTS // | ||||
private ImageButton addToFavorites; | private ImageButton addToFavorites; | ||||
private FragmentHelper fragmentHelper; | private FragmentHelper fragmentHelper; | ||||
private SwipeRefreshLayout swipeRefreshLayout; | private SwipeRefreshLayout swipeRefreshLayout; | ||||
private EditText busStopSearchByIDEditText; | private EditText busStopSearchByIDEditText; | ||||
private EditText busStopSearchByNameEditText; | private EditText busStopSearchByNameEditText; | ||||
private ProgressBar progressBar; | private ProgressBar progressBar; | ||||
private TextView howDoesItWorkTextView; | private TextView howDoesItWorkTextView; | ||||
private Button hideHintButton; | private Button hideHintButton; | ||||
private MenuItem actionHelpMenuItem; | private MenuItem actionHelpMenuItem; | ||||
private FloatingActionButton floatingActionButton; | private FloatingActionButton floatingActionButton; | ||||
private boolean setupOnAttached = true; | private boolean setupOnResume = true; | ||||
private boolean suppressArrivalsReload = false; | private boolean suppressArrivalsReload = false; | ||||
private boolean instanceStateSaved = 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; // TODO: implement this -- https://gitpull.it/T12 | ||||
private int searchMode; | private int searchMode; | ||||
Show All 15 Lines | private final Runnable refreshStop = new Runnable() { | ||||
String stopName = fragment.getStopID(); | String stopName = fragment.getStopID(); | ||||
new AsyncArrivalsSearcher(fragmentHelper, fragment.getCurrentFetchersAsArray(), getContext()).execute(stopName); | new AsyncArrivalsSearcher(fragmentHelper, fragment.getCurrentFetchersAsArray(), getContext()).execute(stopName); | ||||
} | } | ||||
} else //we create a new fragment, which is WRONG | } else //we create a new fragment, which is WRONG | ||||
new AsyncArrivalsSearcher(fragmentHelper, arrivalsFetchers, getContext()).execute(); | new AsyncArrivalsSearcher(fragmentHelper, arrivalsFetchers, getContext()).execute(); | ||||
} | } | ||||
}; | }; | ||||
// | |||||
private final ActivityResultLauncher<BarcodeScanOptions> barcodeLauncher = registerForActivityResult(new BarcodeScanContract(), | |||||
result -> { | |||||
if(result!=null && result.getContents()!=null) { | |||||
//Toast.makeText(MyActivity.this, "Cancelled", Toast.LENGTH_LONG).show(); | |||||
Uri uri; | |||||
try { | |||||
uri = Uri.parse(result.getContents()); // this apparently prevents NullPointerException. Somehow. | |||||
} catch (NullPointerException e) { | |||||
if (getContext()!=null) | |||||
Toast.makeText(getContext().getApplicationContext(), | |||||
R.string.no_qrcode, Toast.LENGTH_SHORT).show(); | |||||
return; | |||||
} | |||||
String busStopID = getBusStopIDFromUri(uri); | |||||
busStopSearchByIDEditText.setText(busStopID); | |||||
requestArrivalsForStopID(busStopID); | |||||
} else { | |||||
//Toast.makeText(MyActivity.this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show(); | |||||
if (getContext()!=null) | |||||
Toast.makeText(getContext().getApplicationContext(), | |||||
R.string.no_qrcode, Toast.LENGTH_SHORT).show(); | |||||
} | |||||
}); | |||||
/// LOCATION STUFF /// | /// LOCATION STUFF /// | ||||
boolean pendingNearbyStopsRequest = false; | boolean pendingNearbyStopsRequest = false; | ||||
boolean locationPermissionGranted, locationPermissionAsked = false; | boolean locationPermissionGranted, locationPermissionAsked = false; | ||||
AppLocationManager locationManager; | AppLocationManager locationManager; | ||||
private final LocationCriteria cr = new LocationCriteria(2000, 10000); | private final LocationCriteria cr = new LocationCriteria(2000, 10000); | ||||
▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | public static MainScreenFragment newInstance() { | ||||
return fragment; | return fragment; | ||||
} | } | ||||
@Override | @Override | ||||
public void onCreate(Bundle savedInstanceState) { | public void onCreate(Bundle savedInstanceState) { | ||||
super.onCreate(savedInstanceState); | super.onCreate(savedInstanceState); | ||||
if (getArguments() != null) { | if (getArguments() != null) { | ||||
//do nothing | //do nothing | ||||
Log.d(DEBUG_TAG, "ARGS ARE NOT NULL: "+getArguments()); | |||||
if (getArguments().getString(PENDING_STOP_SEARCH)!=null) | |||||
pendingStopID = getArguments().getString(PENDING_STOP_SEARCH); | |||||
} | } | ||||
} | } | ||||
@Override | @Override | ||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, | public View onCreateView(LayoutInflater inflater, ViewGroup container, | ||||
Bundle savedInstanceState) { | Bundle savedInstanceState) { | ||||
// Inflate the layout for this fragment | // Inflate the layout for this fragment | ||||
View root = inflater.inflate(R.layout.fragment_main_screen, container, false); | View root = inflater.inflate(R.layout.fragment_main_screen, container, false); | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | public View onCreateView(LayoutInflater inflater, ViewGroup container, | ||||
return root; | return root; | ||||
} | } | ||||
@Override | @Override | ||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { | ||||
super.onViewCreated(view, savedInstanceState); | super.onViewCreated(view, savedInstanceState); | ||||
Log.d(DEBUG_TAG, "onViewCreated, SwipeRefreshLayout visible: "+(swipeRefreshLayout.getVisibility()==View.VISIBLE)); | Log.d(DEBUG_TAG, "onViewCreated, SwipeRefreshLayout visible: "+(swipeRefreshLayout.getVisibility()==View.VISIBLE)); | ||||
Log.d(DEBUG_TAG, "Setup on attached: "+setupOnAttached); | Log.d(DEBUG_TAG, "Setup on attached: "+ setupOnResume); | ||||
//Restore instance state | //Restore instance state | ||||
if (savedInstanceState!=null){ | if (savedInstanceState!=null){ | ||||
Fragment fragment = getChildFragmentManager().getFragment(savedInstanceState, SAVED_FRAGMENT); | Fragment fragment = getChildFragmentManager().getFragment(savedInstanceState, SAVED_FRAGMENT); | ||||
if (fragment!=null){ | if (fragment!=null){ | ||||
getChildFragmentManager().beginTransaction().add(R.id.resultFrame, fragment).commit(); | getChildFragmentManager().beginTransaction().add(R.id.resultFrame, fragment).commit(); | ||||
setupOnAttached = false; | setupOnResume = false; | ||||
} | } | ||||
} | } | ||||
if (getChildFragmentManager().findFragmentById(R.id.resultFrame)!= null){ | if (getChildFragmentManager().findFragmentById(R.id.resultFrame)!= null){ | ||||
swipeRefreshLayout.setVisibility(View.VISIBLE); | swipeRefreshLayout.setVisibility(View.VISIBLE); | ||||
} | } | ||||
instanceStateSaved = false; | |||||
} | } | ||||
@Override | @Override | ||||
public void onSaveInstanceState(@NonNull Bundle outState) { | public void onSaveInstanceState(@NonNull Bundle outState) { | ||||
super.onSaveInstanceState(outState); | super.onSaveInstanceState(outState); | ||||
Fragment fragment = getChildFragmentManager().findFragmentById(R.id.resultFrame); | Fragment fragment = getChildFragmentManager().findFragmentById(R.id.resultFrame); | ||||
if (fragment!=null) | if (fragment!=null) | ||||
getChildFragmentManager().putFragment(outState, SAVED_FRAGMENT, fragment); | getChildFragmentManager().putFragment(outState, SAVED_FRAGMENT, fragment); | ||||
fragmentHelper.setBlockAllActivities(true); | fragmentHelper.setBlockAllActivities(true); | ||||
instanceStateSaved = true; | |||||
} | } | ||||
public void setSuppressArrivalsReload(boolean value){ | public void setSuppressArrivalsReload(boolean value){ | ||||
suppressArrivalsReload = value; | suppressArrivalsReload = value; | ||||
// we have to suppress the reloading of the (possible) ArrivalsFragment | // we have to suppress the reloading of the (possible) ArrivalsFragment | ||||
/*if(value) { | /*if(value) { | ||||
Fragment fragment = getChildFragmentManager().findFragmentById(R.id.resultFrame); | Fragment fragment = getChildFragmentManager().findFragmentById(R.id.resultFrame); | ||||
if (fragment instanceof ArrivalsFragment) { | if (fragment instanceof ArrivalsFragment) { | ||||
Show All 18 Lines | public void cancelReloadArrivalsIfNeeded(){ | ||||
toggleSpinner(false); | toggleSpinner(false); | ||||
} | } | ||||
@Override | @Override | ||||
public void onAttach(@NonNull Context context) { | public void onAttach(@NonNull Context context) { | ||||
super.onAttach(context); | super.onAttach(context); | ||||
Log.d(DEBUG_TAG, "OnAttach called, setupOnAttach: "+setupOnAttached); | Log.d(DEBUG_TAG, "OnAttach called, setupOnAttach: "+ setupOnResume); | ||||
mainHandler = new Handler(); | mainHandler = new Handler(); | ||||
if (context instanceof CommonFragmentListener) { | if (context instanceof CommonFragmentListener) { | ||||
mListener = (CommonFragmentListener) context; | mListener = (CommonFragmentListener) context; | ||||
} else { | } else { | ||||
throw new RuntimeException(context | throw new RuntimeException(context | ||||
+ " must implement CommonFragmentListener"); | + " must implement CommonFragmentListener"); | ||||
} | } | ||||
if (setupOnAttached) { | |||||
if (pendingStopID==null) | |||||
//We want the nearby bus stops! | |||||
mainHandler.post(new NearbyStopsRequester(context, cr)); | |||||
else{ | |||||
///TODO: if there is a stop displayed, we need to hold the update | |||||
} | |||||
setupOnAttached = false; | |||||
} | |||||
} | } | ||||
@Override | @Override | ||||
public void onDetach() { | public void onDetach() { | ||||
super.onDetach(); | super.onDetach(); | ||||
mListener = null; | mListener = null; | ||||
// setupOnAttached = true; | // setupOnAttached = true; | ||||
} | } | ||||
Show All 33 Lines | public void onResume() { | ||||
// 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); | ||||
} | } | ||||
suppressArrivalsReload = false; | suppressArrivalsReload = false; | ||||
} | } | ||||
if (setupOnResume) { | |||||
if (pendingStopID==null) | |||||
//We want the nearby bus stops! | |||||
mainHandler.post(new NearbyStopsRequester(getContext(), cr)); | |||||
else{ | |||||
///TODO: if there is a stop displayed, we need to hold the update | |||||
} | |||||
setupOnResume = false; | |||||
} | |||||
if(pendingStopID!=null){ | if(pendingStopID!=null){ | ||||
Log.d(DEBUG_TAG, "Re-requesting arrivals for pending stop "+pendingStopID); | |||||
requestArrivalsForStopID(pendingStopID); | requestArrivalsForStopID(pendingStopID); | ||||
pendingStopID = null; | pendingStopID = null; | ||||
} | } | ||||
mListener.readyGUIfor(FragmentKind.MAIN_SCREEN_FRAGMENT); | mListener.readyGUIfor(FragmentKind.MAIN_SCREEN_FRAGMENT); | ||||
fragmentHelper.setBlockAllActivities(false); | fragmentHelper.setBlockAllActivities(false); | ||||
} | } | ||||
@Override | @Override | ||||
public void onPause() { | public void onPause() { | ||||
//mainHandler = null; | //mainHandler = null; | ||||
locationManager.removeLocationRequestFor(requester); | locationManager.removeLocationRequestFor(requester); | ||||
super.onPause(); | super.onPause(); | ||||
fragmentHelper.setBlockAllActivities(true); | fragmentHelper.setBlockAllActivities(true); | ||||
fragmentHelper.stopLastRequestIfNeeded(true); | fragmentHelper.stopLastRequestIfNeeded(true); | ||||
} | } | ||||
/* | /* | ||||
GUI METHODS | GUI METHODS | ||||
*/ | */ | ||||
/** | /** | ||||
* QR scan button clicked | * QR scan button clicked | ||||
* | * | ||||
* @param v View QRButton clicked | * @param v View QRButton clicked | ||||
*/ | */ | ||||
public void onQRButtonClick(View v) { | public void onQRButtonClick(View v) { | ||||
IntentIntegrator integrator = new IntentIntegrator(getActivity()); | |||||
integrator.initiateScan(); | BarcodeScanOptions scanOptions = new BarcodeScanOptions(); | ||||
Intent intent = scanOptions.createScanIntent(); | |||||
if(!BarcodeScanUtils.checkTargetPackageExists(getContext(), intent)){ | |||||
BarcodeScanUtils.showDownloadDialog(null, this); | |||||
}else { | |||||
barcodeLauncher.launch(scanOptions); | |||||
} | |||||
} | } | ||||
public void onHideHint(View v) { | public void onHideHint(View v) { | ||||
hideHints(); | hideHints(); | ||||
setOption(OPTION_SHOW_LEGEND, false); | setOption(OPTION_SHOW_LEGEND, false); | ||||
} | } | ||||
/** | /** | ||||
* OK this is pure shit | * OK this is pure shit | ||||
▲ Show 20 Lines • Show All 129 Lines • ▼ Show 20 Lines | void showNearbyStopsFragment(){ | ||||
swipeRefreshLayout.setVisibility(View.VISIBLE); | swipeRefreshLayout.setVisibility(View.VISIBLE); | ||||
final Fragment existingFrag = fragMan.findFragmentById(R.id.resultFrame); | final Fragment existingFrag = fragMan.findFragmentById(R.id.resultFrame); | ||||
NearbyStopsFragment fragment; | NearbyStopsFragment fragment; | ||||
if (!(existingFrag instanceof NearbyStopsFragment)){ | if (!(existingFrag instanceof NearbyStopsFragment)){ | ||||
//there is no fragment showing | //there is no fragment showing | ||||
fragment = NearbyStopsFragment.newInstance(NearbyStopsFragment.TYPE_STOPS); | fragment = NearbyStopsFragment.newInstance(NearbyStopsFragment.TYPE_STOPS); | ||||
FragmentTransaction ft = fragMan.beginTransaction(); | FragmentTransaction ft = fragMan.beginTransaction(); | ||||
//if (oldFrag != null) | |||||
// ft.remove(oldFrag); | |||||
ft.replace(R.id.resultFrame, fragment, NearbyStopsFragment.FRAGMENT_TAG); | ft.replace(R.id.resultFrame, fragment, NearbyStopsFragment.FRAGMENT_TAG); | ||||
if (getActivity()!=null && !getActivity().isFinishing() &&!instanceStateSaved) | |||||
ft.commit(); | ft.commit(); | ||||
else Log.e(DEBUG_TAG, "Not showing nearby fragment because we saved instanceState"); | |||||
} | } | ||||
} | } | ||||
@Override | @Override | ||||
public void showFloatingActionButton(boolean yes) { | public void showFloatingActionButton(boolean yes) { | ||||
mListener.showFloatingActionButton(yes); | mListener.showFloatingActionButton(yes); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | public class MainScreenFragment extends ScreenBaseFragment implements FragmentListenerMain{ | ||||
* Main method for stops requests | * Main method for stops requests | ||||
* @param ID the Stop ID | * @param ID the Stop ID | ||||
*/ | */ | ||||
@Override | @Override | ||||
public void requestArrivalsForStopID(String ID) { | public void requestArrivalsForStopID(String ID) { | ||||
if (!isResumed()){ | if (!isResumed()){ | ||||
//defer request | //defer request | ||||
pendingStopID = ID; | pendingStopID = ID; | ||||
Log.d(DEBUG_TAG, "Deferring update for stop "+ID); | Log.d(DEBUG_TAG, "Deferring update for stop "+ID+ " saved: "+pendingStopID); | ||||
return; | return; | ||||
} | } | ||||
final boolean delayedRequest = !(pendingStopID==null); | final boolean delayedRequest = !(pendingStopID==null); | ||||
final FragmentManager framan = getChildFragmentManager(); | final FragmentManager framan = getChildFragmentManager(); | ||||
if (getContext()==null){ | if (getContext()==null){ | ||||
Log.e(DEBUG_TAG, "Asked for arrivals with null context"); | Log.e(DEBUG_TAG, "Asked for arrivals with null context"); | ||||
return; | return; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | class NearbyStopsRequester implements Runnable { | ||||
} else if(!haveProviders){ | } else if(!haveProviders){ | ||||
Log.e(DEBUG_TAG, "NO PROVIDERS FOR POSITION"); | Log.e(DEBUG_TAG, "NO PROVIDERS FOR POSITION"); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
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