Chạy bộ điều hợp đồng bộ hoá

Lưu ý: Bạn nên dùng WorkManager là giải pháp được đề xuất cho hầu hết các trường hợp sử dụng xử lý ở chế độ nền. Vui lòng tham khảo hướng dẫn xử lý nền để tìm hiểu giải pháp nào phù hợp nhất với bạn.

Trong các bài học trước của lớp này, bạn đã tìm hiểu cách tạo thành phần bộ điều hợp đồng bộ hoá đóng gói mã chuyển dữ liệu và cách thêm các thành phần bổ sung cho phép bạn cắm bộ điều hợp đồng bộ hoá vào hệ thống. Giờ đây, bạn đã có mọi thông tin cần thiết để cài đặt một ứng dụng bao gồm bộ điều hợp đồng bộ hoá, nhưng không có mã nào trong số mã bạn thấy thực sự chạy bộ điều hợp đồng bộ hoá.

Bạn nên cố gắng chạy bộ điều hợp đồng bộ hoá dựa trên lịch biểu hoặc dưới dạng kết quả gián tiếp của một số sự kiện. Ví dụ: bạn có thể muốn bộ điều hợp đồng bộ hoá chạy theo lịch biểu định kỳ, sau một khoảng thời gian hoặc thời điểm cụ thể trong ngày. Bạn cũng có thể muốn chạy quá trình đồng bộ hoá của mình bộ chuyển đổi khi có thay đổi đối với dữ liệu được lưu trữ trên thiết bị. Bạn nên tránh chạy bộ điều hợp đồng bộ hoá dưới dạng kết quả trực tiếp của hành động của người dùng, bởi vì khi thực hiện việc này, bạn sẽ không có tận dụng khả năng lên lịch của khung bộ điều hợp đồng bộ hoá. Ví dụ: bạn nên tránh cung cấp nút làm mới trong giao diện người dùng.

Bạn có các tuỳ chọn sau để chạy bộ điều hợp đồng bộ hoá:

Khi dữ liệu máy chủ thay đổi
Chạy bộ điều hợp đồng bộ hoá để phản hồi thông báo từ máy chủ, cho biết rằng nền tảng này đã thay đổi. Tuỳ chọn này cho phép bạn làm mới dữ liệu từ máy chủ đến thiết bị mà không làm giảm hiệu suất hay làm lãng phí thời lượng pin bằng cách thăm dò máy chủ.
Khi dữ liệu thiết bị thay đổi
Chạy bộ điều hợp đồng bộ hoá khi dữ liệu thay đổi trên thiết bị. Lựa chọn này cho phép bạn gửi sửa đổi dữ liệu từ thiết bị đến máy chủ và đặc biệt hữu ích nếu bạn cần đảm bảo rằng máy chủ luôn có dữ liệu mới nhất của thiết bị. Tuỳ chọn này dễ hiểu nếu bạn thực sự lưu trữ dữ liệu trong trình cung cấp nội dung của mình. Nếu bạn đang dùng mã giả lập nhà cung cấp nội dung, nhưng việc phát hiện các thay đổi về dữ liệu có thể khó phát hiện hơn.
Định kỳ
Chạy bộ điều hợp đồng bộ hoá sau khi hết khoảng thời gian bạn chọn hoặc chạy vào một khoảng thời gian nhất định mỗi ngày.
Theo yêu cầu
Chạy bộ điều hợp đồng bộ hoá để phản hồi hành động của người dùng. Tuy nhiên, để cung cấp cho người dùng tốt nhất bạn nên chủ yếu dựa vào một trong số các tùy chọn tự động hơn. Bằng cách sử dụng tự động, bạn tiết kiệm pin và tài nguyên mạng.

Phần còn lại của bài học này sẽ mô tả chi tiết hơn về từng tuỳ chọn.

Chạy bộ điều hợp đồng bộ hoá khi dữ liệu máy chủ thay đổi

Nếu ứng dụng của bạn chuyển dữ liệu từ một máy chủ và dữ liệu máy chủ thay đổi thường xuyên, bạn có thể sử dụng bộ điều hợp đồng bộ hoá để tải xuống nhằm phản hồi thay đổi về dữ liệu. Để chạy bộ điều hợp đồng bộ hoá, hãy thì máy chủ sẽ gửi một thông báo đặc biệt đến BroadcastReceiver trong ứng dụng của bạn. Để phản hồi thông báo này, hãy gọi ContentResolver.requestSync() để báo hiệu cho khung bộ điều hợp đồng bộ hoá chạy bộ điều hợp đồng bộ hoá.

