Loading README.md +6 −4 Original line number Diff line number Diff line Loading @@ -11,10 +11,15 @@ It's a framework for from/into data classes that are compatible with the Android Contacts Provider, and * accessing the Android Contacts Provider by a unified API. It has been primarily developed for [DAVdroid](https://www.davdroid.com). It has been primarily developed for [DAVx⁵](https://www.davx5.com). _This software is not affiliated to, nor has it been authorized, sponsored or otherwise approved by Google LLC. Android is a trademark of Google LLC._ Generated KDoc: https://bitfireAT.gitlab.io/vcard4android/dokka/vcard4android/ Discussion: https://forums.bitfire.at/category/18/libraries ## Contact Loading @@ -26,9 +31,6 @@ Florastraße 27 Email: [play@bitfire.at](mailto:play@bitfire.at) (do not use this) For questions, suggestions etc. please use the DAVdroid forum: https://www.davdroid.com/forums/ ## License Loading build.gradle +27 −13 Original line number Diff line number Diff line buildscript { ext.versions = [ kotlin: '1.3.31', dokka: '0.9.17' kotlin: '1.3.60', dokka: '0.10.0' ] repositories { Loading @@ -11,9 +11,9 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:3.4.1' classpath 'com.android.tools.build:gradle:3.5.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}" classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:${versions.dokka}" classpath "org.jetbrains.dokka:dokka-gradle-plugin:${versions.dokka}" } } Loading @@ -24,16 +24,22 @@ repositories { apply plugin: 'com.android.library' apply plugin: 'kotlin-android' apply plugin: 'org.jetbrains.dokka-android' apply plugin: 'org.jetbrains.dokka' android { compileSdkVersion 27 buildToolsVersion '27.1.1' compileSdkVersion 29 buildToolsVersion '29.0.2' defaultConfig { minSdkVersion 24 targetSdkVersion 27 targetSdkVersion 29 } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } buildTypes { release { minifyEnabled false Loading @@ -53,12 +59,20 @@ android { defaultConfig { testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } dokka.configuration { sourceLink { url = "https://gitlab.com/bitfireAT/vcard4android/tree/master/" lineSuffix = "#L" } jdkVersion = 7 } } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${versions.kotlin}" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${versions.kotlin}" implementation 'org.apache.commons:commons-text:1.6' implementation 'org.apache.commons:commons-text:1.7' implementation 'commons-io:commons-io:2.6' // ez-vcard to parse/generate VCards Loading @@ -70,8 +84,8 @@ dependencies { exclude group: 'com.fasterxml.jackson.core' } androidTestImplementation 'androidx.test:runner:1.1.1' androidTestImplementation 'androidx.test:rules:1.1.1' androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test:rules:1.2.0' testImplementation 'junit:junit:4.12' } gradle/wrapper/gradle-wrapper.properties +1 −1 Original line number Diff line number Diff line Loading @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-all.zip src/main/AndroidManifest.xml +1 −2 Original line number Diff line number Diff line Loading @@ -12,7 +12,6 @@ <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_CONTACTS" /> <application android:allowBackup="true" android:label="@string/app_name"/> <application /> </manifest> src/main/java/foundation/e/vcard4android/AndroidContact.kt +19 −20 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ import android.graphics.BitmapFactory import android.net.Uri import android.os.RemoteException import android.provider.ContactsContract import android.provider.ContactsContract.CommonDataKinds import android.provider.ContactsContract.CommonDataKinds.* import android.provider.ContactsContract.CommonDataKinds.Email import android.provider.ContactsContract.CommonDataKinds.Nickname Loading @@ -41,6 +40,7 @@ import java.text.ParseException import java.text.SimpleDateFormat import java.util.* import java.util.logging.Level import kotlin.math.min open class AndroidContact( val addressBook: AndroidAddressBook<out AndroidContact, out AndroidGroup> Loading Loading @@ -115,7 +115,7 @@ open class AndroidContact( try { iter = RawContacts.newEntityIterator(addressBook.provider!!.query( addressBook.syncAdapterURI(ContactsContract.RawContactsEntity.CONTENT_URI), null, ContactsContract.RawContacts._ID + "=?", arrayOf(id.toString()), null)) null, RawContacts._ID + "=?", arrayOf(id.toString()), null)) if (iter.hasNext()) { val e = iter.next() Loading @@ -135,8 +135,7 @@ open class AndroidContact( it.remove() } val mimeType = values.getAsString(ContactsContract.RawContactsEntity.MIMETYPE) when (mimeType) { when (val mimeType = values.getAsString(ContactsContract.RawContactsEntity.MIMETYPE)) { StructuredName.CONTENT_ITEM_TYPE -> populateStructuredName(values) Phone.CONTENT_ITEM_TYPE -> Loading Loading @@ -252,13 +251,13 @@ open class AndroidContact( Phone.TYPE_MMS -> number.types += Contact.PHONE_TYPE_MMS Phone.TYPE_CUSTOM -> { row.getAsString(CommonDataKinds.Phone.LABEL)?.let { row.getAsString(Phone.LABEL)?.let { labeledNumber.label = it number.types += TelephoneType.get(labelToXName(it)) } } } if (row.getAsInteger(CommonDataKinds.Phone.IS_PRIMARY) != 0) if (row.getAsInteger(Phone.IS_PRIMARY) != 0) number.pref = 1 contact!!.phoneNumbers += labeledNumber Loading Loading @@ -454,7 +453,7 @@ open class AndroidContact( } protected open fun populateEvent(row: ContentValues) { val dateStr = row.getAsString(CommonDataKinds.Event.START_DATE) val dateStr = row.getAsString(Event.START_DATE) var full: Date? = null var partial: PartialDate? = null val fullFormat = SimpleDateFormat("yyyy-MM-dd", Locale.US) Loading Loading @@ -652,7 +651,7 @@ open class AndroidContact( op = BatchOperation.Operation(builder) builder.withValue(StructuredName.RAW_CONTACT_ID, id) } builder .withValue(Data.MIMETYPE, CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) builder .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE) .withValue(StructuredName.DISPLAY_NAME, contact.displayName) .withValue(StructuredName.PREFIX, contact.prefix) .withValue(StructuredName.GIVEN_NAME, contact.givenName) Loading Loading @@ -682,9 +681,9 @@ open class AndroidContact( } catch(e: IllegalStateException) { Constants.log.log(Level.FINER, "Can't understand phone number PREF", e) } var is_primary = pref != null var isPrimary = pref != null if (types.contains(TelephoneType.PREF)) { is_primary = true isPrimary = true types -= TelephoneType.PREF } Loading Loading @@ -756,8 +755,8 @@ open class AndroidContact( .withValue(Phone.NUMBER, number.text) .withValue(Phone.TYPE, typeCode) .withValue(Phone.LABEL, typeLabel) .withValue(Phone.IS_PRIMARY, if (is_primary) 1 else 0) .withValue(Phone.IS_SUPER_PRIMARY, if (is_primary) 1 else 0) .withValue(Phone.IS_PRIMARY, if (isPrimary) 1 else 0) .withValue(Phone.IS_SUPER_PRIMARY, if (isPrimary) 1 else 0) if (addressBook.readOnly) builder.withValue(Data.IS_READ_ONLY, 1) Loading @@ -778,9 +777,9 @@ open class AndroidContact( } catch(e: IllegalStateException) { Constants.log.log(Level.FINER, "Can't understand email PREF", e) } var is_primary = pref != null var isPrimary = pref != null if (types.contains(EmailType.PREF)) { is_primary = true isPrimary = true types -= EmailType.PREF } Loading Loading @@ -818,8 +817,8 @@ open class AndroidContact( .withValue(Email.ADDRESS, email.value) .withValue(Email.TYPE, typeCode) .withValue(Email.LABEL, typeLabel) .withValue(Email.IS_PRIMARY, if (is_primary) 1 else 0) .withValue(Phone.IS_SUPER_PRIMARY, if (is_primary) 1 else 0) .withValue(Email.IS_PRIMARY, if (isPrimary) 1 else 0) .withValue(Phone.IS_SUPER_PRIMARY, if (isPrimary) 1 else 0) if (addressBook.readOnly) builder.withValue(Data.IS_READ_ONLY, 1) Loading Loading @@ -1030,9 +1029,9 @@ open class AndroidContact( val lineLocality = arrayOf(address.postalCode, address.locality).filterNot { it.isNullOrEmpty() }.joinToString(" ") val lines = LinkedList<String>() if (!lineStreet.isEmpty()) if (lineStreet.isNotEmpty()) lines += lineStreet if (!lineLocality.isEmpty()) if (lineLocality.isNotEmpty()) lines += lineLocality if (!address.region.isNullOrEmpty()) lines += address.region Loading Loading @@ -1241,7 +1240,7 @@ open class AndroidContact( if (width > max || height > max) { val scaleWidth = max/width val scaleHeight = max/height val scale = Math.min(scaleWidth, scaleHeight) val scale = min(scaleWidth, scaleHeight) val newWidth = (width * scale).toInt() val newHeight = (height * scale).toInt() Loading Loading @@ -1298,7 +1297,7 @@ open class AndroidContact( protected fun rawContactSyncURI(): Uri { val id = requireNotNull(id) return addressBook.syncAdapterURI(ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, id)) return addressBook.syncAdapterURI(ContentUris.withAppendedId(RawContacts.CONTENT_URI, id)) } protected fun dataSyncURI() = addressBook.syncAdapterURI(ContactsContract.Data.CONTENT_URI) Loading Loading
README.md +6 −4 Original line number Diff line number Diff line Loading @@ -11,10 +11,15 @@ It's a framework for from/into data classes that are compatible with the Android Contacts Provider, and * accessing the Android Contacts Provider by a unified API. It has been primarily developed for [DAVdroid](https://www.davdroid.com). It has been primarily developed for [DAVx⁵](https://www.davx5.com). _This software is not affiliated to, nor has it been authorized, sponsored or otherwise approved by Google LLC. Android is a trademark of Google LLC._ Generated KDoc: https://bitfireAT.gitlab.io/vcard4android/dokka/vcard4android/ Discussion: https://forums.bitfire.at/category/18/libraries ## Contact Loading @@ -26,9 +31,6 @@ Florastraße 27 Email: [play@bitfire.at](mailto:play@bitfire.at) (do not use this) For questions, suggestions etc. please use the DAVdroid forum: https://www.davdroid.com/forums/ ## License Loading
build.gradle +27 −13 Original line number Diff line number Diff line buildscript { ext.versions = [ kotlin: '1.3.31', dokka: '0.9.17' kotlin: '1.3.60', dokka: '0.10.0' ] repositories { Loading @@ -11,9 +11,9 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:3.4.1' classpath 'com.android.tools.build:gradle:3.5.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}" classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:${versions.dokka}" classpath "org.jetbrains.dokka:dokka-gradle-plugin:${versions.dokka}" } } Loading @@ -24,16 +24,22 @@ repositories { apply plugin: 'com.android.library' apply plugin: 'kotlin-android' apply plugin: 'org.jetbrains.dokka-android' apply plugin: 'org.jetbrains.dokka' android { compileSdkVersion 27 buildToolsVersion '27.1.1' compileSdkVersion 29 buildToolsVersion '29.0.2' defaultConfig { minSdkVersion 24 targetSdkVersion 27 targetSdkVersion 29 } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } buildTypes { release { minifyEnabled false Loading @@ -53,12 +59,20 @@ android { defaultConfig { testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } dokka.configuration { sourceLink { url = "https://gitlab.com/bitfireAT/vcard4android/tree/master/" lineSuffix = "#L" } jdkVersion = 7 } } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${versions.kotlin}" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${versions.kotlin}" implementation 'org.apache.commons:commons-text:1.6' implementation 'org.apache.commons:commons-text:1.7' implementation 'commons-io:commons-io:2.6' // ez-vcard to parse/generate VCards Loading @@ -70,8 +84,8 @@ dependencies { exclude group: 'com.fasterxml.jackson.core' } androidTestImplementation 'androidx.test:runner:1.1.1' androidTestImplementation 'androidx.test:rules:1.1.1' androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test:rules:1.2.0' testImplementation 'junit:junit:4.12' }
gradle/wrapper/gradle-wrapper.properties +1 −1 Original line number Diff line number Diff line Loading @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-all.zip
src/main/AndroidManifest.xml +1 −2 Original line number Diff line number Diff line Loading @@ -12,7 +12,6 @@ <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.WRITE_CONTACTS" /> <application android:allowBackup="true" android:label="@string/app_name"/> <application /> </manifest>
src/main/java/foundation/e/vcard4android/AndroidContact.kt +19 −20 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ import android.graphics.BitmapFactory import android.net.Uri import android.os.RemoteException import android.provider.ContactsContract import android.provider.ContactsContract.CommonDataKinds import android.provider.ContactsContract.CommonDataKinds.* import android.provider.ContactsContract.CommonDataKinds.Email import android.provider.ContactsContract.CommonDataKinds.Nickname Loading @@ -41,6 +40,7 @@ import java.text.ParseException import java.text.SimpleDateFormat import java.util.* import java.util.logging.Level import kotlin.math.min open class AndroidContact( val addressBook: AndroidAddressBook<out AndroidContact, out AndroidGroup> Loading Loading @@ -115,7 +115,7 @@ open class AndroidContact( try { iter = RawContacts.newEntityIterator(addressBook.provider!!.query( addressBook.syncAdapterURI(ContactsContract.RawContactsEntity.CONTENT_URI), null, ContactsContract.RawContacts._ID + "=?", arrayOf(id.toString()), null)) null, RawContacts._ID + "=?", arrayOf(id.toString()), null)) if (iter.hasNext()) { val e = iter.next() Loading @@ -135,8 +135,7 @@ open class AndroidContact( it.remove() } val mimeType = values.getAsString(ContactsContract.RawContactsEntity.MIMETYPE) when (mimeType) { when (val mimeType = values.getAsString(ContactsContract.RawContactsEntity.MIMETYPE)) { StructuredName.CONTENT_ITEM_TYPE -> populateStructuredName(values) Phone.CONTENT_ITEM_TYPE -> Loading Loading @@ -252,13 +251,13 @@ open class AndroidContact( Phone.TYPE_MMS -> number.types += Contact.PHONE_TYPE_MMS Phone.TYPE_CUSTOM -> { row.getAsString(CommonDataKinds.Phone.LABEL)?.let { row.getAsString(Phone.LABEL)?.let { labeledNumber.label = it number.types += TelephoneType.get(labelToXName(it)) } } } if (row.getAsInteger(CommonDataKinds.Phone.IS_PRIMARY) != 0) if (row.getAsInteger(Phone.IS_PRIMARY) != 0) number.pref = 1 contact!!.phoneNumbers += labeledNumber Loading Loading @@ -454,7 +453,7 @@ open class AndroidContact( } protected open fun populateEvent(row: ContentValues) { val dateStr = row.getAsString(CommonDataKinds.Event.START_DATE) val dateStr = row.getAsString(Event.START_DATE) var full: Date? = null var partial: PartialDate? = null val fullFormat = SimpleDateFormat("yyyy-MM-dd", Locale.US) Loading Loading @@ -652,7 +651,7 @@ open class AndroidContact( op = BatchOperation.Operation(builder) builder.withValue(StructuredName.RAW_CONTACT_ID, id) } builder .withValue(Data.MIMETYPE, CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) builder .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE) .withValue(StructuredName.DISPLAY_NAME, contact.displayName) .withValue(StructuredName.PREFIX, contact.prefix) .withValue(StructuredName.GIVEN_NAME, contact.givenName) Loading Loading @@ -682,9 +681,9 @@ open class AndroidContact( } catch(e: IllegalStateException) { Constants.log.log(Level.FINER, "Can't understand phone number PREF", e) } var is_primary = pref != null var isPrimary = pref != null if (types.contains(TelephoneType.PREF)) { is_primary = true isPrimary = true types -= TelephoneType.PREF } Loading Loading @@ -756,8 +755,8 @@ open class AndroidContact( .withValue(Phone.NUMBER, number.text) .withValue(Phone.TYPE, typeCode) .withValue(Phone.LABEL, typeLabel) .withValue(Phone.IS_PRIMARY, if (is_primary) 1 else 0) .withValue(Phone.IS_SUPER_PRIMARY, if (is_primary) 1 else 0) .withValue(Phone.IS_PRIMARY, if (isPrimary) 1 else 0) .withValue(Phone.IS_SUPER_PRIMARY, if (isPrimary) 1 else 0) if (addressBook.readOnly) builder.withValue(Data.IS_READ_ONLY, 1) Loading @@ -778,9 +777,9 @@ open class AndroidContact( } catch(e: IllegalStateException) { Constants.log.log(Level.FINER, "Can't understand email PREF", e) } var is_primary = pref != null var isPrimary = pref != null if (types.contains(EmailType.PREF)) { is_primary = true isPrimary = true types -= EmailType.PREF } Loading Loading @@ -818,8 +817,8 @@ open class AndroidContact( .withValue(Email.ADDRESS, email.value) .withValue(Email.TYPE, typeCode) .withValue(Email.LABEL, typeLabel) .withValue(Email.IS_PRIMARY, if (is_primary) 1 else 0) .withValue(Phone.IS_SUPER_PRIMARY, if (is_primary) 1 else 0) .withValue(Email.IS_PRIMARY, if (isPrimary) 1 else 0) .withValue(Phone.IS_SUPER_PRIMARY, if (isPrimary) 1 else 0) if (addressBook.readOnly) builder.withValue(Data.IS_READ_ONLY, 1) Loading Loading @@ -1030,9 +1029,9 @@ open class AndroidContact( val lineLocality = arrayOf(address.postalCode, address.locality).filterNot { it.isNullOrEmpty() }.joinToString(" ") val lines = LinkedList<String>() if (!lineStreet.isEmpty()) if (lineStreet.isNotEmpty()) lines += lineStreet if (!lineLocality.isEmpty()) if (lineLocality.isNotEmpty()) lines += lineLocality if (!address.region.isNullOrEmpty()) lines += address.region Loading Loading @@ -1241,7 +1240,7 @@ open class AndroidContact( if (width > max || height > max) { val scaleWidth = max/width val scaleHeight = max/height val scale = Math.min(scaleWidth, scaleHeight) val scale = min(scaleWidth, scaleHeight) val newWidth = (width * scale).toInt() val newHeight = (height * scale).toInt() Loading Loading @@ -1298,7 +1297,7 @@ open class AndroidContact( protected fun rawContactSyncURI(): Uri { val id = requireNotNull(id) return addressBook.syncAdapterURI(ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, id)) return addressBook.syncAdapterURI(ContentUris.withAppendedId(RawContacts.CONTENT_URI, id)) } protected fun dataSyncURI() = addressBook.syncAdapterURI(ContactsContract.Data.CONTENT_URI) Loading