de.storyquest.client.ContentActivity.java Source code

Java tutorial

Introduction

Here is the source code for de.storyquest.client.ContentActivity.java

Source

/*
 * StoryQuest Android Client NG
 * Copyright (c) 2016 Questor GmbH, Berlin
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this
 * software and associated documentation files (the "Software"), to deal in the Software
 * without restriction, including without limitation the rights to use, copy, modify,
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies
 * or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package de.storyquest.client;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.view.MenuItem;
import android.view.WindowManager;
import android.webkit.ConsoleMessage;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.InputStream;

public class ContentActivity extends PlatformServicesActivity
        implements NavigationView.OnNavigationItemSelectedListener {

    public static String LOGTAG = ContentActivity.class.getName();

    public static final String BOOKMARKID = "bookmark";

    protected ProgressDialog progressDialog = null;
    protected WebView web = null;
    protected WebView character = null;
    protected String bookmarkId = null;

    protected ScriptSystem scriptSystem = null;
    protected ScriptStorage scriptStorage = null;
    protected ScriptSound scriptSound = null;
    protected ScriptGameServices scriptGameServices = null;

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

        // enable immersive mode
        getWindow().getDecorView()
                .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
        getWindow().addFlags(
                WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);

        // load initial layout
        setContentView(R.layout.activity_content);
        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
        View header = navigationView.getHeaderView(0);

        // apply theme
        try {
            Drawable d = Drawable.createFromStream(getAssets().open("sidebar.jpg"), null);
            navigationView.setBackground(d);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        // wire the drawer open event to the character sheet refresh
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer != null) {
            drawer.addDrawerListener(new DrawerLayout.SimpleDrawerListener() {
                @Override
                public void onDrawerOpened(View drawerView) {
                    super.onDrawerOpened(drawerView);
                    execJavaScriptInCharactersheet("if(typeof refresh!='undefined')refresh()");
                }
            });
        }

        // get extra data with bookmark to load
        Intent intent = getIntent();
        if (intent.hasExtra(BOOKMARKID))
            bookmarkId = intent.getStringExtra(BOOKMARKID);

        // set the cover image from assets
        ImageView coverImage = (ImageView) header.findViewById(R.id.coverImage);
        try {
            InputStream ims = getAssets().open("cover.png");
            Drawable d = Drawable.createFromStream(ims, null);
            coverImage.setImageDrawable(d);
        } catch (Exception e) {
            throw new RuntimeException("Error loading cover image. Is 'cover.png' available in assets?", e);
        }

        // make the web content debuggable from external chrome tools
        WebView.setWebContentsDebuggingEnabled(true);

        // enable script interfaces
        scriptSystem = new ScriptSystem(this);
        scriptStorage = new ScriptStorage(this,
                getApplicationContext().getSharedPreferences(ScriptStorage.CONTEXT, Context.MODE_PRIVATE));
        scriptSound = new ScriptSound(this);
        scriptGameServices = new ScriptGameServices(this);

        // setup character webview
        character = (WebView) header.findViewById(R.id.characterView);
        character.getSettings().setJavaScriptEnabled(true);
        character.getSettings().setDomStorageEnabled(true);
        character.getSettings().setAllowFileAccess(true);
        character.getSettings().setAppCacheEnabled(true);
        character.addJavascriptInterface(scriptSystem, "sqSystem");
        character.addJavascriptInterface(scriptStorage, "nativeStorage");
        character.addJavascriptInterface(scriptSound, "sqSound");
        character.addJavascriptInterface(scriptGameServices, "sqGameServices");
        character.loadUrl("file:///android_asset/character.html");

        // setup web view
        web = (WebView) findViewById(R.id.webView);
        web.getSettings().setJavaScriptEnabled(true);
        web.getSettings().setDomStorageEnabled(true);
        web.getSettings().setAllowFileAccess(true);
        web.getSettings().setAppCacheEnabled(true);
        web.addJavascriptInterface(scriptSystem, "sqSystem");
        web.addJavascriptInterface(scriptStorage, "nativeStorage");
        web.addJavascriptInterface(scriptSound, "sqSound");
        web.addJavascriptInterface(scriptGameServices, "sqGameServices");

        // adding event overrides for the web view
        web.setWebChromeClient(new WebChromeClient());
        web.setWebViewClient(new WebViewClient() {
            public boolean shouldOverrideUrlLoading(WebView view, String urlText) {
                if (urlText.startsWith("http")) { // Could be cleverer and use a regex
                    Log.d(LOGTAG, "Opening standard web intent window for " + urlText);
                    Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(urlText));
                    startActivity(i);
                    return true;
                } else {
                    Log.d(LOGTAG, "Loading in webview: " + urlText);
                    web.loadUrl(urlText);
                    return true;
                }
            }

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                Log.d(LOGTAG, "Page rendering started: " + url + ".");
                displaySpinner(R.string.loading);
                super.onPageStarted(view, url, favicon);
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                Log.d(LOGTAG, "Page rendering finished: " + url + ".");
                hideSpinner();
                if (bookmarkId != null && url.startsWith("file:///android_asset/content.html")) {
                    Log.i(LOGTAG, "Loading bookmark " + bookmarkId + ".");
                    execJavaScriptInContent("loadBookmark('" + bookmarkId + "')");
                    bookmarkId = null;
                }
                super.onPageFinished(view, url);
            }

            @Override
            public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
                Log.d(LOGTAG, "Intercepted call: " + url + ".");
                return null;
            }
        });
        web.setWebChromeClient(new WebChromeClient() {
            public boolean onConsoleMessage(ConsoleMessage cm) {
                Log.d(LOGTAG, cm.message() + " - from line " + cm.lineNumber() + " of " + cm.sourceId());
                return true;
            }
        });
        web.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
        web.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
        web.requestFocus(View.FOCUS_DOWN);

        // finally loading content bootstrap
        Log.i(LOGTAG, "Loading index.html");
        web.loadUrl("file:///android_asset/index.html");
    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.nav_main) {
            displayMain();
        } else if (id == R.id.nav_achievements) {
            getGooglePlayServices().showAchievementsView();
        } else if (id == R.id.nav_bookmarks) {
            displayBookmarks();
        } else if (id == R.id.nav_help) {
            displayHelp();
        } else if (id == R.id.nav_storebookmark) {
            execJavaScriptInContent("storeBookmark()");
            Toast.makeText(this, getResources().getText(R.string.bookmarkStored), Toast.LENGTH_SHORT).show();
        }
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

    private void displayMain() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(getResources().getString(R.string.mainMenuSecurityTitle));
        builder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                Log.i(LOGTAG, "Displaying Main Menu..");
                Intent mainMenuIntent = new Intent(ContentActivity.this, MainMenuActivity.class);
                startActivity(mainMenuIntent);
                dialog.dismiss();
            }
        });
        builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                dialog.dismiss();
            }
        });
        AlertDialog dialog = builder.create();
        dialog.show();
    }

    private void displayBookmarks() {
        Log.i(LOGTAG, "Displaying Bookmarks..");
        Intent bookmarkIntent = new Intent(this, BookmarkActivity.class);
        startActivityForResult(bookmarkIntent, 42);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        if (requestCode == 42) {
            Log.i(LOGTAG, "Returning from bookmarks, refreshing bookmark model..");
            execJavaScriptInContent("initBookmarks()");
        }
    }

    private void displayHelp() {
        Log.i(LOGTAG, "Displaying Help..");
        Intent helpIntent = new Intent(this, GenericActivity.class);
        helpIntent.putExtra(GenericActivity.TITLE, getResources().getString(R.string.helpTitle));
        helpIntent.putExtra(GenericActivity.HTMLPATH, "help.html");
        helpIntent.putExtra(GenericActivity.BACKGROUNDIMAGE, "help.jpg");
        startActivity(helpIntent);
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            getWindow().getDecorView().setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
            getWindow().addFlags(
                    WindowManager.LayoutParams.FLAG_FULLSCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
        }
    }

    public void execJavaScriptInContent(final String javaScript) {
        Log.d(LOGTAG, "Executing JavaScript in existing WebView: " + javaScript);
        this.runOnUiThread(new Runnable() {
            public void run() {
                web.loadUrl("javascript:" + javaScript);
            }
        });
    }

    public void execJavaScriptInCharactersheet(final String javaScript) {
        Log.d(LOGTAG, "Executing JavaScript in existing WebView: " + javaScript);
        this.runOnUiThread(new Runnable() {
            public void run() {
                character.loadUrl("javascript:" + javaScript);
            }
        });
    }

    public final void displaySpinner(int resource) {
        Log.d(LOGTAG, "Showing wait dialog.");
        if (progressDialog != null) {
            progressDialog = new ProgressDialog(this, R.style.AppDialog);
            progressDialog.setMessage(getString(resource));
            // making immersive mode stay while the dialog is shown
            progressDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
            progressDialog.show();
            progressDialog.getWindow().getDecorView()
                    .setSystemUiVisibility(this.getWindow().getDecorView().getSystemUiVisibility());
        }
    }

    public final void hideSpinner() {
        Log.d(LOGTAG, "Hiding wait dialog.");
        if (progressDialog != null) {
            progressDialog.dismiss();
            progressDialog = null;
        }
    }
}