itachi1706/SingBuses

View on GitHub
app/src/main/java/com/itachi1706/busarrivalsg/MainMenuActivity.java

Summary

Maintainability
A
40 mins
Test Coverage
package com.itachi1706.busarrivalsg;

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.app.ProgressDialog;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.firebase.analytics.FirebaseAnalytics;
import com.google.firebase.crashlytics.FirebaseCrashlytics;
import com.itachi1706.appupdater.AppUpdateInitializer;
import com.itachi1706.appupdater.object.CAAnalytics;
import com.itachi1706.appupdater.utils.AnalyticsHelper;
import com.itachi1706.busarrivalsg.AsyncTasks.GetAllBusStops;
import com.itachi1706.busarrivalsg.AsyncTasks.GetBusServicesFavouritesRecycler;
import com.itachi1706.busarrivalsg.Database.BusStopsDB;
import com.itachi1706.busarrivalsg.RecyclerViews.FavouritesRecyclerAdapter;
import com.itachi1706.busarrivalsg.Services.BusStorage;
import com.itachi1706.busarrivalsg.objects.BusServices;
import com.itachi1706.busarrivalsg.util.LogInitializer;
import com.itachi1706.busarrivalsg.util.StaticVariables;
import com.itachi1706.busarrivalsg.util.SwipeFavouriteCallback;
import com.itachi1706.busarrivalsg.util.SwipeMoveFavouriteCallback;
import com.itachi1706.helperlib.helpers.ConnectivityHelper;
import com.itachi1706.helperlib.helpers.LogHelper;

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

public class MainMenuActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {

