eu.focusnet.app.util.ApplicationHelper.java Source code

Java tutorial

Introduction

Here is the source code for eu.focusnet.app.util.ApplicationHelper.java

Source

/*
 * The MIT License (MIT)
 * Copyright (c) 2015 Berner Fachhochschule (BFH) - www.bfh.ch
 * 
 * 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 eu.focusnet.app.util;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.provider.Settings;
import android.support.v4.app.ActivityCompat;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import eu.focusnet.app.controller.FocusAppLogic;
import eu.focusnet.app.model.AppContentInstance;
import eu.focusnet.app.ui.FocusApplication;

/**
 * A helper class to retrieve application configuration and Android facilities.
 * <p/>
 * All these facilities should be accessed through this class, and not via the
 * {@link  FocusAppLogic} singleton.
 */
final public class ApplicationHelper {
    /**
     * Retrieve a property.
     *
     * @param key The key of the property to retrieve
     * @return A String containing the value of the property, or {@code null} on failure.
     */
    public static String getProperty(String key) {
        AssetManager assetManager = getAssets();
        return getProperty(key, assetManager);
    }

    /**
     * Same as {@link #getProperty(String)}, but used when no asset application is ready, yet
     *
     * @param key          The key of the property to retrieve
     * @param assetManager Asset Manager
     * @return A String containing the value of the property, or {@code null} on failure.
     */
    public static String getProperty(String key, AssetManager assetManager) {
        Properties properties = new Properties();
        try {
            InputStream inputStream = assetManager.open(Constant.AppConfig.ASSETS_PROPERTY_FILE);
            properties.load(inputStream);
        } catch (IOException ex) {
            throw new FocusInternalErrorException("IO error when accessing property file.");
        }
        return properties.getProperty(key);
    }

    /**
     * Load the proper language based on the value found in the {@link AppContentInstance}
     * and modify the current {@link Configuration}. This method must be called when appropriate,
     * but will impact all the rest of the life of the application. It does not impact the UI
     * directly but is typically called from an Activity's on Resume() method, or just before
     * redirecting to another Activity.
     */
    public static void changeLanguage(String language) {
        Locale targetLocale = ApplicationHelper.getDefaultLocale();
        if (ApplicationHelper.getSupportedLanguages().contains(language)) {
            // ok
            targetLocale = new Locale(language);
        } else {
            // perhaps we have a cousin locale (e.g. fr if fr_CH was requested)?
            //
            // FIXME FIXME FIXME
            // that is not optimal. We change the language but also the l10n
            // For Switzerland, for example, we may prefer to keep the fr_CH locale
            // (so that Date/number formatting is like we do in CH), but only change the
            // language to French or German
            // -> would be solved if we could define a parent translation set in our translation
            //    sets, e.g. fr_CH is child of fr, but we still set fr_CH as an app locale, and
            //    therefore we will have good formatting without having to translate everything
            //    again in French.
            //    alternate solution: symlinks on the filesystem. UNIX-only.
            Pattern p = Pattern.compile("^([a-z]{2})_.*");
            Matcher m = p.matcher(language);
            if (m.matches()) {
                targetLocale = new Locale(m.group(1));
            } else {
                FocusApplication.reportError(new FocusNotImplementedException(
                        "Non fatal: Attempting to initialize an application content with unsupported language |"
                                + language + "|"));
            }
        }

        // set the language
        Locale.setDefault(targetLocale);
        Configuration config = new Configuration();
        config.locale = targetLocale;
        getApplicationContext().getResources().updateConfiguration(config,
                getApplicationContext().getResources().getDisplayMetrics());
    }

    /**
     * Get the list of languages for which we have a translation. This is hard-coded.
     *
     * @return An array consisting of supported languages. The languages can be also a localized
     * versions, e.g. fr_CH instead of fr.
     */
    private static List<String> getSupportedLanguages() {
        return Arrays.asList("en", "fr");
    }

