package com.thebluealliance.androidclient.activities; import com.thebluealliance.androidclient.BuildConfig; import com.thebluealliance.androidclient.Constants; import com.thebluealliance.androidclient.R; import com.thebluealliance.androidclient.TBAAndroid; import com.thebluealliance.androidclient.TbaLogger; import com.thebluealliance.androidclient.adapters.FirstLaunchPagerAdapter; import com.thebluealliance.androidclient.background.LoadTBADataTaskFragment; import com.thebluealliance.androidclient.background.firstlaunch.LoadTBAData; import com.thebluealliance.androidclient.di.components.DaggerDatafeedComponent; import com.thebluealliance.androidclient.di.components.DatafeedComponent; import com.thebluealliance.androidclient.di.components.HasDatafeedComponent; import com.thebluealliance.androidclient.helpers.ConnectionDetector; import com.thebluealliance.androidclient.views.DisableSwipeViewPager; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; import android.preference.PreferenceManager; import android.support.v4.app.Fragment; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.text.Html; import android.view.View; import android.view.WindowManager; import android.widget.ProgressBar; import android.widget.TextView; import java.io.BufferedReader; import java.io.InputStreamReader; public class RedownloadActivity extends AppCompatActivity implements View.OnClickListener, LoadTBAData.LoadTBADataCallbacks, HasDatafeedComponent { private static final String CURRENT_LOADING_MESSAGE_KEY = "current_loading_message"; private static final String LOADING_COMPLETE = "loading_complete"; private static final String LOAD_FRAGMENT_TAG = "loadFragment"; private DatafeedComponent mComponent; private DisableSwipeViewPager viewPager; private TextView loadingMessage; private ProgressBar loadingProgressBar; private View continueToEndButton; private String currentLoadingMessage = ""; private LoadTBADataTaskFragment loadFragment; private boolean isDataFinishedLoading = false; private short[] mDataToLoad; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Extract relevant data from the intent Bundle extras = getIntent().getExtras(); if (extras != null && extras.containsKey(LoadTBAData.DATA_TO_LOAD)) { mDataToLoad = extras.getShortArray(LoadTBAData.DATA_TO_LOAD); } setContentView(R.layout.activity_redownload); viewPager = (DisableSwipeViewPager) findViewById(R.id.view_pager); viewPager.setSwipeEnabled(false); viewPager.setOffscreenPageLimit(10); viewPager.setAdapter(new FirstLaunchPagerAdapter(this)); loadingMessage = (TextView) findViewById(R.id.loading_message); loadingProgressBar = (ProgressBar) findViewById(R.id.loading_progress_bar); continueToEndButton = findViewById(R.id.continue_to_end); continueToEndButton.setOnClickListener(this); // Setup the changelog TextView changelog = (TextView) findViewById(R.id.changelog); try { BufferedReader br = new BufferedReader(new InputStreamReader(getResources().openRawResource(R.raw.changelog))); try { StringBuilder sb = new StringBuilder(); String line = br.readLine(); while (line != null) { sb.append(line); sb.append(System.getProperty("line.separator")); line = br.readLine(); } String everything = sb.toString(); changelog.setText(Html.fromHtml(everything)); } finally { br.close(); } } catch (Exception e) { e.printStackTrace(); changelog.setText("Error reading changelog file."); } // If the activity is being recreated after a config change, restore the message that was // being shown when the last activity was destroyed if (savedInstanceState != null) { if (savedInstanceState.containsKey(CURRENT_LOADING_MESSAGE_KEY)) { currentLoadingMessage = savedInstanceState.getString(CURRENT_LOADING_MESSAGE_KEY); loadingMessage.setText(currentLoadingMessage); } if (savedInstanceState.containsKey(LOADING_COMPLETE)) { isDataFinishedLoading = savedInstanceState.getBoolean(LOADING_COMPLETE); } } findViewById(R.id.welcome_next_page).setOnClickListener(this); findViewById(R.id.finish).setOnClickListener(this); loadFragment = (LoadTBADataTaskFragment) getSupportFragmentManager().findFragmentByTag(LOAD_FRAGMENT_TAG); if (loadFragment != null) { viewPager.setCurrentItem(1, false); LoadTBAData.LoadProgressInfo info = loadFragment.getLastProgressUpdate(); if (info != null) { if (!loadFragment.wasLastUpdateDelivered() && info.state != LoadTBAData.LoadProgressInfo.STATE_FINISHED) { onProgressUpdate(info); } } } /* If the data has already finished loading and we're being restored after an orientation change, hide the loading indicators and show the continue button */ if (isDataFinishedLoading) { loadingProgressBar.setVisibility(View.GONE); loadingMessage.setVisibility(View.GONE); continueToEndButton.setVisibility(View.VISIBLE); continueToEndButton.setAlpha(1.0f); } } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString(CURRENT_LOADING_MESSAGE_KEY, currentLoadingMessage); outState.putBoolean(LOADING_COMPLETE, isDataFinishedLoading); } @Override public void onClick(View view) { int id = view.getId(); switch (id) { case R.id.welcome_next_page: beginLoadingIfConnected(); break; case R.id.continue_to_end: viewPager.setCurrentItem(2); break; case R.id.finish: startActivity(new Intent(this, HomeActivity.class)); finish(); break; } } private void beginLoadingIfConnected() { if (ConnectionDetector.isConnectedToInternet(this)) { viewPager.setCurrentItem(1); beginLoading(); } else { AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this); alertDialogBuilder.setTitle(R.string.check_connection_title); alertDialogBuilder.setMessage(getString(R.string.warning_no_internet_connection)).setCancelable(false) .setPositiveButton(getString(R.string.retry), (dialog, id) -> { beginLoadingIfConnected(); dialog.dismiss(); }).setNegativeButton(getString(R.string.cancel), (dialog, id) -> { finish(); }); // Create alert dialog AlertDialog alertDialog = alertDialogBuilder.create(); alertDialog.show(); } } private void beginLoading() { Fragment f = new LoadTBADataTaskFragment(); Bundle args = new Bundle(); args.putShortArray(LoadTBAData.DATA_TO_LOAD, mDataToLoad); f.setArguments(args); f.setRetainInstance(true); getSupportFragmentManager().beginTransaction().add(f, LOAD_FRAGMENT_TAG).commit(); } private void onError(final String stacktrace) { PreferenceManager.getDefaultSharedPreferences(this).edit().putBoolean(Constants.ALL_DATA_LOADED_KEY, false).commit(); // Return to the first page viewPager.setCurrentItem(0); AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this); alertDialogBuilder.setTitle(getString(R.string.fatal_error)); alertDialogBuilder.setMessage(getString(R.string.fatal_error_message)).setCancelable(false).setPositiveButton(R.string.contact_developer, (dialog, id) -> { Intent emailIntent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts( "mailto", "contact@thebluealliance.com", null)); emailIntent.putExtra(Intent.EXTRA_SUBJECT, "FATAL ERROR"); emailIntent.putExtra(Intent.EXTRA_TEXT, "Version: " + BuildConfig.VERSION_NAME + "\nStacktrace:\n" + stacktrace); startActivity(Intent.createChooser(emailIntent, getString(R.string.send_email))); finish(); }).setNegativeButton(R.string.cancel, (dialog, id) -> { finish(); }); AlertDialog alertDialog = alertDialogBuilder.create(); try { alertDialog.show(); } catch (WindowManager.BadTokenException e) { // Activity is already gone. Just log the exception TbaLogger.e("Error loading data: " + stacktrace); e.printStackTrace(); } } private void onLoadFinished() { SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit(); editor.putBoolean(Constants.ALL_DATA_LOADED_KEY, true); editor.putInt(Constants.APP_VERSION_KEY, BuildConfig.VERSION_CODE).apply(); isDataFinishedLoading = true; loadingMessage.setText("Loading complete"); // After two seconds, fade out the message and spinner and fade in the "continue" button loadingMessage.postDelayed(() -> { ValueAnimator fadeOutAnimation = ValueAnimator.ofFloat(1.0f, 0.0f); fadeOutAnimation.addUpdateListener(animation -> { loadingMessage.setAlpha((float) animation.getAnimatedValue()); loadingProgressBar.setAlpha((float) animation.getAnimatedValue()); }); fadeOutAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { loadingMessage.setVisibility(View.GONE); loadingProgressBar.setVisibility(View.GONE); } }); fadeOutAnimation.setDuration(250); ValueAnimator fadeInAnimation = ValueAnimator.ofFloat(0.0f, 1.0f); fadeInAnimation.addUpdateListener(animation -> { continueToEndButton.setAlpha((float) animation.getAnimatedValue()); }); fadeInAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { continueToEndButton.setAlpha(0.0f); continueToEndButton.setVisibility(View.VISIBLE); } }); fadeInAnimation.setDuration(250); AnimatorSet animationSet = new AnimatorSet(); animationSet.play(fadeOutAnimation); animationSet.play(fadeInAnimation).after(fadeOutAnimation); animationSet.start(); }, 2000); } private void onConnectionLost() { // Scroll to first page viewPager.setCurrentItem(0); // Cancel task if (loadFragment != null) { loadFragment.cancelTask(); } // Show a warning AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this); alertDialogBuilder.setTitle(R.string.connection_lost_title); alertDialogBuilder.setMessage(getString(R.string.connection_lost)).setCancelable(false) .setPositiveButton(getString(R.string.ok), (dialog, id) -> { dialog.dismiss(); }); AlertDialog alertDialog = alertDialogBuilder.create(); if (!isFinishing()) { alertDialog.show(); } } private void onLoadingMessageUpdated(String message) { if (message == null) { return; } currentLoadingMessage = message; loadingMessage.setText(message); } public void onProgressUpdate(LoadTBAData.LoadProgressInfo info) { switch (info.state) { case LoadTBAData.LoadProgressInfo.STATE_LOADING: onLoadingMessageUpdated(info.message); break; case LoadTBAData.LoadProgressInfo.STATE_FINISHED: onLoadFinished(); break; case LoadTBAData.LoadProgressInfo.STATE_NO_CONNECTION: onConnectionLost(); break; case LoadTBAData.LoadProgressInfo.STATE_ERROR: onError(info.message); break; } } public DatafeedComponent getComponent() { if (mComponent == null) { TBAAndroid application = ((TBAAndroid) getApplication()); mComponent = DaggerDatafeedComponent.builder() .applicationComponent(application.getComponent()) .datafeedModule(application.getDatafeedModule()) .build(); } return mComponent; } }