de.stadtrallye.rallyesoft.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for de.stadtrallye.rallyesoft.MainActivity.java

Source

/*
 * Copyright (c) 2014 Jakob Wenzel, Ramon Wirsch.
 *
 * This file is part of RallyeSoft.
 *
 * RallyeSoft is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * RallyeSoft is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with RallyeSoft. If not, see <http://www.gnu.org/licenses/>.
 */

package de.stadtrallye.rallyesoft;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.graphics.drawable.TransitionDrawable;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.Window;
import android.widget.Toast;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.zxing.integration.android.IntentIntegrator;

import de.stadtrallye.rallyesoft.common.Std;
import de.stadtrallye.rallyesoft.model.IServer;
import de.stadtrallye.rallyesoft.model.Server;
import de.stadtrallye.rallyesoft.model.pictures.IPictureManager;
import de.stadtrallye.rallyesoft.model.pictures.PictureManager;
import de.stadtrallye.rallyesoft.net.NfcCallback;
import de.stadtrallye.rallyesoft.storage.Storage;
import de.stadtrallye.rallyesoft.uimodel.IPictureHandler;
import de.stadtrallye.rallyesoft.uimodel.IProgressUI;
import de.stadtrallye.rallyesoft.uimodel.ITabActivity;
import de.stadtrallye.rallyesoft.uimodel.RallyeTabManager;
import de.stadtrallye.rallyesoft.uimodel.TabManager;
import de.stadtrallye.rallyesoft.util.converters.Serialization;
import de.wirsch.gcm.GcmHelper;

import static de.stadtrallye.rallyesoft.uimodel.Util.getDefaultMapOptions;

