I have a sync adapter that works fine. It does not need internet connection because it needs to sync the addressbook with another local storage (my application).
When the Wifi is turned off and the device does not have any internet connection Android disables the sync in the Account & Synch settings activity.
Is there a way to keep my synch adapter on even when the connection is off?
Well there is no way, SyncAdpater framework won't work without internet connection So its better to Re-implement your sync adapter as a intent Service.
There is no way to achieve this without modifying AOSP or changing design as rAm answered.
My answer is for those open to modifying AOSP :
Google enforces this as follows :
Job is scheduled with Network constraint by SyncManager.java
final int networkType = syncOperation.isNotAllowedOnMetered() ?
JobInfo.NETWORK_TYPE_UNMETERED : JobInfo.NETWORK_TYPE_ANY;
JobInfo.Builder b = new JobInfo.Builder(syncOperation.jobId,
new ComponentName(mContext, SyncJobService.class))
.setExtras(syncOperation.toJobInfoExtras())
.setRequiredNetworkType(networkType)
.setPersisted(true)
.setPriority(priority);
But NETWORK_TYPE_ANY is mapped to CONSTRAINT_CONNECTIVITY in JobStatus.java
switch (job.getNetworkType()) {
case JobInfo.NETWORK_TYPE_NONE:
// No constraint.
break;
case JobInfo.NETWORK_TYPE_ANY:
requiredConstraints |= CONSTRAINT_CONNECTIVITY;
break;
There are two solutions :
1.
First removes check for internet connectivity and just checks for regular connectivity
diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
index 4d5a920..6680c4e 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -118,7 +118,8 @@ public final class ConnectivityController extends StateController implements
&& !info.isRoaming();
boolean changed = false;
- changed |= jobStatus.setConnectivityConstraintSatisfied(connectionUsable);
+ //change to AOSP : use connected instead of connectionUsable - since connection maybe considered usable within enterprise without NET_CAPABILITY_VALIDATED
+ changed |= jobStatus.setConnectivityConstraintSatisfied(connected);
changed |= jobStatus.setMeteredConstraintSatisfied(metered);
changed |= jobStatus.setUnmeteredConstraintSatisfied(unmetered);
changed |= jobStatus.setNotRoamingConstraintSatisfied(notRoaming);
2.
Second is you need to add an alternative condition conditionally to SyncManager.java
I added charging condition since custom device I work on is always charging - this can be changed to any other condition - but one additional condition is necessary.
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 205e828..81f9a8c 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1539,6 +1539,13 @@ public class SyncManager {
.setRequiredNetworkType(networkType)
.setPersisted(true)
.setPriority(priority);
+
+ if (syncOperation.owningPackage.contains("com.example.yourcompany")) {
+ //Change to AOSP : Custom accounts need to sync wihout access to public internet
+ Slog.i(TAG, "set JobInfo.NETWORK_TYPE_NONE for "+syncOperation.target.toString());
+ b.setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE);
+ b.setRequiresCharging(true);
+ }
if (syncOperation.isPeriodic) {
b.setPeriodic(syncOperation.periodMillis, syncOperation.flexMillis);
Add the extra SYNC_EXTRAS_MANUAL
before calling requestSync(account,authority, extras);
extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
ContentResolver.requestSync(account,authority, extras);
In SyncManager try to set mDataConnection to true when account-type is yours.
public static void requestManualSync(Account account, Bundle extras) {
//Do your Stuff here...
}
Put above method in Syncadapter..