Senkronizasyon bağdaştırıcısı çalıştırma

Not: WorkManager'ı öneririz. . Lütfen şu sayfaya bakın: arka plan işleme rehberini inceleyin.

Bu sınıftaki önceki derslerde, ayarlarınızı değiştirmek için senkronizasyon bağdaştırıcısı bileşenini nasıl Veri aktarımı kodunu ve başarılı bir şekilde işlem yapmanızı sağlayan ek bileşenlerin nasıl senkronizasyon adaptörünü sisteme takın. Artık Google Play'de uygulamanızı yüklemek için bir senkronizasyon bağdaştırıcısı içerir, ancak gördüğünüz kodların hiçbiri senkronizasyon bağdaştırıcısını çalıştırmaz.

Senkronizasyon bağdaştırıcınızı bir programa göre veya bazı özelliklerin dolaylı sonucu olarak çalıştırmayı denemeniz gerekir unutmayın. Örneğin, senkronizasyon bağdaştırıcınızın belirli bir zamanda veya günün belirli bir saatinde Senkronizasyonu otomatik olarak bağdaştırıcısını kontrol edin. senkronizasyon bağdaştırıcısını bir kullanıcı işleminin doğrudan sonucu olarak ayarlar, çünkü bunu yaptığınızda senkronizasyon bağdaştırıcısı çerçevesinin programlama kabiliyetinden kaynaklanır. Örneğin, yenileme düğmesi sunar.

Senkronizasyon bağdaştırıcınızı çalıştırmak için aşağıdaki seçeneklere sahipsiniz:

Sunucu verileri değiştiğinde
. Senkronizasyon bağdaştırıcısını, sunucudan gelen ve sunucu tabanlı verileri değişti. Bu seçenek, verileri sunucudan cihaza yenilemenize olanak tanır. performansı düşürmeden veya sunucuyu yoklayarak pil ömrünü boşa harcamadan kullanabilirsiniz.
Cihaz verileri değiştiğinde
. Cihazdaki veriler değiştiğinde senkronizasyon bağdaştırıcısı çalıştırın. Bu seçenek bir sunucuya aktarıldığından farklı olabilir ve özellikle de sunucu yapılandırmalı her zaman en güncel cihaz verilerine sahip olmasını sağlar. Bu seçeneği kullanarak depoluyorsanız bu işlemi yapmanızı öneririz. Saplama kullanıyorsanız veri değişikliklerini tespit etmek daha zor olabilir.
Düzenli aralıklarla
. Seçtiğiniz bir aralığın süresi dolduktan sonra bir senkronizasyon bağdaştırıcısı çalıştırın veya bağdaştırıcıyı belirli bir zamanda çalıştırın her gün çalışıyor.
İstek üzerine
. Kullanıcı işlemine yanıt olarak senkronizasyon bağdaştırıcısını çalıştırın. Ancak en iyi kullanıcıya öncelikle daha otomatik olan seçeneklerden birine güvenmeniz gerekir. Şunu kullanarak: otomatik seçeneklerle pil ve ağ kaynaklarından tasarruf edersiniz.

Bu dersin geri kalanında bu seçeneklerin her biri daha ayrıntılı olarak açıklanmaktadır.

Sunucu verileri değiştiğinde senkronizasyon bağdaştırıcısını çalıştırma

Uygulamanız bir sunucudan veri aktarıyor ve sunucu verileri sık sık değişiyorsa veri değişikliklerine yanıt olarak indirme işlemi yapmak için bir senkronizasyon adaptörü. Senkronizasyon bağdaştırıcısını çalıştırmak için Sunucu, uygulamanızdaki bir BroadcastReceiver adresine özel bir mesaj gönderir. Bu mesaja yanıt olarak, ContentResolver.requestSync() senkronizasyon adaptörünü kullanmanız gerekir.

Google Cloud Messaging (GCM) hem bu mesajlaşma sisteminin çalışması için gereken sunucu ve cihaz bileşenlerini içerir. Tetiklemek için GCM kullanma aktarımları durum için yoklama sunucularından daha güvenilir ve verimlidir. Oy kullanırken her zaman etkin olan bir Service gerektirir. GCM, BroadcastReceiver Mesaj geldiğinde etkinleştirilir. Oy kullanırken düzenli aralıklarla, kullanılabilir güncelleme olmasa bile pil gücünü kullanır, GCM yalnızca mesaj gönderebilirsiniz.

