org.quantumbadger.redreader.common.General.java Source code

Java tutorial

Introduction

Here is the source code for org.quantumbadger.redreader.common.General.java

Source

/*******************************************************************************
 * This file is part of RedReader.
 *
 * RedReader 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.
 *
 * RedReader 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 RedReader.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/

package org.quantumbadger.redreader.common;

import android.content.Context;
import android.content.DialogInterface;
import android.content.res.Configuration;
import android.graphics.Typeface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
import android.util.TypedValue;
import android.widget.Toast;
import org.apache.http.StatusLine;
import org.holoeverywhere.app.Activity;
import org.holoeverywhere.app.AlertDialog;
import org.holoeverywhere.preference.SharedPreferences;
import org.quantumbadger.redreader.R;
import org.quantumbadger.redreader.activities.BugReportActivity;
import org.quantumbadger.redreader.cache.RequestFailureType;
import org.quantumbadger.redreader.fragments.ErrorPropertiesDialog;
import org.quantumbadger.redreader.reddit.APIResponseHandler;

import java.io.*;
import java.net.URI;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class General {

    private static long lastBackPress = -1;

    public static boolean onBackPressed() {

        if (lastBackPress < SystemClock.uptimeMillis() - 300) {
            lastBackPress = SystemClock.uptimeMillis();
            return true;
        }

        return false;
    }

    private static Typeface monoTypeface;

    public static Typeface getMonoTypeface(Context context) {

        if (monoTypeface == null) {
            monoTypeface = Typeface.createFromAsset(context.getAssets(), "fonts/VeraMono.ttf");
        }

        return monoTypeface;
    }

    public static Message handlerMessage(int what, Object obj) {
        final Message msg = new Message();
        msg.what = what;
        msg.obj = obj;
        return msg;
    }

    public static void moveFile(final File src, final File dst) throws IOException {

        if (!src.renameTo(dst)) {

            copyFile(src, dst);

            if (!src.delete()) {
                src.deleteOnExit();
            }
        }
    }

    public static void copyFile(final File src, final File dst) throws IOException {

        final FileInputStream fis = new FileInputStream(src);
        final FileOutputStream fos = new FileOutputStream(dst);

        copyFile(fis, fos);
    }

    public static void copyFile(final InputStream fis, final File dst) throws IOException {
        final FileOutputStream fos = new FileOutputStream(dst);
        copyFile(fis, fos);
    }

    public static void copyFile(final InputStream fis, final OutputStream fos) throws IOException {

        final byte[] buf = new byte[32 * 1024];

        int bytesRead;
        while ((bytesRead = fis.read(buf)) > 0) {
            fos.write(buf, 0, bytesRead);
        }

        fis.close();
        fos.close();
    }

    public static File getBestCacheDir(final Context context) {

        final File externalCacheDir = context.getExternalCacheDir();

        if (externalCacheDir != null) {
            return externalCacheDir;
        }

        return context.getCacheDir();
    }

    public static int dpToPixels(final Context context, final float dp) {
        return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                context.getResources().getDisplayMetrics()));
    }

    public static void quickToast(final Context context, final int textRes) {
        quickToast(context, context.getString(textRes));
    }

    public static void quickToast(final Context context, final String text) {
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            public void run() {
                Toast.makeText(context, text, Toast.LENGTH_LONG).show();
            }
        });
    }

    public static void quickToast(final Context context, final String text, final int duration) {
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            public void run() {
                Toast.makeText(context, text, duration).show();
            }
        });
    }

    public static boolean isTablet(final Context context, final SharedPreferences sharedPreferences) {

        final PrefsUtility.AppearanceTwopane pref = PrefsUtility.appearance_twopane(context, sharedPreferences);

        switch (pref) {
        case AUTO:
            return (context.getResources().getConfiguration().screenLayout
                    & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE;
        case NEVER:
            return false;
        case FORCE:
            return true;
        default:
            BugReportActivity.handleGlobalError(context, "Unknown AppearanceTwopane value " + pref.name());
            return false;
        }
    }

    public static boolean isConnectionWifi(final Context context) {
        final ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        final NetworkInfo info = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
        return info != null && info.isConnected();
    }

    public static RRError getGeneralErrorForFailure(Context context, RequestFailureType type, Throwable t,
            StatusLine status, String url) {

        final int title, message;

        switch (type) {
        case CANCELLED:
            title = R.string.error_cancelled_title;
            message = R.string.error_cancelled_message;
            break;
        case PARSE:
            title = R.string.error_parse_title;
            message = R.string.error_parse_message;
            break;
        case CACHE_MISS:
            title = R.string.error_unexpected_cache_title;
            message = R.string.error_unexpected_cache_message;
            break;
        case STORAGE:
            title = R.string.error_unexpected_storage_title;
            message = R.string.error_unexpected_storage_message;
            break;
        case CONNECTION:
            // TODO check network and customise message
            title = R.string.error_connection_title;
            message = R.string.error_connection_message;
            break;
        case MALFORMED_URL:
            title = R.string.error_malformed_url_title;
            message = R.string.error_malformed_url_message;
            break;
        case REQUEST:

            if (status != null) {
                switch (status.getStatusCode()) {
                case 403:
                    title = R.string.error_403_title;
                    message = R.string.error_403_message;
                    break;
                case 404:
                    title = R.string.error_404_title;
                    message = R.string.error_404_message;
                    break;
                case 502:
                case 503:
                case 504:
                    title = R.string.error_redditdown_title;
                    message = R.string.error_redditdown_message;
                    break;
                default:
                    title = R.string.error_unknown_api_title;
                    message = R.string.error_unknown_api_message;
                    break;
                }
            } else {
                title = R.string.error_unknown_api_title;
                message = R.string.error_unknown_api_message;
            }

            break;

        default:
            title = R.string.error_unknown_title;
            message = R.string.error_unknown_message;
            break;
        }

        return new RRError(context.getString(title), context.getString(message), t, status, url);
    }

    public static RRError getGeneralErrorForFailure(Context context, final APIResponseHandler.APIFailureType type) {

        final int title, message;

        switch (type) {

        case INVALID_USER:
            title = R.string.error_403_title;
            message = R.string.error_403_message;
            break;

        case BAD_CAPTCHA:
            title = R.string.error_bad_captcha_title;
            message = R.string.error_bad_captcha_message;
            break;

        case NOTALLOWED:
            title = R.string.error_403_title;
            message = R.string.error_403_message;
            break;

        case SUBREDDIT_REQUIRED:
            title = R.string.error_subreddit_required_title;
            message = R.string.error_subreddit_required_message;
            break;

        default:
            title = R.string.error_unknown_api_title;
            message = R.string.error_unknown_api_message;
            break;
        }

        return new RRError(context.getString(title), context.getString(message));
    }

    // TODO add button to show more detail
    public static void showResultDialog(final Activity context, final RRError error) {
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            public void run() {
                final AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
                alertBuilder.setNeutralButton(R.string.dialog_close, null);
                alertBuilder.setNegativeButton(R.string.button_moredetail, new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        ErrorPropertiesDialog.newInstance(error).show(context);
                    }
                });
                alertBuilder.setTitle(error.title);
                alertBuilder.setMessage(error.message);
                alertBuilder.create().show();
            }
        });
    }

    private static final Pattern urlPattern = Pattern
            .compile("^(https?)://([^/]+)/+([^\\?#]+)((?:\\?[^#]+)?)((?:#.+)?)$");

    public static URI uriFromString(String url) {

        try {
            return new URI(url);

        } catch (Throwable t1) {
            try {

                Log.i("RR DEBUG uri", "Beginning aggressive parse of '" + url + "'");

                final Matcher urlMatcher = urlPattern.matcher(url);

                if (urlMatcher.find()) {

                    final String scheme = urlMatcher.group(1);
                    final String authority = urlMatcher.group(2);
                    final String path = urlMatcher.group(3).length() == 0 ? null : "/" + urlMatcher.group(3);
                    final String query = urlMatcher.group(4).length() == 0 ? null : urlMatcher.group(4);
                    final String fragment = urlMatcher.group(5).length() == 0 ? null : urlMatcher.group(5);

                    try {
                        return new URI(scheme, authority, path, query, fragment);
                    } catch (Throwable t3) {

                        if (path != null && path.contains(" ")) {
                            return new URI(scheme, authority, path.replace(" ", "%20"), query, fragment);
                        } else {
                            return null;
                        }
                    }

                } else {
                    return null;
                }

            } catch (Throwable t2) {
                return null;
            }
        }
    }
}