Nhắn tin qua đám mây của Google (GCM) cung cấp cả máy chủ và thiết bị bạn cần để hệ thống nhắn tin này hoạt động. Sử dụng GCM để kích hoạt quá trình chuyển sẽ đáng tin cậy và hiệu quả hơn so với máy chủ thăm dò trạng thái. Trong khi thăm dò ý kiến yêu cầu một Service luôn hoạt động, GCM sử dụng BroadcastReceiver được kích hoạt khi có thư đến. Trong khi thăm dò ý kiến định kỳ sử dụng nguồn pin ngay cả khi không có bản cập nhật, GCM chỉ gửi khi cần.

Lưu ý: Nếu bạn sử dụng GCM để kích hoạt bộ điều hợp đồng bộ hóa qua thông báo truyền tin tới tất cả trên các thiết bị cài đặt ứng dụng của bạn, hãy nhớ rằng họ nhận được tin nhắn của bạn tại gần như cùng lúc. Trường hợp này có thể khiến nhiều thực thể của bộ điều hợp đồng bộ hoá chạy cùng một lúc, gây ra tình trạng quá tải cho máy chủ và mạng. Để tránh trường hợp này khi phát sóng cho tất cả thiết bị, bạn nên cân nhắc trì hoãn thời gian bắt đầu bộ điều hợp đồng bộ hoá trong một khoảng thời gian dành riêng cho mỗi thiết bị.

Đoạn mã sau đây hướng dẫn bạn cách chạy requestSync() để phản hồi một tin nhắn đến GCM:

Kotlin

...
// Constants
// Content provider authority
const val AUTHORITY = "com.example.android.datasync.provider"
// Account type
const val ACCOUNT_TYPE = "com.example.android.datasync"
// Account
const val ACCOUNT = "default_account"
// Incoming Intent key for extended data
const val KEY_SYNC_REQUEST = "com.example.android.datasync.KEY_SYNC_REQUEST"
...
class GcmBroadcastReceiver : BroadcastReceiver() {
    ...
    override fun onReceive(context: Context, intent: Intent) {
        // Get a GCM object instance
        val gcm: GoogleCloudMessaging = GoogleCloudMessaging.getInstance(context)
        // Get the type of GCM message
        val messageType: String? = gcm.getMessageType(intent)
        /*
         * Test the message type and examine the message contents.
         * Since GCM is a general-purpose messaging system, you
         * may receive normal messages that don't require a sync
         * adapter run.
         * The following code tests for a a boolean flag indicating
         * that the message is requesting a transfer from the device.
         */
        if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE == messageType
            && intent.getBooleanExtra(KEY_SYNC_REQUEST, false)) {
            /*
             * Signal the framework to run your sync adapter. Assume that
             * app initialization has already created the account.
             */
            ContentResolver.requestSync(mAccount, AUTHORITY, null)
            ...
        }
        ...
    }
    ...
}

Java

public class GcmBroadcastReceiver extends BroadcastReceiver {
    ...
    // Constants
    // Content provider authority
    public static final String AUTHORITY = "com.example.android.datasync.provider";
    // Account type
    public static final String ACCOUNT_TYPE = "com.example.android.datasync";
    // Account
    public static final String ACCOUNT = "default_account";
    // Incoming Intent key for extended data
    public static final String KEY_SYNC_REQUEST =
            "com.example.android.datasync.KEY_SYNC_REQUEST";
    ...
    @Override
    public void onReceive(Context context, Intent intent) {
        // Get a GCM object instance
        GoogleCloudMessaging gcm =
                GoogleCloudMessaging.getInstance(context);
        // Get the type of GCM message
        String messageType = gcm.getMessageType(intent);
        /*
         * Test the message type and examine the message contents.
         * Since GCM is a general-purpose messaging system, you
         * may receive normal messages that don't require a sync
         * adapter run.
         * The following code tests for a a boolean flag indicating
         * that the message is requesting a transfer from the device.
         */
        if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)
            &&
            intent.getBooleanExtra(KEY_SYNC_REQUEST)) {
            /*
             * Signal the framework to run your sync adapter. Assume that
             * app initialization has already created the account.
             */
            ContentResolver.requestSync(mAccount, AUTHORITY, null);
            ...
        }
        ...
    }
    ...
}

