【问题标题】:Running sync adapter periodically定期运行同步适配器
【发布时间】:2016-02-25 07:24:09
【问题描述】:

我已经在我的应用程序中实现了同步适配器功能。我允许用户在离线模式下使用该应用程序,并且在该离线模式下数据库中的任何更改都保存在一个表中,我想根据定期同步功能将该表的数据同步到服务器。 我在设置中给出了每小时、每天和每周同步的选项。 我面临的问题是,尽管用户选择了同步频率,但只要有可用的互联网连接,表的数据就会同步。请帮我解决这个问题

【问题讨论】:

  • 您是否创建了任何服务,例如警报服务或类似的服务以定期调用以进行同步过程?
  • 我认为只有在条件与用户设置的时间段匹配时才需要同步的标志的问题可能是您在找到连接时直接同步这可能是问题。
  • 我没有使用任何报警服务。我举个例子。假设用户从设置中选择了每周同步,并在离线模式下使用了应用程序。然后,只要用户打开互联网连接,同步就会开始。如果假设用户每天两次做同样的事情,那么数据将被同步两次。然后不使用每周同步功能
  • 这就是为什么我指向标志的点我的意思是共享偏好,因为你的方式不正确
  • 请记住,操作系统会在它认为最好的时候触发同步适配器 - 所以如果你错过了一个并且有一个待处理,它可能会在你再次连接时执行

标签: android


【解决方案1】:

看看这个简单的代码

public class TimerReceiverSyncInterval extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {

    Log.d("TAG", "Sync OnReceive--");


    scheduleAlarms(context);
    context.startService(new Intent(context, NotificationServiceSyncInterval.class));

}

public static void scheduleAlarms(Context paramContext) {

    Calendar calendar = Calendar.getInstance();

    String[] splited = mPrefs.getSyncTime().split("\\s+");
    if (mPrefs.getSyncTime().contains("Minute")) {

        calendar.set(Calendar.MINUTE, Integer.parseInt(splited[0]));
    } else if (mPrefs.getSyncTime().contains("Hour")) {
        calendar.set(Calendar.HOUR, Integer.parseInt(splited[0]));
    }

    AlarmManager localAlarmManager = (AlarmManager) paramContext.getSystemService(Context.ALARM_SERVICE);
    PendingIntent localPendingIntent = PendingIntent.getService(paramContext, 0,
            new Intent(paramContext, NotificationServiceSyncInterval.class), PendingIntent.FLAG_UPDATE_CURRENT);

    if (mPrefs.getSyncTime().contains("Minute")) {

        localAlarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(),
                Integer.parseInt(splited[0]) * (60 * 1000), localPendingIntent);

    } else if (mPrefs.getSyncTime().contains("Hour")) {

        localAlarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(),
                Integer.parseInt(splited[0]) * (60 * 60 * 1000), localPendingIntent);

    }

    Log.d("TAG", "Sync------");

}

我在这里拆分小时、分钟,因为我的设置包含 15 分钟、1 小时等,您可以根据需要设置它,例如天、周等

public class NotificationServiceSyncInterval extends IntentService {

public NotificationServiceSyncInterval() {
    super("Sync Tracker Online");

}

public NotificationServiceSyncInterval(String paramString) {
    super(paramString);

}

@Override
protected void onHandleIntent(Intent intent) {


    Log.d("TAG", "Sync Handler call");
    // todo
    callSync();

}

public static void callSync() {

    try {
        //Your Sync Code here

    } catch (Exception e) {
        e.printStackTrace();
    }

}

上述类的清单条目

    <receiver
        android:name="com.yourpackage.TimerReceiverSyncInterval"
        android:enabled="true" >
        <intent-filter android:priority="999" >
            <action android:name="android.intent.action.BOOT_COMPLETED" />
            <action android:name="android.intent.action.QUICKBOOT_POWERON" />
        </intent-filter>
    </receiver>

    <service android:name="com.yourpackage.NotificationServiceSyncInterval" >
    </service>

最后在用户选择时间间隔时分配上下文,即 TimerReceiverSyncInterval.scheduleAlarms(this);

【讨论】:

    【解决方案2】:

    我不知道最好的方法是什么。但是您可以创建一个 SharedPreference 变量,例如 LastSyncTime,它将包含同步时间,并在每次同步发生在您实际同步数据的 onPerformSync() 中时更新此值。

    下次调用 onPerformSync() 时,您可以将您的 LastSyncTime 值与当前时间值进行比较。如果已经过了一周,则执行同步并更新 LastSyncTime's 值,否则不执行同步,即退出 onPerformSync() 方法而不执行任何操作。

    【讨论】:

      【解决方案3】:

      syncadapter.xml 中使用android:isAlwaysSyncable="false" 之后它会按预期工作(当互联网可用时不会自动同步)。


      android:isAlwaysSyncable 向同步适配器框架表明它可以在您指定的任何时间运行您的同步适配器。如果您想以编程方式控制同步适配器何时可以运行,请将此标志设置为 false,然后调用 requestSync() 来运行同步适配器。

      阅读documentation

      【讨论】:

      • 我设置了 android:isAlwaysSyncable="false" 但它没有帮助。每当我打开互联网时,都会调用同步适配器并同步所有数据。
      【解决方案4】:

      要定期运行同步适配器,请调用 addPeriodicSync()。这会安排您的同步适配器在经过一定时间后运行。

      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(
                  ACCOUNT,
                  AUTHORITY,
                  Bundle.EMPTY,
                  SYNC_INTERVAL);
          ... 
      } 
      ... 
      

      }

      请注意,addPeriodicSync() 不会在一天中的特定时间运行同步适配器。要在每天大致相同的时间运行同步适配器,请使用重复警报作为触发器。

      【讨论】:

        【解决方案5】:

        在您创建链接到同步服务的用户帐户时添加:

        if (accountManager.addAccountExplicitly(account, null, null)) {
        
            // Inform the system that this account supports sync
            ContentResolver.setIsSyncable(account, BuildConfig.CONTENT_AUTHORITY, 1)
        
            // Inform the system whether this account is eligible for auto sync when the network 
            // is up. In your case should be false
            ContentResolver.setSyncAutomatically(account, BuildConfig.CONTENT_AUTHORITY, false)
        
            // Add a schedule for automatic synchronisation. The system may call the sync function
            // a few seconds early or late for battery and network optimisation.
            ContentResolver.addPeriodicSync(account, BuildConfig.CONTENT_AUTHORITY, Bundle(), 
                    SYNC_FREQUENCY)
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-03-28
          • 2015-08-26
          • 2013-11-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多