{"action":"created","comment":{"url":"https://api.github.com/repos/cloudant/sync-android/pulls/comments/39255917","id":39255917,"diff_hunk":"@@ -0,0 +1,90 @@\n+package com.cloudant.sync.replication;\n+\n+import android.content.Context;\n+import android.content.Intent;\n+import android.net.ConnectivityManager;\n+import android.net.NetworkInfo;\n+\n+/**\n+ * This class extends {@link PeriodicReplicationReceiver} so that periodic replications are only\n+ * started when the device is connected to a WiFi network and are stopped when the device\n+ * disconnects from a WiFi network.\n+ *","path":"cloudant-sync-datastore-android/src/main/java/com/cloudant/sync/replication/WifiPeriodicReplicationReceiver.java","position":null,"original_position":12,"commit_id":"e02818a297e3a6e4945ae4aca8cfd04322b3cfb1","original_commit_id":"4dc8c0e2ec40d07c33941be3ad3f3d93a485b1d5","user":{"login":"brynh","id":12249863,"avatar_url":"https://avatars.githubusercontent.com/u/12249863?v=3","gravatar_id":"","url":"https://api.github.com/users/brynh","html_url":"https://github.com/brynh","followers_url":"https://api.github.com/users/brynh/followers","following_url":"https://api.github.com/users/brynh/following{/other_user}","gists_url":"https://api.github.com/users/brynh/gists{/gist_id}","starred_url":"https://api.github.com/users/brynh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brynh/subscriptions","organizations_url":"https://api.github.com/users/brynh/orgs","repos_url":"https://api.github.com/users/brynh/repos","events_url":"https://api.github.com/users/brynh/events{/privacy}","received_events_url":"https://api.github.com/users/brynh/received_events","type":"User","site_admin":false},"body":"Fixed in e02818a. Also reformatted some long lines in comment.","created_at":"2015-09-11T09:41:29Z","updated_at":"2015-09-11T09:41:29Z","html_url":"https://github.com/cloudant/sync-android/pull/200#discussion_r39255917","pull_request_url":"https://api.github.com/repos/cloudant/sync-android/pulls/200","_links":{"self":{"href":"https://api.github.com/repos/cloudant/sync-android/pulls/comments/39255917"},"html":{"href":"https://github.com/cloudant/sync-android/pull/200#discussion_r39255917"},"pull_request":{"href":"https://api.github.com/repos/cloudant/sync-android/pulls/200"}}},"pull_request":{"url":"https://api.github.com/repos/cloudant/sync-android/pulls/200","id":44434310,"html_url":"https://github.com/cloudant/sync-android/pull/200","diff_url":"https://github.com/cloudant/sync-android/pull/200.diff","patch_url":"https://github.com/cloudant/sync-android/pull/200.patch","issue_url":"https://api.github.com/repos/cloudant/sync-android/issues/200","number":200,"state":"open","locked":false,"title":"Add policy for periodic replication only on Wifi.","user":{"login":"brynh","id":12249863,"avatar_url":"https://avatars.githubusercontent.com/u/12249863?v=3","gravatar_id":"","url":"https://api.github.com/users/brynh","html_url":"https://github.com/brynh","followers_url":"https://api.github.com/users/brynh/followers","following_url":"https://api.github.com/users/brynh/following{/other_user}","gists_url":"https://api.github.com/users/brynh/gists{/gist_id}","starred_url":"https://api.github.com/users/brynh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brynh/subscriptions","organizations_url":"https://api.github.com/users/brynh/orgs","repos_url":"https://api.github.com/users/brynh/repos","events_url":"https://api.github.com/users/brynh/events{/privacy}","received_events_url":"https://api.github.com/users/brynh/received_events","type":"User","site_admin":false},"body":"This is part 5 of a 6 part change to implement replication policies. Each of the 6 parts of the implementation of replication policies are each in a separate branch.\r\n\r\n_The following text is common to all 6 PRs._\r\n\r\nThe 6 branches include:\r\n1. _48607-policies-1-replicator-id_: Adding an ID to replicators so we can easily identify which replicators are completed or have errored in subsequent callbacks.\r\n2. _48607-policies-2-java_: Adding replication policies for Java.\r\n3. _48607-policies-3-android-service_:Adding basic replication policies for Android.\r\n4. _48607-policies-4-android-periodic_: Adding replication at regular intervals for Android.\r\n5. _48607-policies-5-android-wifi_: Adding replication only when on Wifi.\r\n6. _48607-policies-6-docs_: Documentation updates.\r\n\r\n_What?_\r\nAdd mechanism to enable users to more easily specify the circumstances under which they want replication to occur. This allows relatively simple definition of policies such as:\r\n* Do a pull replication every 2 hours;\r\n* Do a full sync every hour, but only when we have a Wifi connection;\r\n* Sync whenever we connect to Wifi.\r\n\r\n_Why?_\r\nPrior to this PR, it was very difficult to implement such policies, particularly on Android where many aspects of the way the Android operating system works would need to be taken into account in order for such policies to work reliably.\r\n\r\n_How?_\r\nOn Android we want the replication policy management to be reliable, battery efficient and not hog system resources unnecessarily. To achieve this we typically might trigger our replications from a `BroadcastReceiver`. This allows our code to be completely inactive on the device and be started when events of interest are broadcast.  We can also use a `BroadcastReceiver` to trigger periodic replications via the `AlarmManager` mechanism in an efficient way.  However, a `BroadcastReceiver` is intended to only run for a short time in response to receiving a broadcast, so the replication is carried on inside a `Service` that may be started from a `BroadcastReceiver`.\r\n\r\nRunning replications in a `Service` allows them to run independently of the lifecycle of other application components and be started easily via other application components.  We must also handle the fact that when we wish replication to occur, the device may be asleep, so we need to hold a `WakeLock` for the duration of the replication to prevent the device going back to sleep once the `onReceive()` method of the `BroadcastReceiver` triggering the replications has completed.  Also, if our replications are over Wifi, we need to hold a `Wifi` lock to keep the Wifi radio awake.\r\n\r\nOn Java, replication policies are much simpler than on Android. The new `ReplicationPolicyManager` class takes care of ensuring that if replications are in progress they are not restarted.\r\n\r\nSee the [Replication Policies User Guide](https://github.com/cloudant/sync-android/blob/48607-replication-policies/REPLICATION_POLICIES.md) for further information on how replication policies are implemented on Android and on Java.\r\n\r\nreviewer @mikerhodes\r\nreviewer @ricellis ","created_at":"2015-09-08T13:51:11Z","updated_at":"2015-09-11T09:41:29Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2de94ad835392bb3766d7c199c1c9be1093f66f2","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/cloudant/sync-android/pulls/200/commits","review_comments_url":"https://api.github.com/repos/cloudant/sync-android/pulls/200/comments","review_comment_url":"https://api.github.com/repos/cloudant/sync-android/pulls/comments{/number}","comments_url":"https://api.github.com/repos/cloudant/sync-android/issues/200/comments","statuses_url":"https://api.github.com/repos/cloudant/sync-android/statuses/e02818a297e3a6e4945ae4aca8cfd04322b3cfb1","head":{"label":"cloudant:48607-policies-5-android-wifi","ref":"48607-policies-5-android-wifi","sha":"e02818a297e3a6e4945ae4aca8cfd04322b3cfb1","user":{"login":"cloudant","id":44642,"avatar_url":"https://avatars.githubusercontent.com/u/44642?v=3","gravatar_id":"","url":"https://api.github.com/users/cloudant","html_url":"https://github.com/cloudant","followers_url":"https://api.github.com/users/cloudant/followers","following_url":"https://api.github.com/users/cloudant/following{/other_user}","gists_url":"https://api.github.com/users/cloudant/gists{/gist_id}","starred_url":"https://api.github.com/users/cloudant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cloudant/subscriptions","organizations_url":"https://api.github.com/users/cloudant/orgs","repos_url":"https://api.github.com/users/cloudant/repos","events_url":"https://api.github.com/users/cloudant/events{/privacy}","received_events_url":"https://api.github.com/users/cloudant/received_events","type":"Organization","site_admin":false},"repo":{"id":16811502,"name":"sync-android","full_name":"cloudant/sync-android","owner":{"login":"cloudant","id":44642,"avatar_url":"https://avatars.githubusercontent.com/u/44642?v=3","gravatar_id":"","url":"https://api.github.com/users/cloudant","html_url":"https://github.com/cloudant","followers_url":"https://api.github.com/users/cloudant/followers","following_url":"https://api.github.com/users/cloudant/following{/other_user}","gists_url":"https://api.github.com/users/cloudant/gists{/gist_id}","starred_url":"https://api.github.com/users/cloudant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cloudant/subscriptions","organizations_url":"https://api.github.com/users/cloudant/orgs","repos_url":"https://api.github.com/users/cloudant/repos","events_url":"https://api.github.com/users/cloudant/events{/privacy}","received_events_url":"https://api.github.com/users/cloudant/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/cloudant/sync-android","description":"A JSON-based document datastore for Android applications","fork":false,"url":"https://api.github.com/repos/cloudant/sync-android","forks_url":"https://api.github.com/repos/cloudant/sync-android/forks","keys_url":"https://api.github.com/repos/cloudant/sync-android/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cloudant/sync-android/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cloudant/sync-android/teams","hooks_url":"https://api.github.com/repos/cloudant/sync-android/hooks","issue_events_url":"https://api.github.com/repos/cloudant/sync-android/issues/events{/number}","events_url":"https://api.github.com/repos/cloudant/sync-android/events","assignees_url":"https://api.github.com/repos/cloudant/sync-android/assignees{/user}","branches_url":"https://api.github.com/repos/cloudant/sync-android/branches{/branch}","tags_url":"https://api.github.com/repos/cloudant/sync-android/tags","blobs_url":"https://api.github.com/repos/cloudant/sync-android/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cloudant/sync-android/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cloudant/sync-android/git/refs{/sha}","trees_url":"https://api.github.com/repos/cloudant/sync-android/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cloudant/sync-android/statuses/{sha}","languages_url":"https://api.github.com/repos/cloudant/sync-android/languages","stargazers_url":"https://api.github.com/repos/cloudant/sync-android/stargazers","contributors_url":"https://api.github.com/repos/cloudant/sync-android/contributors","subscribers_url":"https://api.github.com/repos/cloudant/sync-android/subscribers","subscription_url":"https://api.github.com/repos/cloudant/sync-android/subscription","commits_url":"https://api.github.com/repos/cloudant/sync-android/commits{/sha}","git_commits_url":"https://api.github.com/repos/cloudant/sync-android/git/commits{/sha}","comments_url":"https://api.github.com/repos/cloudant/sync-android/comments{/number}","issue_comment_url":"https://api.github.com/repos/cloudant/sync-android/issues/comments{/number}","contents_url":"https://api.github.com/repos/cloudant/sync-android/contents/{+path}","compare_url":"https://api.github.com/repos/cloudant/sync-android/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cloudant/sync-android/merges","archive_url":"https://api.github.com/repos/cloudant/sync-android/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cloudant/sync-android/downloads","issues_url":"https://api.github.com/repos/cloudant/sync-android/issues{/number}","pulls_url":"https://api.github.com/repos/cloudant/sync-android/pulls{/number}","milestones_url":"https://api.github.com/repos/cloudant/sync-android/milestones{/number}","notifications_url":"https://api.github.com/repos/cloudant/sync-android/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cloudant/sync-android/labels{/name}","releases_url":"https://api.github.com/repos/cloudant/sync-android/releases{/id}","created_at":"2014-02-13T17:52:09Z","updated_at":"2015-08-29T11:56:12Z","pushed_at":"2015-09-11T09:40:30Z","git_url":"git://github.com/cloudant/sync-android.git","ssh_url":"git@github.com:cloudant/sync-android.git","clone_url":"https://github.com/cloudant/sync-android.git","svn_url":"https://github.com/cloudant/sync-android","homepage":"","size":31113,"stargazers_count":101,"watchers_count":101,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":30,"mirror_url":null,"open_issues_count":14,"forks":30,"open_issues":14,"watchers":101,"default_branch":"master"}},"base":{"label":"cloudant:48607-policies-4-android-periodic","ref":"48607-policies-4-android-periodic","sha":"07a1fe06a85c02ec1a5f3d620fa3d26fd705622f","user":{"login":"cloudant","id":44642,"avatar_url":"https://avatars.githubusercontent.com/u/44642?v=3","gravatar_id":"","url":"https://api.github.com/users/cloudant","html_url":"https://github.com/cloudant","followers_url":"https://api.github.com/users/cloudant/followers","following_url":"https://api.github.com/users/cloudant/following{/other_user}","gists_url":"https://api.github.com/users/cloudant/gists{/gist_id}","starred_url":"https://api.github.com/users/cloudant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cloudant/subscriptions","organizations_url":"https://api.github.com/users/cloudant/orgs","repos_url":"https://api.github.com/users/cloudant/repos","events_url":"https://api.github.com/users/cloudant/events{/privacy}","received_events_url":"https://api.github.com/users/cloudant/received_events","type":"Organization","site_admin":false},"repo":{"id":16811502,"name":"sync-android","full_name":"cloudant/sync-android","owner":{"login":"cloudant","id":44642,"avatar_url":"https://avatars.githubusercontent.com/u/44642?v=3","gravatar_id":"","url":"https://api.github.com/users/cloudant","html_url":"https://github.com/cloudant","followers_url":"https://api.github.com/users/cloudant/followers","following_url":"https://api.github.com/users/cloudant/following{/other_user}","gists_url":"https://api.github.com/users/cloudant/gists{/gist_id}","starred_url":"https://api.github.com/users/cloudant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cloudant/subscriptions","organizations_url":"https://api.github.com/users/cloudant/orgs","repos_url":"https://api.github.com/users/cloudant/repos","events_url":"https://api.github.com/users/cloudant/events{/privacy}","received_events_url":"https://api.github.com/users/cloudant/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/cloudant/sync-android","description":"A JSON-based document datastore for Android applications","fork":false,"url":"https://api.github.com/repos/cloudant/sync-android","forks_url":"https://api.github.com/repos/cloudant/sync-android/forks","keys_url":"https://api.github.com/repos/cloudant/sync-android/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cloudant/sync-android/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cloudant/sync-android/teams","hooks_url":"https://api.github.com/repos/cloudant/sync-android/hooks","issue_events_url":"https://api.github.com/repos/cloudant/sync-android/issues/events{/number}","events_url":"https://api.github.com/repos/cloudant/sync-android/events","assignees_url":"https://api.github.com/repos/cloudant/sync-android/assignees{/user}","branches_url":"https://api.github.com/repos/cloudant/sync-android/branches{/branch}","tags_url":"https://api.github.com/repos/cloudant/sync-android/tags","blobs_url":"https://api.github.com/repos/cloudant/sync-android/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cloudant/sync-android/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cloudant/sync-android/git/refs{/sha}","trees_url":"https://api.github.com/repos/cloudant/sync-android/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cloudant/sync-android/statuses/{sha}","languages_url":"https://api.github.com/repos/cloudant/sync-android/languages","stargazers_url":"https://api.github.com/repos/cloudant/sync-android/stargazers","contributors_url":"https://api.github.com/repos/cloudant/sync-android/contributors","subscribers_url":"https://api.github.com/repos/cloudant/sync-android/subscribers","subscription_url":"https://api.github.com/repos/cloudant/sync-android/subscription","commits_url":"https://api.github.com/repos/cloudant/sync-android/commits{/sha}","git_commits_url":"https://api.github.com/repos/cloudant/sync-android/git/commits{/sha}","comments_url":"https://api.github.com/repos/cloudant/sync-android/comments{/number}","issue_comment_url":"https://api.github.com/repos/cloudant/sync-android/issues/comments{/number}","contents_url":"https://api.github.com/repos/cloudant/sync-android/contents/{+path}","compare_url":"https://api.github.com/repos/cloudant/sync-android/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cloudant/sync-android/merges","archive_url":"https://api.github.com/repos/cloudant/sync-android/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cloudant/sync-android/downloads","issues_url":"https://api.github.com/repos/cloudant/sync-android/issues{/number}","pulls_url":"https://api.github.com/repos/cloudant/sync-android/pulls{/number}","milestones_url":"https://api.github.com/repos/cloudant/sync-android/milestones{/number}","notifications_url":"https://api.github.com/repos/cloudant/sync-android/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cloudant/sync-android/labels{/name}","releases_url":"https://api.github.com/repos/cloudant/sync-android/releases{/id}","created_at":"2014-02-13T17:52:09Z","updated_at":"2015-08-29T11:56:12Z","pushed_at":"2015-09-11T09:40:30Z","git_url":"git://github.com/cloudant/sync-android.git","ssh_url":"git@github.com:cloudant/sync-android.git","clone_url":"https://github.com/cloudant/sync-android.git","svn_url":"https://github.com/cloudant/sync-android","homepage":"","size":31113,"stargazers_count":101,"watchers_count":101,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":30,"mirror_url":null,"open_issues_count":14,"forks":30,"open_issues":14,"watchers":101,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/cloudant/sync-android/pulls/200"},"html":{"href":"https://github.com/cloudant/sync-android/pull/200"},"issue":{"href":"https://api.github.com/repos/cloudant/sync-android/issues/200"},"comments":{"href":"https://api.github.com/repos/cloudant/sync-android/issues/200/comments"},"review_comments":{"href":"https://api.github.com/repos/cloudant/sync-android/pulls/200/comments"},"review_comment":{"href":"https://api.github.com/repos/cloudant/sync-android/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/cloudant/sync-android/pulls/200/commits"},"statuses":{"href":"https://api.github.com/repos/cloudant/sync-android/statuses/e02818a297e3a6e4945ae4aca8cfd04322b3cfb1"}}}}