/* * Funambol is a mobile platform developed by Funambol, Inc. * Copyright (C) 2010 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 java.lang.reflect.Constructor; import android.accounts.Account; import android.app.Activity; import android.content.ContentResolver; import android.net.Uri; import com.funambol.client.source.AppSyncSource; import com.funambol.client.ui.DevSettingsUISyncSource; import com.funambol.client.ui.Screen; import com.funambol.client.ui.SettingsUISyncSource; import com.funambol.client.ui.UISyncSource; import com.funambol.sync.SyncSource; import com.funambol.util.Log; import com.funambol.util.StringUtil; import de.chbosync.android.syncmlclient.activities.AndroidUISyncSource; import de.chbosync.android.syncmlclient.activities.settings.AndroidSettingsUISyncSource; import de.chbosync.android.syncmlclient.controller.AndroidController; /** * Implementation of the AppSyncSource for the Android client. Define the * generic AppSyncSource for this particular client */ public class AndroidAppSyncSource extends AppSyncSource { /** The Log String */ private static final String TAG_LOG = "AndroidAppSyncSource"; /** Direct method value = 0 */ public static final int DIRECT = 0; /** Service method value = 1 */ public static final int SERVICE = 1; /** SyncAdapter method value = 2 */ public static final int SYNC_ADAPTER = 2; public static final String AUTHORITY_TYPE_ALL = "all"; private String authority; private String authorityType; private int syncMethod; private boolean isMedia = false; private Uri providerUri; /** * Constructor * @param name is the String formatted name of the AndroidAppSyncSource to * be built * @param source is the SyncSource object to be wrapped by this object */ public AndroidAppSyncSource(String name, SyncSource source) { super(name, source); syncMethod = SYNC_ADAPTER; authorityType = AUTHORITY_TYPE_ALL; } /** * Constructor * @param name is the String formatted name of the AndroidAppSyncSource to * be built */ public AndroidAppSyncSource(String name) { this(name, null); } /** * Get the String representation of this instance related authority * @return String the String formatted representation of the authority * related to this AppSyncSource */ public String getAuthority() { return authority; } /** * Set the String representation of this instance related authority * @param String is the authority to be set */ public void setAuthority(String authority) { this.authority = authority; } public String getAuthorityType() { return authorityType; } public void setAuthorityType(String authorityType) { this.authorityType = authorityType; } @Override public boolean getIsMedia() { return isMedia; } @Override public void setIsMedia(boolean value) { isMedia = value; } /** * Get the sync Method related to this AppSyncSource * @return int the int value related to the sync method defined for this * AndroidAppSyncSource */ public int getSyncMethod() { return syncMethod; } /** * Set the sync Method related to this AppSyncSource: valid values are * defined as constants in this class - SERVICE, DIRECT, SYNC_ADAPTER - * @param int the int value related to the sync method defined for this * AndroidAppSyncSource */ public void setSyncMethod(int syncMethod) { this.syncMethod = syncMethod; } public Uri getProviderUri() { return providerUri; } public void setProviderUri(Uri providerUri) { this.providerUri = providerUri; } /** * Create the SettingsUISyncSource object valid for this * AndroidAppSyncSource using the given screen to retrieve the related * activity. * @param screen the Screen object * @return the created SettingsUISyncSource instance */ @Override public SettingsUISyncSource createSettingsUISyncSource(Screen screen) { if (settingsClass != null) { Activity activity = (Activity)screen.getUiScreen(); // Invoke the constructor try { Constructor c = settingsClass.getConstructor(new Class[]{Class.forName("android.app.Activity")}); settingsUISource = (AndroidSettingsUISyncSource)c.newInstance(activity); } catch (Exception e) { Log.error(TAG_LOG, "Cannot create settings UI view", e); } } else { Log.error(TAG_LOG, "Cannot create instance for source settings"); } if (settingsUISource == null) { throw new IllegalStateException("Cannot create settings for source"); } return settingsUISource; } @Override public DevSettingsUISyncSource createDevSettingsUISyncSource(Screen screen) { if (devSettingsClass != null) { Activity activity = (Activity)screen.getUiScreen(); // Invoke the constructor try { Constructor c = devSettingsClass.getConstructor(new Class[]{Class.forName("android.app.Activity")}); devSettingsUISource = (DevSettingsUISyncSource)c.newInstance(activity); } catch (Exception e) { Log.error(TAG_LOG, "Cannot create settings UI view", e); } } else { Log.info(TAG_LOG, "No dev settings for source " + getName()); } return devSettingsUISource; } /** * Create the UISyncSource representation for this object. The Android * client use buttons representation. * @param screen the screen object * @return UISyncSource the AndroidAppSyncSource UI representation object: * AndroidButtonUISyncSource */ @Override public UISyncSource createButtonUISyncSource(Screen screen) { if (buttonClass != null) { Activity activity = (Activity)screen.getUiScreen(); // Invoke the constructor try { Constructor c = buttonClass.getConstructor(new Class[] { Class.forName("android.app.Activity") } ); uiSource = (AndroidUISyncSource)c.newInstance(activity); } catch (Exception e) { Log.error(TAG_LOG, "Cannot create button UI view for: " + getName(), e); } } else { Log.error(TAG_LOG, "Cannot create instance for button UI view for: " + getName()); } if (uiSource == null) { throw new IllegalStateException("Cannot create representation for source"); } return uiSource; } /** * Create the UISyncSource representation for this object when it is alone * in the screen. The Android client use buttons representation. * @param screen the screen object * @return UISyncSource the AndroidAppSyncSource UI representation object: * AndroidButtonUISyncSource or null if it cannot be created */ @Override public UISyncSource createAloneUISyncSource(Screen screen) { if (aloneClass != null) { Activity activity = (Activity)screen.getUiScreen(); // Invoke the constructor try { Constructor c = aloneClass.getConstructor(new Class[] { Class.forName("android.app.Activity") } ); uiSource = (AndroidUISyncSource)c.newInstance(activity); } catch (Exception e) { Log.error(TAG_LOG, "Cannot create button UI view for: " + getName(), e); } } return uiSource; } /** * Re-Apply the source configuration to this object in order to re-define * it: if a NATIVE Account exists it just define if it is syncable or not * using the related content resolver. */ @Override public void reapplyConfiguration() { if(StringUtil.isNullOrEmpty(authority)) { return; } if (Log.isLoggable(Log.TRACE)) { Log.trace(TAG_LOG, "Reapply configuration for source " + getName() + " with active " + config.getActive() + " and enabled " + config.getEnabled()); } int syncable = config.getActive() && config.getEnabled() ? 1 : 0; Account account = AndroidController.getNativeAccount(); if(account != null) { // Media syncable state cannot be updated since there are multiple // sources pointing to the same native authority if(!getIsMedia()) { ContentResolver.setIsSyncable(account, authority, syncable); } } } public void accountCreated(String accountName, String accountType) { // By default we don't do anything } }