Not: Tüm kullanıcılara bir yayın aracılığıyla senkronizasyon bağdaştırıcınızı tetiklemek için GCM'yi kullanırsanız uygulamanızın yüklü olduğu cihazlarda mesajınızı şu adrese giderek aldıklarını: aşağı yukarı aynı zamana denk geliyor. Bu durum, senkronizasyon bağdaştırıcınızın birden fazla örneğinin çalışmasına neden olabilir sunucu ve ağ yüküne neden olabilir. Yayında bu durumu önlemek için: senkronizasyon bağdaştırıcısının başlangıç tarihini bir süreliğine ertelemeyi benzersiz bir deneyim sunmalısınız.

Aşağıdaki kod snippet'i, requestSync() şuna yanıt olarak: gelen GCM iletisi:

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);
            ...
        }
        ...
    }
    ...
}

İçerik sağlayıcı verileri değiştiğinde senkronizasyon bağdaştırıcısını çalıştırma

Uygulamanız bir içerik sağlayıcıda veri topluyorsa ve her seferinde sunucuyu güncellemek istiyorsanız sağlayıcıyı güncellerseniz uygulamanızı senkronizasyon bağdaştırıcınızı otomatik olarak çalıştıracak şekilde ayarlayabilirsiniz. Yapılacaklar İçerik sağlayıcı için bir gözlemci kaydedersiniz. İçerik sağlayıcınızdaki veriler içerik sağlayıcı çerçevesi ise gözlemciyi çağırır. Gözlemcide Çerçeveye çalışmasını bildirmek için requestSync() senkronize edin.

Not: Bir saplama içerik sağlayıcısı kullanıyorsanız içerik sağlayıcı ve onChange() hiç çağrılmadı. Bu durumda cihaz verileri. Bu mekanizma, müşterilerin telefon araması Veriler değiştiğinde requestSync().

İçerik sağlayıcınız için bir gözlemci oluşturmak üzere sınıfı genişletin. ContentObserver ve her iki biçimini de uygulayın. onChange() yöntemini çağırın. İçinde onChange(), telefon et Senkronizasyon bağdaştırıcısını başlatmak için requestSync().

Gözlemciyi kaydetmek için bunu bir çağrıda bağımsız değişken olarak iletin: registerContentObserver() İçinde çağrısından sonra, izlemek istediğiniz veriler için bir içerik URI'si de iletmeniz gerekir. İçerik provider çerçevesi, bu izleme URI'sini bağımsız değişken olarak iletilen içerik URI'leri ile Sağlayıcınızı değiştiren ContentResolver yöntem, ör. ContentResolver.insert(). Eşleşme varsa ContentObserver.onChange() uygulanması çağrılır.

Aşağıdaki kod snippet'i, bir ContentObserver özelliğini nasıl tanımlayacağınızı göstermektedir bir tablo söz konusu olduğunda, requestSync() değişiklikler:

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);
        ...
    }
    ...
}

Senkronizasyon bağdaştırıcısını düzenli olarak çalıştırma

Çalıştırmalar arasında beklenecek süre belirleyerek senkronizasyon bağdaştırıcınızı düzenli aralıklarla çalıştırabilirsiniz. veya günün belirli saatlerinde ya da her ikisinde birden yayınlayabilirsiniz. Senkronizasyon bağdaştırıcınızı çalıştırma düzenli aralıklarla, sunucunuzun güncelleme aralığını yaklaşık olarak eşleştirmenize olanak tanır.

Benzer şekilde, sunucunuz nispeten boştayken cihazdan veri yükleyebilirsiniz. senkronizasyon bağdaştırıcınızı gece çalışacak şekilde planlama. Çoğu kullanıcı kendi güçlerini açık ve fişe takılı bırakıyor Bu nedenle bu saat de genellikle uygun olur. Dahası, cihaz şu saatte başka görevler çalıştırmıyor: senkronizasyon bağdaştırıcınızla aynı anda çalışır. Ancak bu yaklaşımı benimserseniz, her cihaz biraz farklı bir zamanda veri aktarımını tetikler. Tüm cihazlar senkronizasyon bağdaştırıcısını aynı anda kullanmayı seçerseniz sunucu ve hücre sağlayıcı verilerinizde aşırı miktarda ağlar.

Periyodik çalıştırmalar genel olarak, kullanıcılarınız için anlık güncellemelere ihtiyaç duymayan ancak aynı zamanda düzenli olarak güncellenir. Belirli bir özelliğin kullanılabilirliğini dengelemek isterseniz, Cihazı aşırı kullanmayan daha küçük senkronizasyon bağdaştırıcısı çalıştırmalarının verimliliği sayesinde güncel veriler kaynaklar.

