package de.tum.in.tumcampusapp.activities; import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.res.TypedArray; import android.os.Bundle; import android.os.Environment; import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v4.content.LocalBroadcastManager; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.view.animation.AccelerateDecelerateInterpolator; import android.widget.ImageView; import android.widget.TextView; import java.io.File; import java.util.concurrent.atomic.AtomicBoolean; import de.tum.in.tumcampusapp.R; import de.tum.in.tumcampusapp.activities.wizard.WizNavExtrasActivity; import de.tum.in.tumcampusapp.activities.wizard.WizNavStartActivity; import de.tum.in.tumcampusapp.auxiliary.AuthenticationManager; import de.tum.in.tumcampusapp.auxiliary.Const; import de.tum.in.tumcampusapp.auxiliary.FileUtils; import de.tum.in.tumcampusapp.auxiliary.ImplicitCounter; import de.tum.in.tumcampusapp.auxiliary.Utils; import de.tum.in.tumcampusapp.managers.AbstractManager; import de.tum.in.tumcampusapp.managers.CardManager; import de.tum.in.tumcampusapp.services.DownloadService; import de.tum.in.tumcampusapp.services.StartSyncReceiver; import de.tum.in.tumcampusapp.trace.ExceptionHandler; import static android.Manifest.permission.ACCESS_COARSE_LOCATION; import static android.Manifest.permission.ACCESS_FINE_LOCATION; import static android.content.pm.PackageManager.PERMISSION_GRANTED; /** * Entrance point of the App. */ public class StartupActivity extends AppCompatActivity { private static final int REQUEST_LOCATION = 0; private static final String[] PERMISSIONS_LOCATION = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}; final AtomicBoolean initializationFinished = new AtomicBoolean(false); /** * Broadcast receiver gets notified if {@link de.tum.in.tumcampusapp.services.BackgroundService} * has prepared cards to be displayed */ private final BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(DownloadService.BROADCAST_NAME)) { //Only proceed to start the App, if initialization is finished if (initializationFinished.compareAndSet(false, true)) { return; } startApp(); } } }; private void init() { //Our own Custom exception handler ExceptionHandler.setup(getApplicationContext()); //Check that we have a private key setup in order to authenticate this device AuthenticationManager am = new AuthenticationManager(this); am.generatePrivateKey(null); //Upload stats ImplicitCounter.count(this); ImplicitCounter.submitCounter(this); // For compatibility reasons: big update happened with version 35 int prevVersion = Utils.getInternalSettingInt(this, Const.APP_VERSION, 35); // get current app version int currentVersion = Utils.getAppVersion(this); boolean newVersion = prevVersion < currentVersion; if (newVersion) { this.setupNewVersion(); Utils.setInternalSetting(this, Const.APP_VERSION, currentVersion); } // Also First run wizard for setup of id and token // Check the flag if user wants the wizard to open at startup boolean hideWizardOnStartup = Utils.getSettingBool(this, Const.HIDE_WIZARD_ON_STARTUP, false); String lrzId = Utils.getSetting(this, Const.LRZ_ID, ""); // If new version and LRZ ID is empty, start the full wizard if (!hideWizardOnStartup || (newVersion && lrzId.isEmpty())) { startActivity(new Intent(this, WizNavStartActivity.class)); finish(); return; } else if (newVersion) { Utils.setSetting(this, Const.BACKGROUND_MODE, true); Utils.setSetting(this, CardManager.SHOW_SUPPORT, true); Intent intent = new Intent(this, WizNavExtrasActivity.class); intent.putExtra(Const.TOKEN_IS_SETUP, true); startActivity(intent); finish(); return; } // On first setup show remark that loading could last longer than normally boolean isSetup = Utils.getInternalSettingBool(this, Const.EVERYTHING_SETUP, false); if (!isSetup) { this.runOnUiThread(new Runnable() { @Override public void run() { findViewById(R.id.startup_loading_first).setVisibility(View.VISIBLE); } }); } // Register receiver for background service IntentFilter filter = new IntentFilter(DownloadService.BROADCAST_NAME); LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter); // Start background service and ensure cards are set Intent i = new Intent(this, StartSyncReceiver.class); i.putExtra(Const.APP_LAUNCHES, true); sendBroadcast(i); //Request Permissions for Android 6.0 requestLocationPermission(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //Show a loading screen during boot setContentView(R.layout.activity_startup); new Thread(new Runnable() { @Override public void run() { init(); } }).start(); } @Override protected void onDestroy() { super.onDestroy(); LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver); } /** * Request the Location Permission */ private void requestLocationPermission() { //Check, if we already have permission if (ActivityCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PERMISSION_GRANTED) { //We already got the permissions, to proceed normally //Only proceed to start the App, if initialization is finished if (initializationFinished.compareAndSet(false, true)) { return; } startApp(); } else if (ActivityCompat.shouldShowRequestPermissionRationale(this, ACCESS_COARSE_LOCATION) || ActivityCompat.shouldShowRequestPermissionRationale(this, ACCESS_FINE_LOCATION)) { // Provide an additional rationale to the user if the permission was not granted // and the user would benefit from additional context for the use of the permission. // For example, if the request has been denied previously. // Display an AlertDialog with an explanation and a button to trigger the request. runOnUiThread(new Runnable() { @Override public void run() { new AlertDialog.Builder(StartupActivity.this).setMessage(getString(R.string.permission_location_explanation)).setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int id) { ActivityCompat.requestPermissions(StartupActivity.this, PERMISSIONS_LOCATION, REQUEST_LOCATION); } }).show(); } }); } else { ActivityCompat.requestPermissions(this, PERMISSIONS_LOCATION, REQUEST_LOCATION); } } /** * Callback when the user allowed or denied Permissions * We do not care, if we got the permission or not, since the LocationManager needs to handle * missing permissions anyway */ @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { //Only proceed to start the App, if initialization is finished if (initializationFinished.compareAndSet(false, true)) { return; } startApp(); } /** * Animates the TUM logo into place (left upper corner) and animates background up. * Afterwards {@link MainActivity} gets started */ private void startApp() { // Get views to be moved final View background = findViewById(R.id.startup_background); final ImageView tumLogo = (ImageView) findViewById(R.id.startup_tum_logo); final TextView loadingText = (TextView) findViewById(R.id.startup_loading); final TextView first = (TextView) findViewById(R.id.startup_loading_first); // Make some position calculations final int actionBarHeight = getActionBarHeight(); final float screenHeight = background.getHeight(); // Setup animation AnimatorSet set = new AnimatorSet(); set.playTogether( ObjectAnimator.ofFloat(background, "translationY", background.getTranslationX(), actionBarHeight - screenHeight), ObjectAnimator.ofFloat(tumLogo, "alpha", 1, 0, 0), ObjectAnimator.ofFloat(loadingText, "alpha", 1, 0, 0), ObjectAnimator.ofFloat(first, "alpha", 1, 0, 0), ObjectAnimator.ofFloat(tumLogo, "translationY", 0, -screenHeight / 3), ObjectAnimator.ofFloat(loadingText, "translationY", 0, -screenHeight / 3), ObjectAnimator.ofFloat(first, "translationY", 0, -screenHeight / 3) ); set.setInterpolator(new AccelerateDecelerateInterpolator()); set.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { // NOOP } @Override public void onAnimationEnd(Animator animation) { // Start the demo Activity if demo mode is set Intent intent = new Intent(StartupActivity.this, MainActivity.class); startActivity(intent); finish(); overridePendingTransition(R.anim.fadein, R.anim.fadeout); } @Override public void onAnimationCancel(Animator animation) { // NOOP } @Override public void onAnimationRepeat(Animator animation) { // NOOP } }); set.start(); } /** * Gets the height of the actionbar * * @return Actionbar height */ protected int getActionBarHeight() { int[] attrs = {R.attr.actionBarSize}; TypedArray values = obtainStyledAttributes(attrs); try { return values.getDimensionPixelSize(0, 0); } finally { values.recycle(); } } /** * Delete stuff from old version */ private void setupNewVersion() { // drop database AbstractManager.resetDb(this); // delete tumcampus directory File f = new File(Environment.getExternalStorageDirectory().getPath() + "/tumcampus"); FileUtils.deleteRecursive(f); // Load all on start Utils.setInternalSetting(this, Const.EVERYTHING_SETUP, false); // rename hide_wizzard_on_startup SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this); if (!sp.contains(Const.HIDE_WIZARD_ON_STARTUP)) { SharedPreferences.Editor e = sp.edit(); e.putBoolean(Const.HIDE_WIZARD_ON_STARTUP, sp.getBoolean("hide_wizzard_on_startup", false)); e.remove("hide_wizzard_on_startup"); e.apply(); } } }