Search code examples
androidsecurityexceptioncontentobservercalllog

Registering ContentObserver for Android CallLog causes crash


Recently my app keeps crashing when registering a contentObserver for the Android CallLog (in onCreate of a Service). This is the way I register it:

getContentResolver().registerContentObserver(CallLog.Calls.CONTENT_URI, true, new MyObserver(new Handler()));

Part of the stacktrace:

java.lang.RuntimeException: Unable to create service nl.xelion.restandroid.service.CallLogChanged: java.lang.SecurityException: Permission Denial: opening provider com.android.providers.contacts.CallLogProvider from ProcessRecord{f73a1ed 7949:nl.my.app.debug/u0a119} (pid=7949, uid=10119) requires android.permission.READ_CALL_LOG or android.permission.WRITE_CALL_LOG

...

Caused by: java.lang.SecurityException: Permission Denial: opening provider...etc

I used this tutorial, and it DID work for about a year: http://www.adityathakker.com/android-content-observer-react-on-content-change

Approximately since Android O the crashes started to appear. The javadoc of registerContentObserver does say something along these lines: Starting in O, all content notifications must be backed by a valid ContentProvider. So I was wondering if this would be the problem, and if so, how to solve it?

Anyway, why is it complaining about permissions for contacts, and why didn't this happen before? This doesn't make sense to me.

ps. I do use code which requires permission for contacts, which is called in the onChange of the ContentObserver, but even when I comment this piece of code the crash still occurs.


Solution

  • The problem lies with the update to Android O. Permissions are grouped together and since Android O permission behaviour was changed because of incorrect handling of permission requests.

    In my example I had added the permissions READ_CALL_LOG/WRITE_CALL_LOG and CALL_PHONE to the manifest, but requested only CALL_PHONE at first startup of the app. This caused the permission group PHONE to be accepted, but neither of the call-log permissions. So when the registerContentObserver method was called, Android implicitly accepted it to be used because of accepting the group PHONE.

    When my user upgraded from N to O, and registerContentObserver was called again, it would crash (justly). Solution: check for the READ_CALL_LOG/WRITE_CALL_LOG permisions before calling registerContentObserver.

    Workaround for users on Android O who're still using the old - crashing- code: Manually turn off & on the specific permission in the Android settings of the app (so the PHONE permission group in this case). This causes all permissions in this group to be accepted (or at least those permissions in that group that are required by the app)