Changeset View
Changeset View
Standalone View
Standalone View
src/it/reyboz/bustorino/ActivityMain.java
Show All 11 Lines | BusTO - Arrival times for Turin public transports. | ||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
GNU General Public License for more details. | GNU General Public License for more details. | ||||
You should have received a copy of the GNU General Public License | You should have received a copy of the GNU General Public License | ||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
*/ | */ | ||||
package it.reyboz.bustorino; | package it.reyboz.bustorino; | ||||
import android.annotation.SuppressLint; | import android.Manifest; | ||||
import android.content.Context; | import android.content.Context; | ||||
import android.content.Intent; | import android.content.Intent; | ||||
import android.content.SharedPreferences; | |||||
import android.content.pm.PackageManager; | import android.content.pm.PackageManager; | ||||
import android.content.res.Resources; | |||||
import android.database.sqlite.SQLiteDatabase; | import android.database.sqlite.SQLiteDatabase; | ||||
import android.location.*; | import android.location.*; | ||||
import android.net.Uri; | import android.net.Uri; | ||||
import android.os.Build; | import android.os.Build; | ||||
import android.os.Bundle; | import android.os.Bundle; | ||||
import android.os.Handler; | import android.os.Handler; | ||||
import android.support.annotation.NonNull; | |||||
import android.support.design.widget.Snackbar; | import androidx.annotation.NonNull; | ||||
import android.support.v4.app.Fragment; | import androidx.core.app.ActivityCompat; | ||||
import android.support.v4.app.FragmentManager; | import androidx.work.BackoffPolicy; | ||||
import android.support.v4.app.FragmentTransaction; | import androidx.work.Constraints; | ||||
import android.support.v4.app.NavUtils; | import androidx.work.ExistingPeriodicWorkPolicy; | ||||
import android.support.v4.widget.SwipeRefreshLayout; | import androidx.work.NetworkType; | ||||
import androidx.work.PeriodicWorkRequest; | |||||
import androidx.work.WorkInfo; | |||||
import androidx.work.WorkManager; | |||||
import com.google.android.material.snackbar.Snackbar; | |||||
import androidx.fragment.app.Fragment; | |||||
import androidx.fragment.app.FragmentManager; | |||||
import androidx.fragment.app.FragmentTransaction; | |||||
import androidx.core.app.NavUtils; | |||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; | |||||
import android.util.Log; | import android.util.Log; | ||||
import android.view.KeyEvent; | import android.view.KeyEvent; | ||||
import android.view.Menu; | import android.view.Menu; | ||||
import android.view.MenuItem; | import android.view.MenuItem; | ||||
import android.view.View; | import android.view.View; | ||||
import android.view.inputmethod.EditorInfo; | import android.view.inputmethod.EditorInfo; | ||||
import android.view.inputmethod.InputMethodManager; | import android.view.inputmethod.InputMethodManager; | ||||
import android.widget.*; | import android.widget.*; | ||||
import com.google.zxing.integration.android.IntentIntegrator; | import com.google.zxing.integration.android.IntentIntegrator; | ||||
import com.google.zxing.integration.android.IntentResult; | import com.google.zxing.integration.android.IntentResult; | ||||
import android.support.design.widget.FloatingActionButton; | import com.google.android.material.floatingactionbutton.FloatingActionButton; | ||||
import it.reyboz.bustorino.backend.*; | import it.reyboz.bustorino.backend.*; | ||||
import it.reyboz.bustorino.fragments.*; | import it.reyboz.bustorino.fragments.*; | ||||
import it.reyboz.bustorino.middleware.*; | import it.reyboz.bustorino.middleware.*; | ||||
import java.util.ArrayList; | |||||
import java.util.Arrays; | |||||
import java.util.List; | import java.util.List; | ||||
import java.util.concurrent.TimeUnit; | |||||
public class ActivityMain extends GeneralActivity implements FragmentListener { | public class ActivityMain extends GeneralActivity implements FragmentListener { | ||||
/* | /* | ||||
* Layout elements | * Layout elements | ||||
*/ | */ | ||||
private EditText busStopSearchByIDEditText; | private EditText busStopSearchByIDEditText; | ||||
private EditText busStopSearchByNameEditText; | private EditText busStopSearchByNameEditText; | ||||
Show All 14 Lines | public class ActivityMain extends GeneralActivity implements FragmentListener { | ||||
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; | ||||
private ImageButton addToFavorites; | private ImageButton addToFavorites; | ||||
/* | /* | ||||
* Options | * Options | ||||
*/ | */ | ||||
private final String OPTION_SHOW_LEGEND = "show_legend"; | private final String OPTION_SHOW_LEGEND = "show_legend"; | ||||
private final String LOCATION_PERMISSION_GIVEN = "loc_permission"; | |||||
/* | |||||
* Status | |||||
*/ | |||||
private DBStatusManager prefsManager; | |||||
private DBStatusManager.OnDBUpdateStatusChangeListener updatelistener; | |||||
private static final String DEBUG_TAG = "BusTO - MainActivity"; | private static final String DEBUG_TAG = "BusTO - MainActivity"; | ||||
/* // useful for testing: | /* // useful for testing: | ||||
public class MockFetcher implements ArrivalsFetcher { | public class MockFetcher implements ArrivalsFetcher { | ||||
@Override | @Override | ||||
public Palina ReadArrivalTimesAll(String routeID, AtomicReference<result> res) { | public Palina ReadArrivalTimesAll(String routeID, AtomicReference<result> res) { | ||||
SystemClock.sleep(5000); | SystemClock.sleep(5000); | ||||
res.set(result.SERVER_ERROR); | res.set(result.SERVER_ERROR); | ||||
return new Palina(); | return new Palina(); | ||||
} | } | ||||
} | } | ||||
private ArrivalsFetcher[] ArrivalFetchers = {new MockFetcher(), new MockFetcher(), new MockFetcher(), new MockFetcher(), new MockFetcher()};*/ | private ArrivalsFetcher[] ArrivalFetchers = {new MockFetcher(), new MockFetcher(), new MockFetcher(), new MockFetcher(), new MockFetcher()};*/ | ||||
private ArrivalsFetcher[] arrivalsFetchers = new ArrivalsFetcher[]{new FiveTAPIFetcher(), new GTTJSONFetcher(), new FiveTScraperFetcher()}; | |||||
private RecursionHelper<ArrivalsFetcher> ArrivalFetchersRecursionHelper = new RecursionHelper<>(new ArrivalsFetcher[]{new GTTJSONFetcher(), new FiveTScraperFetcher()}); | private StopsFinderByName[] stopsFinderByNames = new StopsFinderByName[]{new GTTStopsFetcher(), new FiveTStopsFetcher()}; | ||||
private RecursionHelper<StopsFinderByName> StopsFindersByNameRecursionHelper = new RecursionHelper<>(new StopsFinderByName[]{new GTTStopsFetcher(), new FiveTStopsFetcher()}); | |||||
/* | /* | ||||
* Position | * Position | ||||
*/ | */ | ||||
//Fine location criteria | //Fine location criteria | ||||
private final Criteria cr = new Criteria(); | private final Criteria cr = new Criteria(); | ||||
private boolean pendingNearbyStopsRequest = false; | private boolean pendingNearbyStopsRequest = false; | ||||
private LocationManager locmgr; | private LocationManager locmgr; | ||||
/* | |||||
* Database Access | |||||
*/ | |||||
private StopsDB stopsDB; | |||||
private UserDB userDB; | |||||
private FragmentHelper fh; | private FragmentHelper fh; | ||||
///////////////////////////////// EVENT HANDLERS /////////////////////////////////////////////// | ///////////////////////////////// EVENT HANDLERS /////////////////////////////////////////////// | ||||
/* | /* | ||||
* @see swipeRefreshLayout | * @see swipeRefreshLayout | ||||
*/ | */ | ||||
private Handler handler = new Handler(); | private final Handler theHandler = new Handler(); | ||||
private final Runnable refreshing = new Runnable() { | private final Runnable refreshing = new Runnable() { | ||||
public void run() { | public void run() { | ||||
if (framan.findFragmentById(R.id.resultFrame) instanceof ArrivalsFragment) { | if (framan.findFragmentById(R.id.resultFrame) instanceof ArrivalsFragment) { | ||||
ArrivalsFragment fragment = (ArrivalsFragment) framan.findFragmentById(R.id.resultFrame); | ArrivalsFragment fragment = (ArrivalsFragment) framan.findFragmentById(R.id.resultFrame); | ||||
String stopName = fragment.getStopID(); | String stopName = fragment.getStopID(); | ||||
new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS, fh).execute(stopName); | |||||
} else | new AsyncDataDownload(fh, fragment.getCurrentFetchersAsArray()).execute(stopName); | ||||
new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS, fh).execute(); | } else //we create a new fragment, which is WRONG | ||||
new AsyncDataDownload(fh, arrivalsFetchers).execute(); | |||||
} | } | ||||
}; | }; | ||||
//// MAIN METHOD /// | //// MAIN METHOD /// | ||||
@Override | @Override | ||||
protected void onCreate(Bundle savedInstanceState) { | protected void onCreate(Bundle savedInstanceState) { | ||||
super.onCreate(savedInstanceState); | super.onCreate(savedInstanceState); | ||||
framan = getSupportFragmentManager(); | framan = getSupportFragmentManager(); | ||||
this.stopsDB = new StopsDB(getApplicationContext()); | final SharedPreferences theShPr = getMainSharedPreferences(); | ||||
this.userDB = new UserDB(getApplicationContext()); | /* | ||||
* Database Access | |||||
*/ | |||||
setContentView(R.layout.activity_main); | setContentView(R.layout.activity_main); | ||||
busStopSearchByIDEditText = (EditText) findViewById(R.id.busStopSearchByIDEditText); | busStopSearchByIDEditText = findViewById(R.id.busStopSearchByIDEditText); | ||||
busStopSearchByNameEditText = (EditText) findViewById(R.id.busStopSearchByNameEditText); | busStopSearchByNameEditText = findViewById(R.id.busStopSearchByNameEditText); | ||||
progressBar = (ProgressBar) findViewById(R.id.progressBar); | progressBar = findViewById(R.id.progressBar); | ||||
howDoesItWorkTextView = (TextView) findViewById(R.id.howDoesItWorkTextView); | howDoesItWorkTextView = findViewById(R.id.howDoesItWorkTextView); | ||||
hideHintButton = (Button) findViewById(R.id.hideHintButton); | hideHintButton = findViewById(R.id.hideHintButton); | ||||
swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.listRefreshLayout); | swipeRefreshLayout = findViewById(R.id.listRefreshLayout); | ||||
floatingActionButton = (FloatingActionButton) findViewById(R.id.floatingActionButton); | floatingActionButton = findViewById(R.id.floatingActionButton); | ||||
framan.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { | framan.addOnBackStackChangedListener(() -> Log.d("MainActivity, BusTO", "BACK STACK CHANGED")); | ||||
@Override | |||||
public void onBackStackChanged() { | |||||
Log.d("MainActivity, BusTO", "BACK STACK CHANGED"); | |||||
} | |||||
}); | |||||
busStopSearchByIDEditText.setSelectAllOnFocus(true); | busStopSearchByIDEditText.setSelectAllOnFocus(true); | ||||
busStopSearchByIDEditText | busStopSearchByIDEditText | ||||
.setOnEditorActionListener(new TextView.OnEditorActionListener() { | .setOnEditorActionListener((v, actionId, event) -> { | ||||
@Override | |||||
public boolean onEditorAction(TextView v, int actionId, | |||||
KeyEvent event) { | |||||
// IME_ACTION_SEARCH alphabetical option | // IME_ACTION_SEARCH alphabetical option | ||||
if (actionId == EditorInfo.IME_ACTION_SEARCH) { | if (actionId == EditorInfo.IME_ACTION_SEARCH) { | ||||
onSearchClick(v); | onSearchClick(v); | ||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
} | |||||
}); | }); | ||||
busStopSearchByNameEditText | busStopSearchByNameEditText | ||||
.setOnEditorActionListener(new TextView.OnEditorActionListener() { | .setOnEditorActionListener((v, actionId, event) -> { | ||||
@Override | |||||
public boolean onEditorAction(TextView v, int actionId, | |||||
KeyEvent event) { | |||||
// IME_ACTION_SEARCH alphabetical option | // IME_ACTION_SEARCH alphabetical option | ||||
if (actionId == EditorInfo.IME_ACTION_SEARCH) { | if (actionId == EditorInfo.IME_ACTION_SEARCH) { | ||||
onSearchClick(v); | onSearchClick(v); | ||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
} | |||||
}); | }); | ||||
// Called when the layout is pulled down | // Called when the layout is pulled down | ||||
swipeRefreshLayout | swipeRefreshLayout | ||||
.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { | .setOnRefreshListener(() -> theHandler.post(refreshing)); | ||||
@Override | |||||
public void onRefresh() { | |||||
handler.post(refreshing); | |||||
} | |||||
}); | |||||
/** | /** | ||||
* @author Marco Gagino!!! | * @author Marco Gagino!!! | ||||
*/ | */ | ||||
//swipeRefreshLayout.setColorSchemeColors(R.color.blue_500, R.color.orange_500); // setColorScheme is deprecated, setColorSchemeColors isn't | //swipeRefreshLayout.setColorSchemeColors(R.color.blue_500, R.color.orange_500); // setColorScheme is deprecated, setColorSchemeColors isn't | ||||
swipeRefreshLayout.setColorSchemeResources(R.color.blue_500, R.color.orange_500); | swipeRefreshLayout.setColorSchemeResources(R.color.blue_500, R.color.orange_500); | ||||
fh = new FragmentHelper(this, R.id.listRefreshLayout, R.id.resultFrame); | fh = new FragmentHelper(this, R.id.listRefreshLayout, R.id.resultFrame); | ||||
setSearchModeBusStopID(); | setSearchModeBusStopID(); | ||||
Show All 32 Lines | protected void onCreate(Bundle savedInstanceState) { | ||||
// Show keyboard if can't start from intent | // Show keyboard if can't start from intent | ||||
// JUST DON'T | // JUST DON'T | ||||
// showKeyboard(); | // showKeyboard(); | ||||
// You haven't obtained anything... from an intent? | // You haven't obtained anything... from an intent? | ||||
if (tryedFromIntent) { | if (tryedFromIntent) { | ||||
// This shows a luser warning | // This shows a luser warning | ||||
ArrivalFetchersRecursionHelper.reset(); | |||||
Toast.makeText(getApplicationContext(), | Toast.makeText(getApplicationContext(), | ||||
R.string.insert_bus_stop_number_error, Toast.LENGTH_SHORT).show(); | R.string.insert_bus_stop_number_error, Toast.LENGTH_SHORT).show(); | ||||
} | } | ||||
} else { | } else { | ||||
// If you are here an intent has worked successfully | // If you are here an intent has worked successfully | ||||
setBusStopSearchByIDEditText(busStopID); | setBusStopSearchByIDEditText(busStopID); | ||||
/* | /* | ||||
//THIS PART SHOULDN'T BE NECESSARY SINCE THE LAST SUCCESSFULLY SEARCHED BUS | //THIS PART SHOULDN'T BE NECESSARY SINCE THE LAST SUCCESSFULLY SEARCHED BUS | ||||
// STOP IS ADDED AUTOMATICALLY | // STOP IS ADDED AUTOMATICALLY | ||||
Stop nextStop = new Stop(busStopID); | Stop nextStop = new Stop(busStopID); | ||||
// forcing it as user name even though it could be standard name, it doesn't really matter | // forcing it as user name even though it could be standard name, it doesn't really matter | ||||
nextStop.setStopUserName(busStopDisplayName); | nextStop.setStopUserName(busStopDisplayName); | ||||
//set stop as last succe | //set stop as last succe | ||||
fh.setLastSuccessfullySearchedBusStop(nextStop); | fh.setLastSuccessfullySearchedBusStop(nextStop); | ||||
*/ | */ | ||||
createFragmentForStop(busStopID); | createFragmentForStop(busStopID); | ||||
} | } | ||||
//Try (hopefully) database update | //Try (hopefully) database update | ||||
//TODO: Start the service in foreground, check last time it ran before | //TODO: Check if service shows the notification | ||||
DatabaseUpdateService.startDBUpdate(getApplicationContext()); | //Old code for the db update | ||||
//DatabaseUpdateService.startDBUpdate(getApplicationContext()); | |||||
PeriodicWorkRequest wr = new PeriodicWorkRequest.Builder(DBUpdateWorker.class, 1, TimeUnit.DAYS) | |||||
.setBackoffCriteria(BackoffPolicy.LINEAR, 30, TimeUnit.MINUTES) | |||||
.setConstraints(new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED) | |||||
.build()) | |||||
.build(); | |||||
final WorkManager workManager = WorkManager.getInstance(this); | |||||
final int version = theShPr.getInt(DatabaseUpdate.DB_VERSION_KEY, -10); | |||||
if (version >= 0) | |||||
workManager.enqueueUniquePeriodicWork(DBUpdateWorker.DEBUG_TAG, | |||||
ExistingPeriodicWorkPolicy.KEEP, wr); | |||||
else workManager.enqueueUniquePeriodicWork(DBUpdateWorker.DEBUG_TAG, | |||||
ExistingPeriodicWorkPolicy.REPLACE, wr); | |||||
/* | /* | ||||
Set database update | Set database update | ||||
*/ | */ | ||||
updatelistener = new DBStatusManager.OnDBUpdateStatusChangeListener() { | workManager.getWorkInfosForUniqueWorkLiveData(DBUpdateWorker.DEBUG_TAG) | ||||
@Override | .observe(this, workInfoList -> { | ||||
public boolean defaultStatusValue() { | // If there are no matching work info, do nothing | ||||
return true; | if (workInfoList == null || workInfoList.isEmpty()) { | ||||
return; | |||||
} | } | ||||
Log.d(DEBUG_TAG, "WorkerInfo: "+workInfoList); | |||||
@Override | boolean showProgress = false; | ||||
public void onDBStatusChanged(boolean updating) { | for (WorkInfo workInfo : workInfoList) { | ||||
if (workInfo.getState() == WorkInfo.State.RUNNING) { | |||||
showProgress = true; | |||||
} | |||||
} | |||||
if (updating) { | if (showProgress) { | ||||
createDefaultSnackbar(); | createDefaultSnackbar(); | ||||
} else if (snackbar != null) { | } else { | ||||
if(snackbar!=null) { | |||||
snackbar.dismiss(); | snackbar.dismiss(); | ||||
snackbar = null; | snackbar = null; | ||||
} | } | ||||
} | |||||
}); | |||||
} | |||||
}; | |||||
prefsManager = new DBStatusManager(getApplicationContext(), updatelistener); | |||||
prefsManager.registerListener(); | |||||
//locationHandler = new GPSLocationAdapter(getApplicationContext()); | //locationHandler = new GPSLocationAdapter(getApplicationContext()); | ||||
//--------- NEARBY STOPS--------// | //--------- NEARBY STOPS--------// | ||||
//SETUP LOCATION | //SETUP LOCATION | ||||
locmgr = (LocationManager) getSystemService(LOCATION_SERVICE); | locmgr = (LocationManager) getSystemService(LOCATION_SERVICE); | ||||
cr.setAccuracy(Criteria.ACCURACY_FINE); | cr.setAccuracy(Criteria.ACCURACY_FINE); | ||||
cr.setAltitudeRequired(false); | cr.setAltitudeRequired(false); | ||||
cr.setBearingRequired(false); | cr.setBearingRequired(false); | ||||
cr.setCostAllowed(true); | cr.setCostAllowed(true); | ||||
cr.setPowerRequirement(Criteria.NO_REQUIREMENT); | cr.setPowerRequirement(Criteria.NO_REQUIREMENT); | ||||
//We want the nearby bus stops! | //We want the nearby bus stops! | ||||
handler.post(new NearbyStopsRequester()); | theHandler.post(new NearbyStopsRequester()); | ||||
//If there are no providers available, then, wait for them | //If there are no providers available, then, wait for them | ||||
Log.d("MainActivity", "Created"); | Log.d("MainActivity", "Created"); | ||||
} | } | ||||
/** | /** | ||||
* Reload bus stop timetable when it's fulled resumed from background. | * Reload bus stop timetable when it's fulled resumed from background. | ||||
*/ | */ | ||||
/** | /** | ||||
* @Override protected void onPostResume() { | * @Override protected void onPostResume() { | ||||
* super.onPostResume(); | * super.onPostResume(); | ||||
* Log.d("ActivityMain", "onPostResume fired. Last successfully bus stop ID: " + fh.getLastSuccessfullySearchedBusStop()); | * Log.d("ActivityMain", "onPostResume fired. Last successfully bus stop ID: " + fh.getLastSuccessfullySearchedBusStop()); | ||||
* if (searchMode == SEARCH_BY_ID && fh.getLastSuccessfullySearchedBusStop() != null) { | * if (searchMode == SEARCH_BY_ID && fh.getLastSuccessfullySearchedBusStop() != null) { | ||||
* setBusStopSearchByIDEditText(fh.getLastSuccessfullySearchedBusStop().ID); | * setBusStopSearchByIDEditText(fh.getLastSuccessfullySearchedBusStop().ID); | ||||
* //new asyncWgetBusStopFromBusStopID(lastSuccessfullySearchedBusStop.ID, ArrivalFetchersRecursionHelper, lastSuccessfullySearchedBusStop); | |||||
* new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS,fh).execute(); | * new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS,fh).execute(); | ||||
* } else { | * } else { | ||||
* //we have new activity or we don't have a new searched stop. | * //we have new activity or we don't have a new searched stop. | ||||
* //Let's search stops nearby | * //Let's search stops nearby | ||||
* LocationManager locManager = (LocationManager) getSystemService(LOCATION_SERVICE); | * LocationManager locManager = (LocationManager) getSystemService(LOCATION_SERVICE); | ||||
* Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.resultFrame); | * Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.resultFrame); | ||||
* <p> | * <p> | ||||
* <p> | * <p> | ||||
* } | * } | ||||
* //show the FAB since it remains hidden | * //show the FAB since it remains hidden | ||||
* floatingActionButton.show(); | * floatingActionButton.show(); | ||||
* <p> | * <p> | ||||
* } | * } | ||||
**/ | **/ | ||||
@Override | @Override | ||||
protected void onPause() { | protected void onPause() { | ||||
super.onPause(); | super.onPause(); | ||||
fh.stopLastRequestIfNeeded(); | fh.stopLastRequestIfNeeded(); | ||||
fh.setBlockAllActivities(true); | fh.setBlockAllActivities(true); | ||||
if (updatelistener != null && prefsManager != null) prefsManager.unregisterListener(); | |||||
locmgr.removeUpdates(locListener); | locmgr.removeUpdates(locListener); | ||||
} | } | ||||
@Override | @Override | ||||
protected void onResume() { | protected void onResume() { | ||||
super.onResume(); | super.onResume(); | ||||
fh.setBlockAllActivities(false); | fh.setBlockAllActivities(false); | ||||
if (updatelistener != null && prefsManager != null) { | //TODO: check if current LiveData-bound observer works | ||||
prefsManager.registerListener(); | |||||
if (prefsManager.isDBUpdating(true)) { | |||||
createDefaultSnackbar(); | |||||
} | |||||
} | |||||
if (pendingNearbyStopsRequest) | if (pendingNearbyStopsRequest) | ||||
handler.post(new NearbyStopsRequester()); | theHandler.post(new NearbyStopsRequester()); | ||||
} | } | ||||
@Override | @Override | ||||
public boolean onCreateOptionsMenu(Menu menu) { | public boolean onCreateOptionsMenu(Menu menu) { | ||||
// Inflate the menu; this adds items to the action bar if it is present. | // Inflate the menu; this adds items to the action bar if it is present. | ||||
getMenuInflater().inflate(R.menu.main, menu); | getMenuInflater().inflate(R.menu.main, menu); | ||||
actionHelpMenuItem = menu.findItem(R.id.action_help); | actionHelpMenuItem = menu.findItem(R.id.action_help); | ||||
Show All 18 Lines | public boolean onOptionsItemSelected(MenuItem item) { | ||||
return true; | return true; | ||||
case R.id.action_help: | case R.id.action_help: | ||||
showHints(); | showHints(); | ||||
return true; | return true; | ||||
case R.id.action_favorites: | case R.id.action_favorites: | ||||
startActivity(new Intent(ActivityMain.this, ActivityFavorites.class)); | startActivity(new Intent(ActivityMain.this, ActivityFavorites.class)); | ||||
return true; | return true; | ||||
case R.id.action_map: | case R.id.action_map: | ||||
//ensure storage permission is granted | |||||
final String permission = Manifest.permission.WRITE_EXTERNAL_STORAGE; | |||||
int result = askForPermissionIfNeeded(permission, STORAGE_PERMISSION_REQ); | |||||
switch (result) { | |||||
case PERMISSION_OK: | |||||
startActivity(new Intent(ActivityMain.this, ActivityMap.class)); | startActivity(new Intent(ActivityMain.this, ActivityMap.class)); | ||||
break; | |||||
case PERMISSION_ASKING: | |||||
permissionDoneRunnables.put(permission, | |||||
() -> startActivity(new Intent(ActivityMain.this, ActivityMap.class))); | |||||
break; | |||||
case PERMISSION_NEG_CANNOT_ASK: | |||||
Resources res = getResources(); | |||||
String storage_perm = res.getString(R.string.storage_permission); | |||||
String text = res.getString(R.string.too_many_permission_asks, storage_perm); | |||||
Toast.makeText(getApplicationContext(),text, Toast.LENGTH_LONG).show(); | |||||
} | |||||
return true; | return true; | ||||
case R.id.action_about: | case R.id.action_about: | ||||
startActivity(new Intent(ActivityMain.this, ActivityAbout.class)); | startActivity(new Intent(ActivityMain.this, ActivityAbout.class)); | ||||
return true; | return true; | ||||
case R.id.action_news: | case R.id.action_news: | ||||
openIceweasel("https://gitpull.it/w/librebusto/#how-to-get-news"); | openIceweasel("https://gitpull.it/w/librebusto/#how-to-get-news"); | ||||
return true; | return true; | ||||
case R.id.action_bugs: | case R.id.action_bugs: | ||||
openIceweasel("https://gitpull.it/w/librebusto/#how-to-create-a-bug-feature"); | openIceweasel("https://gitpull.it/w/librebusto/#how-to-create-a-bug-feature"); | ||||
Show All 14 Lines | public class ActivityMain extends GeneralActivity implements FragmentListener { | ||||
/** | /** | ||||
* OK this is pure shit | * OK this is pure shit | ||||
* | * | ||||
* @param v View clicked | * @param v View clicked | ||||
*/ | */ | ||||
public void onSearchClick(View v) { | public void onSearchClick(View v) { | ||||
if (searchMode == SEARCH_BY_ID) { | if (searchMode == SEARCH_BY_ID) { | ||||
String busStopID = busStopSearchByIDEditText.getText().toString(); | String busStopID = busStopSearchByIDEditText.getText().toString(); | ||||
//OLD ASYNCTASK | createFragmentForStop(busStopID); | ||||
//new asyncWgetBusStopFromBusStopID(busStopID, ArrivalFetchersRecursionHelper, lastSuccessfullySearchedBusStop); | |||||
if (busStopID == null || busStopID.length() <= 0) { | |||||
showMessage(R.string.insert_bus_stop_number_error); | |||||
toggleSpinner(false); | |||||
} else { | |||||
new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS, fh).execute(busStopID); | |||||
Log.d("MainActiv", "Started search for arrivals of stop " + busStopID); | |||||
} | |||||
} else { // searchMode == SEARCH_BY_NAME | } else { // searchMode == SEARCH_BY_NAME | ||||
String query = busStopSearchByNameEditText.getText().toString(); | String query = busStopSearchByNameEditText.getText().toString(); | ||||
//new asyncWgetBusStopSuggestions(query, stopsDB, StopsFindersByNameRecursionHelper); | //new asyncWgetBusStopSuggestions(query, stopsDB, StopsFindersByNameRecursionHelper); | ||||
new AsyncDataDownload(AsyncDataDownload.RequestType.STOPS, fh).execute(query); | new AsyncDataDownload(fh, stopsFinderByNames).execute(query); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* PERMISSION STUFF | * PERMISSION STUFF | ||||
**/ | **/ | ||||
@Override | @Override | ||||
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { | ||||
switch (requestCode) { | switch (requestCode) { | ||||
case PERMISSION_REQUEST_POSITION: | case PERMISSION_REQUEST_POSITION: | ||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { | if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { | ||||
setOption(LOCATION_PERMISSION_GIVEN, true); | setOption(LOCATION_PERMISSION_GIVEN, true); | ||||
//if we sent a request for a new NearbyStopsFragment | //if we sent a request for a new NearbyStopsFragment | ||||
if (pendingNearbyStopsRequest) { | if (pendingNearbyStopsRequest) { | ||||
pendingNearbyStopsRequest = false; | pendingNearbyStopsRequest = false; | ||||
handler.post(new NearbyStopsRequester()); | theHandler.post(new NearbyStopsRequester()); | ||||
} | } | ||||
} else { | } else { | ||||
//permission denied | //permission denied | ||||
setOption(LOCATION_PERMISSION_GIVEN, false); | setOption(LOCATION_PERMISSION_GIVEN, false); | ||||
} | } | ||||
//add other cases for permissions | //add other cases for permissions | ||||
break; | |||||
case STORAGE_PERMISSION_REQ: | |||||
final String storageKey = Manifest.permission.WRITE_EXTERNAL_STORAGE; | |||||
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { | |||||
Log.d(DEBUG_TAG, "Permissions check: " + Arrays.toString(permissions)); | |||||
if (permissionDoneRunnables.containsKey(storageKey)) { | |||||
Runnable toRun = permissionDoneRunnables.get(storageKey); | |||||
if (toRun != null) | |||||
toRun.run(); | |||||
permissionDoneRunnables.remove(storageKey); | |||||
} | |||||
} else { | |||||
//permission denied | |||||
showToastMessage(R.string.permission_storage_maps_msg, false); | |||||
/*final int canGetPermission = askForPermissionIfNeeded(Manifest.permission.ACCESS_FINE_LOCATION, STORAGE_PERMISSION_REQ); | |||||
switch (canGetPermission) { | |||||
case PERMISSION_ASKING: | |||||
break; | |||||
case PERMISSION_NEG_CANNOT_ASK: | |||||
permissionDoneRunnables.remove(storageKey); | |||||
showToastMessage(R.string.closing_act_crash_msg, false); | |||||
}*/ | |||||
} | |||||
} | } | ||||
} | } | ||||
@Override | @Override | ||||
public void createFragmentForStop(String ID) { | public void createFragmentForStop(String ID) { | ||||
//new asyncWgetBusStopFromBusStopID(ID, ArrivalFetchersRecursionHelper,lastSuccessfullySearchedBusStop); | |||||
if (ID == null || ID.length() <= 0) { | if (ID == null || ID.length() <= 0) { | ||||
// we're still in UI thread, no need to mess with Progress | // we're still in UI thread, no need to mess with Progress | ||||
showMessage(R.string.insert_bus_stop_number_error); | showToastMessage(R.string.insert_bus_stop_number_error, true); | ||||
toggleSpinner(false); | toggleSpinner(false); | ||||
} else if (framan.findFragmentById(R.id.resultFrame) instanceof ArrivalsFragment) { | |||||
ArrivalsFragment fragment = (ArrivalsFragment) framan.findFragmentById(R.id.resultFrame); | |||||
if (fragment.getStopID() != null && fragment.getStopID().equals(ID)){ | |||||
// Run with previous fetchers | |||||
//fragment.getCurrentFetchers().toArray() | |||||
new AsyncDataDownload(fh,fragment.getCurrentFetchersAsArray()).execute(ID); | |||||
} else { | } else{ | ||||
new AsyncDataDownload(AsyncDataDownload.RequestType.ARRIVALS, fh).execute(ID); | new AsyncDataDownload(fh, arrivalsFetchers).execute(ID); | ||||
} | |||||
} | |||||
else { | |||||
new AsyncDataDownload(fh,arrivalsFetchers).execute(ID); | |||||
Log.d("MainActiv", "Started search for arrivals of stop " + ID); | Log.d("MainActiv", "Started search for arrivals of stop " + ID); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* 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(this); | IntentIntegrator integrator = new IntentIntegrator(this); | ||||
integrator.initiateScan(); | integrator.initiateScan(); | ||||
} | } | ||||
/** | /** | ||||
* Receive the Barcode Scanner Intent | * Receive the Barcode Scanner Intent | ||||
*/ | */ | ||||
public void onActivityResult(int requestCode, int resultCode, Intent intent) { | public void onActivityResult(int requestCode, int resultCode, Intent intent) { | ||||
super.onActivityResult(requestCode, resultCode, intent); | |||||
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent); | IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent); | ||||
Uri uri; | Uri uri; | ||||
try { | try { | ||||
uri = Uri.parse(scanResult != null ? scanResult.getContents() : null); // this apparently prevents NullPointerException. Somehow. | uri = Uri.parse(scanResult != null ? scanResult.getContents() : null); // this apparently prevents NullPointerException. Somehow. | ||||
} catch (NullPointerException e) { | } catch (NullPointerException e) { | ||||
Toast.makeText(getApplicationContext(), | Toast.makeText(getApplicationContext(), | ||||
R.string.no_qrcode, Toast.LENGTH_SHORT).show(); | R.string.no_qrcode, Toast.LENGTH_SHORT).show(); | ||||
Show All 31 Lines | private void createDefaultSnackbar() { | ||||
snackbar.show(); | snackbar.show(); | ||||
} | } | ||||
///////////////////////////////// POSITION STUFF////////////////////////////////////////////// | ///////////////////////////////// POSITION STUFF////////////////////////////////////////////// | ||||
private void resolveStopRequest(String provider) { | private void resolveStopRequest(String provider) { | ||||
Log.d(DEBUG_TAG, "Provider " + provider + " got enabled"); | Log.d(DEBUG_TAG, "Provider " + provider + " got enabled"); | ||||
if (locmgr != null && pendingNearbyStopsRequest && locmgr.getProvider(provider).meetsCriteria(cr)) { | if (locmgr != null && pendingNearbyStopsRequest && locmgr.getProvider(provider).meetsCriteria(cr)) { | ||||
pendingNearbyStopsRequest = false; | pendingNearbyStopsRequest = false; | ||||
handler.post(new NearbyStopsRequester()); | theHandler.post(new NearbyStopsRequester()); | ||||
} | } | ||||
} | } | ||||
final LocationListener locListener = new LocationListener() { | final LocationListener locListener = new LocationListener() { | ||||
@Override | @Override | ||||
public void onLocationChanged(Location location) { | public void onLocationChanged(Location location) { | ||||
Log.d(DEBUG_TAG, "Location changed"); | Log.d(DEBUG_TAG, "Location changed"); | ||||
} | } | ||||
Show All 12 Lines | final LocationListener locListener = new LocationListener() { | ||||
} | } | ||||
@Override | @Override | ||||
public void onProviderDisabled(String provider) { | public void onProviderDisabled(String provider) { | ||||
} | } | ||||
}; | }; | ||||
/** | |||||
* Run location requests separately and asynchronously | |||||
*/ | |||||
class NearbyStopsRequester implements Runnable { | class NearbyStopsRequester implements Runnable { | ||||
@SuppressLint("MissingPermission") | |||||
@Override | @Override | ||||
public void run() { | public void run() { | ||||
final boolean canRunPosition = Build.VERSION.SDK_INT < Build.VERSION_CODES.M || getOption(LOCATION_PERMISSION_GIVEN, false); | final boolean canRunPosition = Build.VERSION.SDK_INT < Build.VERSION_CODES.M || getOption(LOCATION_PERMISSION_GIVEN, false); | ||||
final boolean noPermission = ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && | |||||
ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED; | |||||
//if we don't have the permission, we have to ask for it, if we haven't | |||||
// asked too many times before | |||||
if (noPermission) { | |||||
if (!canRunPosition) { | if (!canRunPosition) { | ||||
pendingNearbyStopsRequest = true; | pendingNearbyStopsRequest = true; | ||||
assertLocationPermissions(); | assertLocationPermissions(); | ||||
Log.w(DEBUG_TAG, "Cannot get position: Asking permission, noPositionFromSys: " + noPermission); | |||||
return; | return; | ||||
} else { | |||||
Toast.makeText(getApplicationContext(), "Asked for permission position too many times", Toast.LENGTH_LONG).show(); | |||||
} | |||||
} else setOption(LOCATION_PERMISSION_GIVEN, true); | } else setOption(LOCATION_PERMISSION_GIVEN, true); | ||||
LocationManager locManager = (LocationManager) getSystemService(LOCATION_SERVICE); | LocationManager locManager = (LocationManager) getSystemService(LOCATION_SERVICE); | ||||
if (locManager == null) { | if (locManager == null) { | ||||
Log.e(DEBUG_TAG, "location manager is nihil, cannot create NearbyStopsFragment"); | Log.e(DEBUG_TAG, "location manager is nihil, cannot create NearbyStopsFragment"); | ||||
return; | return; | ||||
} | } | ||||
if (anyLocationProviderMatchesCriteria(locManager, cr, true) && fh.getLastSuccessfullySearchedBusStop() == null) { | if (anyLocationProviderMatchesCriteria(locManager, cr, true) | ||||
&& fh.getLastSuccessfullySearchedBusStop() == null | |||||
&& !framan.isDestroyed()) { | |||||
//Go ahead with the request | //Go ahead with the request | ||||
Log.d("mainActivity", "Recreating stop fragment"); | Log.d("mainActivity", "Recreating stop fragment"); | ||||
swipeRefreshLayout.setVisibility(View.VISIBLE); | swipeRefreshLayout.setVisibility(View.VISIBLE); | ||||
NearbyStopsFragment fragment = NearbyStopsFragment.newInstance(NearbyStopsFragment.TYPE_STOPS); | NearbyStopsFragment fragment = NearbyStopsFragment.newInstance(NearbyStopsFragment.TYPE_STOPS); | ||||
Fragment oldFrag = framan.findFragmentById(R.id.resultFrame); | Fragment oldFrag = framan.findFragmentById(R.id.resultFrame); | ||||
FragmentTransaction ft = framan.beginTransaction(); | FragmentTransaction ft = framan.beginTransaction(); | ||||
if (oldFrag != null) | if (oldFrag != null) | ||||
ft.remove(oldFrag); | ft.remove(oldFrag); | ||||
ft.add(R.id.resultFrame, fragment, "nearbyStop_correct"); | ft.add(R.id.resultFrame, fragment, "nearbyStop_correct"); | ||||
ft.commit(); | ft.commit(); | ||||
framan.executePendingTransactions(); | framan.executePendingTransactions(); | ||||
pendingNearbyStopsRequest = false; | pendingNearbyStopsRequest = false; | ||||
} else if (!anyLocationProviderMatchesCriteria(locManager, cr, true)) { | } else if (!anyLocationProviderMatchesCriteria(locManager, cr, true)) { | ||||
//Wait for the providers | //Wait for the providers | ||||
Log.d(DEBUG_TAG, "Queuing position request"); | Log.d(DEBUG_TAG, "Queuing position request"); | ||||
pendingNearbyStopsRequest = true; | pendingNearbyStopsRequest = true; | ||||
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10, 0.1f, locListener); | locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10, 0.1f, locListener); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
private boolean anyLocationProviderMatchesCriteria(LocationManager mng, Criteria cr, boolean enabled) { | private boolean anyLocationProviderMatchesCriteria(LocationManager mng, Criteria cr, boolean enabled) { | ||||
List<String> providers = mng.getProviders(cr, enabled); | List<String> providers = mng.getProviders(cr, enabled); | ||||
▲ Show 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | public class ActivityMain extends GeneralActivity implements FragmentListener { | ||||
} | } | ||||
@Override | @Override | ||||
public void enableRefreshLayout(boolean yes) { | public void enableRefreshLayout(boolean yes) { | ||||
swipeRefreshLayout.setEnabled(yes); | swipeRefreshLayout.setEnabled(yes); | ||||
} | } | ||||
////////////////////////////////////// GUI HELPERS ///////////////////////////////////////////// | ////////////////////////////////////// GUI HELPERS ///////////////////////////////////////////// | ||||
@Override | |||||
public void showKeyboard() { | public void showKeyboard() { | ||||
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); | InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); | ||||
View view = searchMode == SEARCH_BY_ID ? busStopSearchByIDEditText : busStopSearchByNameEditText; | View view = searchMode == SEARCH_BY_ID ? busStopSearchByIDEditText : busStopSearchByNameEditText; | ||||
imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); | imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); | ||||
} | } | ||||
@Override | |||||
public void showMessage(int messageID) { | |||||
Toast.makeText(getApplicationContext(), messageID, Toast.LENGTH_SHORT).show(); | |||||
} | |||||
private void setSearchModeBusStopID() { | private void setSearchModeBusStopID() { | ||||
searchMode = SEARCH_BY_ID; | searchMode = SEARCH_BY_ID; | ||||
busStopSearchByNameEditText.setVisibility(View.GONE); | busStopSearchByNameEditText.setVisibility(View.GONE); | ||||
busStopSearchByNameEditText.setText(""); | busStopSearchByNameEditText.setText(""); | ||||
busStopSearchByIDEditText.setVisibility(View.VISIBLE); | busStopSearchByIDEditText.setVisibility(View.VISIBLE); | ||||
floatingActionButton.setImageResource(R.drawable.alphabetical); | floatingActionButton.setImageResource(R.drawable.alphabetical); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 150 Lines • ▼ Show 20 Lines | public void changeStarFilled() { | ||||
addToFavorites.setImageResource(R.drawable.ic_star_filled); | addToFavorites.setImageResource(R.drawable.ic_star_filled); | ||||
} | } | ||||
public void changeStarOutline() { | public void changeStarOutline() { | ||||
addToFavorites.setImageResource(R.drawable.ic_star_outline); | addToFavorites.setImageResource(R.drawable.ic_star_outline); | ||||
} | } | ||||
} | } | ||||
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