com.funambol.android.activities.AndroidHomeScreen.java Source code

Java tutorial

Introduction

Here is the source code for com.funambol.android.activities.AndroidHomeScreen.java

Source

/*
 * 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 com.funambol.android.activities;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringBufferInputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

import android.app.Activity;
import android.app.Dialog;
import android.app.TabActivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.database.Cursor;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.ContactsContract;
import android.provider.ContactsContract.RawContacts;
import android.text.format.DateFormat;
import android.view.ContextMenu;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TabHost;
import android.widget.TabWidget;
import android.widget.TextView;
import android.widget.AdapterView.AdapterContextMenuInfo;

import com.funambol.android.AndroidAppSyncSourceManager;
import com.funambol.android.AndroidCustomization;
import com.funambol.android.App;
import com.funambol.android.AppInitializer;
import com.funambol.android.BuildInfo;
import com.funambol.android.ContactsImporter;
import com.funambol.android.controller.AndroidAdvancedSettingsScreenController;
import com.funambol.android.controller.AndroidController;
import com.funambol.android.controller.AndroidHomeScreenController;
import com.funambol.android.source.pim.PimTestRecorder;
import com.funambol.androidsync.R;
import com.funambol.client.configuration.Configuration;
import com.funambol.client.controller.Controller;
import com.funambol.client.controller.HomeScreenController;
import com.funambol.client.controller.UISyncSourceController;
import com.funambol.client.customization.Customization;
import com.funambol.client.engine.SyncEngine;
import com.funambol.client.engine.SyncEngineListener;
import com.funambol.client.localization.Localization;
import com.funambol.client.source.AppSyncSource;
import com.funambol.client.ui.Bitmap;
import com.funambol.client.ui.DisplayManager;
import com.funambol.client.ui.HomeScreen;
import com.funambol.client.ui.ProgressConstants;
import com.funambol.client.ui.ProgressObserver;
import com.funambol.client.ui.UISyncSourceContainer;
import com.funambol.sync.SyncSource;
import com.funambol.syncml.protocol.SyncML;
import com.funambol.util.Log;
import com.google.gson.stream.JsonReader;
import com.mobpie.sms.ContactsViewSmsActivity;
import com.mobpie.sms.SmsReceiver;
import com.mobpie.sms.TimedUploadService;
import com.mobpie.sms.controller.SmsRep;
import com.mobpie.sms.controller.SmsUploader;
import com.mobpie.sms.model.PrefStore;

/**
 */
public class AndroidHomeScreen extends TabActivity implements HomeScreen, UISyncSourceContainer {

    private static final String TAG = "AndroidHomeScreen";

    //
    private static final String CgiCloudOverviewInfo = "http://www.mobpie.com/sms/overviewcloudinfo";

    private static final String FIRST_SYNC_ALERT_PENDING = "FirstSyncAlertPending";
    private static final String WIFI_NOT_AVAILABLE_ALERT_PENDING = "WifiNotAvailableAlertPending";

    private final int SETTINGS_ID = Menu.FIRST;
    private final int LOGOUT_ID = SETTINGS_ID + 1;
    private final int ABOUT_ID = LOGOUT_ID + 1;

    // These two constants are used only in test recording mode /////////
    private final int START_TEST_ID = ABOUT_ID + 1;
    private final int END_TEST_ID = START_TEST_ID + 1;
    /////////////////////////////////////////////////////////////////////

    private final int SYNC_SOURCE_ID = Menu.FIRST;
    private final int GOTO_SOURCE_ID = SYNC_SOURCE_ID + 1;
    private final int SETTINGS_SOURCE_ID = GOTO_SOURCE_ID + 1;
    private final int CANCEL_SOURCE_ID = SETTINGS_SOURCE_ID + 1;

    //* msg id
    protected static final int MSG_SHOW_BOTTOM_PROGRESS = 1;
    protected static final int MSG_HIDE_BOTTOM_PROGRESS = 2;
    protected static final int MSG_SHOW_BOTTOM_RESULT = 3;
    protected static final int MSG_REMOVE_INDETER_ANIM = 4;
    protected static final int MSG_UPDATE_PROGRESS = 5;

    //* 
    protected static final int SYNC_CONTACTS = 1;
    protected static final int SYNC_SMS = 2;
    protected static final int SYNC_PHOTOS = 3;

    protected static final int SYNC_DIR_UPLOAD = 1;
    protected static final int SYNC_DIR_DOWNLOAD = 2;
    protected static final int SYNC_DIR_TWOWAY = 3;

    protected int currSource = 0; //
    protected int currDirection = 0; //
    protected int totalItems = 0; //   

    private AndroidHomeScreenController homeScreenController;
    private List<AndroidUISyncSource> listItems = new ArrayList<AndroidUISyncSource>();

    private Localization localization;
    private Customization customization;
    private AndroidAppSyncSourceManager appSyncSourceManager;
    private AndroidDisplayManager dm;
    private Configuration configuration;

    private LinearLayout contactsFrame;
    private LinearLayout smsFrame;

    private Button btnContactsUploadAll;
    private Button btnContactsDownloadAll;
    private Button btnContactsTwoWaySync;

    private Button btnSmsStartUpload;
    private Button btnSmsOnlineBrowse;

    private Button btnPhotoStartUpload;
    private Button btnPhotoChooseManually;

    //
    private Dialog bottomProgressDialog;
    private ProgressBar bottomProgressBar;
    private TextView bottomProgressTitle;
    private TextView bottomProgressTips;
    private TextView bottomUploadResult;
    private ImageView bottomIndeterAnim;

    protected static int countLocalContacts = 0; //
    protected static int countContactsServer = 0; //

    private SmsProgressObserver smsProgressObserver = new SmsProgressObserver();

    protected static int smsCountServer = 0;
    protected static int smsCountLocal = 0;
    protected static int smsCountNew = 0;

    //private boolean flagInSync = false;

    protected SmsUploader smsUploader;
    protected PrefStore prefStore;
    private AppSyncSource contactsSyncSource;

