org.catrobat.catroid.ui.MainMenuActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.catrobat.catroid.ui.MainMenuActivity.java

Source

/*
 * Catroid: An on-device visual programming system for Android devices
 * Copyright (C) 2010-2016 The Catrobat Team
 * (<http://developer.catrobat.org/credits>)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * An additional term exception under section 7 of the GNU Affero
 * General Public License, version 3, is available at
 * http://developer.catrobat.org/license_additional_term
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.catrobat.catroid.ui;

import android.app.ActionBar;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.AssetManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.content.ContextCompat;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.text.style.TextAppearanceSpan;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;

import com.facebook.AccessToken;
import com.facebook.CallbackManager;
import com.facebook.FacebookCallback;
import com.facebook.FacebookException;
import com.facebook.FacebookSdk;
import com.facebook.appevents.AppEventsLogger;
import com.facebook.login.LoginManager;
import com.facebook.login.LoginResult;

import org.catrobat.catroid.BuildConfig;
import org.catrobat.catroid.ProjectManager;
import org.catrobat.catroid.R;
import org.catrobat.catroid.common.Constants;
import org.catrobat.catroid.content.Project;
import org.catrobat.catroid.formulaeditor.SensorHandler;
import org.catrobat.catroid.io.LoadProjectTask;
import org.catrobat.catroid.io.LoadProjectTask.OnLoadProjectCompleteListener;
import org.catrobat.catroid.io.StorageHandler;
import org.catrobat.catroid.stage.PreStageActivity;
import org.catrobat.catroid.stage.StageActivity;
import org.catrobat.catroid.transfers.GetFacebookUserInfoTask;
import org.catrobat.catroid.ui.dialogs.NewProjectDialog;
import org.catrobat.catroid.ui.dialogs.SignInDialog;
import org.catrobat.catroid.utils.DownloadUtil;
import org.catrobat.catroid.utils.FlashUtil;
import org.catrobat.catroid.utils.StatusBarNotificationManager;
import org.catrobat.catroid.utils.ToastUtil;
import org.catrobat.catroid.utils.UtilFile;
import org.catrobat.catroid.utils.UtilUi;
import org.catrobat.catroid.utils.UtilZip;
import org.catrobat.catroid.utils.Utils;
import org.rauschig.jarchivelib.Archiver;
import org.rauschig.jarchivelib.ArchiverFactory;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Locale;
import java.util.concurrent.locks.Lock;

public class MainMenuActivity extends BaseActivity implements OnLoadProjectCompleteListener {

    private static final String TAG = ProjectActivity.class.getSimpleName();

    private static final String START_PROJECT = BuildConfig.START_PROJECT;
    private static final Boolean STANDALONE_MODE = BuildConfig.FEATURE_APK_GENERATOR_ENABLED;
    private static final String ZIP_FILE_NAME = START_PROJECT + ".zip";
    private static final String STANDALONE_PROJECT_NAME = BuildConfig.PROJECT_NAME;

    public static final String SHARED_PREFERENCES_SHOW_BROWSER_WARNING = "shared_preferences_browser_warning";
    public static final int REQUEST_CODE_GOOGLE_PLUS_SIGNIN = 100;

    private static final String TYPE_FILE = "file";
    private static final String TYPE_HTTP = "http";

    private Lock viewSwitchLock = new ViewSwitchLock();
    private CallbackManager callbackManager;
    private SignInDialog signInDialog;
    private Menu mainMenu;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (!Utils.checkForExternalStorageAvailableAndDisplayErrorIfNot(this)) {
            return;
        }
        initializeFacebookSdk();

        PreferenceManager.setDefaultValues(this, R.xml.preferences, true);
        UtilUi.updateScreenWidthAndHeight(this);

        if (STANDALONE_MODE) {
            /*requestWindowFeature(Window.FEATURE_NO_TITLE);
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
               WindowManager.LayoutParams.FLAG_FULLSCREEN);*/
            getActionBar().hide();
            setContentView(R.layout.activity_main_menu_splashscreen);
            unzipProgram();
        } else {
            setContentView(R.layout.activity_main_menu);

            final ActionBar actionBar = getActionBar();
            actionBar.setDisplayUseLogoEnabled(true);
            actionBar.setHomeButtonEnabled(false);
            actionBar.setDisplayHomeAsUpEnabled(false);
            actionBar.setTitle(R.string.app_name);

            findViewById(R.id.main_menu_button_continue).setEnabled(false);

            // Load external project from URL or local file system.
            Uri loadExternalProjectUri = getIntent().getData();
            getIntent().setData(null);

            if (loadExternalProjectUri != null) {
                loadProgramFromExternalSource(loadExternalProjectUri);
            }
        }
    }

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

        if (!Utils.checkForExternalStorageAvailableAndDisplayErrorIfNot(this)) {
            return;
        }

        AppEventsLogger.activateApp(this);

        SettingsActivity.setLegoMindstormsNXTSensorChooserEnabled(this, false);

        SettingsActivity.setDroneChooserEnabled(this, false);

        findViewById(R.id.progress_circle).setVisibility(View.VISIBLE);
        final Activity activity = this;
        Runnable r = new Runnable() {
            @Override
            public void run() {
                UtilFile.createStandardProjectIfRootDirectoryIsEmpty(activity);
                activity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        finishOnCreateAfterRunnable();
                    }
                });
            }
        };
        (new Thread(r)).start();
    }

    @Override
    public void onPause() {
        super.onPause();
        if (!Utils.externalStorageAvailable()) {
            return;
        }

        AppEventsLogger.deactivateApp(this);

        Project currentProject = ProjectManager.getInstance().getCurrentProject();
        if (currentProject != null) {
            ProjectManager.getInstance().saveProject(getApplicationContext());
            Utils.saveToPreferences(this, Constants.PREF_PROJECTNAME_KEY, currentProject.getName());
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main_menu, menu);
        mainMenu = menu;

        final MenuItem scratchConverterMenuItem = menu.findItem(R.id.menu_scratch_converter);
        if (scratchConverterMenuItem != null) {
            final String title = getString(R.string.main_menu_scratch_converter);
            final String beta = getString(R.string.beta).toUpperCase(Locale.getDefault());
            final SpannableString spanTitle = new SpannableString(title + " " + beta);
            final int begin = title.length() + 1;
            final int end = begin + beta.length();
            final int betaLabelColor = ContextCompat.getColor(this, R.color.beta_label_color);
            spanTitle.setSpan(new ForegroundColorSpan(betaLabelColor), begin, end,
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            scratchConverterMenuItem.setTitle(spanTitle);
        }
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        MenuItem logout = mainMenu.findItem(R.id.menu_logout);
        MenuItem login = mainMenu.findItem(R.id.menu_login);
        logout.setVisible(Utils.isUserLoggedIn(this));
        login.setVisible(!Utils.isUserLoggedIn(this));

        if (!BuildConfig.FEATURE_SCRATCH_CONVERTER_ENABLED) {
            mainMenu.removeItem(R.id.menu_scratch_converter);
        }
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void finishOnCreateAfterRunnable() {
        if (!STANDALONE_MODE) {
            findViewById(R.id.progress_circle).setVisibility(View.GONE);
            findViewById(R.id.main_menu_buttons_container).setVisibility(View.VISIBLE);
        }
        PreStageActivity.shutdownPersistentResources();
        if (!STANDALONE_MODE) {
            setMainMenuButtonContinueText();
            findViewById(R.id.main_menu_button_continue).setEnabled(true);
        } else {
            FlashUtil.initializeFlash();
        }
        String projectName = getIntent().getStringExtra(StatusBarNotificationManager.EXTRA_PROJECT_NAME);
        if (projectName != null) {
            loadProjectInBackground(projectName);
        }
        getIntent().removeExtra(StatusBarNotificationManager.EXTRA_PROJECT_NAME);

        if (ProjectManager.getInstance().getHandleNewSceneFromScriptActivity()) {
            Intent intent = new Intent(this, ProjectActivity.class);
            intent.putExtra(ProjectActivity.EXTRA_FRAGMENT_POSITION, ProjectActivity.FRAGMENT_SCENES);
            intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
            startActivity(intent);
        }
    }

    // needed because of android:onClick in activity_main_menu.xml
    public void handleContinueButton(View view) {
        handleContinueButton();
    }

    public void handleContinueButton() {
        LoadProjectTask loadProjectTask = new LoadProjectTask(this, Utils.getCurrentProjectName(this), true, true);
        loadProjectTask.setOnLoadProjectCompleteListener(this);
        findViewById(R.id.main_menu_buttons_container).setVisibility(View.GONE);
        loadProjectTask.execute();
    }

    private void loadProjectInBackground(String projectName) {
        if (!viewSwitchLock.tryLock()) {
            return;
        }
        LoadProjectTask loadProjectTask = new LoadProjectTask(this, projectName, true, true);
        loadProjectTask.setOnLoadProjectCompleteListener(this);
        findViewById(R.id.main_menu_buttons_container).setVisibility(View.GONE);
        loadProjectTask.execute();
    }

    @Override
    public void onLoadProjectSuccess(boolean startProjectActivity) {
        if (STANDALONE_MODE) {
            Log.d("STANDALONE", "onLoadProjectSucess -> startStage");
            startStageProject();
        } else if (ProjectManager.getInstance().getCurrentProject() != null && startProjectActivity) {
            Intent intent = new Intent(MainMenuActivity.this, ProjectActivity.class);
            startActivity(intent);
        }
    }

    public void handleNewButton(View view) {
        if (!viewSwitchLock.tryLock()) {
            return;
        }
        NewProjectDialog dialog = new NewProjectDialog();
        dialog.show(getFragmentManager(), NewProjectDialog.DIALOG_FRAGMENT_TAG);
    }

    public void handleProgramsButton(View view) {
        findViewById(R.id.progress_circle).setVisibility(View.VISIBLE);
        if (!viewSwitchLock.tryLock()) {
            return;
        }
        Intent intent = new Intent(MainMenuActivity.this, MyProjectsActivity.class);
        startActivity(intent);
    }

    public void handleHelpButton(View view) {
        if (!Utils.isNetworkAvailable(view.getContext(), true)) {
            return;
        }

        if (!viewSwitchLock.tryLock()) {
            return;
        }

        startWebViewActivity(Constants.CATROBAT_HELP_URL);
    }

    public void handleWebButton(View view) {
        if (!Utils.isNetworkAvailable(view.getContext(), true)) {
            return;
        }

        if (!viewSwitchLock.tryLock()) {
            return;
        }

        if (Utils.isUserLoggedIn(this)) {
            SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
            String username = sharedPreferences.getString(Constants.USERNAME, Constants.NO_USERNAME);
            String token = sharedPreferences.getString(Constants.TOKEN, Constants.NO_TOKEN);

            String url = Constants.CATROBAT_TOKEN_LOGIN_URL + username + Constants.CATROBAT_TOKEN_LOGIN_AMP_TOKEN
                    + token;
            startWebViewActivity(url);
        } else {
            startWebViewActivity(Constants.BASE_URL_HTTPS);
        }
    }

    public void startWebViewActivity(String url) {
        Intent intent = new Intent(MainMenuActivity.this, WebViewActivity.class);
        intent.putExtra(WebViewActivity.INTENT_PARAMETER_URL, url);
        startActivity(intent);
    }

    public void handleUploadButton(View view) {
        if (!Utils.isNetworkAvailable(view.getContext(), true)) {
            return;
        }

        if (!viewSwitchLock.tryLock()) {
            return;
        }
        ProjectManager.getInstance().uploadProject(Utils.getCurrentProjectName(this), this);
    }

    private void loadProgramFromExternalSource(Uri loadExternalProjectUri) {
        String scheme = loadExternalProjectUri.getScheme();
        if (scheme.startsWith(TYPE_HTTP)) {
            String url = loadExternalProjectUri.toString();
            DownloadUtil.getInstance().prepareDownloadAndStartIfPossible(this, url);
        } else if (scheme.equals(TYPE_FILE)) {

            String path = loadExternalProjectUri.getPath();
            int a = path.lastIndexOf('/') + 1;
            int b = path.lastIndexOf('.');
            String projectName = path.substring(a, b);
            if (!UtilZip.unZipFile(path, Utils.buildProjectPath(projectName))) {
                Utils.showErrorDialog(this, R.string.error_load_project);
            }
        }
    }

    private void setMainMenuButtonContinueText() {
        Button mainMenuButtonContinue = (Button) this.findViewById(R.id.main_menu_button_continue);
        TextAppearanceSpan textAppearanceSpan = new TextAppearanceSpan(this, R.style.MainMenuButtonTextSecondLine);
        SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
        String mainMenuContinue = this.getString(R.string.main_menu_continue);

        spannableStringBuilder.append(mainMenuContinue);
        spannableStringBuilder.append("\n");
        spannableStringBuilder.append(Utils.getCurrentProjectName(this));

        spannableStringBuilder.setSpan(textAppearanceSpan, mainMenuContinue.length() + 1,
                spannableStringBuilder.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);

        mainMenuButtonContinue.setText(spannableStringBuilder);
    }

    @Override
    public void onLoadProjectFailure() {
        findViewById(R.id.main_menu_buttons_container).setVisibility(View.VISIBLE);
    }

    public void initializeFacebookSdk() {
        FacebookSdk.sdkInitialize(getApplicationContext());
        callbackManager = CallbackManager.Factory.create();

        LoginManager.getInstance().registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
            @Override
            public void onSuccess(LoginResult loginResult) {
                Log.d(TAG, loginResult.toString());
                AccessToken accessToken = loginResult.getAccessToken();
                GetFacebookUserInfoTask getFacebookUserInfoTask = new GetFacebookUserInfoTask(MainMenuActivity.this,
                        accessToken.getToken(), accessToken.getUserId());
                getFacebookUserInfoTask.setOnGetFacebookUserInfoTaskCompleteListener(signInDialog);
                getFacebookUserInfoTask.execute();
            }

            @Override
            public void onCancel() {
                Log.d(TAG, "cancel");
            }

            @Override
            public void onError(FacebookException exception) {
                ToastUtil.showError(MainMenuActivity.this, exception.getMessage());
                Log.d(TAG, exception.getMessage());
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (!STANDALONE_MODE) {
            super.onActivityResult(requestCode, resultCode, data);
            callbackManager.onActivityResult(requestCode, resultCode, data);
        } else {
            if (requestCode == PreStageActivity.REQUEST_RESOURCES_INIT && resultCode == RESULT_OK) {
                SensorHandler.startSensorListener(this);

                Intent intent = new Intent(MainMenuActivity.this, StageActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
                    intent.addFlags(0x8000); // equal to Intent.FLAG_ACTIVITY_CLEAR_TASK which is only available from API level 11
                }
                startActivityForResult(intent, StageActivity.STAGE_ACTIVITY_FINISH);
            }
            if (requestCode == StageActivity.STAGE_ACTIVITY_FINISH) {
                finish();
            }
        }
    }

    public void setSignInDialog(SignInDialog signInDialog) {
        this.signInDialog = signInDialog;
    }

    private void unzipProgram() {
        StorageHandler.getInstance();
        String zipFileString = Constants.DEFAULT_ROOT + "/" + ZIP_FILE_NAME;
        copyProgramZip();
        Log.d("STANDALONE", "default root " + Constants.DEFAULT_ROOT);
        Log.d("STANDALONE", "zip file name:" + ZIP_FILE_NAME);
        Archiver archiver = ArchiverFactory.createArchiver("zip");
        File unpackedDirectory = new File(Constants.DEFAULT_ROOT + "/" + START_PROJECT);
        try {
            archiver.extract(new File(zipFileString), unpackedDirectory);
        } catch (IOException e) {
            Log.d("STANDALONE", "Can't extract program", e);
        }

        File destination = new File(Constants.DEFAULT_ROOT + "/" + STANDALONE_PROJECT_NAME);
        if (unpackedDirectory.isDirectory()) {
            unpackedDirectory.renameTo(destination);
        }

        loadStageProject(STANDALONE_PROJECT_NAME);

        File zipFile = new File(zipFileString);
        if (zipFile.exists()) {
            zipFile.delete();
        }
    }

    private void copyProgramZip() {
        AssetManager assetManager = getResources().getAssets();
        String[] files = null;
        try {
            files = assetManager.list("");
        } catch (IOException e) {
            Log.e("STANDALONE", "Failed to get asset file list.", e);
        }
        for (String filename : files) {
            if (filename.contains(ZIP_FILE_NAME)) {
                InputStream in;
                OutputStream out;
                try {
                    in = assetManager.open(filename);
                    File outFile = new File(Constants.DEFAULT_ROOT, filename);
                    out = new FileOutputStream(outFile);
                    copyFile(in, out);
                    out.flush();
                    out.close();
                    in.close();
                } catch (IOException e) {
                    Log.e("STANDALONE", "Failed to copy asset file: " + filename, e);
                }
            }
        }
    }

    private void copyFile(InputStream in, OutputStream out) throws IOException {
        byte[] buffer = new byte[1024];
        int read;
        while ((read = in.read(buffer)) != -1) {
            out.write(buffer, 0, read);
        }
    }

    private void loadStageProject(String projectName) {
        LoadProjectTask loadProjectTask = new LoadProjectTask(this, projectName, false, false);
        loadProjectTask.setOnLoadProjectCompleteListener(this);
        Log.e("STANDALONE", "going to execute standalone project");
        loadProjectTask.execute();
    }

    private void startStageProject() {
        //ProjectManager.getInstance().getCurrentProject().getUserVariables().resetAllUserVariables();
        Intent intent = new Intent(this, PreStageActivity.class);
        startActivityForResult(intent, PreStageActivity.REQUEST_RESOURCES_INIT);
    }
}