Chạy bộ điều hợp đồng bộ hoá khi dữ liệu của trình cung cấp nội dung thay đổi

Nếu ứng dụng của bạn thu thập dữ liệu thông qua một nhà cung cấp nội dung và bạn muốn cập nhật máy chủ bất cứ khi nào bạn cập nhật nhà cung cấp, bạn có thể thiết lập ứng dụng để tự động chạy bộ điều hợp đồng bộ hoá. Việc cần làm thao tác này, bạn đăng ký trình quan sát cho trình cung cấp nội dung. Khi dữ liệu trong trình cung cấp nội dung của bạn thì khung trình cung cấp nội dung sẽ gọi trình quan sát. Trong trình quan sát, gọi requestSync() để yêu cầu khung chạy bộ điều hợp đồng bộ hoá của bạn.

Lưu ý: Nếu đang sử dụng một nhà cung cấp nội dung giả lập, thì bạn không có dữ liệu nào trong trình cung cấp nội dung và onChange() là chưa bao giờ được gọi. Trong trường hợp này, bạn phải cung cấp cơ chế riêng để phát hiện các thay đổi cho dữ liệu trên thiết bị của bạn. Cơ chế này cũng chịu trách nhiệm gọi requestSync() khi dữ liệu thay đổi.

Để tạo trình quan sát cho trình cung cấp nội dung, hãy mở rộng lớp này ContentObserver rồi triển khai cả hai dạng onChange(). Trong onChange(), gọi requestSync() để khởi động bộ điều hợp đồng bộ hoá.

Để đăng ký trình quan sát, hãy truyền đối tượng này dưới dạng một đối số trong lệnh gọi đến registerContentObserver(). Trong lệnh gọi này, bạn cũng phải chuyển vào một URI nội dung cho dữ liệu mà bạn muốn xem. Nội dung khung của nhà cung cấp so sánh URI theo dõi này với các URI nội dung được truyền dưới dạng đối số để ContentResolver phương thức sửa đổi nhà cung cấp của bạn, chẳng hạn như ContentResolver.insert() Nếu có kết quả trùng khớp, cách triển khai ContentObserver.onChange() sẽ được gọi.

Đoạn mã sau đây cho bạn biết cách xác định ContentObserver gọi requestSync() khi một bảng các thay đổi:

Kotlin

// Constants
// Content provider scheme
const val SCHEME = "content://"
// Content provider authority
const val AUTHORITY = "com.example.android.datasync.provider"
// Path for the content provider table
const val TABLE_PATH = "data_table"
...
class MainActivity : FragmentActivity() {
    ...
    // A content URI for the content provider's data table
    private lateinit var uri: Uri
    // A content resolver for accessing the provider
    private lateinit var mResolver: ContentResolver
    ...
    inner class TableObserver(...) : ContentObserver(...) {
        /*
         * Define a method that's called when data in the
         * observed content provider changes.
         * This method signature is provided for compatibility with
         * older platforms.
         */
        override fun onChange(selfChange: Boolean) {
            /*
             * Invoke the method signature available as of
             * Android platform version 4.1, with a null URI.
             */
            onChange(selfChange, null)
        }

        /*
         * Define a method that's called when data in the
         * observed content provider changes.
         */
        override fun onChange(selfChange: Boolean, changeUri: Uri?) {
            /*
             * Ask the framework to run your sync adapter.
             * To maintain backward compatibility, assume that
             * changeUri is null.
             */
            ContentResolver.requestSync(account, AUTHORITY, null)
        }
        ...
    }
    ...
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ...
        // Get the content resolver object for your app
        mResolver = contentResolver
        // Construct a URI that points to the content provider data table
        uri = Uri.Builder()
                .scheme(SCHEME)
                .authority(AUTHORITY)
                .path(TABLE_PATH)
                .build()
        /*
         * Create a content observer object.
         * Its code does not mutate the provider, so set
         * selfChange to "false"
         */
        val observer = TableObserver(false)
        /*
         * Register the observer for the data table. The table's path
         * and any of its subpaths trigger the observer.
         */
        mResolver.registerContentObserver(uri, true, observer)
        ...
    }
    ...
}