    static { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); }

    //Android Stuff
    private TextView syncState;
    private FloatingActionButton fab;
    private FavouritesRecyclerAdapter adapter;
    private SwipeRefreshLayout swipeToRefresh;

    private SharedPreferences sp;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(!BuildConfig.DEBUG);
        LogInitializer.initLogger();
        setContentView(R.layout.activity_main_menu_recycler);

        fab = findViewById(R.id.add_fab);
        RecyclerView favouritesList = findViewById(R.id.rvFav);
        syncState = findViewById(R.id.firebase_sync_status);

        // Obtain the FirebaseAnalytics instance.
        FirebaseAnalytics mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);
        AnalyticsHelper helper = new AnalyticsHelper(this, true);
        @SuppressLint("WrongThread") CAAnalytics analytics = helper.getData(BuildConfig.DEBUG);
        setAnalyticsData(analytics != null, mFirebaseAnalytics, analytics); // Update Firebase User Properties
        mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.APP_OPEN, null);

        if (favouritesList != null) favouritesList.setHasFixedSize(true);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(RecyclerView.VERTICAL);
        favouritesList.setLayoutManager(linearLayoutManager);
        favouritesList.setItemAnimator(new DefaultItemAnimator());

        swipeToRefresh = findViewById(R.id.refresh_favourites);
        if (swipeToRefresh != null) {
            swipeToRefresh.setOnRefreshListener(this);
            swipeToRefresh.setColorSchemeResources(
                    R.color.refresh_progress_1,
                    R.color.refresh_progress_2,
                    R.color.refresh_progress_3,
                    R.color.refresh_progress_4);
        }

        sp = PreferenceManager.getDefaultSharedPreferences(this.getApplicationContext());
        sp.edit().putBoolean("cepas_dark_theme", true).apply();
        adapter = new FavouritesRecyclerAdapter(new ArrayList<>(), this, StaticVariables.INSTANCE.useServerTime(sp));
        favouritesList.setAdapter(adapter);

        ItemTouchHelper moveAdapter = new ItemTouchHelper(new SwipeMoveFavouriteCallback(this, new SwipeFavouriteCallback.ISwipeCallback() {
            @Override public boolean getFavouriteState(int position) { return true; } // Always favourited
            @Override public boolean moveFavourite(int oldPosition, int newPosition) { return adapter.moveItem(oldPosition, newPosition); }
            @Override public boolean toggleFavourite(int position) { return adapter.removeFavourite(position); }
        }));
        moveAdapter.attachToRecyclerView(favouritesList);

        LogHelper.d("MainMenu", "Checking for app updates");
        new AppUpdateInitializer(this, sp, R.drawable.notification_icon, StaticVariables.BASE_SERVER_URL, true).setOnlyOnWifiCheck(true).checkForUpdate();
        LogHelper.d("MainMenu", "onCreate complete");

        // Create the Firebase Notification Channel
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) createFirebaseNotifChannel();
    }

    @Override
    public void onResume(){
        super.onResume();

        fab.setOnClickListener(v -> startActivity(new Intent(MainMenuActivity.this, BusStopsTabbedActivity.class)));
        fab.setOnLongClickListener(v -> {
            Toast.makeText(MainMenuActivity.this, R.string.fab_hint_main_menu, Toast.LENGTH_SHORT).show();
            return true;
        });

        //Android Stuff now again :D
        checkIfDatabaseUpdated();

        //Update Favourites
        swipeToRefresh.setRefreshing(true);
        updateFavourites();

        /*switch (sp.getString("companionDevice", "none")) {
            case "none":
            default:  break;
        }*/

        syncState.setClickable(true);
        syncState.setOnClickListener(v -> {
            // TODO: Start Activity for result
            startActivity(new Intent(getApplicationContext(), FirebaseLoginActivity.class));
        });

        invalidateOptionsMenu();
    }

    private void setAnalyticsData(boolean enabled, FirebaseAnalytics firebaseAnalytics, CAAnalytics analytics) {
        firebaseAnalytics.setUserProperty("debug_mode", (enabled) ? analytics.isDebug() + "" : null);
        firebaseAnalytics.setUserProperty("device_manufacturer", (enabled) ? analytics.getdManufacturer() : null);
        firebaseAnalytics.setUserProperty("device_codename", (enabled) ? analytics.getdCodename() : null);
        firebaseAnalytics.setUserProperty("device_fingerprint", (enabled) ? analytics.getdFingerprint() : null);
        firebaseAnalytics.setUserProperty("device_cpu_abi", (enabled) ? analytics.getdCPU() : null);
        firebaseAnalytics.setUserProperty("device_tags", (enabled) ? analytics.getdTags() : null);
        firebaseAnalytics.setUserProperty("app_version_code", (enabled) ? Long.toString(analytics.getAppVerCode()) : null);
        firebaseAnalytics.setUserProperty("android_sec_patch", (enabled) ? analytics.getSdkPatch() : null);
        firebaseAnalytics.setUserProperty("AndroidOS", (enabled) ? Integer.toString(analytics.getSdkver()) : null);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main_menu, menu);
        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);
        menu.findItem(R.id.ntu_tracker).setVisible(sp.getBoolean("showntushuttle", false));

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == R.id.action_settings) startActivity(new Intent(this, MainSettings.class));
        else if (id == R.id.view_all_stops) startActivity(new Intent(this, ListAllBusStopsActivity.class));
        else if (id == R.id.action_refresh) {
            swipeToRefresh.setRefreshing(true);
            updateFavourites();
        } else if (id == R.id.ntu_tracker) startActivity(new Intent(this, NTUBusActivity.class));
        else if (id == R.id.scan_cepas) startActivity(new Intent(this, CEPASScanActivity.class));
        else return super.onOptionsItemSelected(item);

        return true;
    }

    private void updateFavourites(){
        final String TAG = "FAVOURITES";
        //Populate favourites from favourites list
        LogHelper.d(TAG, "Favourites Pref: " + sp.getString("stored", "wot"));

        if (BusStorage.hasFavourites(sp)) {
            //Go ahead with loading and getting data
            LogHelper.d(TAG, "Has Favourites. Processing");
            StaticVariables.INSTANCE.setFavouritesList(BusStorage.getStoredBuses(sp));
            adapter.updateAdapter(StaticVariables.INSTANCE.getFavouritesList(), null);
            adapter.notifyDataSetChanged();

            LogHelper.d(TAG, "Finished Processing, retrieving estimated arrival data now");
            new GetBusServicesFavouritesRecycler(this, adapter).executeOnExecutor(StaticVariables.INSTANCE.getFavouritesList().toArray(new BusServices[0]));
            LogHelper.d(TAG, "Finished creating AsyncTasks to retrieve estimated arrival data");
        }

        if (swipeToRefresh.isRefreshing()){
            swipeToRefresh.setRefreshing(false);
        }
    }

    private void checkIfDatabaseUpdated(){
        long busDBLastUpdate = sp.getLong("busDBTimeUpdated", -1);
        boolean busDBUpdate = false;
        if (busDBLastUpdate != -1){
            long day = TimeUnit.MILLISECONDS.toDays(System.currentTimeMillis() - busDBLastUpdate);
            LogHelper.d("INIT", "Bus DB Last Update: " + day);
            if (day > 30)
                busDBUpdate = true;
        }

        // Check upgrade
        final String DBTAG = "DB UPGRADE";
        int dbver = sp.getInt("busDBVerCheck", 0);
        LogHelper.d(DBTAG, "Current DB Version: " + dbver);
        switch (dbver) {
            case 0:
            case 1: LogHelper.i(DBTAG, "Upgrading to V2 API DB"); busDBUpdate = true; sp.edit().putInt("busDBVerCheck", 2).apply(); break;
            case 2: LogHelper.i(DBTAG, "Upgrading to DB with Bus Services"); busDBUpdate = true; sp.edit().putInt("busDBVerCheck", 3).apply(); break;
        }

        //Main Database
        if (!sp.getBoolean("busDBLoaded", false) || busDBUpdate){
            //First Boot, populate database
            if (!ConnectivityHelper.hasInternetConnection(getApplicationContext())) {
                networkUnavailable(getString(R.string.database_name_bus));
            } else {
                LogHelper.d("INIT", "Initializing Bus Stop Database");
                ProgressDialog dialog = new ProgressDialog(this);
                dialog.setTitle(getString(R.string.database_name_bus));
                dialog.setMessage(getString(R.string.dialog_message_retrieve_data_from_server));
                dialog.setCancelable(false);
                dialog.setIndeterminate(true);
                dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

                BusStopsDB db = new BusStopsDB(this);
                db.dropAndRebuildDB();
                sp.edit().putBoolean("busDBLoaded", false).apply();
                dialog.show();

                new GetAllBusStops(dialog, db, this, sp).executeOnExecutor(0);
            }
        } else {
            //Legacy Check
            if (sp.getLong("busDBTimeUpdated", -1) == -1){
                sp.edit().putLong("busDBTimeUpdated", System.currentTimeMillis()).apply();
            }
        }
    }

    private void networkUnavailable(String reason){
        new AlertDialog.Builder(this).setTitle(R.string.dialog_title_no_internet)
                .setMessage(getString(R.string.dialog_message_no_internet, reason)).setCancelable(false)
                .setNeutralButton(R.string.dialog_action_neutral_override, null)
                .setPositiveButton(android.R.string.ok, (dialog, which) -> MainMenuActivity.this.finish()).show();
    }

    @Override
    public void onRefresh() {
        updateFavourites();
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private void createFirebaseNotifChannel() {
        NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        if (notificationManager == null) return;
        NotificationChannel notificationChannel = new NotificationChannel("firebase-msg", "Server Alerts (FB)", NotificationManager.IMPORTANCE_LOW);
        notificationChannel.enableLights(true);
        notificationChannel.setLightColor(Color.RED);
        notificationChannel.enableVibration(true);
        notificationChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
        notificationChannel.setGroup("server-msg");

        NotificationChannelGroup notificationChannelGroup = new NotificationChannelGroup("server-msg", "Server Messages");
        notificationManager.createNotificationChannelGroup(notificationChannelGroup);
        notificationManager.createNotificationChannel(notificationChannel);
    }
}