com.metaphyze.hackernewsfrontpage.HackerNewsFrontPageActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.metaphyze.hackernewsfrontpage.HackerNewsFrontPageActivity.java

Source

package com.metaphyze.hackernewsfrontpage;

/*
 * Copyright (C) 2014 Robert Ryan Brown
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Date;

import org.json.JSONObject;

import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import com.google.gson.Gson;

public class HackerNewsFrontPageActivity extends Activity {
    private RequestQueue requestQueue = null;
    private Gson gson = new Gson();

    private DrawerLayout drawerLayout;
    private WebView webView;
    private ListView drawerList;
    private ActionBarDrawerToggle drawerToggle;
    private View loadingView;
    private TextView location;
    private String bookFileName;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_hacker_news_front_page);

        bookFileName = getFilesDir() + File.separator + "bookmarked_posts.js";
        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawerList = (ListView) findViewById(R.id.drawer);
        location = (TextView) findViewById(R.id.location);

        webView = (WebView) findViewById(R.id.content_frame);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setDomStorageEnabled(true);
        webView.getSettings().setAppCacheEnabled(true);
        loadingView = findViewById(R.id.loading);
        ProgressBar progressBar = ((ProgressBar) findViewById(R.id.progress_bar));
        progressBar.setIndeterminate(true);
        drawerList.setAdapter(new HackerNewsAdapter(HackerNewsFrontPageActivity.this, R.layout.post_item,
                new ArrayList<HackerNewsPost>(), true));
        getActionBar().setTitle("Hacker News Front Page (Loading Live Stream...)");
        drawerList.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                HackerNewsPost post = (HackerNewsPost) parent.getItemAtPosition(position);

                webView.loadUrl(post.getUrl());
                webView.setWebViewClient(new WebViewClient() {

                    @Override
                    public void onPageStarted(WebView view, String url, Bitmap favicon) {
                        super.onPageStarted(view, url, favicon);
                        loadingView.setVisibility(View.VISIBLE);
                        location.setText("LOADING......" + url);
                    }

                    @Override
                    public void onPageFinished(WebView view, String url) {
                        super.onPageFinished(view, url);
                        loadingView.setVisibility(View.INVISIBLE);
                        location.setText(url);
                    }

                    @Override
                    public boolean shouldOverrideUrlLoading(WebView view, String url) {
                        view.loadUrl(url);
                        return true;
                    }

                    @Override
                    public void onReceivedError(WebView view, int errorCode, String description,
                            String failingUrl) {
                        loadingView.setVisibility(View.INVISIBLE);
                        location.setText("ERROR LOADING PAGE");
                        view.loadUrl("file:///android_asset/failed_to_load_page.html");
                    }

                });
                drawerLayout.closeDrawer(drawerList);
            }
        });

        drawerList.setOnItemLongClickListener(new OnItemLongClickListener() {

            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                final HackerNewsPost clonedPost = ((HackerNewsPost) parent.getItemAtPosition(position)).clone();
                clonedPost.setPostedAgo(new Date().toString());
                AlertDialog.Builder builder = new AlertDialog.Builder(HackerNewsFrontPageActivity.this);
                if (((HackerNewsAdapter) parent.getAdapter()).isLive()) {
                    builder.setTitle("Bookmark?");
                    builder.setMessage("Do you want to bookmark the post\n" + clonedPost.getTitle());
                    builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            try {
                                HackerNewsFrontPageContents contents = readContentsFromBookmarksFile();
                                if (contents == null) {
                                    showError("ERROR", "Failed to read bookmark file");
                                    dialog.dismiss();
                                    return;
                                }

                                if (!contents.addPost(clonedPost)) {
                                    showError("Already Exists", "Not added becasue bookmark already exists");
                                    dialog.dismiss();
                                    return;
                                }

                                if (!saveContentsToBookmarksFile(contents)) {
                                    showError("ERROR", "Failed to save bookmark");
                                    dialog.dismiss();
                                }

                            } catch (Exception ex) {
                                ex.printStackTrace();
                                showError("ERROR", "Internal error: " + ex);
                            }
                        }
                    }).setNegativeButton("No", new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }
                    });
                } else {
                    builder.setTitle("Delete?");
                    builder.setMessage("Do you want to delete the bookmarked post:\n" + clonedPost.getTitle());
                    builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            try {

                                HackerNewsFrontPageContents contents = readContentsFromBookmarksFile();
                                if (contents == null) {
                                    showError("ERROR", "Unable to find or generate bookmarks file");
                                    dialog.dismiss();
                                    return;
                                }

                                if (!contents.removePost(clonedPost)) {
                                    showError("Not Removed", "Does not exist? How's that possible?");
                                    dialog.dismiss();
                                    return;
                                }

                                if (saveContentsToBookmarksFile(contents)) {
                                    if (contents.getItems().size() > 0) {
                                        drawerList
                                                .setAdapter(new HackerNewsAdapter(HackerNewsFrontPageActivity.this,
                                                        R.layout.post_item, contents.getItems(), false));
                                    } else {
                                        showError("No more bookmarks", "Reverting to live stream");
                                        loadLiveStream();
                                    }
                                } else {
                                    showError("ERROR", "Failed to save bookmark deletion");
                                }
                                dialog.dismiss();

                            } catch (Exception ex) {
                                ex.printStackTrace();
                                showError("ERROR", "Internal Error: " + ex);
                            }

                        }
                    }).setNegativeButton("No", new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }
                    });
                }

                builder.setCancelable(true);
                builder.create().show();

                return false;
            }
        });

        drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.drawable.drawer_icon, 0, 0);
        drawerLayout.setDrawerListener(drawerToggle);

        ActionBar actionBar = getActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
        //      actionBar.setHomeButtonEnabled(true);

        requestQueue = Volley.newRequestQueue(this);
        loadLiveStream();

    }

    private void showError(String title, String error) {
        AlertDialog.Builder builder = new AlertDialog.Builder(HackerNewsFrontPageActivity.this);

        builder.setTitle(title);
        builder.setMessage(error);
        builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();

            }
        });

        builder.create().show();
    }

    private HackerNewsFrontPageContents readContentsFromBookmarksFile() {
        File bookmarksFile = new File(bookFileName);

        HackerNewsFrontPageContents contents = null;
        try {
            if (bookmarksFile.exists()) {
                contents = gson.fromJson(new FileReader(bookmarksFile), HackerNewsFrontPageContents.class);
            } else {
                contents = new HackerNewsFrontPageContents("N/A", "N/A", "N/A");
            }

            return contents;
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    private boolean saveContentsToBookmarksFile(HackerNewsFrontPageContents contents) {
        String fileContent = gson.toJson(contents);

        File bookmarksFile = new File(bookFileName);
        FileOutputStream outputStream;

        try {
            outputStream = new FileOutputStream(bookmarksFile);
            outputStream.write(fileContent.getBytes());
            outputStream.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private void loadLiveStream() {
        JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET,
                "http://api.ihackernews.com/page", null, new Response.Listener<JSONObject>() {

                    @Override
                    public void onResponse(JSONObject response) {
                        try {
                            String responseText = response.toString();
                            HackerNewsFrontPageContents reply = gson.fromJson(responseText,
                                    HackerNewsFrontPageContents.class);
                            drawerList.setAdapter(new HackerNewsAdapter(HackerNewsFrontPageActivity.this,
                                    R.layout.post_item, reply.getItems(), true));
                            getActionBar().setTitle("Hacker News Front Page (Live)");
                            drawerLayout.openDrawer(GravityCompat.START);
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }

                    }

                }, new Response.ErrorListener() {

                    @Override
                    public void onErrorResponse(VolleyError error) {
                        showError("Error loading live feed", "There was a problem contacting the site");
                        getActionBar().setTitle("Hacker News Front Page (ERROR LOADING Live Stream)");
                    }
                });

        requestQueue.cancelAll(null);
        requestQueue.add(jsObjRequest);
    }

    private void loadBookmarks() {
        try {
            HackerNewsFrontPageContents contents = readContentsFromBookmarksFile();
            if (contents == null) {
                showError("ERROR", "Error laoding bookmark file.  Returning to live stream.");
                loadLiveStream();
                return;
            }

            if (contents.getItems().size() == 0) {
                showError("No Bookmarks", "Returning to live stream.");
                loadLiveStream();
                return;
            }
            drawerList.setAdapter(new HackerNewsAdapter(HackerNewsFrontPageActivity.this, R.layout.post_item,
                    contents.getItems(), false));
            getActionBar().setTitle("Bookmarks");
            drawerLayout.openDrawer(GravityCompat.START);
        } catch (Exception ex) {
            File bookmarksFile = new File(bookFileName);
            if (!bookmarksFile.exists()) {
                showError("No Bookmarks Yet", "Returning to Live Stream");
                loadLiveStream();
            } else {
                ex.printStackTrace();
                showError("ERROR", "Error loading bookmarks file: " + ex);
                drawerList.setAdapter(new HackerNewsAdapter(HackerNewsFrontPageActivity.this, R.layout.post_item,
                        new ArrayList<HackerNewsPost>(), false));
                getActionBar().setTitle("Bookmarks (Error Loading Bookmarks)");
                drawerLayout.openDrawer(GravityCompat.START);
            }
        }

    }

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

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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (drawerToggle.onOptionsItemSelected(item)) {
            return true;
        }

        switch (item.getItemId()) {
        case R.id.live_stream:
            loadLiveStream();
            break;
        case R.id.archived_items:
            loadBookmarks();
            break;

        }
        return super.onOptionsItemSelected(item);
    }

}