Java

public class MainActivity extends FragmentActivity {
    ...
    // Constants
    // Content provider scheme
    public static final String SCHEME = "content://";
    // Content provider authority
    public static final String AUTHORITY = "com.example.android.datasync.provider";
    // Path for the content provider table
    public static final String TABLE_PATH = "data_table";
    // Account
    public static final String ACCOUNT = "default_account";
    // Global variables
    // A content URI for the content provider's data table
    Uri uri;
    // A content resolver for accessing the provider
    ContentResolver mResolver;
    ...
    public class TableObserver extends ContentObserver {
        /*
         * Define a method that's called when data in the
         * observed content provider changes.
         * This method signature is provided for compatibility with
         * older platforms.
         */
        @Override
        public void onChange(boolean selfChange) {
            /*
             * Invoke the method signature available as of
             * Android platform version 4.1, with a null URI.
             */
            onChange(selfChange, null);
        }
        /*
         * Define a method that's called when data in the
         * observed content provider changes.
         */
        @Override
        public void onChange(boolean selfChange, Uri changeUri) {
            /*
             * Ask the framework to run your sync adapter.
             * To maintain backward compatibility, assume that
             * changeUri is null.
             */
            ContentResolver.requestSync(mAccount, AUTHORITY, null);
        }
        ...
    }
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        // Get the content resolver object for your app
        mResolver = getContentResolver();
        // Construct a URI that points to the content provider data table
        uri = new Uri.Builder()
                  .scheme(SCHEME)
                  .authority(AUTHORITY)
                  .path(TABLE_PATH)
                  .build();
        /*
         * Create a content observer object.
         * Its code does not mutate the provider, so set
         * selfChange to "false"
         */
        TableObserver observer = new TableObserver(false);
        /*
         * Register the observer for the data table. The table's path
         * and any of its subpaths trigger the observer.
         */
        mResolver.registerContentObserver(uri, true, observer);
        ...
    }
    ...
}

Chạy bộ điều hợp đồng bộ hoá định kỳ

Bạn có thể chạy bộ điều hợp đồng bộ hoá định kỳ bằng cách đặt khoảng thời gian chờ giữa các lần chạy, hoặc bằng cách chạy ứng dụng vào những thời điểm nhất định trong ngày hoặc cả hai. Chạy bộ điều hợp đồng bộ hoá định kỳ giúp bạn có được khoảng thời gian cập nhật gần như khớp với máy chủ của bạn.

Tương tự, bạn có thể tải dữ liệu lên từ thiết bị khi máy chủ của bạn tương đối ở trạng thái rảnh, bằng cách đang lên lịch để bộ điều hợp đồng bộ hoá chạy vào ban đêm. Hầu hết người dùng vẫn bật nguồn và cắm nguồn vào ban đêm, nên thời gian này thường rảnh. Ngoài ra, thiết bị hiện không thực hiện các tác vụ khác tại cùng lúc với bộ điều hợp đồng bộ hoá. Tuy nhiên, nếu áp dụng phương pháp này, bạn cần đảm bảo rằng mỗi thiết bị sẽ kích hoạt quá trình chuyển dữ liệu tại một thời điểm hơi khác nhau. Nếu tất cả thiết bị đều chạy bộ điều hợp đồng bộ hoá cùng lúc, bạn có thể làm quá tải dữ liệu máy chủ và dữ liệu của nhà cung cấp dịch vụ di động mạng.

Nhìn chung, các lần chạy định kỳ là hợp lý nếu người dùng không cần bản cập nhật tức thì, nhưng vẫn muốn có các bản cập nhật thường xuyên. Việc chạy định kỳ cũng sẽ hợp lý nếu bạn muốn cân bằng tính sẵn có của dữ liệu mới nhất với hiệu quả của bộ điều hợp đồng bộ hoá nhỏ hơn mà không sử dụng thiết bị quá mức của chúng tôi.

Để chạy bộ điều hợp đồng bộ hoá theo định kỳ, hãy gọi addPeriodicSync(). Việc này sẽ lên lịch bộ điều hợp đồng bộ hoá để chạy sau một khoảng thời gian nhất định đã trôi qua. Vì khung bộ điều hợp đồng bộ hoá phải tính đến các hoạt động thực thi bộ điều hợp đồng bộ hoá khác và cố gắng tối đa hoá hiệu quả pin, thời gian đã trôi qua có thể chênh lệch vài giây. Ngoài ra, khung này sẽ không chạy bộ điều hợp đồng bộ hoá nếu mạng không khả dụng.