public class MainActivity extends ActionBarActivity implements IProgressUI, ITabActivity, IPictureHandler,
        IServer.ICurrentServerListener, SharedPreferences.OnSharedPreferenceChangeListener {

    private static final String THIS = MainActivity.class.getSimpleName();

    private android.support.v7.app.ActionBar actionBar;

    private boolean progressCircle = false;

    private Integer lastTab;

    private RallyeTabManager tabManager;
    private IPictureManager.IPicture picture = null;
    private TransitionDrawable logo;
    private Server server;
    private boolean hasServerChanged = false;
    private boolean pref_autoUpload;
    private SharedPreferences pref;
    private PictureManager pictureManager;
    private boolean running = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //      android.support.v4.app.FragmentManager.enableDebugLogging(true);

        // Layout, Title, ProgressCircle etc.
        supportRequestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

        setTitle(R.string.app_name);
        setContentView(R.layout.main);

        DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

        actionBar = getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.setDisplayShowTitleEnabled(true);
        logo = (TransitionDrawable) getResources().getDrawable(R.drawable.transition_logo);
        actionBar.setIcon(logo);

        // Check if Google Play Services is working
        int errorCode;
        if ((errorCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this)) != ConnectionResult.SUCCESS) {
            GooglePlayServicesUtil.getErrorDialog(errorCode, this, 0).show();
            finish();
        }

        // Google Cloud Messaging Init
        //PushInit.ensureRegistration(this);
        GcmHelper.ensureRegistration(getApplicationContext());

        Storage.aquireStorage(getApplicationContext(), this);
        pref = Storage.getAppPreferences();
        pref.registerOnSharedPreferenceChangeListener(this);
        pref_autoUpload = pref.getBoolean("auto_upload", true);
        pictureManager = Storage.getPictureManager();

        // Initialize Model
        Server.addListener(this);
        server = Server.getCurrentServer();

        // Manages all fragments that will be displayed as Tabs in this activity
        tabManager = new RallyeTabManager(this, server, drawerLayout);

        tabManager.setArguments(RallyeTabManager.TAB_MAP, getDefaultMapOptions(null));// this map is currently not used anyway, so for the time being we always do lateInitialization
        // Recover Last State
        tabManager.restoreState(savedInstanceState);

        //      forceOverflowMenu(); // Force devices with hardware menu key to display the modern overflow menu

        // Initialize NFC ability
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            initNFC();
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        Log.i(THIS, "Receiving Intent");

        if (intent != null && intent.hasExtra(Std.TAB)) {
            Log.i(THIS, "Receiving Intent with Tab");
            if (intent.getStringExtra(Std.TAB).equals(Std.CHATROOM)) {
                int chatroom = intent.getIntExtra(Std.CHATROOM, -1);
                int chatID = intent.getIntExtra(Std.CHAT_ID, -1);
                Bundle b = new Bundle();
                b.putInt(Std.CHATROOM, chatroom);
                b.putInt(Std.CHAT_ID, chatID);
                tabManager.setArguments(RallyeTabManager.TAB_CHAT, b);
                tabManager.switchToTab(RallyeTabManager.TAB_CHAT);
            }
        }
    }

    @TargetApi(14)
    private void initNFC() {
        NfcAdapter nfc = NfcAdapter.getDefaultAdapter(this);
        if (nfc != null) {
            nfc.setNdefPushMessageCallback(new NfcCallback(server), this);
        }
    }

    /**
     * Force the Menu SoftButton even if hardware button present (only for 4.0 and greater)
     */
    //   private void forceOverflowMenu() {
    //      try {
    //         ViewConfiguration config = ViewConfiguration.get(this);
    //         Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");
    //         if (menuKeyField != null) {
    //            menuKeyField.setAccessible(true);
    //            menuKeyField.setBoolean(config, false);
    //         }
    //      } catch (Exception e) {
    //         e.printStackTrace();
    //      }
    //   }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);

        setProgressBarIndeterminateVisibility(false);
        tabManager.onPostCreate();
    }

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

        if (hasServerChanged) {
            updateServerState();
        }

        if (isLoggedIn())
            logo.startTransition(0);
        else
            logo.resetTransition();

        tabManager.showTab();

        running = true;
    }

    private void updateServerState() {
        tabManager.setServer(server);

        //      onConnectionStateChange(model.getConnectionState());
        hasServerChanged = false;
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        tabManager.saveState(outState);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.activity_main, menu);

        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // If the nav drawer is open, hide action items related to the content view
        boolean drawerOpen = tabManager.isMenuOpen();
        boolean loggedIn = isLoggedIn();

        menu.findItem(R.id.menu_logout).setVisible(!drawerOpen && loggedIn);
        menu.findItem(R.id.menu_share_barcode).setVisible(!drawerOpen).setEnabled(loggedIn);
        //      menu.findItem(R.id.menu_reconnect).setVisible(!drawerOpen && model.canReconnect());

        return true;
    }

    private boolean isLoggedIn() {
        return server != null && server.hasUserAuth();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            return tabManager.onAndroidHome(item);
        case R.id.menu_login:
            Intent intent = new Intent(this, ConnectionAssistantActivity.class);
            lastTab = tabManager.getCurrentTab();
            //            tabManager.switchToTab(RallyeTabManager.TAB_WAIT_FOR_MODEL);
            startActivityForResult(intent, ConnectionAssistantActivity.REQUEST_CODE);
            break;
        case R.id.menu_logout:
            new AlertDialog.Builder(this).setTitle(R.string.logout).setMessage(R.string.are_you_sure)
                    .setCancelable(true).setNegativeButton(android.R.string.cancel, null)
                    .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            server.logout();
                        }
                    }).create().show();
            server.tryLogout();
            break;
        case R.id.menu_upload_overview:
            intent = new Intent(this, UploadOverviewActivity.class);
            startActivity(intent);
            break;
        case R.id.menu_share_barcode:
            IntentIntegrator zx = new IntentIntegrator(this);
            ObjectMapper mapper = Serialization.getJsonInstance();
            try {
                zx.shareText(mapper.writeValueAsString(server.exportLogin()));
            } catch (JsonProcessingException e) {
                Log.e(THIS, "Could not serialize exported Login", e);
                Toast.makeText(this, R.string.export_barcode_error, Toast.LENGTH_SHORT).show();
            }
            break;
        //         case R.id.menu_reconnect: //there is no more temporary offline, we cannot know if push messages will reach us
        //            model.reconnect();
        //            break;
        case R.id.menu_settings:
            intent = new Intent(this, SettingsActivity.class);
            startActivity(intent);
            break;
        default:
            return false;
        }
        return true;
    }

    @Override
    public void onBackPressed() {
        if (!tabManager.onBackPressed())
            super.onBackPressed();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        tabManager.onConfigurationChanged(newConfig);
    }

    @Override
    protected void onPause() {
        //      model.saveState();// model should always save important data immediately

        super.onPause();
    }

    @Override
    protected void onStop() {
        running = false;

        super.onStop();
    }

    /**git status
     * 
     * Passed-Through to Model (if not kept for ConfigurationChange) and GCMRegistrar
     */
    @Override
    protected void onDestroy() {
        Log.i(THIS, "Destroying...");

        server = null;
        Server.removeListener(this);

        Storage.releaseStorage(this);
        pref.unregisterOnSharedPreferenceChangeListener(this);

        super.onDestroy();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        // Android changes the upper 16 bits of a request generated from a fragment, so that
        // it can deliver the result back to the fragment.
        // We want to handle the result here, so we only look at the lower bits
        if ((requestCode & 0xffff) == ConnectionAssistantActivity.REQUEST_CODE) {
            Log.v(THIS, "ConnectionAssistant finished with " + resultCode);
            if (resultCode == Activity.RESULT_OK) {
                Log.i(THIS, "ConnectionAssistant has connected to a new Server");

                //            model.removeListener(this);
                //            model = Model.getInstance(getApplicationContext());
                //            model.addListener(this);
                //            updateServerState();
            }
            findViewById(R.id.content_frame).post(new Runnable() {
                @Override
                public void run() {
                    tabManager.switchToTab(RallyeTabManager.TAB_OVERVIEW);
                }
            });
        } else if ((requestCode & 0xffff) == SubmitNewSolutionActivity.REQUEST_CODE) {
            Log.i(THIS, "Task Submission");
            if (resultCode == Activity.RESULT_OK) {
                //            Log.i(THIS, "Submitted: "+ data.getExtras());
            }
        } else {
            Log.i(THIS,
                    "Received ActivityResult: Req: " + requestCode + ", res: " + resultCode + ", intent: " + data);
            picture = pictureManager.onActivityResult(requestCode, resultCode, data);

            /*if (tabManager.getCurrentTab() == RallyeTabManager.TAB_CHAT && picture != null) {
               IPictureTakenListener chatTab = (IPictureTakenListener) tabManager.getActiveFragment();
               chatTab.pictureTaken(picture);
            }*/

            //         ImageLoader.getInstance().handleSlowNetwork();
        }

        super.onActivityResult(requestCode, resultCode, data);//TODO: this call is redundant, it only distributes teh result to the originating fragment, (we handle this ourselves)
    }

    /**
     * IModelListener
     */
    //   @Override
    //   public void onConnectionStateChange(ConnectionState newState) {
    //      switch (newState) {//TODO: Add "No Network" status to UI (requires Model to have a "No Network" status) [Model has NoNetwork status, but never uses it] [Listen to Network Status Changes]
    //         case Disconnecting:
    //         case Connecting:
    //            activateProgressAnimation();
    //            break;
    //         case Disconnected:
    //         case Connected:
    //         default:
    //            deactivateProgressAnimation();
    //      }
    //
    //      tabManager.conditionChange();
    //
    //      switch (newState) {
    //         case Connected:
    ////            d.setColorFilter(null);
    ////            actionBar.setIcon(d);
    //            logo.startTransition(500);
    //            break;
    //         default:
    ////            d.setColorFilter(0x66666666, Mode.MULTIPLY);
    ////            actionBar.setIcon(d);
    //            logo.reverseTransition(500);
    //      }
    //   }

    //   @Override
    //   public void onConnectionFailed(Exception e) {
    //      Toast.makeText(this, getString(R.string.connection_failure) +": "+ e.toString(), Toast.LENGTH_LONG).show();
    //   }

    //   @Override
    //   public void onMapConfigChange() {
    //      tabManager.setArguments(RallyeTabManager.TAB_MAP, getDefaultMapOptions(server));
    //   }

    /**
     * ITabActivity
     */
    @Override
    public TabManager getTabManager() {
        return tabManager;
    }

    /**
     * IProgressUI
     */
    @Override
    public void activateProgressAnimation() {
        progressCircle = true;
        setProgressBarIndeterminateVisibility(true);
    }

    /**
     * IProgressUI
     */
    @Override
    public void deactivateProgressAnimation() {
        if (progressCircle) {
            progressCircle = false;
            setProgressBarIndeterminateVisibility(false);
        }
    }

    @Override //TODO remove / revise
    public IPictureManager.IPicture getPicture() {
        return picture;
    }

    @Override
    public boolean hasPicture() {
        return picture != null;
    }

    @Override
    public void discardPicture() {
        picture = null;
    }

    @Override
    public void onNewCurrentServer(Server server) {
        this.server = server;

        if (isLoggedIn()) {
            logo.startTransition(500);
        } else {
            logo.reverseTransition(500);
        }

        if (running) {
            tabManager.setServer(server);
        } else {
            this.hasServerChanged = true;
        }
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        if (key.equals("auto_upload")) {
            pref_autoUpload = sharedPreferences.getBoolean("auto_upload", true);//TODO prettier
        }
    }
}