/* * Copyright (C) 2007-2015 FBReader.ORG Limited <contact@fbreader.org> * * This program 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 2 of the License, or * (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ package org.geometerplus.android.fbreader.config; import java.util.*; import android.app.Service; import android.content.*; import android.os.IBinder; import android.os.RemoteException; import org.geometerplus.zlibrary.core.options.Config; import org.geometerplus.android.fbreader.api.FBReaderIntents; public final class ConfigShadow extends Config implements ServiceConnection { private final Context myContext; private volatile ConfigInterface myInterface; private final List<Runnable> myDeferredActions = new LinkedList<Runnable>(); private final BroadcastReceiver myReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { try { setToCache( intent.getStringExtra("group"), intent.getStringExtra("name"), intent.getStringExtra("value") ); } catch (Exception e) { // ignore } } }; public ConfigShadow(Context context) { myContext = context; context.bindService( FBReaderIntents.internalIntent(FBReaderIntents.Action.CONFIG_SERVICE), this, Service.BIND_AUTO_CREATE ); } @Override public boolean isInitialized() { return myInterface != null; } @Override public void runOnConnect(Runnable runnable) { if (myInterface != null) { runnable.run(); } else { synchronized (myDeferredActions) { myDeferredActions.add(runnable); } } } @Override public List<String> listGroups() { if (myInterface == null) { return Collections.emptyList(); } try { return myInterface.listGroups(); } catch (RemoteException e) { return Collections.emptyList(); } } @Override public List<String> listNames(String group) { if (myInterface == null) { return Collections.emptyList(); } try { return myInterface.listNames(group); } catch (RemoteException e) { return Collections.emptyList(); } } @Override public void removeGroup(String name) { if (myInterface != null) { try { myInterface.removeGroup(name); } catch (RemoteException e) { } } } public boolean getSpecialBooleanValue(String name, boolean defaultValue) { return myContext.getSharedPreferences("fbreader.ui", Context.MODE_PRIVATE) .getBoolean(name, defaultValue); } public void setSpecialBooleanValue(String name, boolean value) { myContext.getSharedPreferences("fbreader.ui", Context.MODE_PRIVATE).edit() .putBoolean(name, value).commit(); } public String getSpecialStringValue(String name, String defaultValue) { return myContext.getSharedPreferences("fbreader.ui", Context.MODE_PRIVATE) .getString(name, defaultValue); } public void setSpecialStringValue(String name, String value) { myContext.getSharedPreferences("fbreader.ui", Context.MODE_PRIVATE).edit() .putString(name, value).commit(); } @Override protected String getValueInternal(String group, String name) throws NotAvailableException { if (myInterface == null) { throw new NotAvailableException("Config is not initialized for " + group + ":" + name); } try { return myInterface.getValue(group, name); } catch (RemoteException e) { throw new NotAvailableException("RemoteException for " + group + ":" + name); } } @Override protected void setValueInternal(String group, String name, String value) { if (myInterface != null) { try { myInterface.setValue(group, name, value); } catch (RemoteException e) { } } } @Override protected void unsetValueInternal(String group, String name) { if (myInterface != null) { try { myInterface.unsetValue(group, name); } catch (RemoteException e) { } } } @Override protected Map<String,String> requestAllValuesForGroupInternal(String group) throws NotAvailableException { if (myInterface == null) { throw new NotAvailableException("Config is not initialized for " + group); } try { final Map<String,String> values = new HashMap<String,String>(); for (String pair : myInterface.requestAllValuesForGroup(group)) { final String[] split = pair.split("\000"); switch (split.length) { case 1: values.put(split[0], ""); break; case 2: values.put(split[0], split[1]); break; } } return values; } catch (RemoteException e) { throw new NotAvailableException("RemoteException for " + group); } } // method from ServiceConnection interface public void onServiceConnected(ComponentName name, IBinder service) { synchronized (this) { myInterface = ConfigInterface.Stub.asInterface(service); myContext.registerReceiver( myReceiver, new IntentFilter(FBReaderIntents.Event.CONFIG_OPTION_CHANGE) ); } final List<Runnable> actions; synchronized (myDeferredActions) { actions = new ArrayList<Runnable>(myDeferredActions); myDeferredActions.clear(); } for (Runnable a : actions) { a.run(); } } // method from ServiceConnection interface public synchronized void onServiceDisconnected(ComponentName name) { myContext.unregisterReceiver(myReceiver); } }