Lưu ý rằng addPeriodicSync() không chạy bộ điều hợp đồng bộ hoá vào thời điểm cụ thể trong ngày. Để chạy bộ điều hợp đồng bộ hoá ở mức khoảng vào cùng một thời điểm hằng ngày, hãy dùng chuông báo lặp lại làm kích hoạt. Các chuông báo lặp lại được mô tả trong phần mô tả chi tiết hơn trong tài liệu tham khảo cho AlarmManager. Nếu bạn sử dụng phương thức setInexactRepeating() để đặt điều kiện kích hoạt thời gian trong ngày có một số biến thể, bạn vẫn nên sắp xếp ngẫu nhiên thời gian bắt đầu để đảm bảo rằng bộ điều hợp đồng bộ hoá chạy từ các thiết bị khác nhau được bố trí so le.

Phương thức addPeriodicSync() không tắt setSyncAutomatically(), do đó bạn có thể thực hiện nhiều lần đồng bộ hoá trong một khoảng thời gian tương đối ngắn. Ngoài ra, chỉ một vài cờ điều khiển bộ điều hợp đồng bộ hoá được phép trong lệnh gọi đến addPeriodicSync(); những cờ được mô tả trong tài liệu tham khảo đối với addPeriodicSync()

Đoạn mã sau đây cho bạn biết cách lên lịch chạy bộ điều hợp đồng bộ hoá định kỳ:

Kotlin

// Content provider authority
const val AUTHORITY = "com.example.android.datasync.provider"
// Account
const val ACCOUNT = "default_account"
// Sync interval constants
const val SECONDS_PER_MINUTE = 60L
const val SYNC_INTERVAL_IN_MINUTES = 60L
const val SYNC_INTERVAL = SYNC_INTERVAL_IN_MINUTES * SECONDS_PER_MINUTE
...
class MainActivity : FragmentActivity() {
    ...
    // A content resolver for accessing the provider
    private lateinit var mResolver: ContentResolver

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ...
        // Get the content resolver for your app
        mResolver = contentResolver
        /*
         * Turn on periodic syncing
         */
        ContentResolver.addPeriodicSync(
                mAccount,
                AUTHORITY,
                Bundle.EMPTY,
                SYNC_INTERVAL)
        ...
    }
    ...
}

Java

public class MainActivity extends FragmentActivity {
    ...
    // Constants
    // Content provider authority
    public static final String AUTHORITY = "com.example.android.datasync.provider";
    // Account
    public static final String ACCOUNT = "default_account";
    // Sync interval constants
    public static final long SECONDS_PER_MINUTE = 60L;
    public static final long SYNC_INTERVAL_IN_MINUTES = 60L;
    public static final long SYNC_INTERVAL =
            SYNC_INTERVAL_IN_MINUTES *
            SECONDS_PER_MINUTE;
    // Global variables
    // A content resolver for accessing the provider
    ContentResolver mResolver;
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        // Get the content resolver for your app
        mResolver = getContentResolver();
        /*
         * Turn on periodic syncing
         */
        ContentResolver.addPeriodicSync(
                mAccount,
                AUTHORITY,
                Bundle.EMPTY,
                SYNC_INTERVAL);
        ...
    }
    ...
}

Chạy bộ điều hợp đồng bộ hoá theo yêu cầu

Chạy bộ điều hợp đồng bộ hoá để phản hồi yêu cầu của người dùng là chiến lược ít được ưu tiên nhất để chạy bộ điều hợp đồng bộ hoá. Khung này được thiết kế đặc biệt để tiết kiệm pin khi nó chạy bộ điều hợp đồng bộ hoá theo lịch biểu. Các tuỳ chọn chạy đồng bộ hoá để phản hồi dữ liệu các thay đổi sẽ sử dụng hiệu quả nguồn pin, vì nguồn điện được dùng để cung cấp dữ liệu mới.

