com.purplefrog.glitchclocka.LearningReadout.java Source code

Java tutorial

Introduction

Here is the source code for com.purplefrog.glitchclocka.LearningReadout.java

Source

/*
Copyright (C) 2011 Robert Forsman
    
This file is part of Glitch clock for android.
    
Glitch clock for android 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.
    
Glitch clock for android 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 Glitch clock for android.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.purplefrog.glitchclocka;

import android.app.*;
import android.content.*;
import android.net.*;
import android.os.*;
import android.util.*;
import android.view.*;
import android.widget.*;
import com.tinyspeck.android.*;
import org.json.*;

import java.util.*;

/**
 * Created by IntelliJ IDEA.
 * User: thoth
 * Date: 10/25/11
 * Time: 4:31 PM
 */
public class LearningReadout extends Activity {
    Glitch glitch;
    private TextView debugText;
    private static final String LOG_TAG = "LearningReadout";
    private TextView nameW;
    private TextView descriptionW;
    private ProgressBar progressBar;
    private ImageView skillIconW;
    private Timer timer;
    //    private long timeComplete;
    //    private int totalTime;
    protected LearningState learningState;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //        Log.d(LOG_TAG, "onCreate()");

        super.onCreate(savedInstanceState);

        setContentView(R.layout.learning);

        glitch = new Glitch(glitchClientKey(), "glitchandroidsdk://auth");

        debugText = (TextView) findViewById(R.id.debug);
        nameW = (TextView) findViewById(R.id.skillName);
        skillIconW = (ImageView) findViewById(R.id.skillIcon);
        descriptionW = (TextView) findViewById(R.id.description);
        progressBar = (ProgressBar) findViewById(R.id.progressBar);

        glitch.accessToken = memorizedAccessToken();

