/*
* Funambol is a mobile platform developed by Funambol, Inc.
* Copyright (C) 2009 Funambol, Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by
* the Free Software Foundation with the addition of the following permission
* added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
* WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* 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 Affero General Public License
* along with this program; if not, see http://www.gnu.org/licenses or write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA.
*
* You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
* 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Powered by Funambol" logo. If the display of the logo is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Powered by Funambol".
*/
package de.chbosync.android.syncmlclient;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import android.telephony.TelephonyManager;
import com.funambol.client.configuration.Configuration;
import com.funambol.client.customization.Customization;
import com.funambol.client.source.AppSyncSourceManager;
import com.funambol.syncml.spds.DeviceConfig;
import com.funambol.util.Base64;
/**
* Container for the main client client configuration information. Realized using
* the singleton pattern. Access this class using the getInstance() method
* invocation.
*/
public class AndroidConfiguration extends Configuration {
private static final String TAG_LOG = "AndroidConfiguration";
/** Key for the preferences file, will lead to file "fnblPref.xml"
* in the app's folder "shared_prefs".
*/
public static final String KEY_FUNAMBOL_PREFERENCES = "fnblPref";
private static AndroidConfiguration instance = null;
private Context context;
protected SharedPreferences settings;
protected SharedPreferences.Editor editor;
private DeviceConfig devconf;
/**
* Private contructor to enforce the Singleton implementation.
*
* The SharedPreferences will be saved at the following path on the Android device:
* /data/data/de.chbosync.android.syncmlclient/shared_prefs/fnblPref.xml
*
* @param context the application Context
* @param customization the Customization object passed by the getInstance
* call
* @param appSyncSourceManager the AppSyncSourceManager object. Better to
* use an AndroidAppSyncSourceManager or an extension of its super class
*/
private AndroidConfiguration(Context context,
Customization customization,
AppSyncSourceManager appSyncSourceManager)
{
super(customization, appSyncSourceManager);
this.context = context;
settings = context.getSharedPreferences(KEY_FUNAMBOL_PREFERENCES, 0); // Name for preferences file: fnblPref.xml
editor = settings.edit();
}
/**
* Static method that returns the AndroidConfiguration unique instance
* @param context the application Context object
* @param customization the AndoidCustomization object used in this client
* @param appSyncSourceManager the AppSyncSourceManager object. Better to
* use an AndroidAppSyncSourceManager or an extension of its super class
* @return AndroidConfiguration an AndroidConfiguration unique instance
*/
public static AndroidConfiguration getInstance(Context context,
Customization customization,
AppSyncSourceManager appSyncSourceManager)
{
if (instance == null) {
instance = new AndroidConfiguration(context, customization, appSyncSourceManager);
}
return instance;
}
/**
* Dispose this object referencing it with the null object
*/
public static void dispose() {
instance = null;
}
/**
* Load the value referred to the configuration given the key
* @param key the String formatted key representing the value to be loaded
* @return String String formatted value related to the given key
*/
protected String loadKey(String key) {
return settings.getString(key, null);
}
/**
* Save the loaded twin key-value using the android context package
* SharedPreferences.Editor instance
* @param key the key to be saved
* @param value the value related to the key String formatted
*/
protected void saveKey(String key, String value) {
editor.putString(key, value);
}
/**
* Save the loaded twin key-value using the android context package
* SharedPreferences.Editor instance
* @param key the key to be saved
* @param value the value related to the key byte[] formatted
*/
public void saveByteArrayKey(String key, byte[] value) {
String b64 = new String(Base64.encode(value));
saveKey(key, b64);
}
/**
* Load the value referred to the configuration given the key and the
* default value
* @param key the String formatted key representing the value to be loaded
* @param defaultValue the default byte[] formatted value related to the
* given key
* @return byte[] String formatted vlaue related to the give key byte[]
* formatted
*/
public byte[] loadByteArrayKey(String key, byte[] defaultValue) {
String b64 = loadKey(key);
if (b64 != null) {
return Base64.decode(b64);
} else {
return defaultValue;
}
}
/**
* Commit the changes
* @return true if new values were correctly written into the persistent
* storage
*/
public boolean commit() {
return editor.commit();
}
/**
* Get the device id related to this client. Useful when doing syncml
* requests
* @return String the device id that is formatted as the string "fac-" plus
* the information of the deviceId field got by the TelephonyManager service
*/
protected String getDeviceId() {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
// must have android.permission.READ_PHONE_STATE
String deviceId = tm.getDeviceId();
return ((AndroidCustomization)customization).getDeviceIdPrefix() + deviceId;
}
/**
* Get the device related configuration
* @return DeviceConfig the DeviceConfig object related to this device
*/
public DeviceConfig getDeviceConfig() {
if (devconf != null) {
return devconf;
}
devconf = new DeviceConfig();
devconf.setMan(Build.MANUFACTURER);
devconf.setMod(Build.MODEL);
// See here for possible values of SDK_INT
// http://developer.android.com/reference/android/os/Build.VERSION_CODES.html
devconf.setSwV(Build.VERSION.CODENAME + "(" + Build.VERSION.SDK_INT + ")");
devconf.setFwV(devconf.getSwV());
devconf.setHwV(Build.FINGERPRINT);
devconf.setDevID(getDeviceId());
devconf.setMaxMsgSize(64 * 1024);
devconf.setLoSupport(true);
devconf.setUtc(true);
devconf.setNocSupport(true);
devconf.setWBXML(customization.getUseWbxml());
return devconf;
}
/**
* Get the user agent id related to this client. Useful when doing syncml
* requests.
*/
protected String getUserAgent() {
StringBuffer ua = new StringBuffer( ((AndroidCustomization)customization).getUserAgentName() );
ua.append(" ");
String appVersion = AndroidUtils.getVersionNumberFromManifest(context);
ua.append(appVersion);
return ua.toString();
}
/**
* Migrate the configuration (anything specific to the client)
*/
@Override
protected void migrateConfig() {
// From 6 to 7 means from Diablo to Gallardo, where we introduced a new
// mechanism for picture sync. We need to check what the server supports
// to switch to the new method.
if ("6".equals(version)) {
setForceServerCapsRequest(true);
}
// In version 11 we introduced the c2sPushEnabled property. On Android
// we can use the master auto sync in order to initialize it to a proper
// value.
int versionNumber = Integer.parseInt(version);
if(versionNumber < 11) {
boolean masterAutoSync = ContentResolver.getMasterSyncAutomatically();
setC2SPushEnabled(masterAutoSync);
}
// Now migrate the basic configuration (this will update version)
super.migrateConfig();
}
// *** Starting here: Methods/attributes added for ChBoSync ***
/** Key for the preference "showDummyButtonForNotesSyncing". */
protected static final String CONF_SHOW_DUMMY_BUTTON_FOR_SYNCING_NOTES = "DUMMY_BUTTON_FOR_SYNCING_NOTES";
/** Member variable holding the current state of the preference value "showDummyButtonForNotesSyncing". */
protected boolean showDummyButtonForNotesSyncing = true;
/**
*
* @return <tt>true</tt> if dummy button instead of sync button
* for notes should be shown when "OI Notepad" is not available
* on the device; <tt>false</tt> otherwise.
*/
public boolean getShowDummyButtonForNotesSyncing() {
return showDummyButtonForNotesSyncing;
}
/**
*
* @param enabled <tt>true</tt> if dummy button instead of sync button
* for notes should be shown when "OI Notepad" is not available
* on the device; <tt>false</tt> otherwise.
*/
public void setShowDummyButtonForNotesSyncing(boolean enabled) {
showDummyButtonForNotesSyncing = enabled;
}
/**
* Overwriting of method for loading of preferences from shared preferences, so
* that preference for "showDummyButtonForNotesSyncing" is also loaded.
*/
@Override
public int load() {
if (loaded) {
return CONF_OK;
}
showDummyButtonForNotesSyncing = loadBooleanKey(CONF_SHOW_DUMMY_BUTTON_FOR_SYNCING_NOTES, true); // "true" is default value
return super.load();
}
/**
* Overwriting of method for loading of preferences from shared preferences, so
* that preference for "showDummyButtonForNotesSyncing" is also saved.
*
* @return Either {@link com.funambol.client.configuration.Configuration.CONF_OK} or
* {@link com.funambol.client.configuration.Configuration.CONF_INVALID}.
*/
@Override
public int save() {
saveBooleanKey(CONF_SHOW_DUMMY_BUTTON_FOR_SYNCING_NOTES, showDummyButtonForNotesSyncing);
return super.save();
}
}