Local sync between phone and laptop

  • Hi,

    This post is somehow related to https://forums.bitfire.at/topic/2379/cannot-sync-to-local-server-without-internet-connectivity but not exactly the same request (typically I always have Internet connectivity even when I don’t use it).

    I’m looking for a way to get back Palm PDA capabilities with my phone. The plan is to set up Radicale on the laptop and use DAVx5 on the phone.

    At home both will be in the subnet of my DSL box, so the phone should be able to connect to the laptop Radicale HTTP port (if I understand correctly how all this works). But at work there are strict restrictions, so the Radicale port will probably be inaccessible even if both devices are in the same Wifi subnet.

    I think that, for the time of synchronisation (which will always be manual), I could set the phone as access point and connect the laptop to it.

    Do you think this will work? Do you have any suggestions to improve or simplify my plan?


  • developer

    That should work. You could also set up a server at home (e.g. Raspberry Pi, or a Synology system, or a home server …) and then sync with this server, and also use the laptop and maybe other systems to access that server. This will also allow easier backups.

  • Hi,

    I’m facing some problems and I’m so new to this *DAV thing that I don’t even know how to look for a solution: any help will be appreciated. I’m knew to Evolution, Radicale, DAVx5 and calendar apps!

    The Radicale server is up and I’ve configured nothing (I just installed the package and ran the daemon). http://localhost:5232/ shows “Radicale works!”. Then in Evolution I did New > Calendar, chose type CalDAV, named it Foo, chose a color and entered the latter URL. After this I created an appointment in this calendar.

    First problem (not related to DAVx5 but may be relevant): if I try to move the appointment in the grid, I get an error message in Evolution “Failed to modify an event in the calendar “CalDAV : Foo”. Cannot modify calendar object: Failed to put data: HTTP error code 412 (Precondition Failed)”

    Next, in DAVx5 I add an account that I call “me”, choose Advanced login, type in the URL “http://(the_laptop_IP):5232/”. Under the CALDAV tab I then see one calendar whose name is “/”. I tap the sync button.

    Then I open a calendar app; I’ve tried Etar and Simple Calendar. In both the appointment show up, but:

    • the calendar name is “/”, not “Foo”,
    • the color is wrong (in DAVx5, in parameters of account “me” both toggles in the CalDAV section are on).

    And when I go back to Evolution and refresh, the appointment is gone!

    Can you help me?

    Note: on Palm I had categories to categorize (!) my appointments and give them a color. AFAIU this should be possible under the CalDAV protocol, but the few calendar apps I have tested seem not to offer this capability (Simple Calendar has this but only for its internal calendar), so I resolved to resort to separate calendars to emulate categories. Am I right?

  • Some more testing: the disappearance is unrelated to DAVx5 sync. It’s enough to refresh Evolution to make the appointment disappear. Nevertheless if I sync DAVx5 after that the “disappeared” appointment does show up in the calendar apps. However, if I try and change the appointment time in the app, then sync DAVx5, the initial time is set back!

  • Well, problems solved!

    Linux Mint 19 which I’m using distributes Radicale 1.1.6, when the current version is 3.0 !.. So I completely removed the packages and installed through python as instructed on the Radicale website.

    For future reference:

    • you have to create a config file with this setting https://radicale.org/3.0.html#tutorials/basic-configuration/addresses for the server to be accessible
    • not knowing how to add a calendar from Evolution, I added one with the web interface. It shows a complex URL for the calendar, like http://localhost:5232/loginname/long_hash/ . This has to be put as-is in Evolution to add this new calendar; I didn’t manage to fetch calendars from Evolution. However in DAVx5 it was enough to enter the base URL http://laptop_IP:5232/, loginname and PW for it to find the calendars created in Radicale.

    I hope this will help other newbies!

  • Bottom line: the color is OK in DAVx5 and Etar. In Evolution and Simple Calendar it’s not (it may have been corrected in Simple Calendar Pro).

  • admin

    @LL Great!

    Most other clients don’t have a resource detection like DAVx5 has. In these clients you must point them directly to the respective URLs that represent the calendar/addressbook.

  • I’m facing another problem. Let me recall the setup: Radicale server on a Linux laptop, DAVx5 on an Android 8.1 phone. I want to interconnect them in two possible ways: at home they are both connected to a Wifi router; when roaming the laptop connects to the phone used as access point (AP).

    The difficulty is the subnets have different IPs in the two situations. At home both devices are 192.168.1.x ; in the phone AP the latop is 192.168.43.y . The Wifi router subnet number cannot be changed; for the phone AP subnet I don’t know (the phone is not rooted).

    I thought “whatever, I’ll use named URLs”. I point DAVx5 to http://coulomb:5232/ (coulomb is the hostname of the laptop). In the Wifi router subnet it works. But when the laptop is connected to the phone AP it doesn’t. The phone DNS seems OK because if I run host coulomb this gives the correct IP (obtained from Here is the log of DAVx5 for the failed sync (I trimmed the collection which I believe to be irrelevant):

    --- BEGIN DEBUG INFO ---
    Account: Account {name=-, type=bitfire.at.davdroid}
    Authority: com.android.calendar
    java.net.UnknownHostException: Unable to resolve host "coulomb": No address associated with hostname
    	at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:111)
    	at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:90)
    	at java.net.InetAddress.getAllByName(InetAddress.java:787)
    	at okhttp3.Dns$Companion$DnsSystem.lookup(Dns.kt:1)
    	at okhttp3.internal.connection.ExchangeFinder.findHealthyConnection(ExchangeFinder.kt:67)
    	at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:20)
    	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:14)
    	at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:213)
    	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:14)
    	at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:38)
    	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:14)
    	at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:35)
    	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:14)
    	at okhttp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.kt:52)
    	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:14)
    	at okhttp3.brotli.BrotliInterceptor.intercept(BrotliInterceptor.kt:31)
    	at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:14)
    	at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:25)
    	at okhttp3.internal.connection.RealCall.execute(RealCall.kt:13)
    	at at.bitfire.dav4jvm.DavResource$propfind$2.invoke(DavResource.kt:19)
    	at at.bitfire.dav4jvm.DavResource$propfind$2.invoke(DavResource.kt:1)
    	at at.bitfire.dav4jvm.DavResource.followRedirects$build(DavResource.kt:1)
    	at at.bitfire.dav4jvm.DavResource.propfind(DavResource.kt:10)
    	at at.bitfire.davdroid.syncadapter.CalendarSyncManager$queryCapabilities$1.invoke(CalendarSyncManager.kt:3)
    	at at.bitfire.davdroid.syncadapter.CalendarSyncManager$queryCapabilities$1.invoke(CalendarSyncManager.kt:1)
    	at at.bitfire.davdroid.syncadapter.SyncManager.remoteExceptionContext(SyncManager.kt:1)
    	at at.bitfire.davdroid.syncadapter.SyncManager.remoteExceptionContext(SyncManager.kt:8)
    	at at.bitfire.davdroid.syncadapter.CalendarSyncManager.queryCapabilities(CalendarSyncManager.kt:1)
    	at at.bitfire.davdroid.syncadapter.SyncManager$performSync$1.invoke(SyncManager.kt:6)
    	at at.bitfire.davdroid.syncadapter.SyncManager$performSync$1.invoke(SyncManager.kt:1)
    	at at.bitfire.davdroid.syncadapter.SyncManager.unwrapExceptions(SyncManager.kt:1)
    	at at.bitfire.davdroid.syncadapter.SyncManager.performSync(SyncManager.kt:5)
    	at at.bitfire.davdroid.syncadapter.CalendarsSyncAdapterService$CalendarsSyncAdapter.sync(CalendarsSyncAdapterService.kt:14)
    	at at.bitfire.davdroid.syncadapter.SyncAdapterService$SyncAdapter.onPerformSync(SyncAdapterService.kt:13)
    	at android.content.AbstractThreadedSyncAdapter$SyncThread.run(AbstractThreadedSyncAdapter.java:321)
    │ Package                        │ Version                  │ Code       │ Installer                           │ Notes │
    │ at.bitfire.davdroid            │              │ 303040100  │ com.google.android.packageinstaller │       │
    │ org.dmfs.tasks                 │ 1.2.4                    │ 78500      │ com.google.android.packageinstaller │       │
    │ com.android.providers.contacts │ 8.1.0                    │ 27         │ —                                   │       │
    │ com.android.providers.calendar │ 8.1.0                    │ 27         │ —                                   │       │
    │ com.android.contacts           │ 1.7.10                   │ 10710      │ —                                   │       │
    │ com.google.android.calendar    │ 5.8.34-198051655-release │ 2015821617 │ —                                   │       │
    │ ws.xsoh.etar                   │ 1.0.23                   │ 25         │ com.google.android.packageinstaller │       │
    │ com.mobisystems.fileman        │ 6.12.37871               │ 37871      │ com.android.vending                 │       │
    Android version: 8.1.0 (ECHO_FEELING_V01_20180821)
     ☒ [ Transports: CELLULAR Capabilities: INTERNET NOT_RESTRICTED TRUSTED NOT_VPN VALIDATED FOREGROUND LinkUpBandwidth>=51200Kbps LinkDnBandwidth>=102400Kbps Specifier: <1>]
    Data saver: disabled
    Power saving disabled: no
    System-wide synchronization: automatically
     - sync 
     - syncProblems: importance=3
     - general: importance=3
     - debug: importance=4
     - syncIoErrors: importance=1
     - syncWarnings: importance=2
     - ACCESS_NETWORK_STATE: granted
     - ACCESS_WIFI_STATE: granted
     - INTERNET: granted
     - READ_SYNC_SETTINGS: granted
     - READ_SYNC_STATS: granted
     - WRITE_SYNC_SETTINGS: granted
     - READ_CONTACTS: granted
     - WRITE_CONTACTS: granted
     - READ_CALENDAR: granted
     - WRITE_CALENDAR: granted
     - org.dmfs.permission.READ_TASKS: granted
     - org.dmfs.permission.WRITE_TASKS: granted
     - org.tasks.permission.READ_TASKS: denied
     - org.tasks.permission.WRITE_TASKS: denied
     - Account: -
    │ Authority                        │ isSyncable │ getSyncAutomatically │ Sync interval │
    │ at.bitfire.davdroid.addressbooks │ 1          │ false                │ 240 min       │
    │ com.android.calendar             │ 1          │ false                │ 240 min       │
    │ com.android.contacts             │ 0          │ false                │ —             │
    │ org.dmfs.tasks                   │ 1          │ false                │ 240 min       │
      WiFi only: false
      Contact group method: CATEGORIES
      Time range (past days): 90
      Default alarm (min before): null
      Manage calendar colors: true
      Use event colors: false
      * Address book: répertoire (- Gw)
       │ isSyncable │ getSyncAutomatically │ Sync interval │
       │ 1          │ true                 │ 1440 min      │
           URL: http://coulomb:5232/any/280916a1-8333-f36a-fac0-5e7d2eed2531/
        Read-only: 0
    │ locale │
    │ fr_FR  │
    │ id │ accountName │ type    │ principal                │
    │ 7  │ -           │ carddav │ http://coulomb:5232/any/ │
    │ 8  │ -           │ caldav  │ http://coulomb:5232/any/ │
    │ name       │ seq │
    │ service    │ 8   │
    │ homeset    │ 8   │
    │ collection │ 21  │
    │ id │ serviceId │ url                      │ privBind │ displayName │
    │ 7  │ 7         │ http://coulomb:5232/any/ │ 1        │ —           │
    │ 8  │ 8         │ http://coulomb:5232/any/ │ 1        │ —           │
    │ id │ identity_hash                    │
    │ 42 │ a7554d1ebc5ecfe0c7aefe271485d63c │
    1. SharedPreferencesProvider canWrite=true
    │ Setting                   │ Value         │
    │ distrust_system_certs     │ false         │
    │ hint_BatteryOptimizations │ false         │
    │ log_to_file               │ true          │
    │ override_proxy            │ false         │
    │ override_proxy_host       │ localhost     │
    │ override_proxy_port       │ 8118          │
    │ time_nextDonationPopup    │ 1611923475688 │
    2. DefaultsProvider canWrite=false
    │ Setting               │ Value     │
    │ distrust_system_certs │ false     │
    │ override_proxy        │ false     │
    │ override_proxy_host   │ localhost │
    │ override_proxy_port   │ 8118      │
    --- END DEBUG INFO ---

    Thanks for any help!

  • developer

    @LL said in Local sync between phone and laptop:

    The phone DNS seems OK because if I run host coulomb this gives the correct IP

    Did you run the host command on the phone (where DAVx5 runs)?

    DAVx5 uses okhttp, which uses the system DNS to resolve the host names. So nothing special…

  • @rfc2822 no I ran it on the laptop. Is it possible to run such commands on a non rooted phone? With adb maybe?

  • developer

    @LL adb shell, and nslookup/host should be there

  • adb shell → I have neither nslookup nor host…
    But ping coulomb answers “unknown host”, so it looks like the phone cannot use its own DNS 😕 ?

  • developer

    @LL Sounds reasonable, because DAVx5 uses the same DNS. So DAVx5 should work when ping works and in the other direction.

    Maybe coulomb.domain?

  • I finally solved this last problem. I posted it on SE: https://android.stackexchange.com/questions/230983/the-phone-as-hotspot-doesnt-use-its-own-dns/231206#231206
    It turns out this is expected behavior: the phone as a DNS client doesn’t use the DNS server it runs.

    However I installed Virtual Hosts which allows to define custom hosts entries without rooting the phone. The app is really easy to switch on/off, so I’ll be able to use it only when I sync DAVx5 (which I do manually only) through the phone access point.

    Happy syncing!

Similar topics