Senkronizasyon bağdaştırıcınızı düzenli aralıklarla çalıştırmak için addPeriodicSync() Bu, senkronizasyon bağdaştırıcısını belirli bir süre geçtikten sonra çalışacak şekilde ayarlayın. Senkronizasyon bağdaştırıcısı çerçevesinin diğer senkronizasyon bağdaştırıcısı yürütmelerini hesaba katması gerekir ve pil verimliliğini en üst düzeye çıkarmaya çalışırsa geçen süre birkaç saniye farklılık gösterebilir. Ayrıca çerçeve, aşağıdaki durumlarda senkronizasyon bağdaştırıcınızı çalıştırmaz ağı kullanılamıyor.

addPeriodicSync() şunu yapmaz: senkronizasyon bağdaştırıcısını günün belirli bir saatinde çalıştırmanız gerekir. Senkronizasyon bağdaştırıcınızı yaklaşık olarak her gün aynı saatte çalışıyorsa tetikleyici olarak tekrarlanan bir alarmı kullanın. Tekrarlanan alarmlar daha fazla bilgi için açıklanmaktadır bu AlarmManager referans belgelerinde bulabilirsiniz. URL'yi ayarlamak için setInexactRepeating() yöntemini kullanın günün saati tetikleyicileri varsa, bu tetikleyicileri kullanmak için başlangıç zamanını senkronizasyon bağdaştırıcısının farklı cihazlarda çalıştığından emin olun.

addPeriodicSync() yöntemi şunları yapmaz: setSyncAutomatically() devre dışı bırak, Bu nedenle, nispeten kısa bir süre içinde birden fazla senkronizasyon çalıştırmanız olabilir. Ayrıca çok az sayıda senkronizasyon bağdaştırıcısı kontrol bayraklarına yapılan çağrıda izin verilir addPeriodicSync(); önemli olan izin verilmeyen konular, addPeriodicSync().

Aşağıdaki kod snippet'i, düzenli senkronizasyon bağdaştırıcısı çalıştırmalarının nasıl planlanacağını gösterir:

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);
        ...
    }
    ...
}

Senkronizasyon bağdaştırıcısını isteğe bağlı olarak çalıştırma

Senkronizasyon bağdaştırıcınızı bir kullanıcı isteğine yanıt olarak çalıştırmak, en az tercih edilen stratejidir bir senkronizasyon bağdaştırıcısı çalıştırmak için idealdir. Çerçeve, pil gücünü korumak için özel olarak tasarlanmıştır senkronizasyon bağdaştırıcılarını bir programa göre çalıştırır. Verilere göre senkronizasyon yapan seçenekler Güç Kaynağı yeni veri sağlamak için kullanıldığından değişiklikler pil gücünü etkili bir şekilde kullanır.

Buna karşılık, kullanıcıların istek üzerine senkronizasyon çalıştırmasına izin vermek, senkronizasyonun kendiliğinden çalıştığı anlamına gelir. ağın ve güç kaynaklarının verimsiz kullanımıdır. Ayrıca, istek üzerine senkronizasyon sağlamak, kullanıcıları verilerin değiştiğine dair bir kanıt olmasa bile senkronizasyon isteğinde bulunmalı ve , pil gücünün verimsiz bir şekilde kullanılmasıdır. Genel olarak, uygulamanız Kullanıcı girişi olmadan senkronizasyonu tetiklemek veya düzenli aralıklarla programlamak için diğer sinyalleri kullanma

Ancak senkronizasyon bağdaştırıcısını yine de istek üzerine çalıştırmak istiyorsanız senkronizasyon bağdaştırıcısı bayraklarını manuel senkronizasyon bağdaştırıcısı çalıştırıp şunu ara: ContentResolver.requestSync()

Aşağıdaki işaretlerle isteğe bağlı aktarımları çalıştırın:

SYNC_EXTRAS_MANUAL
. Manuel senkronizasyonu zorunlu kılar. Senkronizasyon bağdaştırıcısı çerçevesi mevcut ayarları yoksayar örneğin setSyncAutomatically() tarafından ayarlanan bayrak gibi.
SYNC_EXTRAS_EXPEDITED
. Senkronizasyonu hemen başlamaya zorlar. Bunu ayarlamazsanız sistem, saniyeler içinde pil kullanımını optimize etmeye çalıştığı için, istek çalıştırılmadan önce kısa bir süre içinde çok sayıda istek planlamaktır.

Aşağıdaki kod snippet'i, Bir düğmeye yanıt olarak requestSync() tıklayın:

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);
    }