    /**
     * Reset language to the default language
     */
    public static void resetLanguage() {
        Locale defaultLocale = ApplicationHelper.getDefaultLocale();
        Locale.setDefault(defaultLocale);
        Configuration config = new Configuration();
        config.locale = defaultLocale;
        getApplicationContext().getResources().updateConfiguration(config,
                getApplicationContext().getResources().getDisplayMetrics());
    }

    /**
     * Retrieve the default locale to use as a fallback.
     *
     * @return The {@code Locale} to use.
     */
    private static Locale getDefaultLocale() {
        String defaultLocale = ApplicationHelper.getProperty(Constant.AppConfig.PROPERTY_DEFAULT_LOCALE);
        String[] parts = defaultLocale.split("_");
        String[] ret = new String[] { Constant.AppConfig.LOCALE_FALLBACK_LANGUAGE,
                Constant.AppConfig.LOCALE_FALLBACK_COUNTRY };
        for (int i = 0; i < 2; ++i) {
            if (parts.length > i && !parts[i].isEmpty()) {
                ret[i] = parts[i];
            }
        }
        return new Locale(ret[0], ret[1]);
    }

    /**
     * Save provided preferences into the SharedPreferences store.
     *
     * @param preferences A key-value pair set to save. All saved values are String.
     */
    public static void savePreferences(HashMap<String, String> preferences) {
        SharedPreferences store = getApplicationContext().getSharedPreferences(
                Constant.SharedPreferences.SHARED_PREFERENCES_STORE_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = store.edit();
        for (Map.Entry e : preferences.entrySet()) {
            editor.putString((String) e.getKey(), (String) e.getValue());
        }
        editor.apply();
    }

    /**
     * Get all values for the SharedPreferences store
     *
     * @return The complete set of preferences.
     */
    public static HashMap<String, String> getPreferences() {
        SharedPreferences store = getApplicationContext().getSharedPreferences(
                Constant.SharedPreferences.SHARED_PREFERENCES_STORE_NAME, Context.MODE_PRIVATE);

        HashMap<String, String> ret = new HashMap<>();
        Map<String, ?> prefs = store.getAll();
        for (Map.Entry e : prefs.entrySet()) {
            ret.put((String) e.getKey(), (String) e.getValue());
        }
        return ret;
    }

    /**
     * Delete all values from the SharedPreferences
     */
    public static void resetPreferences() {
        SharedPreferences store = getApplicationContext().getSharedPreferences(
                Constant.SharedPreferences.SHARED_PREFERENCES_STORE_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = store.edit();
        editor.clear();
        editor.apply();
    }

    /**
     * Get the application-wide Android context.
     *
     * @return The Android ApplicationContext.
     */
    public static Context getApplicationContext() {
        return FocusAppLogic.getApplicationContext();
    }

    /**
     * Get application assets.
     *
     * @return The {@code AssetManager} to use to browse assets.
     */
    public static AssetManager getAssets() {
        return getApplicationContext().getAssets();
    }

    /**
     * Get the Android ID of this device.
     *
     * @return The Android ID.
     */
    public static String getAndroidId() {
        return Settings.Secure.getString(getApplicationContext().getContentResolver(), Settings.Secure.ANDROID_ID);
    }

    /**
     * Get the Resources of the application.
     *
     * @return The object used to access resources.
     */
    public static Resources getResources() {
        return getApplicationContext().getResources();
    }

    /**
     * Get the package manager of the system.
     *
     * @return The {@code PackageManager} to use to retrieve information.
     */
    public static PackageManager getPackageManager() {
        return getApplicationContext().getPackageManager();
    }

    /**
     * Check a specific permissions.
     *
     * @param what The name of the permission.
     * @return {@code true} if the permission is granted, {@code false} otherwise.
     */
    public static boolean checkPermission(String what) {
        return ActivityCompat.checkSelfPermission(getApplicationContext(),
                what) == PackageManager.PERMISSION_GRANTED;
    }

    /**
     * Get a system service.
     *
     * @param name The name of the service to acquire.
     * @return The service of interest
     */
    public static Object getSystemService(String name) {
        return getApplicationContext().getSystemService(name);
    }
}