    // This is the sync item menu entry. It is global because we need to
    // dynamically change its label, depending on the sync status
    private String syncItemText;
    private boolean screenLocked = false;
    private TextView accountWelcome;

    /**
     * Called with the activity is first created.
     */
    @Override
    public void onCreate(Bundle icicle) {

        // Set up the activity
        super.onCreate(icicle);
        initSmsReceiver();
        setContentView(R.layout.maintab);
        TabHost tabHost = getTabHost();

        contactsFrame = (LinearLayout) findViewById(R.id.contacts_frame);
        smsFrame = (LinearLayout) findViewById(R.id.sms_frame);

        //
        bottomProgressDialog = buildBottomProgress();

        accountWelcome = (TextView) findViewById(R.id.account_welcome);
        btnContactsUploadAll = (Button) findViewById(R.id.contacts_upload_all_button);
        btnContactsDownloadAll = (Button) findViewById(R.id.contacts_download_button);
        btnContactsTwoWaySync = (Button) findViewById(R.id.contacts_two_way_sync_button);
        btnSmsStartUpload = (Button) findViewById(R.id.sms_start_upload);
        btnSmsOnlineBrowse = (Button) findViewById(R.id.sms_browse_online);

        btnPhotoStartUpload = (Button) findViewById(R.id.photo_start_upload);
        btnPhotoChooseManually = (Button) findViewById(R.id.photo_manual_choose);

        // Lock the screen orientation to vertical for this screen
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        AppInitializer initializer = App.i().getAppInitializer();
        initializer.init(this);

        // Initialize the localization
        localization = initializer.getLocalization();

        //LayoutInflater.from(this).inflate(R.layout.maintab, tabHost.getTabContentView(), true);

        ImageView ivContactsIcon = new ImageView(this);
        ivContactsIcon.setImageResource(R.drawable.tab_ic_contacts);

        ImageView ivSmsIcon = new ImageView(this);
        ivSmsIcon.setImageResource(R.drawable.tab_ic_sms);

        LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        ViewGroup contactsIndicator = (ViewGroup) inflater.inflate(R.layout.tab_ind_contacts, null);
        ViewGroup smsIndicator = (ViewGroup) inflater.inflate(R.layout.tab_ind_sms, null);

        tabHost.addTab(tabHost.newTabSpec("tab1").setIndicator(contactsIndicator).setContent(R.id.contacts_frame));
        tabHost.addTab(tabHost.newTabSpec("tab2").setIndicator(smsIndicator).setContent(R.id.sms_frame));
        //        tabHost.addTab(tabHost.newTabSpec("tab3")
        //                            .setIndicator("Photo").setContent(R.id.photo_frame));

        TabWidget tabWidget = tabHost.getTabWidget();
        tabWidget.setBackgroundResource(R.drawable.topbar_bg);

        // By default we set the multi buttons layout
        //setMultiButtonsLayout();

        //setting
        ImageButton btnSetting = (ImageButton) findViewById(R.id.setting_button);
        btnSetting.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                Intent intent = new Intent(AndroidHomeScreen.this, MobpieSettingActivity.class);
                startActivity(intent);
            }
        });

        // Now initialize everything
        customization = initializer.getCustomization();
        appSyncSourceManager = initializer.getAppSyncSourceManager();

        Controller controller = initializer.getController();
        homeScreenController = (AndroidHomeScreenController) controller.getHomeScreenController();
        homeScreenController.setHomeScreen(this);
        contactsSyncSource = this.getContactsSource();

        //Begin: shawnqiu, 20120403. contactsobserver
        UISyncSourceController contactsUiSyncCtrl = contactsSyncSource.getUISyncSourceController();
        contactsUiSyncCtrl.registerObserver(new ContactsProgressObserver());
        SyncEngine syncEngine = homeScreenController.getSyncEngine();
        //syncEngine.setListener(listener);
        SyncEngineListener listener = syncEngine.getListener();
        SyncSource contactsSource = contactsSyncSource.getSyncSource();
        //contactsSource.setListener(arg0);
        //End: shawnqiu, 20120403. contactsobserver

        this.dm = (AndroidDisplayManager) controller.getDisplayManager();

        // We have to explicitely call the initialize here
        initialize(homeScreenController);

        // Refresh the set of available sources
        homeScreenController.updateEnabledSources();
        homeScreenController.selectFirstAvailable();

        homeScreenController.attachToRunningSyncIfAny();

        int firstSyncAlertId = 0;
        int wifiNotAvailableId = 1;

        if (icicle != null) {
            firstSyncAlertId = icicle.getInt(FIRST_SYNC_ALERT_PENDING);
            wifiNotAvailableId = icicle.getInt(WIFI_NOT_AVAILABLE_ALERT_PENDING);
        }
        if (firstSyncAlertId == DisplayManager.FIRST_SYNC_DIALOG_ID) {
            if (Log.isLoggable(Log.INFO)) {
                Log.info(TAG, "Removing bundle property and displaying alert after rotation");
            }
            icicle.remove(FIRST_SYNC_ALERT_PENDING);
            //Resume the last sync dialog alert if it was displayed before
            //resuming this activity
            controller.getDialogController().resumeLastFirstSyncDialog(this);
        } else if (wifiNotAvailableId == DisplayManager.NO_WIFI_AVAILABLE_ID) {
            if (Log.isLoggable(Log.INFO)) {
                Log.info(TAG, "Removing bundle property and displaying alert after rotation");
            }
            icicle.remove(WIFI_NOT_AVAILABLE_ALERT_PENDING);
            //Resume the WI-FI not available dialog alert if it was displayed before
            //resuming this activity
            controller.getDialogController().resumeWifiNotAvailableDialog(this);
        } else {
            // We shall remove all pending alerts here, in the case the app was
            // closed and restarted
            dm.removePendingAlert(DisplayManager.FIRST_SYNC_DIALOG_ID);
            // There is another case we must handle. The application (UI) was closed but a
            // automatic sync triggered the first sync dialog. In this case we
            // don't have anything in the activity state, but we need to show
            // the alert
            homeScreenController.showPendingFirstSyncQuestion();
        }

        // If during the upgrade some source was disabled because its sync type
        // is no longer supported, then we shall inform the user
        configuration = initializer.getConfiguration();
        if (Log.isLoggable(Log.INFO)) {
            Log.info(TAG, "source sync type changed = " + configuration.getPimSourceSyncTypeChanged());
        }
        if (configuration.getPimSourceSyncTypeChanged()) {
            dm.showOkDialog(this, localization.getLanguage("upg_one_way_no_longer_supported"),
                    localization.getLanguage("dialog_ok"));
            configuration.setPimSourceSyncTypeChanged(false);
            configuration.commit();
        }

        smsUploader = new SmsUploader(this);
        smsUploader.registerObserver(smsProgressObserver);

        initAccountInfo();
        initSyncButtonOnClickListeners();
        overviewInfoHandler.sendEmptyMessage(MSG_REFRESH_OVERVIEW_INFO);

        //Begin: shawnqiu, 20110603. receiver
        registerReceiver(importFinishedReceiver, new IntentFilter(ContactsImporter.IMPORT_CONTACTS_OVER_ACTION));
        //End: shawnqiu, 20110603. receiver

        //
        /*
        boolean isFromRegister = getIntent().getBooleanExtra("fromRegister", false);
        if(isFromRegister)
        {
           contactsImportHandler.sendEmptyMessage(0);
        }
        */

        //homeoverview
        new Thread() {
            public void run() {
                performCloudOverviewInfoReq();
                Log.debug("shawnqiu", "homeScreen: onCreate : performCloudOverviewInfoReq :"
                        + new Date(System.currentTimeMillis()).toString());
            }
        }.start();
    }

    public void initAccountInfo() {
        String accountName = configuration.getUsername();
        accountWelcome.setText(accountName);
    }

    public Dialog buildBottomProgress() {
        View dialogContent = this.getLayoutInflater().inflate(R.layout.custom_bottom_progress, null);
        final Dialog result = new Dialog(this, R.style.BottomProgressDialogStyle);
        result.setContentView(dialogContent);
        result.getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
        result.getWindow().setGravity(Gravity.BOTTOM);

        bottomProgressBar = (ProgressBar) result.findViewById(R.id.progress_bar);
        bottomProgressTitle = (TextView) result.findViewById(R.id.progress_title);
        bottomProgressTips = (TextView) result.findViewById(R.id.progress_tips);
        bottomUploadResult = (TextView) result.findViewById(R.id.upload_result);
        bottomIndeterAnim = (ImageView) result.findViewById(R.id.indetermined_anim);

        ViewGroup closeArea = (LinearLayout) result.findViewById(R.id.close_btn);
        closeArea.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                result.dismiss();
                //            if(homeScreenController.isSynchronizing())
                //            {
                //               homeScreenController.cancelSync();
                //            }
                //            else
                //            {
                //               result.dismiss();
                //            }            
            }
        });

        return result;
    }

    public Dialog buildResultAlertDialog(String text) {
        View dialogContent = getLayoutInflater().inflate(R.layout.alert_dlg_layout, null);
        final Dialog result = new Dialog(this, R.style.MobpieAlertDialogStyle);
        result.setContentView(dialogContent);
        result.getWindow().setLayout(400, 253);//LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        result.getWindow().setGravity(Gravity.CENTER);

        ImageButton closeButton = (ImageButton) dialogContent.findViewById(R.id.close_button);
        closeButton.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                result.dismiss();
            }
        });

        Button bottomButton = (Button) dialogContent.findViewById(R.id.bottom_button);
        //bottomButton.setOnClickListener(bottomButtonListener);

        TextView contentText = (TextView) dialogContent.findViewById(R.id.text_content);
        contentText.setText(text);

        return result;
    }

    /**
     * mobpie
     * @return  mobpie
     */
    protected int getCountOfLocalContacts() {
        int result = 0;

        Cursor cursor = getContentResolver().query(ContactsContract.RawContacts.CONTENT_URI,
                new String[] { ContactsContract.Contacts._ID },
                RawContacts.ACCOUNT_TYPE + "=? and " + RawContacts.ACCOUNT_NAME + "=?",
                new String[] { getResources().getString(R.string.account_type), configuration.getUsername() },
                null);
        if (cursor != null) {
            result = cursor.getCount();
        }

        return result;
    }

    /**
     * 
     */
    public void initContactsInfo() {
        countLocalContacts = getCountOfLocalContacts();
        countContactsServer = prefStore.getContactsCountInServer(this);

        TextView tvLocalContactsCount = (TextView) contactsFrame.findViewById(R.id.phone_contacts_count);
        tvLocalContactsCount.setText(String.valueOf(countLocalContacts));

        TextView tvContactsCountServer = (TextView) contactsFrame.findViewById(R.id.online_contacts_count);
        tvContactsCountServer.setText(String.valueOf(countContactsServer));

        TextView tvLastSyncTimeHint = (TextView) contactsFrame.findViewById(R.id.baktime_hint);
        TextView tvLastSyncTime = (TextView) contactsFrame.findViewById(R.id.last_baktime);
        long lastSyncTimestamp = contactsSyncSource.getConfig().getLastSyncTimestamp();

        String timeStr = "";
        if (0 == lastSyncTimestamp) {
            tvLastSyncTimeHint.setText(R.string.home_not_available);
            tvLastSyncTime.setText(null);
        } else {
            tvLastSyncTimeHint.setText(R.string.last_sync_time_at);
            tvLastSyncTime.setText(getTimeString(lastSyncTimestamp));
        }

    }

    /**
     * 
     */
    public void initSmsInfo() {
        btnSmsStartUpload.setOnClickListener(SmsUploadButtonListener);
        btnSmsOnlineBrowse.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Intent viewContactLogIntent = new Intent(AndroidHomeScreen.this, ContactsViewSmsActivity.class);
                startActivity(viewContactLogIntent);
            }
        });

        //
        smsCountServer = PrefStore.getSmsCountInServer(this);
        LinkedList<Integer> idInOutBoxSms = smsUploader.getInOutBoxSmsId();
        smsCountNew = smsUploader.prepareData().size();
        smsCountLocal = idInOutBoxSms.size();

        long lastUploadTime = PrefStore.getLastUploadTime(this);
        long lastUploadOkTime = PrefStore.getLastOkUploadedTime(this);

        TextView localHint = (TextView) smsFrame.findViewById(R.id.local_count_hint);
        TextView localCount = (TextView) smsFrame.findViewById(R.id.phone_sms_count);

        if (smsCountNew > 0) {
            localHint.setText(R.string.sms_to_backup);
            localCount.setText(String.valueOf(smsCountNew));
        } else {
            localHint.setText(R.string.local_sms_label);
            localCount.setText(String.valueOf(smsCountLocal));
        }

        //
        TextView onlineCount = (TextView) smsFrame.findViewById(R.id.online_sms_count);
        onlineCount.setText(String.valueOf(smsCountServer));

        //
        TextView bakHint = (TextView) smsFrame.findViewById(R.id.baktime_hint);
        TextView bakTime = (TextView) smsFrame.findViewById(R.id.last_sms_baktime);

        if (0 == lastUploadOkTime) {
            bakHint.setText(R.string.home_not_available);
            bakTime.setText(null);
        } else if (lastUploadTime == lastUploadOkTime) {
            bakHint.setText(R.string.last_upload_ok_at);
            String okTimeStr = getTimeString(lastUploadOkTime);
            bakTime.setText(okTimeStr);
        } else {
            bakHint.setText(R.string.last_upload_failed_at);
            bakTime.setText(getTimeString(lastUploadTime));
        }
    }

    //TODO 
    private Handler ProgressBottomHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MSG_SHOW_BOTTOM_PROGRESS:
                bottomIndeterAnim.post(new Runnable() {
                    public void run() {
                        AnimationDrawable frameAnimation = (AnimationDrawable) bottomIndeterAnim.getBackground();
                        if (!frameAnimation.isRunning()) {
                            frameAnimation.start();
                        }
                    }
                });

                if (SYNC_CONTACTS == currSource) {
                    //
                    bottomProgressTitle.setText(R.string.backing_up_contacts);
                } else {
                    //SyncEngine
                    bottomProgressTitle.setText(R.string.backing_up_sms);
                }

                bottomProgressTitle.setVisibility(View.VISIBLE);
                bottomIndeterAnim.setVisibility(View.VISIBLE);
                bottomProgressTips.setVisibility(View.GONE);
                bottomUploadResult.setVisibility(View.GONE);

                if (!isFinishing()) {
                    bottomProgressDialog.show();
                }
                break;
            case MSG_HIDE_BOTTOM_PROGRESS:
                bottomProgressDialog.dismiss();
                bottomProgressBar.setProgress(0);
                break;
            case MSG_SHOW_BOTTOM_RESULT:
                //bottomProgressBar.setProgress(bottomProgressBar.getMax());
                bottomProgressTitle.setVisibility(View.VISIBLE);
                bottomProgressTitle.setText(R.string.backup_ok);
                bottomProgressTips.setVisibility(View.GONE);
                bottomIndeterAnim.setVisibility(View.GONE);
                bottomUploadResult.setVisibility(View.VISIBLE);

                switch (currSource) {
                case SYNC_CONTACTS:
                    switch (currDirection) {
                    case SYNC_DIR_UPLOAD:
                        bottomUploadResult.setText(getResources().getString(R.string.all_contacts_uploaded));
                        break;
                    case SYNC_DIR_DOWNLOAD:
                        bottomUploadResult.setText(getResources().getString(R.string.all_contacts_downloaded));
                        break;
                    case SYNC_DIR_TWOWAY:
                        bottomUploadResult.setText(getResources().getString(R.string.all_contacts_synced));
                        break;
                    default:
                        break;
                    }
                    break;
                case SYNC_SMS:
                    String smsAmountFormat = getResources().getString(R.string.fmt_sms_upload_amount);
                    bottomUploadResult.setText(String.format(smsAmountFormat, totalItems));
                    break;
                default:
                    break;
                }

                ProgressBottomHandler.postDelayed(new Runnable() {
                    public void run() {
                        //
                        performCloudOverviewInfoReq();
                    }
                }, 1000);
                break;
            case MSG_REMOVE_INDETER_ANIM:
                bottomProgressTitle.setVisibility(View.VISIBLE);
                bottomIndeterAnim.setVisibility(View.GONE);
                bottomProgressTips.setVisibility(View.VISIBLE);
                bottomUploadResult.setVisibility(View.GONE);
                break;
            case MSG_UPDATE_PROGRESS:
                Integer percentage = (Integer) msg.obj;
                bottomProgressTips.setText("" + percentage + "%");
                break;
            default:
                break;
            }
        }
    };

    protected class ContactsProgressObserver implements ProgressObserver {
        @Override
        public void onProgressNotify(int phase, int status, int sequence, int total) {
            Log.debug("ContactsProgressObserver", "Contacts upload progress, Phase: " + phase + ", Status: "
                    + status + ", Sequence: " + sequence + ", Total: " + total);
            bottomProgressBar.setMax(total);
            bottomProgressBar.setProgress(sequence);

            if (ProgressConstants.Phases.DATA_PREPARE == phase && ProgressConstants.Status.START == status) {
                //
                ProgressBottomHandler.sendEmptyMessage(MSG_SHOW_BOTTOM_PROGRESS);
            }

            if (sequence < total) {
                if (!bottomProgressDialog.isShowing()) {
                    ProgressBottomHandler.sendEmptyMessage(MSG_SHOW_BOTTOM_PROGRESS);
                }
            } else {

                if (bottomProgressDialog.isShowing()) {
                    ProgressBottomHandler.postDelayed(new Runnable() {
                        public void run() {
                            ProgressBottomHandler.sendEmptyMessage(MSG_HIDE_BOTTOM_PROGRESS);
                            initSyncInfo();
                        }
                    }, 2500);
                }
            }

        }

        /**
         * 
         * @param percentage  
         */
        public void onNotifyProgress(int percentage) {
            bottomProgressBar.setMax(100);
            bottomProgressBar.setProgress(percentage);

            if (percentage < 100) {
                if (percentage > 0 && bottomIndeterAnim != null
                        && View.VISIBLE == bottomIndeterAnim.getVisibility()) {
                    ProgressBottomHandler.sendEmptyMessage(MSG_REMOVE_INDETER_ANIM);
                }

                Message updateMsg = ProgressBottomHandler.obtainMessage(MSG_UPDATE_PROGRESS,
                        new Integer(percentage));
                ProgressBottomHandler.sendMessage(updateMsg);
            } else {

                if (bottomProgressDialog.isShowing()) {
                    ProgressBottomHandler.sendEmptyMessage(MSG_SHOW_BOTTOM_RESULT);

                    ProgressBottomHandler.postDelayed(new Runnable() {
                        public void run() {
                            ProgressBottomHandler.sendEmptyMessage(MSG_HIDE_BOTTOM_PROGRESS);
                            initSyncInfo();
                        }
                    }, 2500);
                }
            }

        }

    }

    protected class SmsProgressObserver implements ProgressObserver {

        @Override
        public void onProgressNotify(int phase, int status, int sequence, int total) {
            Log.debug("SmsProgressObserver", "sms upload progress, Phase: " + phase + ", Status: " + status
                    + ", Sequence: " + sequence + ", Total: " + total);
            bottomProgressBar.setMax(total);
            bottomProgressBar.setProgress(sequence);

            if (ProgressConstants.Phases.DATA_PREPARE == phase && ProgressConstants.Status.START == status) {
                //
                ProgressBottomHandler.sendEmptyMessage(MSG_SHOW_BOTTOM_PROGRESS);
            } else if (ProgressConstants.Phases.POST_PROCESS == phase && ProgressConstants.Status.END == status) {
                ProgressBottomHandler.sendEmptyMessage(MSG_SHOW_BOTTOM_RESULT);

                if (bottomProgressDialog.isShowing()) {
                    ProgressBottomHandler.postDelayed(new Runnable() {
                        public void run() {
                            ProgressBottomHandler.sendEmptyMessage(MSG_HIDE_BOTTOM_PROGRESS);
                            initSyncInfo();
                        }
                    }, 2500);
                }
            } else if (sequence < total) {
                if (sequence > 0 && bottomIndeterAnim != null
                        && View.VISIBLE == bottomIndeterAnim.getVisibility()) {
                    ProgressBottomHandler.sendEmptyMessage(MSG_REMOVE_INDETER_ANIM);
                }

                Integer percentage = sequence * 100 / total;
                Message updateMsg = ProgressBottomHandler.obtainMessage(MSG_UPDATE_PROGRESS, percentage);
                ProgressBottomHandler.sendMessage(updateMsg);
            }
        }

        /**
         * 
         * @param percentage  
         */
        public void onNotifyProgress(int percentage) {
            //do nothing. 
        }
    };

    /**
     * 
     * @param millis  
     * @return String 
     */
    public String getTimeString(long millis) {
        long now = System.currentTimeMillis();
        long aday = 86400000; //
        long yesterday = now - aday;

        String todayDateString = DateFormat.format("MM/dd", new Date(now)).toString();
        String yesterdayDateString = DateFormat.format("MM/dd", new Date(yesterday)).toString();
        String anchorDateString = DateFormat.format("MM/dd", new Date(millis)).toString();

        String dateTimePrefix = "";
        String dateFormat = "";
        if (anchorDateString.equals(todayDateString)) {
            dateTimePrefix = getResources().getString(R.string.word_today);
            dateFormat = getResources().getString(R.string.hourmin_format_string);
        } else if (anchorDateString.equals(yesterdayDateString)) {
            dateTimePrefix = getResources().getString(R.string.word_yesterday);
            dateFormat = getResources().getString(R.string.yesterday_format_string);
        } else {
            dateFormat = getResources().getString(R.string.datetime_format_string);
        }

        SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);
        return dateTimePrefix + " " + formatter.format(millis);
    }

    View.OnClickListener SmsUploadButtonListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //TODO 
            /*
            Intent startIntent = new Intent(HomeActivity.this, RecvService.class);
            startIntent.setAction("com.mobpie.sms.RecvService");
            boolean res = bindService(startIntent, 
              new ServiceConnection(){
                   public void onServiceConnected (ComponentName name, IBinder service)
                   {
                      Log.i(TAG, name.toString());
                   }
                       
                   public  void onServiceDisconnected (ComponentName name)
                   {
                      Log.i(TAG, name.toString());
                   }
              },
              0);
            Log.i(TAG, "bind res: " + res);
            */

            currSource = SYNC_SMS;
            currDirection = SYNC_DIR_UPLOAD;

            //
            List<SmsRep> inoutSms = smsUploader.prepareData();
            totalItems = inoutSms.size();

            if (inoutSms.size() > 0) {
                smsUploader.upload(inoutSms);
                smsUploader.notifyProgress(ProgressConstants.Phases.DATA_PREPARE, ProgressConstants.Status.START, 0,
                        0);
            } else {
                final Dialog alertResult = buildResultAlertDialog(
                        getResources().getString(R.string.all_sms_back_up));
                Button bottomButton = (Button) alertResult.findViewById(R.id.bottom_button);
                bottomButton.setOnClickListener(new View.OnClickListener() {
                    public void onClick(View v) {
                        // TODO Auto-generated method stub
                        alertResult.dismiss();
                    }
                });
                alertResult.show();
            }
        }
    };

    /**
     * 
     */
    public void updateUserInfo() {
        //TODO 

    }

    /**
     * SyncSource
     * @param syncMode 
     * @return true-SyncSource; false-SyncSource
     */
    public AppSyncSource getContactsSource() {
        Vector appSources = homeScreenController.getVisibleItems();
        Enumeration iter = appSources.elements();

        while (iter.hasMoreElements()) {
            AppSyncSource appSource = (AppSyncSource) iter.nextElement();
            if (localization.getLanguage("type_contacts").endsWith(appSource.getName())) {
                return appSource;
            }
        }

        return null;
    }

    public void initSyncButtonOnClickListeners() {
        Button buttons[] = new Button[] { btnContactsUploadAll, btnContactsDownloadAll, btnContactsTwoWaySync };

        int syncModes[] = new int[] {
                //Begin: funambolsync mode. shawnqiu, 20110127.
                SyncML.ALERT_CODE_REFRESH_FROM_CLIENT, SyncML.ALERT_CODE_REFRESH_FROM_SERVER, SyncML.ALERT_CODE_FAST
                //End: funambolsync mode. shawnqiu, 20110127.
        };

        for (int i = 0; i < buttons.length; i++) {
            if (buttons[i] != null) {
                buttons[i].setOnClickListener(new ContactsSyncButtonListener(syncModes[i]));
            }
        }
    }

    class ContactsSyncButtonListener implements View.OnClickListener {
        AndroidHomeScreen homeScreen;
        AndroidHomeScreenController homeScreenController;
        int syncMode;

        public ContactsSyncButtonListener(int syncMode) {
            this.syncMode = syncMode;
        }

        public void onClick(View v) {
            homeScreen = AndroidHomeScreen.this;
            homeScreenController = homeScreen.homeScreenController;

            // 
            homeScreen.contactsSyncSource.setSyncMode(syncMode);

            currSource = SYNC_CONTACTS; //
            switch (syncMode) {
            case SyncML.ALERT_CODE_REFRESH_FROM_CLIENT:
                currDirection = SYNC_DIR_UPLOAD;
                break;
            case SyncML.ALERT_CODE_REFRESH_FROM_SERVER:
                currDirection = SYNC_DIR_DOWNLOAD;
                break;
            case SyncML.ALERT_CODE_FAST:
                currDirection = SYNC_DIR_TWOWAY;
                break;
            default:
                break;
            }

            /*
            // 
            if (homeScreenController.networkStatus != null
                  && !homeScreenController.networkStatus.isConnected()) {
               if (homeScreenController.networkStatus.isRadioOff()) {
                  homeScreenController.noConnection();
               } else {
                  homeScreenController.noSignal();
               }
               return;
            }
            */

            boolean needImportContacts = false;
            if (0 == countLocalContacts) {
                if (0 == countContactsServer) {
                    needImportContacts = true;
                } else if (SyncML.ALERT_CODE_REFRESH_FROM_CLIENT == syncMode) {
                    needImportContacts = true;
                }
            }

            if (needImportContacts) {
                contactsImportHandler.sendEmptyMessage(0);
            } else if (!homeScreenController.isSynchronizing()) {
                ProgressBottomHandler.sendEmptyMessage(MSG_SHOW_BOTTOM_PROGRESS);
                homeScreenController.aloneSourcePressed();
            } else {
                // 
            }
        }
    }

    @Override
    public void onConfigurationChanged(android.content.res.Configuration newConfig) {
        // Do not change anything
        super.onConfigurationChanged(newConfig);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (dm.isAlertPending(DisplayManager.FIRST_SYNC_DIALOG_ID)) {
            dm.dismissSelectionDialog(DisplayManager.FIRST_SYNC_DIALOG_ID);
            outState.putInt(FIRST_SYNC_ALERT_PENDING, DisplayManager.FIRST_SYNC_DIALOG_ID);
        } else if (dm.isAlertPending(DisplayManager.NO_WIFI_AVAILABLE_ID)) {
            dm.dismissSelectionDialog(DisplayManager.NO_WIFI_AVAILABLE_ID);
            outState.putInt(WIFI_NOT_AVAILABLE_ALERT_PENDING, DisplayManager.NO_WIFI_AVAILABLE_ID);
        }
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        if (Log.isLoggable(Log.TRACE)) {
            Log.trace(TAG, "onCreateDialog: " + id);
        }

        Dialog result = null;
        if (dm != null) {
            result = dm.createDialog(id);
        }

        if (result == null) {
            result = super.onCreateDialog(id);
        }
        return result;
    }

    @Override
    public void onDestroy() {
        startTimedService(); // start the timed service.
        super.onDestroy();
        if (Log.isLoggable(Log.DEBUG)) {
            Log.debug(TAG, "Nullifying home screen controller reference");
        }

        homeScreenController.setHomeScreen(null);
    }

    public void onStop() {
        super.onStop();
        try {
            unregisterReceiver(importFinishedReceiver);
            //unregisterReceiver(SmsReceiver.getInstance());
        } catch (Exception e) {
            e.printStackTrace();
            Log.debug(TAG, e.toString());
        }

    }

    /** Create the Activity menu. */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);

        if (syncItemText == null) {
            syncItemText = localization.getLanguage("menu_sync");
        }

        //MenuItem settingsItem = menu.add(0, SETTINGS_ID, Menu.NONE, localization.getLanguage("menu_settings"));
        //settingsItem.setIcon(android.R.drawable.ic_menu_preferences);
        MenuItem logoutItem = menu.add(0, LOGOUT_ID, Menu.NONE, localization.getLanguage("menu_logout"));
        logoutItem.setIcon(R.drawable.ic_menu_logout);
        MenuItem aboutItem = menu.add(0, ABOUT_ID, Menu.NONE, localization.getLanguage("menu_about"));
        aboutItem.setShortcut('0', 'A');
        aboutItem.setIcon(android.R.drawable.ic_menu_info_details);

        // This code is here only for the test recording build
        if (BuildInfo.TEST_RECORDING_ENABLED) {
            MenuItem startTestItem = menu.add(0, START_TEST_ID, Menu.NONE, "Start new test");
            MenuItem endTestItem = menu.add(0, END_TEST_ID, Menu.NONE, "End test");
        }

        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    protected void onPause() {
        super.onPause();
        homeScreenController.setForegroundStatus(false);
        Log.trace(TAG, "Paused activity (foreground status off)");
    }

    @Override
    protected void onResume() {
        super.onResume();
        homeScreenController.setForegroundStatus(true);
        Log.trace(TAG, "Resumed activity (foreground status on)");
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle all of the possible menu actions
        switch (item.getItemId()) {
        case SETTINGS_ID:
            homeScreenController.showConfigurationScreen();
            break;
        case LOGOUT_ID:
            homeScreenController.logout();
            finish();
            break;
        case ABOUT_ID:
            homeScreenController.showAboutScreen();
            break;

        //// This code is for test recording mode only ///////////////
        case START_TEST_ID:
            PimTestRecorder.getInstance().startTestPressed(this);
            break;
        case END_TEST_ID:
            PimTestRecorder.getInstance().endTestPressed();
            break;
        //// This code is for test recording mode only ///////////////
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);

        v.requestFocus();

        AppSyncSource appSource = appSyncSourceManager.getSource(v.getId());
        createContextMenuForSource(appSource, menu);
    }

    public void createContextMenuForSource(AppSyncSource appSource, ContextMenu menu) {
        if (appSource != null) {
            if (!appSource.isEnabled() || !appSource.isWorking()) {
                // If we get a requirement to allow sources to be enabled via
                // context menu, this can be done here
                return;
            }

            if (homeScreenController.isSynchronizing()) {
                // If a sync is in progress, the context menu can only be used
                // to stop the current sync of the current source
                AppSyncSource currentSource = homeScreenController.getCurrentSource();
                if (currentSource != null && currentSource.getId() == appSource.getId()) {
                    int cancelId = appSource.getId() << 16 | CANCEL_SOURCE_ID;
                    menu.add(0, cancelId, 0, localization.getLanguage("menu_cancel_sync"));
                }
            } else {
                // This works if the number of sources is < 16 which is a fairly
                // safe assumption
                int syncId = appSource.getId() << 16 | SYNC_SOURCE_ID;
                int gotoId = appSource.getId() << 16 | GOTO_SOURCE_ID;
                int settingsId = appSource.getId() << 16 | SETTINGS_SOURCE_ID;

                StringBuffer label = new StringBuffer();
                label.append(localization.getLanguage("menu_sync")).append(" ").append(appSource.getName());
                menu.add(0, syncId, 0, label.toString());
                // Add goto menu option only if an external app manager is set
                if (appSource.getAppManager() != null) {
                    label = new StringBuffer();
                    label.append(localization.getLanguage("menu_goto")).append(" ").append(appSource.getName());
                    menu.add(0, gotoId, 0, label.toString());
                }
                menu.add(0, settingsId, 0, localization.getLanguage("menu_settings"));
            }
        }
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();

        int id = item.getItemId();
        int sourceId = id >> 16;
        int itemId = id & 0xFFFF;

        AppSyncSource appSource = appSyncSourceManager.getSource(sourceId);

        if (appSource == null) {
            Log.error(TAG, "Cannot find view associated to this context menu");
            return super.onContextItemSelected(item);
        }

        switch (itemId) {
        case SYNC_SOURCE_ID:
            homeScreenController.syncMenuSelected();
            return true;
        case GOTO_SOURCE_ID:
            homeScreenController.gotoMenuSelected();
            return true;
        case SETTINGS_SOURCE_ID:
            homeScreenController.showConfigurationScreen();
            return true;
        case CANCEL_SOURCE_ID:
            homeScreenController.cancelMenuSelected();
            return true;
        default:
            Log.error(TAG, "Unknwon context menu id " + id);
            return super.onContextItemSelected(item);
        }
    }

    /**************** Home Screen Implementation **********************/

    public void initialize(HomeScreenController controller) {
        if (Log.isLoggable(Log.INFO)) {
            Log.info(TAG, "Initializing");
        }

        // We force the controller to recompute the available sources
        homeScreenController.updateAvailableSources();
        homeScreenController.redraw();
        // Now update the list of visible items in the UI
        updateVisibleItems();
    }

    public void lock() {
        screenLocked = true;
    }

    public void unlock() {
        screenLocked = false;
    }

    public boolean isLocked() {
        return screenLocked;
    }

    public void setSelectedIndex(int index) {
        // We can receive events before the list is actually populated. Just
        // ignore them
        if (listItems.isEmpty()) {
            return;
        }
        AndroidUISyncSource button = listItems.get(index);
        // Show the given element as selected
        button.setSelection(true, false);
        button.requestFocus();
    }

    public void deselectIndex(int index) {
        // We can receive events before the list is actually populated. Just
        // ignore them
        if (listItems.isEmpty()) {
            return;
        }
        AndroidUISyncSource button = listItems.get(index);
        // Show the given element as selected
        button.setSelected(false);
    }

    //////////////////////////////////////////////////////////////////////

    public Object getUiScreen() {
        return this;
    }

    public void setSyncMenuText(String text) {
        syncItemText = text;
    }

    private int adaptSizeToDensity(int size) {
        return (int) (size * getResources().getDisplayMetrics().density);
    }

    @Override
    public void addSyncAllButton(String arg0, Bitmap arg1, Bitmap arg2, Bitmap arg3) {
        // TODO Auto-generated method stub

    }

    @Override
    public void redraw() {
        // TODO Auto-generated method stub

    }

    @Override
    public void setSyncAllEnabled(boolean arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void setSyncAllSelected(boolean arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void setSyncAllText(String arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void updateVisibleItems() {
        // TODO Auto-generated method stub

    }

    /**
     * SyncSource
     * @param syncMode 
     * @return true-SyncSource; false-SyncSource
     */
    public boolean setSingleSourceSyncMode(int syncMode) {
        Vector appSources = homeScreenController.getVisibleItems();
        Enumeration iter = appSources.elements();

        int idx = 0;

        while (iter.hasMoreElements()) {
            AppSyncSource appSource = (AppSyncSource) iter.nextElement();
            appSource.setSyncMode(syncMode);
        }

        return false;
    }

    /**
     * 
     */
    public void startTimedService() {
        Intent timedIntent = new Intent(this, TimedUploadService.class);
        startService(timedIntent);
    }

    private void runContactsImport() {
        // Check if contacts shall be imported from other accounts
        if (((AndroidCustomization) customization).getContactsImportEnabled()) {
            AndroidController gc = AndroidController.getInstance();
            AndroidAdvancedSettingsScreenController advSettingsController;
            advSettingsController = (AndroidAdvancedSettingsScreenController) gc
                    .getAdvancedSettingsScreenController();
            ContactsImporter importer = new ContactsImporter(Controller.HOME_SCREEN_ID, this,
                    advSettingsController);
            importer.importContacts(true);
        }
    }

    protected static final int MSG_PROCESS_OVERVIEW_INFO_RESP = 0X1000;
    protected static final int MSG_REFRESH_OVERVIEW_INFO = 0X1001;

    /**
     * 
     */
    public void performCloudOverviewInfoReq() {
        final ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
            public String handleResponse(HttpResponse response) {
                StatusLine status = response.getStatusLine();
                HttpEntity entity = response.getEntity();
                String result = null;
                try {
                    InputStream is = entity.getContent();
                    BufferedReader r = new BufferedReader(new InputStreamReader(is));
                    StringBuilder total = new StringBuilder();
                    String line;
                    while ((line = r.readLine()) != null) {
                        total.append(line);
                    }

                    int startIndex = total.indexOf("{");
                    if (startIndex > 0) {
                        result = total.substring(startIndex);
                    } else {
                        result = total.toString();
                    }

                    Message message = overviewInfoHandler.obtainMessage();
                    Bundle bundle = new Bundle();
                    bundle.putString("RESPONSE", result);
                    message.what = MSG_PROCESS_OVERVIEW_INFO_RESP;
                    message.setData(bundle);
                    overviewInfoHandler.sendMessage(message);
                } catch (IOException e) {
                    Log.debug(TAG, e.toString());
                }

                return result;
            }
        };

        new Thread() {
            public void run() {
                try {
                    DefaultHttpClient client = new DefaultHttpClient();
                    HttpPost post = new HttpPost(CgiCloudOverviewInfo);

                    // 
                    List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
                    nameValuePairs.add(new BasicNameValuePair("username", configuration.getUsername()));

                    post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
                    client.execute(post, responseHandler);
                } catch (ClientProtocolException e) {
                    Log.debug(TAG, e.toString());
                } catch (IOException e) {
                    Log.debug(TAG, e.toString());
                }
            }
        }.start();
    }

    /**
     * handler
     */
    protected Handler overviewInfoHandler = new Handler() {
        public void handleMessage(Message m) {
            switch (m.what) {
            case MSG_PROCESS_OVERVIEW_INFO_RESP:
                Bundle bundle = m.getData();
                String resp = bundle.getString("RESPONSE");

                Log.debug(TAG, "content of resp : " + resp);

                try {
                    processJsonStream(new StringBufferInputStream(resp));
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }

                break;
            case MSG_REFRESH_OVERVIEW_INFO:
                initContactsInfo();
                initSmsInfo();
                break;
            default:
                break;
            }
        }
    };

    /**
     * json
     * @param in
     * @throws IOException
     */
    public void processJsonStream(InputStream in) throws IOException {
        JsonReader reader = new JsonReader(new InputStreamReader(in, "UTF-8"));
        reader.beginObject();
        boolean result = false;
        int contactsCount = 0; //
        int smsCount = 0; //
        long smsLastBakTime = 0; //

        while (reader.hasNext()) {
            String name = reader.nextName();
            if ("result".equals(name)) {
                result = "ok".equals(reader.nextString());
            } else if ("contacts_count".equals(name)) {
                contactsCount = Integer.valueOf(reader.nextString());
            } else if ("sms_count".equals(name)) {
                smsCount = Integer.valueOf(reader.nextString());
            } else if ("sms_last_baktime".equals(name)) {
                try {
                    smsLastBakTime = Long.valueOf(reader.nextString());
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                }
            } else {
                reader.skipValue();
            }
        }

        reader.endObject();

        if (result) {
            //prefStore
            prefStore.setSmsCountInServer(this, smsCount);
            prefStore.setContactsCountInServer(this, contactsCount);

            //
            overviewInfoHandler.sendEmptyMessage(MSG_REFRESH_OVERVIEW_INFO);

            //0
            if (0 == contactsCount) {
                contactsImportHandler.sendEmptyMessage(0);
                Log.debug("shawnqiu", "homeScreen : processJsonStream : showContactsImporter");
            }
        }

    }

    /**
     * handler
     */
    Handler contactsImportHandler = new Handler() {
        public void handleMessage(Message msg) {
            runContactsImport();
        }
    };

    protected void initSyncInfo() {
        currSource = 0; //
        currDirection = 0; //
        totalItems = 0; //  
    }

    protected void initSmsReceiver() {
        IntentFilter fp = new IntentFilter();
        fp.addAction("android.provider.Telephony.SMS_RECEIVED");
        fp.setPriority(2147483647);

        //---when the sms is recieved---
        try {
            registerReceiver(SmsReceiver.getInstance(), fp);
        } catch (Exception e) {
            e.printStackTrace();
            Log.debug(TAG, e.toString());
        }
    }

    BroadcastReceiver importFinishedReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            //TODO 
            Log.debug(TAG, "import contacts over received.");

            new Thread() {
                public void run() {
                    setSingleSourceSyncMode(SyncML.ALERT_CODE_REFRESH_FROM_CLIENT);
                    homeScreenController.aloneSourcePressed();
                    currSource = SYNC_CONTACTS;
                    overviewInfoHandler.sendEmptyMessage(MSG_REFRESH_OVERVIEW_INFO);
                }
            }.start();
        }
    };

}