From 66a971c14691514230ff0a1f1a19a29c194c74ee Mon Sep 17 00:00:00 2001 From: lado Date: Fri, 22 Mar 2013 01:04:38 +0100 Subject: SharedPreferences refactored --- .../src/de/bjusystems/vdrmanager/QueuedWork.java | 101 ++++ .../vdrmanager/VdrSharedPreferencesImpl.java | 527 +++++++++++++++++++++ .../vdrmanager/data/FetchEditTextPreference.java | 2 +- .../src/de/bjusystems/vdrmanager/data/Vdr.java | 179 +++---- .../vdrmanager/data/VdrSharedPreferences.java | 1 + .../vdrmanager/gui/VdrPreferencesActivity.java | 24 +- .../org/fueri/reeldroid/network/DeviceManager.java | 8 +- 7 files changed, 739 insertions(+), 103 deletions(-) create mode 100644 vdrmanager/src/de/bjusystems/vdrmanager/QueuedWork.java create mode 100644 vdrmanager/src/de/bjusystems/vdrmanager/VdrSharedPreferencesImpl.java diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/QueuedWork.java b/vdrmanager/src/de/bjusystems/vdrmanager/QueuedWork.java new file mode 100644 index 0000000..09bb15b --- /dev/null +++ b/vdrmanager/src/de/bjusystems/vdrmanager/QueuedWork.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * 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. + */ + +package de.bjusystems.vdrmanager; + +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * Internal utility class to keep track of process-global work that's + * outstanding and hasn't been finished yet. + * + * This was created for writing SharedPreference edits out + * asynchronously so we'd have a mechanism to wait for the writes in + * Activity.onPause and similar places, but we may use this mechanism + * for other things in the future. + * + * + */ +public class QueuedWork { + + // The set of Runnables that will finish or wait on any async + // activities started by the application. + private static final ConcurrentLinkedQueue sPendingWorkFinishers = + new ConcurrentLinkedQueue(); + + private static ExecutorService sSingleThreadExecutor = null; // lazy, guarded by class + + /** + * Returns a single-thread Executor shared by the entire process, + * creating it if necessary. + */ + public static ExecutorService singleThreadExecutor() { + synchronized (QueuedWork.class) { + if (sSingleThreadExecutor == null) { + // TODO: can we give this single thread a thread name? + sSingleThreadExecutor = Executors.newSingleThreadExecutor(); + } + return sSingleThreadExecutor; + } + } + + /** + * Add a runnable to finish (or wait for) a deferred operation + * started in this context earlier. Typically finished by e.g. + * an Activity#onPause. Used by SharedPreferences$Editor#startCommit(). + * + * Note that this doesn't actually start it running. This is just + * a scratch set for callers doing async work to keep updated with + * what's in-flight. In the common case, caller code + * (e.g. SharedPreferences) will pretty quickly call remove() + * after an add(). The only time these Runnables are run is from + * waitToFinish(), below. + */ + public static void add(Runnable finisher) { + sPendingWorkFinishers.add(finisher); + } + + public static void remove(Runnable finisher) { + sPendingWorkFinishers.remove(finisher); + } + + /** + * Finishes or waits for async operations to complete. + * (e.g. SharedPreferences$Editor#startCommit writes) + * + * Is called from the Activity base class's onPause(), after + * BroadcastReceiver's onReceive, after Service command handling, + * etc. (so async work is never lost) + */ + public static void waitToFinish() { + Runnable toFinish; + while ((toFinish = sPendingWorkFinishers.poll()) != null) { + toFinish.run(); + } + } + + /** + * Returns true if there is pending work to be done. Note that the + * result is out of data as soon as you receive it, so be careful how you + * use it. + */ + public static boolean hasPendingWork() { + return !sPendingWorkFinishers.isEmpty(); + } + +} diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/VdrSharedPreferencesImpl.java b/vdrmanager/src/de/bjusystems/vdrmanager/VdrSharedPreferencesImpl.java new file mode 100644 index 0000000..0eac4fb --- /dev/null +++ b/vdrmanager/src/de/bjusystems/vdrmanager/VdrSharedPreferencesImpl.java @@ -0,0 +1,527 @@ +/* + * Copyrigsht (C) 2010 The Android Open Source Project + * + * 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. + */ + +package de.bjusystems.vdrmanager; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; +import java.util.concurrent.CountDownLatch; + +import android.content.SharedPreferences; +import android.os.Looper; + +import com.j256.ormlite.dao.RuntimeExceptionDao; + +import de.bjusystems.vdrmanager.data.Vdr; + +public class VdrSharedPreferencesImpl implements SharedPreferences { + + private static final String TAG = "SharedPreferencesImpl"; + + private static final boolean DEBUG = false; + + // Lock ordering rules: + // - acquire SharedPreferencesImpl.this before EditorImpl.this + // - acquire mWritingToDiskLock before EditorImpl.this + + Vdr mVdr; + + + public Vdr getVdr(){ + return mVdr; + } + + RuntimeExceptionDao dao; + + private Map mMap; // guarded by 'this' + private int mDiskWritesInFlight = 0; // guarded by 'this' + private boolean mLoaded = false; // guarded by 'this' + + private final Object mWritingToDiskLock = new Object(); + private static final Object mContent = new Object(); + private final WeakHashMap mListeners = new WeakHashMap(); + + public VdrSharedPreferencesImpl(Vdr vdr, RuntimeExceptionDao dao) { + mVdr = vdr; + this.dao = dao; + mLoaded = false; + mMap = null; + startLoadFromDisk(); + } + + private void startLoadFromDisk() { + synchronized (this) { + mLoaded = false; + } + new Thread("SharedPreferencesImpl-load") { + public void run() { + synchronized (VdrSharedPreferencesImpl.this) { + loadFromDiskLocked(); + } + } + }.start(); + } + + private void loadFromDiskLocked() { + if (mLoaded) { + return; + } + + Map map = mVdr.toMap(); + //StructStat stat = null; + //try { + //stat = Libcore.os.stat(mFile.getPath()); + //if (mFile.canRead()) { + //BufferedInputStream str = null; + //try { + //str = new BufferedInputStream(new FileInputStream(mFile), + // 16 * 1024); + //map = XmlUtils.readMapXml(str); + //} catch (XmlPullParserException e) { +// Log.w(TAG, "getSharedPreferences", e); + // } catch (FileNotFoundException e) { + // Log.w(TAG, "getSharedPreferences", e); + // } catch (IOException e) { + // Log.w(TAG, "getSharedPreferences", e); + //} finally { + //IoUtils.closeQuietly(str); + //} + //} + //} catch (ErrnoException e) { + //} + mLoaded = true; + if (map != null) { + mMap = map; + } else { + mMap = new HashMap(); + } + notifyAll(); + } + + + + public void registerOnSharedPreferenceChangeListener( + OnSharedPreferenceChangeListener listener) { + synchronized (this) { + mListeners.put(listener, mContent); + } + } + + public void unregisterOnSharedPreferenceChangeListener( + OnSharedPreferenceChangeListener listener) { + synchronized (this) { + mListeners.remove(listener); + } + } + + private void awaitLoadedLocked() { + // if (!mLoaded) { + // // Raise an explicit StrictMode onReadFromDisk for this + // // thread, since the real read will be in a different + // // thread and otherwise ignored by StrictMode. + // BlockGuard.getThreadPolicy().onReadFromDisk(); + // } + while (!mLoaded) { + try { + wait(); + } catch (InterruptedException unused) { + } + } + } + + public Map getAll() { + synchronized (this) { + awaitLoadedLocked(); + // noinspection unchecked + return new HashMap(mMap); + } + } + + public String getString(String key, String defValue) { + synchronized (this) { + awaitLoadedLocked(); + String v = String.valueOf(mMap.get(key)); + return v != null ? v : defValue; + } + } + + public Set getStringSet(String key, Set defValues) { + synchronized (this) { + awaitLoadedLocked(); + Set v = (Set) mMap.get(key); + return v != null ? v : defValues; + } + } + + public int getInt(String key, int defValue) { + synchronized (this) { + awaitLoadedLocked(); + Integer v = (Integer) mMap.get(key); + return v != null ? v : defValue; + } + } + + public long getLong(String key, long defValue) { + synchronized (this) { + awaitLoadedLocked(); + Long v = (Long) mMap.get(key); + return v != null ? v : defValue; + } + } + + public float getFloat(String key, float defValue) { + synchronized (this) { + awaitLoadedLocked(); + Float v = (Float) mMap.get(key); + return v != null ? v : defValue; + } + } + + public boolean getBoolean(String key, boolean defValue) { + synchronized (this) { + awaitLoadedLocked(); + Boolean v = (Boolean) mMap.get(key); + return v != null ? v : defValue; + } + } + + public boolean contains(String key) { + synchronized (this) { + awaitLoadedLocked(); + return mMap.containsKey(key); + } + } + + public Editor edit() { + // TODO: remove the need to call awaitLoadedLocked() when + // requesting an editor. will require some work on the + // Editor, but then we should be able to do: + // + // context.getSharedPreferences(..).edit().putString(..).apply() + // + // ... all without blocking. + synchronized (this) { + awaitLoadedLocked(); + } + + return new EditorImpl(); + } + + // Return value from EditorImpl#commitToMemory() + private static class MemoryCommitResult { + public boolean changesMade; // any keys different? + public List keysModified; // may be null + public Set listeners; // may be null + public Map mapToWriteToDisk; + public final CountDownLatch writtenToDiskLatch = new CountDownLatch(1); + public volatile boolean writeToDiskResult = false; + + public void setDiskWriteResult(boolean result) { + writeToDiskResult = result; + writtenToDiskLatch.countDown(); + } + } + + public final class EditorImpl implements Editor { + + private final Map mModified = new HashMap(); + + private boolean mClear = false; + + public Editor putString(String key, String value) { + synchronized (this) { + mModified.put(key, value); + return this; + } + } + + public Editor putStringSet(String key, Set values) { + synchronized (this) { + mModified.put(key, (values == null) ? null + : new HashSet(values)); + return this; + } + } + + public Editor putInt(String key, int value) { + synchronized (this) { + mModified.put(key, value); + return this; + } + } + + public Editor putLong(String key, long value) { + synchronized (this) { + mModified.put(key, value); + return this; + } + } + + public Editor putFloat(String key, float value) { + synchronized (this) { + mModified.put(key, value); + return this; + } + } + + public Editor putBoolean(String key, boolean value) { + synchronized (this) { + mModified.put(key, value); + return this; + } + } + + public Editor remove(String key) { + synchronized (this) { + mModified.put(key, this); + return this; + } + } + + public Editor clear() { + synchronized (this) { + mClear = true; + return this; + } + } + + public void apply() { + final MemoryCommitResult mcr = commitToMemory(); + final Runnable awaitCommit = new Runnable() { + public void run() { + try { + mcr.writtenToDiskLatch.await(); + } catch (InterruptedException ignored) { + } + } + }; + + QueuedWork.add(awaitCommit); + + Runnable postWriteRunnable = new Runnable() { + public void run() { + awaitCommit.run(); + QueuedWork.remove(awaitCommit); + } + }; + + VdrSharedPreferencesImpl.this.enqueueDiskWrite(mcr, postWriteRunnable); + + // Okay to notify the listeners before it's hit disk + // because the listeners should always get the same + // SharedPreferences instance back, which has the + // changes reflected in memory. + notifyListeners(mcr); + } + + // Returns true if any changes were made + private MemoryCommitResult commitToMemory() { + MemoryCommitResult mcr = new MemoryCommitResult(); + synchronized (VdrSharedPreferencesImpl.this) { + // We optimistically don't make a deep copy until + // a memory commit comes in when we're already + // writing to disk. + if (mDiskWritesInFlight > 0) { + // We can't modify our mMap as a currently + // in-flight write owns it. Clone it before + // modifying it. + // noinspection unchecked + mMap = new HashMap(mMap); + } + mcr.mapToWriteToDisk = mMap; + mDiskWritesInFlight++; + + boolean hasListeners = mListeners.size() > 0; + if (hasListeners) { + mcr.keysModified = new ArrayList(); + mcr.listeners = new HashSet( + mListeners.keySet()); + } + + synchronized (this) { + if (mClear) { + if (!mMap.isEmpty()) { + mcr.changesMade = true; + mMap.clear(); + } + mClear = false; + } + + for (Map.Entry e : mModified.entrySet()) { + String k = e.getKey(); + Object v = e.getValue(); + if (v == this) { // magic value for a removal mutation + if (!mMap.containsKey(k)) { + continue; + } + mMap.remove(k); + } else { + boolean isSame = false; + if (mMap.containsKey(k)) { + Object existingValue = mMap.get(k); + if (existingValue != null + && existingValue.equals(v)) { + continue; + } + } + mMap.put(k, v); + } + + mcr.changesMade = true; + if (hasListeners) { + mcr.keysModified.add(k); + } + } + + mModified.clear(); + } + } + return mcr; + } + + public boolean commit() { + MemoryCommitResult mcr = commitToMemory(); + VdrSharedPreferencesImpl.this.enqueueDiskWrite(mcr, null /* + * sync write on + * this thread + * okay + */); + try { + mcr.writtenToDiskLatch.await(); + } catch (InterruptedException e) { + return false; + } + notifyListeners(mcr); + return mcr.writeToDiskResult; + } + + private void notifyListeners(final MemoryCommitResult mcr) { + if (mcr.listeners == null || mcr.keysModified == null + || mcr.keysModified.size() == 0) { + return; + } + //if (Looper.myLooper() == Looper.getMainLooper()) { + for (int i = mcr.keysModified.size() - 1; i >= 0; i--) { + final String key = mcr.keysModified.get(i); + for (OnSharedPreferenceChangeListener listener : mcr.listeners) { + if (listener != null) { + listener.onSharedPreferenceChanged( + VdrSharedPreferencesImpl.this, key); + } + } + } + //} else { + // Run this function on the main thread. + // VdrManagerApp.sMainThreadHandler.post(new Runnable() { + // public void run() { + // notifyListeners(mcr); + // } + // }); + //} + } + } + + /** + * Enqueue an already-committed-to-memory result to be written to disk. + * + * They will be written to disk one-at-a-time in the order that they're + * enqueued. + * + * @param postWriteRunnable + * if non-null, we're being called from apply() and this is the + * runnable to run after the write proceeds. if null (from a + * regular commit()), then we're allowed to do this disk write on + * the main thread (which in addition to reducing allocations and + * creating a background thread, this has the advantage that we + * catch them in userdebug StrictMode reports to convert them + * where possible to apply() ...) + */ + private void enqueueDiskWrite(final MemoryCommitResult mcr, + final Runnable postWriteRunnable) { + final Runnable writeToDiskRunnable = new Runnable() { + public void run() { + synchronized (mWritingToDiskLock) { + writeToFile(mcr); + } + synchronized (VdrSharedPreferencesImpl.this) { + mDiskWritesInFlight--; + } + if (postWriteRunnable != null) { + postWriteRunnable.run(); + } + } + }; + + final boolean isFromSyncCommit = (postWriteRunnable == null); + + // Typical #commit() path with fewer allocations, doing a write on + // the current thread. + if (isFromSyncCommit) { + boolean wasEmpty = false; + synchronized (VdrSharedPreferencesImpl.this) { + wasEmpty = mDiskWritesInFlight == 1; + } + if (wasEmpty) { + writeToDiskRunnable.run(); + return; + } + } + + QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable); + } + + // Note: must hold mWritingToDiskLock + private void writeToFile(MemoryCommitResult mcr) { + // Rename the current file so it may be used as a backup during the next + // read + + // Attempt to write the file, delete the backup and return true as + // atomically as + // possible. If any exception occurs, delete the new file; next time we + // will restore + // from the backup. + // FileOutputStream str = createFileOutputStream(mFile); + // if (str == null) { + // mcr.setDiskWriteResult(false); + // return; + // } + // + // XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str); + mVdr.set(mcr.mapToWriteToDisk); + dao.createOrUpdate(mVdr); + // FileUtils.sync(str); + // str.close(); + // ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0); + // try { + // final StructStat stat = Libcore.os.stat(mFile.getPath()); + // synchronized (this) { + // mStatTimestamp = stat.st_mtime; + // mStatSize = stat.st_size; + // } + // } catch (ErrnoException e) { + // // Do nothing + // } + // Writing was successful, delete the backup file if there is one. + mcr.setDiskWriteResult(true); + return; + + } +} diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/data/FetchEditTextPreference.java b/vdrmanager/src/de/bjusystems/vdrmanager/data/FetchEditTextPreference.java index 5e4022e..17a93b7 100644 --- a/vdrmanager/src/de/bjusystems/vdrmanager/data/FetchEditTextPreference.java +++ b/vdrmanager/src/de/bjusystems/vdrmanager/data/FetchEditTextPreference.java @@ -2,13 +2,13 @@ package de.bjusystems.vdrmanager.data; import android.content.Context; import android.content.DialogInterface; +import android.content.SharedPreferences.Editor; import android.preference.DialogPreference; import android.util.AttributeSet; import android.view.View; import android.widget.EditText; import android.widget.ImageButton; import de.bjusystems.vdrmanager.R; -import de.bjusystems.vdrmanager.data.VdrSharedPreferences.Editor; public class FetchEditTextPreference extends DialogPreference{ diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/data/Vdr.java b/vdrmanager/src/de/bjusystems/vdrmanager/data/Vdr.java index b34c5bd..761a11e 100644 --- a/vdrmanager/src/de/bjusystems/vdrmanager/data/Vdr.java +++ b/vdrmanager/src/de/bjusystems/vdrmanager/data/Vdr.java @@ -17,7 +17,7 @@ public class Vdr { private Integer id; @DatabaseField(columnName = "name") - private String name = "-"; + private String name = "VDR"; /** * Use secure channel @@ -27,15 +27,15 @@ public class Vdr { /** SVDRP host name or ip */ @DatabaseField - private String host = "0.0.0.0"; + private String host = "0.0.0.0"; /** SVDRP port */ @DatabaseField - private int port = 6420; + private Integer port = 6420; /** Password */ @DatabaseField - private String password; + private String password = ""; /** should channels be filtered? */ @DatabaseField @@ -51,15 +51,15 @@ public class Vdr { /** URL of the wakeup script */ @DatabaseField - private String wakeupUrl; + private String wakeupUrl = ""; /** User for wakeup */ @DatabaseField - private String wakeupUser; + private String wakeupUser = ""; /** Password for wakeup */ @DatabaseField - private String wakeupPassword; + private String wakeupPassword = ""; /** * vdr mac for wol @@ -67,7 +67,7 @@ public class Vdr { * @since 0.2 */ @DatabaseField - private String mac; + private String mac = ""; /** * which wakeup method to use @@ -84,7 +84,7 @@ public class Vdr { /** Intervall for alive test */ @DatabaseField - private int aliveCheckInterval; + private Integer aliveCheckInterval; /** Buffer before event */ @DatabaseField @@ -104,7 +104,7 @@ public class Vdr { /** user defined epg search times */ @DatabaseField - private String epgSearchTimes; + private String epgSearchTimes = ""; /** * Which port to use for streaming @@ -140,7 +140,7 @@ public class Vdr { * Remux command */ @DatabaseField - private String remuxCommand = "EXT"; + private String remuxCommand = "EXT"; /** * Remux command Parameter @@ -170,10 +170,10 @@ public class Vdr { private int timeout = 60; @DatabaseField - private String streamingUsername; + private String streamingUsername = ""; @DatabaseField - private String streamingPassword; + private String streamingPassword = ""; @DatabaseField private int livePort = 8008; @@ -184,8 +184,7 @@ public class Vdr { @DatabaseField private boolean enableRecStreaming = false; - - @DatabaseField(columnName="stz") + @DatabaseField(columnName = "stz") private String serverTimeZone = "Europe/Berlin"; public String getServerTimeZone() { @@ -489,10 +488,14 @@ public class Vdr { } private static T get(Map map, String key, Object def) { - if(map.containsKey(key)){ + if (map.containsKey(key)) { return (T) map.get(key); } - return (T)def; + return (T) def; + } + + private static Integer getInteger(Map map, String key) { + return getInteger(map, key, 0); } private static Integer getInteger(Map map, String key, @@ -505,21 +508,26 @@ public class Vdr { if (obj instanceof Integer) { return (Integer) obj; } - return Integer.valueOf(String.valueOf(obj)); - } - private static Integer getInteger(Map map, String key) { - if (map.containsKey(key) == false) { - return Integer.valueOf(0); - } - - Object obj = get(map, key); - if (obj instanceof Integer) { - return (Integer) obj; + try { + return Integer.valueOf(String.valueOf(obj)); + } catch (NumberFormatException nfe) { + return def; } - return Integer.valueOf(String.valueOf(obj)); } + // private static Integer getInteger(Map map, String key) { + // if (map.containsKey(key) == false) { + // return Integer.valueOf(0); + // } + + // Object obj = get(map, key); + // if (obj instanceof Integer) { + // return (Integer) obj; + // } + // return Integer.valueOf(String.valueOf(obj)); + // } + private static Boolean getBoolean(Map map, String key) { return getBoolean(map, key, false); } @@ -580,58 +588,9 @@ public class Vdr { } public void set(Map map) { - name = get(map, "vdr_name", name); - host = get(map, "vdr_host", host); - port = getInteger(map, "vdr_port", port); - password = get(map, "vdr_password", password); - secure = getBoolean(map, "vdr_secure", secure); - - filterChannels = getBoolean(map, "limit_channels", filterChannels); - channelFilter = get(map, "last_channel", channelFilter); - - wakeupEnabled = getBoolean(map, "key_wakeup_enabled", wakeupEnabled); - wakeupUrl = get(map, "key_wakeup_url", wakeupUrl); - wakeupUser = get(map, "key_wakeup_user", wakeupUser); - wakeupPassword = get(map, "key_wakeup_password", wakeupPassword); - wakeupMethod = get(map, "key_wakeup_method", wakeupMethod); - wolCustomBroadcast = get(map, "key_wol_custom_broadcast", - wolCustomBroadcast); - mac = get(map, "key_wakeup_wol_mac", mac); - - connectionTimeout = getInteger(map, "key_conntimeout_key", - connectionTimeout); - readTimeout = getInteger(map, "key_vdr_readtimeout", readTimeout); - timeout = getInteger(map, "key_vdr_timeout", timeout); - - timerPreMargin = getInteger(map, "timer_pre_start_buffer", - timerPreMargin); - timerPostMargin = getInteger(map, "timer_post_end_buffer", - timerPostMargin); - timerDefaultPriority = getInteger(map, "timer_default_priority", - timerDefaultPriority); - timerDefaultLifetime = getInteger(map, "timer_default_lifetime", - timerDefaultLifetime); - - streamPort = getInteger(map, "streamingport", streamPort); - streamingPassword = get(map, "key_streaming_password", - streamingPassword); - streamingUsername = get(map, "key_streaming_username", - streamingUsername); - encoding = get(map, "key_vdr_encoding", encoding); - streamFormat = get(map, "livetv_streamformat", streamFormat); - remuxCommand = get(map, "remux_command", remuxCommand); - remuxParameter = get(map, "remux_parameter", remuxParameter); - enableRemux = getBoolean(map, "remux_enable", enableRemux); - - enableRecStreaming = getBoolean(map, "key_rec_stream_enable", - enableRecStreaming); - livePort = getInteger(map, "key_live_port", livePort); - recStreamMethod = get(map, "key_recstream_method", recStreamMethod); - - } - - public void init(Map map) { - name = get(map, "vdr_name", name); + init(map); +/* + name = get(map, "vdr_name"); host = get(map, "vdr_host"); port = getInteger(map, "vdr_port"); password = get(map, "vdr_password"); @@ -641,19 +600,20 @@ public class Vdr { channelFilter = get(map, "last_channel"); wakeupEnabled = getBoolean(map, "key_wakeup_enabled"); - wakeupUrl = get(map, "key_wakeup_url", "0.0.0.0"); - wakeupUser = get(map, "key_wakeup_user", ""); - wakeupPassword = get(map, "key_wakeup_password", ""); - wakeupMethod = get(map, "key_wakeup_method", "wol"); - wolCustomBroadcast = get(map, "key_wol_custom_broadcast", ""); - mac = get(map, "key_wakeup_wol_mac", ""); + wakeupUrl = get(map, "key_wakeup_url"); + wakeupUser = get(map, "key_wakeup_user"); + wakeupPassword = get(map, "key_wakeup_password"); + wakeupMethod = get(map, "key_wakeup_method"); + wolCustomBroadcast = get(map, "key_wol_custom_broadcast"); + mac = get(map, "key_wakeup_wol_mac"); connectionTimeout = getInteger(map, "key_conntimeout_key"); readTimeout = getInteger(map, "key_vdr_readtimeout"); timeout = getInteger(map, "key_vdr_timeout"); - timerPreMargin = getInteger(map, "timer_pre_start_buffer", 5); - timerPostMargin = getInteger(map, "timer_post_end_buffer", 30); + timerPreMargin = getInteger(map, "timer_pre_start_buffer" + ); + timerPostMargin = getInteger(map, "timer_post_end_buffer"); timerDefaultPriority = getInteger(map, "timer_default_priority"); timerDefaultLifetime = getInteger(map, "timer_default_lifetime"); @@ -669,8 +629,49 @@ public class Vdr { enableRecStreaming = getBoolean(map, "key_rec_stream_enable"); livePort = getInteger(map, "key_live_port"); recStreamMethod = get(map, "key_recstream_method"); - serverTimeZone = get(map, "key_imezone", TimeZone.getDefault()); + */ + } + public void init(Map map) { + name = get(map, "vdr_name", "VDR"); + host = get(map, "vdr_host", "0.0.0.0"); + port = getInteger(map, "vdr_port", 6420); + password = get(map, "vdr_password", ""); + secure = getBoolean(map, "vdr_secure"); + + filterChannels = getBoolean(map, "limit_channels", true); + channelFilter = get(map, "last_channel", ""); + + wakeupEnabled = getBoolean(map, "key_wakeup_enabled", false); + wakeupUrl = get(map, "key_wakeup_url", ""); + wakeupUser = get(map, "key_wakeup_user", ""); + wakeupPassword = get(map, "key_wakeup_password", ""); + wakeupMethod = get(map, "key_wakeup_method", "wol"); + wolCustomBroadcast = get(map, "key_wol_custom_broadcast", ""); + mac = get(map, "key_wakeup_wol_mac", ""); + + connectionTimeout = getInteger(map, "key_conntimeout_key", 10); + readTimeout = getInteger(map, "key_vdr_readtimeout", 10); + timeout = getInteger(map, "key_vdr_timeout", 60); + + timerPreMargin = getInteger(map, "timer_pre_start_buffer", 5); + timerPostMargin = getInteger(map, "timer_post_end_buffer", 30); + timerDefaultPriority = getInteger(map, "timer_default_priority", 50); + timerDefaultLifetime = getInteger(map, "timer_default_lifetime",99); + + streamPort = getInteger(map, "streamingport", 3000); + streamingPassword = get(map, "key_streaming_password", ""); + streamingUsername = get(map, "key_streaming_username", ""); + encoding = get(map, "key_vdr_encoding", "utf-8"); + streamFormat = get(map, "livetv_streamformat", "TS"); + remuxCommand = get(map, "remux_command", "EXT"); + remuxParameter = get(map, "remux_parameter", ""); + enableRemux = getBoolean(map, "remux_enable"); + + enableRecStreaming = getBoolean(map, "key_rec_stream_enable"); + livePort = getInteger(map, "key_live_port", 8008); + recStreamMethod = get(map, "key_recstream_method", "vdr-live"); + serverTimeZone = get(map, "key_imezone", TimeZone.getDefault().getID()); } } diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/data/VdrSharedPreferences.java b/vdrmanager/src/de/bjusystems/vdrmanager/data/VdrSharedPreferences.java index 8839fa0..bb0ad77 100644 --- a/vdrmanager/src/de/bjusystems/vdrmanager/data/VdrSharedPreferences.java +++ b/vdrmanager/src/de/bjusystems/vdrmanager/data/VdrSharedPreferences.java @@ -12,6 +12,7 @@ import android.content.SharedPreferences; import com.j256.ormlite.dao.Dao.CreateOrUpdateStatus; import com.j256.ormlite.dao.RuntimeExceptionDao; +@Deprecated public class VdrSharedPreferences implements SharedPreferences { private static final String EMPTY_STRING = ""; diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/gui/VdrPreferencesActivity.java b/vdrmanager/src/de/bjusystems/vdrmanager/gui/VdrPreferencesActivity.java index 35798d2..6f9d47d 100644 --- a/vdrmanager/src/de/bjusystems/vdrmanager/gui/VdrPreferencesActivity.java +++ b/vdrmanager/src/de/bjusystems/vdrmanager/gui/VdrPreferencesActivity.java @@ -25,12 +25,12 @@ import android.preference.Preference; import android.preference.Preference.OnPreferenceClickListener; import android.view.View; import de.bjusystems.vdrmanager.R; +import de.bjusystems.vdrmanager.VdrSharedPreferencesImpl; import de.bjusystems.vdrmanager.ZonePicker; import de.bjusystems.vdrmanager.app.Intents; import de.bjusystems.vdrmanager.data.FetchEditTextPreference; import de.bjusystems.vdrmanager.data.Preferences; import de.bjusystems.vdrmanager.data.Vdr; -import de.bjusystems.vdrmanager.data.VdrSharedPreferences; import de.bjusystems.vdrmanager.data.db.DBAccess; import de.bjusystems.vdrmanager.tasks.VoidAsyncTask; @@ -41,7 +41,7 @@ public class VdrPreferencesActivity extends BasePreferencesActivity implements Vdr vdr; - VdrSharedPreferences pref; + VdrSharedPreferencesImpl pref; int id = -1; @@ -68,11 +68,16 @@ public class VdrPreferencesActivity extends BasePreferencesActivity implements super.updateSummary(ep); } + + private boolean isNew = false; + + private boolean hasChanged = false; + private void initVDRInstance() { id = getIntent().getIntExtra(Intents.VDR_ID, -1); if (id == -1) {// new vdr vdr = new Vdr(); - + isNew = true; } else {// edit Vdr v = DBAccess.get(this).getVdrDAO().queryForId(id); if (v != null) { @@ -80,9 +85,10 @@ public class VdrPreferencesActivity extends BasePreferencesActivity implements } else { vdr = new Vdr(); id = -1; + isNew = true; } } - pref.setInstance(vdr); + pref = new VdrSharedPreferencesImpl(vdr, DBAccess.get(this).getVdrDAO()); } public static String ARP_CACHE = "/proc/net/arp"; @@ -149,10 +155,6 @@ public class VdrPreferencesActivity extends BasePreferencesActivity implements super.onCreate(savedInstanceState); - pref = new VdrSharedPreferences(); - - pref.dao = DBAccess.get(this).getVdrDAO(); - initVDRInstance(); this.addPreferencesFromResource(R.xml.vdr_prefs); @@ -317,6 +319,7 @@ public class VdrPreferencesActivity extends BasePreferencesActivity implements } public void onSharedPreferenceChanged(SharedPreferences arg0, String key) { + hasChanged = true; updateChildPreferences(); Preference p = findPreference(key); updateSummary(p); @@ -437,8 +440,9 @@ public class VdrPreferencesActivity extends BasePreferencesActivity implements finish(); return; } - if (pref.commits < 2) {// user has not changed anything - DBAccess.get(this).getVdrDAO().delete(pref.getInstance()); + if(isNew == true && hasChanged == false) { + //if (pref.commits < 2) {// user has not changed anything + DBAccess.get(this).getVdrDAO().delete(pref.getVdr()); finish(); return; } diff --git a/vdrmanager/src/org/fueri/reeldroid/network/DeviceManager.java b/vdrmanager/src/org/fueri/reeldroid/network/DeviceManager.java index 59e9e3a..427ff35 100644 --- a/vdrmanager/src/org/fueri/reeldroid/network/DeviceManager.java +++ b/vdrmanager/src/org/fueri/reeldroid/network/DeviceManager.java @@ -61,10 +61,12 @@ public class DeviceManager { WifiManager wifiManager = (WifiManager) context .getSystemService(Context.WIFI_SERVICE); - boolean wifiStatus = (conMgr - .getNetworkInfo(ConnectivityManager.TYPE_WIFI)).isConnected(); + boolean netStatus = conMgr + .getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnected() + || conMgr.getNetworkInfo(ConnectivityManager.TYPE_ETHERNET) + .isConnected(); - if (wifiStatus == false) { + if (netStatus == false) { return list; } -- cgit v1.2.3