Trong khi đó, việc cho phép người dùng chạy đồng bộ hoá theo yêu cầu có nghĩa là quá trình đồng bộ hoá đó sẽ tự chạy. là sử dụng tài nguyên mạng và nguồn điện không hiệu quả. Ngoài ra, việc cung cấp tính năng đồng bộ hoá theo yêu cầu sẽ giúp người dùng yêu cầu đồng bộ hoá ngay cả khi không có bằng chứng cho thấy dữ liệu đã thay đổi và tiến hành đồng bộ hoá không làm mới dữ liệu là sử dụng pin không hiệu quả. Nhìn chung, ứng dụng của bạn nên: sử dụng các tín hiệu khác để kích hoạt quá trình đồng bộ hoá hoặc lên lịch đồng bộ hoá định kỳ mà không cần hoạt động đầu vào của người dùng.

Tuy nhiên, nếu bạn vẫn muốn chạy bộ điều hợp đồng bộ hoá theo yêu cầu, hãy đặt cờ bộ điều hợp đồng bộ hoá cho chạy bộ điều hợp đồng bộ hoá thủ công, sau đó gọi ContentResolver.requestSync().

Chạy quy trình chuyển theo yêu cầu với các cờ sau:

SYNC_EXTRAS_MANUAL
Buộc đồng bộ hoá thủ công. Khung bộ điều hợp đồng bộ hoá bỏ qua các chế độ cài đặt hiện có, chẳng hạn như cờ do setSyncAutomatically() đặt.
SYNC_EXTRAS_EXPEDITED
Buộc quá trình đồng bộ hoá bắt đầu ngay lập tức. Nếu bạn không đặt cài đặt này, hệ thống có thể đợi vài phút giây trước khi chạy yêu cầu đồng bộ hoá vì yêu cầu này cố gắng tối ưu hoá việc sử dụng pin bằng cách lên lịch nhiều yêu cầu trong một khoảng thời gian ngắn.

Đoạn mã sau đây cho bạn biết cách gọi requestSync() để phản hồi một nút nhấp vào:

Kotlin

// Constants
// Content provider authority
val AUTHORITY = "com.example.android.datasync.provider"
// Account type
val ACCOUNT_TYPE = "com.example.android.datasync"
// Account
val ACCOUNT = "default_account"
...
class MainActivity : FragmentActivity() {
    ...
    // Instance fields
    private lateinit var mAccount: Account
    ...
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ...
        /*
         * Create the placeholder account. The code for CreateSyncAccount
         * is listed in the lesson Creating a Sync Adapter
         */

        mAccount = createSyncAccount()
        ...
    }

    /**
     * Respond to a button click by calling requestSync(). This is an
     * asynchronous operation.
     *
     * This method is attached to the refresh button in the layout
     * XML file
     *
     * @param v The View associated with the method call,
     * in this case a Button
     */
    fun onRefreshButtonClick(v: View) {
        // Pass the settings flags by inserting them in a bundle
        val settingsBundle = Bundle().apply {
            putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true)
            putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true)
        }
        /*
         * Request the sync for the default account, authority, and
         * manual sync settings
         */
        ContentResolver.requestSync(mAccount, AUTHORITY, settingsBundle)
    }

Java

public class MainActivity extends FragmentActivity {
    ...
    // Constants
    // Content provider authority
    public static final String AUTHORITY =
            "com.example.android.datasync.provider";
    // Account type
    public static final String ACCOUNT_TYPE = "com.example.android.datasync";
    // Account
    public static final String ACCOUNT = "default_account";
    // Instance fields
    Account mAccount;
    ...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ...
        /*
         * Create the placeholder account. The code for CreateSyncAccount
         * is listed in the lesson Creating a Sync Adapter
         */

        mAccount = CreateSyncAccount(this);
        ...
    }
    /**
     * Respond to a button click by calling requestSync(). This is an
     * asynchronous operation.
     *
     * This method is attached to the refresh button in the layout
     * XML file
     *
     * @param v The View associated with the method call,
     * in this case a Button
     */
    public void onRefreshButtonClick(View v) {
        // Pass the settings flags by inserting them in a bundle
        Bundle settingsBundle = new Bundle();
        settingsBundle.putBoolean(
                ContentResolver.SYNC_EXTRAS_MANUAL, true);
        settingsBundle.putBoolean(
                ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
        /*
         * Request the sync for the default account, authority, and
         * manual sync settings
         */
        ContentResolver.requestSync(mAccount, AUTHORITY, settingsBundle);
    }