        if (checkStateMachine())
            return;

    }

    private String memorizedAccessToken() {
        SharedPreferences prefs = getPreferences(0);
        final String remembered = prefs.getString("glitchToken", null);
        //        Log.d(LOG_TAG, "remembered glitch token = "+remembered);
        return remembered;
    }

    protected void memorizeToken(String token) {
        SharedPreferences prefs = getPreferences(0);
        SharedPreferences.Editor ed = prefs.edit();
        ed.putString("glitchToken", token);
        ed.commit();

        //        Log.d(LOG_TAG, "stashed token "+token);
    }

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

        learningState = savedInstanceState.getParcelable("learningState");
        glitch.accessToken = savedInstanceState.getString("glitchToken");
    }

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

        outState.putParcelable("learningState", learningState);
        outState.putString("glitchToken", glitch.accessToken);
    }

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

        //        Log.d(LOG_TAG, "onResume()");

        if (null == learningState) {
            learningState = new LearningState("fake skill", System.currentTimeMillis() / 1000 + 60, 2 * 60, "",
                    "fake description");

            debugLearningData();

        } else {
            //            Log.d(LOG_TAG, "restored");
            updateReadoutFull();
        }

        ensureTimerRunning();
    }

    public synchronized void ensureTimerRunning() {
        if (timer != null)
            return;

        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                updateProgressTimeBar();
            }
        };
        timer = new Timer();
        timer.scheduleAtFixedRate(timerTask, 0, 10000);
    }

    @Override
    protected void onPause() {
        //        Log.d(LOG_TAG, "onPause()");

        synchronized (this) {
            if (null != timer) {
                timer.cancel();
                timer = null;
            }
        }

        super.onPause();
    }

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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.refresh:
            refreshLearningData();
            return true;
        case R.id.about:
            if (true) {
                startActivity(new Intent(this, AboutActivity.class));
            } else {
                startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("file:///android_asset/about.html")));
            }
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    //

    protected void refreshLearningData() {
        if (!glitch.isAuthenticated()) {
            glitch.authorize("read", this);
            return;
        }

        rpcListLearning();
    }

    /**
     * This intent can be activated two ways, by clicking on one of our AppWidgets, or is a callback from the OAuth mechanism.
     * This function returns true if we've been called from OAuth and need to harvest the auth data.
     * This function returns false if we've been activated by any other mechanism
     */
    protected boolean checkStateMachine() {
        Intent intent = getIntent();

        if (intent.hasCategory(Intent.CATEGORY_BROWSABLE)) {
            final Uri uri = intent.getData();

            if (uri != null) {
                glitch.handleRedirect(uri, new MyGlitchSessionDelegate());
                return true;
            }
        }

        return false;
    }

    /**
     * This exists so I can load test data into the widget without bugging the central server.
     */
    @SuppressWarnings({ "ConstantIfStatement" })
    protected void debugLearningData() {
        Log.d(LOG_TAG, "debugLearningData()");
        if (true) {

            refreshLearningData();

        } else if (true) {

            try {
                final String JSON_1 = "{\"ok\":1,\"learning\":[]}";
                final String JSON_2 = "{\"ok\":1,\"learning\":{\"betterlearning_4\":{\"class_tsid\":\"betterlearning_4\",\"required_skills\":[\"betterlearning_3\"],\"time_remaining\":233323,\"required_level\":0,\"icon_44\":\"http://c1.glitch.bz/img/skills/betterlearning_4_28144.png\",\"icon_460\":\"http://c1.glitch.bz/img/skills-460/betterlearning_4_28144.png\",\"total_time\":242374,\"time_complete\":1319879122,\"name\":\"Better Learning IV\",\"icon_100\":\"http://c1.glitch.bz/img/skills-100/betterlearning_4_28144.png\",\"url\":\"/skills/59/\",\"time_start\":1319643807,\"description\":\"At the fourth level of Better Learning, you can chop a whopping 12% off the time required to learn all future skills - and the first 32 carry no time penalty. Better Learning: for the serious self-edumacator.\"}}}";
                handleJSONResponse(new JSONObject(JSON_2));
            } catch (JSONException e) {
                Log.d(LOG_TAG, "WTF?", e);
            }
        } else {
            learningState = new LearningState("fake skill", System.currentTimeMillis() / 1000 + 60, 2 * 60, "",
                    "fake description");
            updateReadoutFull();
        }
    }

    public static String glitchClientKey() {
        /**
         * The API key is sensitive information and should not be checked in to GIT or shared with anyone.
         * If it is shared, irresponsible entities could use it in a way that forces
         * the Glitch operators to revoke the key and cripple this application.
         *
         * To find out how to register for your own Glitch API key visit
         * http://developer.glitch.com/api/
         */
        return DontCheckInToGit.glitchKey;
    }

    public void updateReadoutFull() {
        nameW.setText(learningState.name);
        if (false && learningState.skillIconURL != null && learningState.skillIconURL.length() > 0) {
            skillIconW.setImageURI(Uri.parse(learningState.skillIconURL));
        }
        descriptionW.setText(learningState.description);

        Log.d(LOG_TAG, "configuring progress bar");
        if (learningState.totalTime > 0) {
            progressBar.setMax(learningState.totalTime);

            ensureTimerRunning();

            updateProgressTimeBar();
            progressBar.setVisibility(View.VISIBLE);
        } else {
            progressBar.setVisibility(View.INVISIBLE);
        }

    }

    protected void updateProgressTimeBar() {
        //        Log.d(LOG_TAG, "tick");
        int prog = learningState.totalTime - (int) (learningState.timeComplete - System.currentTimeMillis() / 1000);
        if (prog > learningState.totalTime) {
            timer.cancel();
        }
        progressBar.setProgress(prog);
    }

    public void handleJSONResponse(JSONObject json) {
        JSONObject learning_ = json.optJSONObject("learning");

        if (learning_ == null) {
            learningState = new LearningState("nothing", System.currentTimeMillis() / 1000, 0, "",
                    "you're not learnin' nuthin.");
            updateReadoutFull();
            return;
        }

        String skillId = learning_.keys().next().toString();
        JSONObject learning = learning_.optJSONObject(skillId);

        String name = learning.optString("name");
        long timeComplete = learning.optLong("time_complete");
        int totalTime = learning.optInt("total_time");
        String skillIconURL = learning.optString("icon_100");
        String description = learning.optString("description");

        learningState = new LearningState(name, timeComplete, totalTime, skillIconURL, description);
        updateReadoutFull();

        final String partial = name + " " + timeComplete + " " + totalTime + " " + skillIconURL + " \n"
                + description;

        debugText.setText(partial + "\n\n" + json);
    }

    protected void rpcListLearning() {
        Log.d(LOG_TAG, "starting glitch API call");
        GlitchRequest req = glitch.getRequest("skills.listLearning");
        req.execute(new GlitchRequestDelegate() {
            public void requestFinished(GlitchRequest request) {
                final JSONObject json = request.response;
                debugText.setText(json.toString());

                Log.d(LOG_TAG, "" + json);

                handleJSONResponse(json);
            }

            public void requestFailed(GlitchRequest request) {
                glitch.accessToken = null;// just in case our remembered token was bad

                Log.d(LOG_TAG, "glitch request failed : " + request.response);

                debugText.setText("blam : " + request.response);

                Toast.makeText(LearningReadout.this,
                        "Glitch authentication failed.  If our access token has expired, perform a refresh to get a new token.",
                        Toast.LENGTH_LONG).show();
            }
        });
    }
    //

    private class MyGlitchSessionDelegate implements GlitchSessionDelegate {
        public void glitchLoginSuccess() {
            debugText.setText("login success");

            memorizeToken(glitch.accessToken);

            Runnable r = new Runnable() {
                public void run() {
                    rpcListLearning();
                }
            };

            runOnUiThread(r);
        }

        public void glitchLoginFail() {
            debugText.setText("login fail");
        }

        public void glitchLoggedOut() {
            debugText.setText("logged out");
        }
    }
}