/* © 2010 Stephan Reichholf <stephan at reichholf dot net> * * Licensed under the Create-Commons Attribution-Noncommercial-Share Alike 3.0 Unported * http://creativecommons.org/licenses/by-nc-sa/3.0/ */ package net.reichholf.dreamdroid; import android.Manifest; import android.content.ComponentName; import android.content.Context; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.preference.PreferenceManager; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatDelegate; import android.util.Log; import net.reichholf.dreamdroid.helpers.SimpleHttpClient; import net.reichholf.dreamdroid.helpers.enigma2.requesthandler.LocationListRequestHandler; import net.reichholf.dreamdroid.helpers.enigma2.requesthandler.TagListRequestHandler; import org.piwik.sdk.PiwikApplication; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.GregorianCalendar; /** * @author sre */ public class DreamDroid extends PiwikApplication { public static final int INITIAL_SERVICELIST_PANE = 1; public static final int INITIAL_VIRTUAL_REMOTE = 2; public static final String PREFS_KEY_HWACCEL = "video_hardware_acceleration"; public static final String PREFS_KEY_PICONS_ONLINE = "picons_online"; public static String VERSION_STRING; public static final String ACTION_CREATE = "dreamdroid.intent.action.NEW"; public static final String LOG_TAG = "DreamDroid"; public static final String PREFS_KEY_QUICKZAP = "quickzap"; public static final String PREFS_KEY_CONFIRM_APP_CLOSE = "confirm_app_close"; public static final String PREFS_KEY_ENABLE_ANIMATIONS = "enable_animations"; public static final String PREFS_KEY_FIRST_START = "first_start"; public static final String PREFS_KEY_SYNC_PICONS_PATH = "sync_picons_path"; public static final String PREFS_KEY_PICONS_ENABLED = "picons"; public static final String PREFS_KEY_PICONS_USE_NAME = "use_name_as_picon_filename"; public static final String PREFS_KEY_INITIALBITS = "initial_bits"; public static final String PREFS_KEY_GRID_MAX_COLS = "grid_max_cols"; public static final String PREFS_KEY_SIMPLE_VRM = "simple_vrm"; public static final String PREFS_KEY_ENABLE_DEVELOPER_SETTINGS = "enable_developer"; public static final String PREFS_KEY_FAKE_PICON = "fake_picon"; public static final String PREFS_KEY_XML_DEBUG = "xml_debug"; public static final String PREFS_KEY_ALLOW_TRACKING = "allow_tracking"; public static final String PREFS_KEY_PRIVACY_STATEMENT_SHOWN = "privacy_statement_shown"; public static final String PREFS_KEY_INTEGRATED_PLAYER = "integrated_video_player"; public static final String PREFS_KEY_THEME_TYPE = "theme_type"; public static final String PREFS_KEY_INSTANT_ZAP = "instant_zap"; public static final String PREFS_KEY_VIDEO_ENABLE_GESTURES = "video_enable_gestures"; public static final String IAB_PUB_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkWyCpE79iRAcqWnC+/I5AuahW/wvbGF5SxcZCELP6I6Rs47hYOydmCBDV5e11FXHZyS3BGuuVKEjf9DxkR2skNtKfgbX/UQD0jpnaEk2GnnsZ9OAaso9pKFn1ZJKtLtP7OKVlt2HpHjag3x8NGayjkno0k0gmvf5T8c77tYLtoHY+uLlUTwo0DiXhzxHjTjzTxc0nbEyRDa/5pDPudBCSien4lg+C8D9K8rdcUCI1QcLjkOgBR888CxT7cyhvUnoHcHZQLGbTFZG0XtyJnxop2AqWMiOepT3txAfq6OjOmo0PofuIk+m0jVrPLYs2eNSxmJrfZ5MddocPYD50cj+2QIDAQAB"; public static final String SKU_DONATE_1 = "donate_1"; public static final String SKU_DONATE_2 = "donate_2"; public static final String SKU_DONATE_3 = "donate_3"; public static final String SKU_DONATE_5 = "donate_5"; public static final String SKU_DONATE_10 = "donate_10"; public static final String SKU_DONATE_15 = "donate_15"; public static final String SKU_DONATE_20 = "donate_20"; public static final String SKU_DONATE_INSANE = "donate_insane"; public static final String[] SKU_LIST = {SKU_DONATE_1, SKU_DONATE_2, SKU_DONATE_3, SKU_DONATE_5, SKU_DONATE_10, SKU_DONATE_15, SKU_DONATE_20, SKU_DONATE_INSANE}; public static final String CURRENT_PROFILE = "currentProfile"; public static boolean DATE_LOCALE_WO; private static boolean sFeatureSleeptimer = true; private static boolean sFeatureNowNext = true; private static boolean sDumpXml = false; private static Profile sProfile; private static ArrayList<String> sLocations; private static ArrayList<String> sTags; private static ProfileChangedListener sCurrentProfileChangedListener = null; private static boolean sFeaturePostRequest = true; /** * @param context * @return */ public static String getVersionString(Context context) { try { ComponentName comp = new ComponentName(context, context.getClass()); PackageInfo pinfo = context.getPackageManager().getPackageInfo(comp.getPackageName(), 0); return String.format("dreamDroid %s (%s)\n© Stephan Reichholf\nstephan@reichholf.net", pinfo.versionName, pinfo.versionCode); } catch (android.content.pm.PackageManager.NameNotFoundException e) { return "dreamDroid\n© 2013 Stephan Reichholf\nstephan@reichholf.net"; } } // PIWIK @Override public String getTrackerUrl() { return "https://reichholf.net/piwik/piwik.php"; } @Override public Integer getSiteId() { return 2; } /* * (non-Javadoc) * * @see android.app.Application#onCreate() */ @Override public void onCreate() { super.onCreate(); // Determine if we require a Date-String-Locale-Missing-Fix // for details please see: // http://code.google.com/p/android/issues/detail?id=9453 SimpleDateFormat sdf = new SimpleDateFormat("E"); Date date = GregorianCalendar.getInstance().getTime(); VERSION_STRING = getVersionString(this); try { String s = sdf.format(date); //noinspection ResultOfMethodCallIgnored Integer.parseInt(s); DATE_LOCALE_WO = true; } catch (Exception e) { DATE_LOCALE_WO = false; } sLocations = new ArrayList<>(); sTags = new ArrayList<>(); loadCurrentProfile(this); } public static void disableNowNext() { sFeatureNowNext = false; } public static void enableNowNext() { sFeatureNowNext = true; } public static boolean featureNowNext() { return sFeatureNowNext; } public static boolean featurePostRequest() { return sFeaturePostRequest; } public static void setFeaturePostRequest(boolean enabled) { sFeaturePostRequest = enabled; } public static void disableSleepTimer() { sFeatureSleeptimer = false; } public static void enableSleepTimer() { sFeatureSleeptimer = true; } public static boolean featureSleepTimer() { return sFeatureSleeptimer; } public static Profile getCurrentProfile() { return sProfile; } public static void loadCurrentProfile(Context context) { SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); int profileId = sp.getInt(CURRENT_PROFILE, 1); if(sProfile != null && sProfile.getId() == profileId) return; DatabaseHelper dbh = DatabaseHelper.getInstance(context); ArrayList<Profile> profiles = dbh.getProfiles(); // the profile-table is initial - let's migrate the current config as // default Profile if (profiles.isEmpty()) { String host = sp.getString("host", "dreamdroid.org"); String streamHost = sp.getString("host", ""); int port = Integer.valueOf(sp.getString("port", "80")); String user = sp.getString("user", "root"); String pass = sp.getString("pass", "dreambox"); boolean login = sp.getBoolean("login", false); boolean ssl = sp.getBoolean("ssl", false); Profile p = new Profile(-1, "Demo", host, streamHost, port, 8001, 80, login, user, pass, ssl, false, false, false, false, "", "", "", ""); dbh.addProfile(p); SharedPreferences.Editor editor = sp.edit(); editor.remove(CURRENT_PROFILE); editor.commit(); } if (!setCurrentProfile(context, profileId)) { // However we got here... we're creating an // "do-not-crash-default-profile now sProfile = new Profile(-1, "Demo", "dreamdroid.org", "", 80, 8001, 80, false, "", "", false, false, false, false, false, "", "", "", ""); } } public static boolean setCurrentProfile(Context context, int id) { return setCurrentProfile(context, id, false); } public static boolean dumpXml() { return sDumpXml; } /** * @param id * @return */ public static boolean setCurrentProfile(Context context, int id, boolean forceEvent) { sDumpXml = PreferenceManager.getDefaultSharedPreferences(context).getBoolean("xml_debug", false); Profile oldProfile = sProfile; if (oldProfile == null) oldProfile = Profile.getDefault(); if(isTV(context)) { SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); String name = sp.getString(DatabaseHelper.KEY_PROFILE_PROFILE, "Demo"); String host = sp.getString(DatabaseHelper.KEY_PROFILE_HOST, "dreamdroid.org"); int port = Integer.parseInt(sp.getString(DatabaseHelper.KEY_PROFILE_PORT, "80")); boolean ssl = sp.getBoolean(DatabaseHelper.KEY_PROFILE_SSL, false); boolean login = sp.getBoolean(DatabaseHelper.KEY_PROFILE_LOGIN, false); String user = sp.getString(DatabaseHelper.KEY_PROFILE_USER, "root"); String pass = sp.getString(DatabaseHelper.KEY_PROFILE_PASS, "dreambox"); sProfile = new Profile(-1, name, host, host, port, 8001, port, login, user, pass, ssl, false, false, false, false, "", "", "", ""); } else { DatabaseHelper dbh = DatabaseHelper.getInstance(context); sProfile = dbh.getProfile(id); } if (sProfile != null) { SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit(); editor.putInt(CURRENT_PROFILE, id); editor.commit(); if (!sProfile.equals(oldProfile) || forceEvent) { //reset locations and tags, they will be reloaded when needed the next time sLocations.clear(); sTags.clear(); activeProfileChanged(); } else if (sProfile.getId() == oldProfile.getId()) { sProfile.setSessionId(oldProfile.getSessionId()); } return true; } else { Log.w(DreamDroid.LOG_TAG, "no profile with given id [" + id + "] found"); } return false; } public static void setCurrentProfile(Profile profile) { sProfile = profile; } public static void profileChanged(Context context, Profile p) { if (p.getId() == sProfile.getId()) { reloadCurrentProfile(context); } } private static void activeProfileChanged() { if (sCurrentProfileChangedListener != null) { sCurrentProfileChangedListener.onProfileChanged(sProfile); } } public static void setCurrentProfileChangedListener(ProfileChangedListener listener) { sCurrentProfileChangedListener = listener; } /** * @return */ public static boolean reloadCurrentProfile(Context ctx) { return setCurrentProfile(ctx, sProfile.getId(), true); } /** * @param shc */ public static synchronized boolean loadLocations(SimpleHttpClient shc) { sLocations.clear(); boolean gotLoc = false; LocationListRequestHandler handler = new LocationListRequestHandler(); String xml = handler.getList(shc); if (xml != null) { if (handler.parseList(xml, sLocations)) { gotLoc = true; } } if (!gotLoc) { Log.e(LOG_TAG, "Error parsing locations, falling back to /hdd/movie"); sLocations = new ArrayList<>(); sLocations.add("/hdd/movie"); } return gotLoc; } public static ArrayList<String> getLocations() { return sLocations; } /** * @param shc */ public static synchronized boolean loadTags(SimpleHttpClient shc) { sTags.clear(); boolean gotTags = false; TagListRequestHandler handler = new TagListRequestHandler(); String xmlLoc = handler.getList(shc); if (xmlLoc != null) { if (handler.parseList(xmlLoc, sTags)) { gotTags = true; } } if (!gotTags) { Log.e(LOG_TAG, "Error parsing Tags, no more Tags will be available"); sTags = new ArrayList<>(); } return gotTags; } public static ArrayList<String> getTags() { return sTags; } @SuppressWarnings({"rawtypes", "unchecked"}) public static void scheduleBackup(Context context) { Log.d(LOG_TAG, "Scheduling backup"); try { Class managerClass = Class.forName("android.app.backup.BackupManager"); Constructor managerConstructor = managerClass.getConstructor(Context.class); Object manager = managerConstructor.newInstance(context); Method m = managerClass.getMethod("dataChanged"); m.invoke(manager); Log.d(LOG_TAG, "Backup requested"); } catch (ClassNotFoundException e) { Log.d(LOG_TAG, "No backup manager found"); } catch (Throwable t) { Log.d(LOG_TAG, "Scheduling backup failed " + t); t.printStackTrace(); } } public static int getThemeType(Context context) { SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); return Integer.parseInt(sp.getString("theme_type", "0")); } public static void setTheme(AppCompatActivity activity) { int mode; switch(getThemeType(activity)){ case 0: mode = AppCompatDelegate.MODE_NIGHT_AUTO; break; case 1: mode = AppCompatDelegate.MODE_NIGHT_NO; break; case 2: mode = AppCompatDelegate.MODE_NIGHT_YES; break; case 3: mode = AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM; break; default: mode = AppCompatDelegate.MODE_NIGHT_AUTO; } if (ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED && mode == AppCompatDelegate.MODE_NIGHT_AUTO) { mode = AppCompatDelegate.MODE_NIGHT_NO; } AppCompatDelegate.setDefaultNightMode(mode); activity.getDelegate().setLocalNightMode(mode); } public static boolean checkInitial(Context context, int which) { SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); int mask = sp.getInt(PREFS_KEY_INITIALBITS, 0); return (mask & which) != which; } public static void setNotInitial(Context context, int which) { SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); int mask = sp.getInt(PREFS_KEY_INITIALBITS, 0); mask |= which; SharedPreferences.Editor editor = sp.edit(); editor.putInt(PREFS_KEY_INITIALBITS, mask); editor.commit(); } public static boolean isTrackingEnabled(Context context) { return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(PREFS_KEY_ALLOW_TRACKING, true); } public static boolean isTV(Context context) { return context.getResources().getBoolean(R.bool.is_television); } }