use of com.thebluealliance.androidclient.models.ApiStatus in project the-blue-alliance-android by the-blue-alliance.
the class DatafeedActivity method onResume.
@Override
protected void onResume() {
super.onResume();
mEventBus.register(this);
ApiStatus status = mStatusController.fetchApiStatus();
commonStatusUpdate(status);
}
use of com.thebluealliance.androidclient.models.ApiStatus in project the-blue-alliance-android by the-blue-alliance.
the class StatusRefreshService method updateTbaStatus.
@WorkerThread
private void updateTbaStatus() {
if (!ConnectionDetector.isConnectedToInternet(this)) {
return;
}
/* Updating FirebaseRemoteConfig */
try {
mAppConfig.updateRemoteDataBlocking();
} catch (ExecutionException | InterruptedException e) {
TbaLogger.w("Error updating FirebaseRemoteConfig: " + e.getMessage(), e);
}
Response<ApiStatus> response;
try {
response = mRetrofitAPI.fetchApiStatus().toBlocking().first();
} catch (Exception ex) {
TbaLogger.w("Error updating TBA status: " + ex.getMessage(), ex);
return;
}
if (!response.isSuccessful()) {
TbaLogger.w("Unable to update myTBA Status\n" + response.code() + " " + response.message());
return;
}
ApiStatus status = response.body();
/* Write the new data to shared prefs */
mPrefs.edit().putString(TBAStatusController.STATUS_PREF_KEY, status.getJsonBlob()).apply();
/* Post the update to the EventBus */
mEventBus.post(status);
/* Update Champs pit locations if necessary */
PitLocationHelper.updateRemoteDataIfNeeded(getApplicationContext(), mAppConfig, mHttpClient);
if (status.getMinAppVersion() != null && BuildConfig.VERSION_CODE < status.getMinAppVersion()) {
startActivity(new Intent(this, UpdateRequiredActivity.class));
}
}
use of com.thebluealliance.androidclient.models.ApiStatus in project the-blue-alliance-android by the-blue-alliance.
the class TBAStatusController method onActivityResumed.
@Override
public void onActivityResumed(Activity activity) {
/* Update myTBA Status */
double timeout = mUserIsLoggedIn ? UPDATE_TIMEOUT_LOGGED_IN_NS : UPDATE_TIMEOUT_LOGGED_OUT_NS;
if (mLastUpdateTime + timeout < System.nanoTime()) {
scheduleStatusUpdate(activity);
mLastUpdateTime = System.nanoTime();
}
/* App updates required/recommended */
if (!Utilities.isDebuggable() && BuildConfig.VERSION_CODE < getMinAppVersion()) {
activity.startActivity(new Intent(activity, UpdateRequiredActivity.class));
} else if (!Utilities.isDebuggable() && BuildConfig.VERSION_CODE < getLatestAppVersion() && mLastDialogTime + DIALOG_TIMEOUT < System.nanoTime()) {
/* Show an app update dialog */
new AlertDialog.Builder(activity).setTitle(R.string.update_dialog_title).setMessage(R.string.update_dialog_text).setPositiveButton(R.string.update_dialog_action, (dialog, which) -> {
/* Open Play Store page */
dialog.dismiss();
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse("https://play.google.com/store/apps/details?id=com.thebluealliance.androidclient"));
activity.startActivity(i);
}).setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss()).show();
mLastDialogTime = System.nanoTime();
}
/* Admin push message */
ApiStatus status = fetchApiStatus();
Date now = new Date();
if (status != null && status.getHasMessage() && mLastMessageTime + DIALOG_TIMEOUT < System.nanoTime() && status.getMessageExpiration().compareTo(now.getTime()) > 0) {
new AlertDialog.Builder(activity).setMessage(status.getMessageText()).setCancelable(false).setPositiveButton(R.string.ok, ((dialog, which) -> dialog.dismiss())).show();
mLastMessageTime = System.nanoTime();
}
/* Clear OkHttp Cache when commanded */
clearOkCacheIfNeeded(status, false);
}
use of com.thebluealliance.androidclient.models.ApiStatus in project the-blue-alliance-android by the-blue-alliance.
the class LoadTBADataWorker method doWork.
@NonNull
@Override
public Result doWork() {
mStartTime = System.currentTimeMillis();
int[] params = getInputData().getIntArray(DATA_TO_LOAD);
int[] dataToLoad;
if (params == null || params.length == 0) {
dataToLoad = new int[] { LOAD_TEAMS, LOAD_EVENTS, LOAD_DISTRICTS };
} else {
dataToLoad = params;
}
try {
/* First, do a blocking update of Remote Config */
publishProgress(new LoadProgressInfo(LoadProgressInfo.STATE_LOADING, mApplicationContext.getString(R.string.loading_config)));
mAppConfig.updateRemoteDataBlocking();
Call<ApiStatus> statusCall = mDatafeed.fetchApiStatus();
Response<ApiStatus> statusResponse = statusCall.execute();
if (!statusResponse.isSuccessful() || statusResponse.body() == null || statusResponse.body().getMaxSeason() == null) {
TbaLogger.e("Bad API status response: " + statusResponse);
return onConnectionError();
}
int maxCompYear = statusResponse.body().getMaxSeason();
List<Team> allTeams = new ArrayList<>();
int maxPageNum = 0;
if (Arrays.binarySearch(dataToLoad, LOAD_TEAMS) != -1) {
mDb.getTeamsTable().deleteAllRows();
// First we will load all the teams
for (int pageNum = 0; pageNum < 20; pageNum++) {
// limit to 20 pages to prevent potential infinite loop
if (isStopped()) {
return Result.failure();
}
int start = pageNum * Constants.API_TEAM_LIST_PAGE_SIZE;
int end = start + Constants.API_TEAM_LIST_PAGE_SIZE - 1;
start = start == 0 ? 1 : start;
publishProgress(new LoadProgressInfo(LoadProgressInfo.STATE_LOADING, mApplicationContext.getString(R.string.loading_teams, start, end)));
Call<List<Team>> teamListCall = mDatafeed.fetchTeamPage(pageNum, ApiConstants.TBA_CACHE_WEB);
Response<List<Team>> teamListResponse = teamListCall.execute();
if (!teamListResponse.isSuccessful()) {
return onConnectionError();
}
if (teamListResponse.body() == null || teamListResponse.body().isEmpty()) {
// No teams found for a page; we are done
break;
}
Date lastModified = teamListResponse.headers().getDate("Last-Modified");
List<Team> responseBody = teamListResponse.body();
if (lastModified != null) {
long lastModifiedTimestamp = lastModified.getTime();
for (int i = 0; i < responseBody.size(); i++) {
responseBody.get(i).setLastModified(lastModifiedTimestamp);
}
}
allTeams.addAll(responseBody);
maxPageNum = Math.max(maxPageNum, pageNum);
}
}
List<Event> allEvents = new ArrayList<>();
if (Arrays.binarySearch(dataToLoad, LOAD_EVENTS) != -1) {
mDb.getEventsTable().deleteAllRows();
// Now we load all events
for (int year = Constants.FIRST_COMP_YEAR; year <= maxCompYear; year++) {
if (isStopped()) {
return Result.failure();
}
publishProgress(new LoadProgressInfo(LoadProgressInfo.STATE_LOADING, mApplicationContext.getString(R.string.loading_events, Integer.toString(year))));
Call<List<Event>> eventListCall = mDatafeed.fetchEventsInYear(year, ApiConstants.TBA_CACHE_WEB);
Response<List<Event>> eventListResponse = eventListCall.execute();
if (!eventListResponse.isSuccessful()) {
return onConnectionError();
}
if (eventListResponse.body() == null) {
continue;
}
Date lastModified = eventListResponse.headers().getDate("Last-Modified");
List<Event> responseBody = eventListResponse.body();
if (lastModified != null) {
long lastModifiedTimestamp = lastModified.getTime();
for (int i = 0; i < responseBody.size(); i++) {
responseBody.get(i).setLastModified(lastModifiedTimestamp);
}
}
allEvents.addAll(responseBody);
TbaLogger.i(String.format("Loaded %1$d events in %2$d", eventListResponse.body().size(), year));
}
}
List<District> allDistricts = new ArrayList<>();
if (Arrays.binarySearch(dataToLoad, LOAD_DISTRICTS) != -1) {
mDb.getDistrictsTable().deleteAllRows();
// load all districts
for (int year = Constants.FIRST_DISTRICT_YEAR; year <= maxCompYear; year++) {
if (isStopped()) {
return Result.failure();
}
publishProgress(new LoadProgressInfo(LoadProgressInfo.STATE_LOADING, mApplicationContext.getString(R.string.loading_districts, year)));
AddDistrictKeys keyAdder = new AddDistrictKeys(year);
Call<List<District>> districtListCall = mDatafeed.fetchDistrictList(year, ApiConstants.TBA_CACHE_WEB);
Response<List<District>> districtListResponse = districtListCall.execute();
if (!districtListResponse.isSuccessful() || districtListResponse.body() == null) {
return onConnectionError();
}
List<District> newDistrictList = districtListResponse.body();
keyAdder.call(newDistrictList);
Date lastModified = districtListResponse.headers().getDate("Last-Modified");
if (lastModified != null) {
long lastModifiedTimestamp = lastModified.getTime();
for (int i = 0; i < newDistrictList.size(); i++) {
newDistrictList.get(i).setLastModified(lastModifiedTimestamp);
}
}
allDistricts.addAll(newDistrictList);
TbaLogger.i(String.format("Loaded %1$d districts in %2$d", newDistrictList.size(), year));
}
}
if (isStopped()) {
return Result.failure();
}
// If no exception has been thrown at this point, we have all the data. We can now
// insert it into the database. Pass a 0 as the last-modified time here, because we set
// it individually above
publishProgress(new LoadProgressInfo(LoadProgressInfo.STATE_LOADING, mApplicationContext.getString(R.string.loading_almost_finished)));
TbaLogger.i("Writing " + allTeams.size() + " teams");
mTeamWriter.write(allTeams, 0L);
TbaLogger.i("Writing " + allEvents.size() + " events");
mEventWriter.write(allEvents, 0L);
TbaLogger.i("Writing " + allDistricts.size() + " districts");
mDistrictWriter.write(allDistricts, 0L);
SharedPreferences.Editor editor = mSharedPreferences.edit();
// Write TBA Status
editor.putString(TBAStatusController.STATUS_PREF_KEY, statusResponse.body().getJsonBlob());
editor.putInt(Constants.LAST_YEAR_KEY, statusResponse.body().getMaxSeason());
// Loop through all pages
for (int pageNum = 0; pageNum <= maxPageNum; pageNum++) {
editor.putBoolean(Database.ALL_TEAMS_LOADED_TO_DATABASE_FOR_PAGE + pageNum, true);
}
// Loop through all years
for (int year = Constants.FIRST_COMP_YEAR; year <= maxCompYear; year++) {
editor.putBoolean(Database.ALL_EVENTS_LOADED_TO_DATABASE_FOR_YEAR + year, true);
}
// Loop through years for districts
for (int year = Constants.FIRST_DISTRICT_YEAR; year <= maxCompYear; year++) {
editor.putBoolean(Database.ALL_DISTRICTS_LOADED_TO_DATABASE_FOR_YEAR + year, true);
}
editor.putInt(Constants.APP_VERSION_KEY, BuildConfig.VERSION_CODE);
editor.apply();
AnalyticsHelper.sendTimingUpdate(mApplicationContext, System.currentTimeMillis() - mStartTime, "load all data", "");
return Result.success(new LoadProgressInfo(LoadProgressInfo.STATE_FINISHED, mApplicationContext.getString(R.string.loading_finished)).toData());
} catch (RuntimeException ex) {
// This is bad, probably an error in the response from the server
TbaLogger.e("Error loading initial data", ex);
return onFailure(new LoadProgressInfo(LoadProgressInfo.STATE_ERROR, Utilities.exceptionStacktraceToString(ex)));
} catch (IOException | InterruptedException | ExecutionException e) {
/* Some sort of network error */
TbaLogger.e("Error loading initial data", e);
return onConnectionError();
}
}
use of com.thebluealliance.androidclient.models.ApiStatus in project the-blue-alliance-android by the-blue-alliance.
the class APIStatusDeserializer method deserialize.
@Override
public ApiStatus deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (!json.isJsonObject()) {
throw new JsonParseException("Data is not JsonObject");
}
JsonObject data = json.getAsJsonObject();
ApiStatus status = new ApiStatus();
JsonElement maxSeason = data.get(MAX_SEASON_TAG);
if (maxSeason == null || !maxSeason.isJsonPrimitive()) {
throw new JsonParseException("Max Season is not a primitive");
}
status.setMaxSeason(maxSeason.getAsInt());
JsonElement currentSeason = data.get(CURRENT_SEASON_TAG);
if (currentSeason == null || !currentSeason.isJsonPrimitive()) {
// Default to the current year if not set
int currentYear = Calendar.getInstance().get(Calendar.YEAR);
status.setCurrentSeason(currentYear);
} else {
status.setCurrentSeason(currentSeason.getAsInt());
}
// Ensure that maxSeason always is max(current, given max)
int maxSeasonCheck = Math.max(status.getMaxSeason(), status.getCurrentSeason());
status.setMaxSeason(maxSeasonCheck);
JsonElement fmsApiDown = data.get(FMS_API_DOWN_TAG);
if (fmsApiDown == null || !fmsApiDown.isJsonPrimitive()) {
throw new JsonParseException("Is Datafeed Down is not a primitive");
}
status.setFmsApiDown(fmsApiDown.getAsBoolean());
JsonElement downEvents = data.get(DOWN_EVENTS_TAG);
if (downEvents == null || !downEvents.isJsonArray()) {
throw new JsonParseException("Down Events is not an array");
}
List<String> downKeys = new ArrayList<>();
for (JsonElement eventKey : downEvents.getAsJsonArray()) {
if (!eventKey.isJsonPrimitive()) {
continue;
}
downKeys.add(eventKey.getAsString());
}
status.setDownEvents(downKeys);
JsonElement androidSpecific = data.get(ANDROID_SETTINGS_TAG);
if (androidSpecific == null || !androidSpecific.isJsonObject()) {
throw new JsonParseException("No Android specific settings");
}
JsonObject androidSettings = androidSpecific.getAsJsonObject();
JsonElement minAppVersion = androidSettings.get(MIN_APP_VERSION_TAG);
if (minAppVersion == null || !minAppVersion.isJsonPrimitive()) {
throw new JsonParseException("Min App Version not found");
}
status.setMinAppVersion(minAppVersion.getAsInt());
JsonElement latestAppVersion = androidSettings.get(LATEST_APP_VERSION_TAG);
if (latestAppVersion == null || !latestAppVersion.isJsonPrimitive()) {
throw new JsonParseException("Latest app version not found");
}
status.setLatestAppVersion(latestAppVersion.getAsInt());
JsonElement message = data.get(MESSAGE_DICT);
if (message != null && !message.isJsonNull() && message.isJsonObject()) {
JsonObject adminMessage = data.get(MESSAGE_DICT).getAsJsonObject();
JsonElement messageText = adminMessage.get(MESSAGE_TEXT);
JsonElement messageExpiration = adminMessage.get(MESSAGE_EXPIRATION);
if (messageText == null || messageText.isJsonNull() || messageExpiration == null || messageExpiration.isJsonNull()) {
throw new JsonParseException("Message requires text and expiration");
}
status.setHasMessage(true);
status.setMessageText(messageText.getAsString());
status.setMessageExpiration(new Date(messageExpiration.getAsLong() * MS_PER_SECOND).getTime());
} else {
status.setHasMessage(false);
}
JsonElement lastCacheClear = data.get(LAST_OKHTTP_CACHE_CLEAR);
if (lastCacheClear != null && !lastCacheClear.isJsonNull() && lastCacheClear.isJsonPrimitive()) {
JsonPrimitive lastCacheTime = lastCacheClear.getAsJsonPrimitive();
long lastTimestamp = lastCacheTime.getAsLong();
status.setLastOkHttpCacheClear(lastTimestamp);
} else {
status.setLastOkHttpCacheClear((long) -1);
}
status.setJsonBlob(json.toString());
return status;
}
Aggregations