de.electricdynamite.pasty.PastyLoader.java Source code

Java tutorial

Introduction

Here is the source code for de.electricdynamite.pasty.PastyLoader.java

Source

package de.electricdynamite.pasty;

/*
 *  Copyright 2012-2013 Philipp Geschke
 *
 *  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.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import org.json.JSONArray;
import org.json.JSONException;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.support.v4.content.AsyncTaskLoader;
import android.util.Log;

public class PastyLoader extends AsyncTaskLoader<PastyLoader.PastyResponse> {
    private static final String TAG = PastyLoader.class.getName();
    private boolean LOCAL_LOG = false;

    // Delta to determine if our cached response is old
    private static final String CACHEFILE = PastySharedStatics.CACHEFILE;

    private PastyClient client;
    private PastyPreferencesProvider prefs;
    private Context context;
    private ConnectivityManager mConnMgr;

    private boolean isOnline = false;
    private boolean firstLoad = true;
    private boolean permitCache = true;

    public static final int TASK_CLIPBOARD_FETCH = 0xA1;
    public static final int TASK_ITEM_ADD = 0xB1;
    public static final int TASK_ITEM_DELETE = 0xB2;

    public static final Boolean CACHE_PERMITTED = true;
    public static final Boolean CACHE_DENIED = false;

    private int taskId = 0x0;

    public static class PastyResponse {
        private JSONArray mClipboard;
        private String mItemId;
        private PastyException mException;
        private int resultSource;
        public boolean isFinal = false;
        public static final int SOURCE_MEM = 0x1;
        public static final int SOURCE_CACHE = 0x2;
        public static final int SOURCE_NETWORK = 0x3;
        public boolean hasException = false;

        public PastyResponse() {
        }

        public PastyResponse(JSONArray clipboard, int resultSource, boolean isFinal) {
            this.mClipboard = clipboard;
            this.resultSource = resultSource;
            this.isFinal = isFinal;
        }

        public PastyResponse(JSONArray clipboard, int resultSource) {
            this.mClipboard = clipboard;
            this.resultSource = resultSource;
        }

        public PastyResponse(PastyException e) {
            this.mException = e;
            this.hasException = true;
        }

        public PastyResponse(String itemId) {
            this.mItemId = itemId;
        }

        public JSONArray getClipboard() {
            return mClipboard;
        }

        public String getItemId() {
            return mItemId;
        }

        public int getResultSource() {
            return resultSource;
        }

        public PastyException getException() {
            return this.mException;
        }
    }

    private PastyResponse mCachePastyResponse;

    public PastyLoader(Context context, int taskId, Bundle args) {
        super(context);
        if (PastySharedStatics.LOCAL_LOG == true)
            this.LOCAL_LOG = true;
        if (args == null)
            args = new Bundle();
        this.context = context;
        // Restore preferences
        this.prefs = new PastyPreferencesProvider(context);
        // Create a PastyClient
        client = new PastyClient(prefs.getRESTBaseURL(), true);
        client.setUsername(prefs.getUsername());
        client.setPassword(prefs.getPassword());
        this.taskId = taskId;
        this.permitCache = args.getBoolean("permitCache", PastyLoader.CACHE_PERMITTED);
    }

    @Override
    public PastyResponse loadInBackground() {
        if (LOCAL_LOG)
            Log.v(TAG, "loadInBackground(): called");
        try {
            // At the very least we always need an action.
            if (taskId == 0x0) {
                Log.w(TAG, "loadinBackground(): No taskId provided.");
                return new PastyResponse();
            }
            switch (taskId) {
            case TASK_CLIPBOARD_FETCH:
                JSONArray clipboard = client.getClipboard();
                cacheClipboard(clipboard);
                if (LOCAL_LOG)
                    Log.v(TAG, "loadInBackground(): Delivered result from network");
                return new PastyResponse(clipboard, PastyResponse.SOURCE_NETWORK, true);
            case TASK_ITEM_ADD:
                break;
            case TASK_ITEM_DELETE:
                break;
            default:
                return new PastyResponse();
            }
            // Request was null if we get here, so let's just send our empty RESTResponse like usual.
            return new PastyResponse();
        } catch (PastyException e) {
            return new PastyResponse(e);
        }
    }

    @Override
    public void deliverResult(PastyResponse response) {
        // Store our PastyResponse as cached result
        mCachePastyResponse = response;
        super.deliverResult(response);
    }

    @Override
    protected void onStartLoading() {
        if (mConnMgr == null) {
            mConnMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        }
        NetworkInfo networkInfo = mConnMgr.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected()) {
            this.isOnline = true;
        } else {
            this.isOnline = false;
        }
        networkInfo = null;
        if (mCachePastyResponse != null && permitCache) {
            // Instantly return a cached version
            if (LOCAL_LOG)
                Log.v(TAG, "onStartLoading(): Delivering result from memory");
            super.deliverResult(mCachePastyResponse);
        } else if (firstLoad && permitCache) {
            JSONArray jsonCache = getCachedClipboard();
            if (jsonCache != null) {
                // Got clipboard from device cache
                if (LOCAL_LOG)
                    Log.v(TAG, "onStartLoading(): Delivering result from cache");
                if (!isOnline) {
                    deliverResult(new PastyResponse(jsonCache, PastyResponse.SOURCE_CACHE, true));
                } else {
                    deliverResult(new PastyResponse(jsonCache, PastyResponse.SOURCE_CACHE));
                }
                firstLoad = false;
            } else {
                if (!isOnline) {
                    PastyException e = new PastyException(PastyException.ERROR_NO_CACHE_EXCEPTION);
                    deliverResult(new PastyResponse(e));
                }
            }
        }

        if (isOnline) {
            forceLoad();
        }
    }

    @Override
    protected void onStopLoading() {
        // This prevents the AsyncTask backing this
        // loader from completing if it is currently running.
        cancelLoad();
    }

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

        // Stop the Loader if it is currently running.
        onStopLoading();

        // Reset cache
        mCachePastyResponse = null;
    }

    protected JSONArray getCachedClipboard() {
        File mDeviceCacheFile = new File(context.getCacheDir(), CACHEFILE);

        try {
            BufferedReader reader = new BufferedReader(new FileReader(mDeviceCacheFile));
            String line, results = "";
            while ((line = reader.readLine()) != null) {
                results += line;
            }
            reader.close();
            JSONArray jsonCache;
            try {
                jsonCache = new JSONArray(results);
                return jsonCache;
            } catch (JSONException e) {
                Log.w(TAG, "getCachedClipboard(): Invalid JSON in cache file");
            }

        } catch (IOException e) {
            Log.i(TAG, "getCachedClipboard(): Cache file not existing");
        }
        return null;
    }

    private void cacheClipboard(JSONArray clipboard) {
        File mDeviceCacheFile = new File(context.getCacheDir(), CACHEFILE);

        try {
            mDeviceCacheFile.createNewFile();
            FileWriter fw = new FileWriter(mDeviceCacheFile);
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(clipboard.toString());
            bw.newLine();
            bw.close();
            if (LOCAL_LOG)
                Log.v(TAG, "cacheClipboard(): Saved result to cache");

        } catch (IOException e) {
            Log.w(TAG, "cacheClipboard(): Could not create cache file");
        }
    }
}