Skip to content

Commit

Permalink
Fix openExternalInsert returning null on android (QuisApp#100, QuisAp…
Browse files Browse the repository at this point in the history
  • Loading branch information
joachimvalente committed Jul 31, 2024
1 parent f153f98 commit 019da7e
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,32 @@ class FlutterContacts {
val REQUEST_CODE_PICK = 77883
val REQUEST_CODE_INSERT = 77884

fun findIdWithLookupKey(
resolver: ContentResolver,
lookupKey: String
): String? {
val projection = listOf(Data.CONTACT_ID)
val selectionClause = "${Data.LOOKUP_KEY} = ?"
val selectionArgs = arrayOf(lookupKey)
val cursor = resolver.query(
Data.CONTENT_URI,
projection.toTypedArray(),
selectionClause,
selectionArgs,
/*sortOrder=*/null
)
if (cursor == null) {
return null
}
if (!cursor.moveToNext()) {
return null
}
fun getString(col: String): String = cursor.getString(cursor.getColumnIndex(col)) ?: ""
val id = getString(Data.CONTACT_ID)
cursor.close()
return id
}

fun select(
resolver: ContentResolver,
id: String?,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,39 +105,8 @@ class FlutterContactsPlugin : FlutterPlugin, MethodCallHandler, EventChannel.Str
}
FlutterContacts.REQUEST_CODE_INSERT ->
if (insertResult != null) {
// Result is of the form:
// content://com.android.contacts/raw_contacts/<raw_id>
// So we need to get the ID from the raw ID.
val rawId = intent?.getData()?.getLastPathSegment()
val readPermission = Manifest.permission.READ_CONTACTS
val hasContactsReadPermission = ContextCompat.checkSelfPermission(
context!!, readPermission
) == PackageManager.PERMISSION_GRANTED
if (rawId != null && hasContactsReadPermission) {
// Check the contacts read permission since 'open external insert' can be
// called even without contacts permission. So while selecting contacts, be sure
// that we have read permission.
val contacts: List<Map<String, Any?>> =
FlutterContacts.select(
resolver!!,
rawId,
/*withProperties=*/false,
/*withThumbnail=*/false,
/*withPhoto=*/false,
/*withGroups=*/false,
/*withAccounts=*/false,
/*returnUnifiedContacts=*/true,
/*includeNonVisible=*/true,
/*idIsRawContactId=*/true
)
if (contacts.isNotEmpty()) {
insertResult!!.success(contacts[0]["id"])
} else {
insertResult!!.success(null)
}
} else {
insertResult!!.success(null)
}
val contactId = getContactIdFromExternalInsertResult(intent)
insertResult!!.success(contactId)
insertResult = null
}
}
Expand Down Expand Up @@ -344,6 +313,64 @@ class FlutterContactsPlugin : FlutterPlugin, MethodCallHandler, EventChannel.Str
}
}

private fun getContactIdFromExternalInsertResult(intent: Intent?): String? {
if (intent == null) {
return null
}

val uri = intent.getData()?.getPath()
if (uri == null) {
return null
}

val hasContactsReadPermission = ContextCompat.checkSelfPermission(
context!!, Manifest.permission.READ_CONTACTS
) == PackageManager.PERMISSION_GRANTED
if (!hasContactsReadPermission) {
// Check the contacts read permission since 'open external insert' can be
// called even without contacts permission. So while selecting contacts, be
// sure that we have read permission.
return null
}

// Result can be of two forms:
// content://com.android.contacts/<lookup_key>/<raw_id>
// content://com.android.contacts/raw_contacts/<raw_id>
val segments = intent.getData()?.getPathSegments()
if (segments == null || segments.size < 2) {
return null
}
val secondToLastSegment = segments[segments.size - 2]

if (secondToLastSegment == "raw_contacts") {
val rawId = segments.last()
val contacts: List<Map<String, Any?>> =
FlutterContacts.select(
resolver!!,
rawId,
/*withProperties=*/false,
/*withThumbnail=*/false,
/*withPhoto=*/false,
/*withGroups=*/false,
/*withAccounts=*/false,
/*returnUnifiedContacts=*/true,
/*includeNonVisible=*/true,
/*idIsRawContactId=*/true
)
if (contacts.isEmpty()) {
return null
}
return contacts[0]["id"] as String?
} else {
val lookupKey = secondToLastSegment
val contactId = FlutterContacts.findIdWithLookupKey(
resolver!!,
lookupKey
)
return contactId
}
}

// --- StreamHandler implementation ---

var _eventObserver: ContactChangeObserver? = null
Expand Down
13 changes: 10 additions & 3 deletions example_full/lib/pages/contact_list_page.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:developer';

import 'package:after_layout/after_layout.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_contacts/flutter_contacts.dart';
import 'package:flutter/material.dart';
import 'package:flutter_contacts_example/util/avatar.dart';
Expand Down Expand Up @@ -110,16 +111,19 @@ class _ContactListPageState extends State<ContactListPage>
);
}

void _handleOverflowSelected(String value) {
Future<void> _handleOverflowSelected(String value) async {
switch (value) {
case 'Groups':
Navigator.of(context).pushNamed('/groups');
break;
case 'Insert external':
FlutterContacts.openExternalInsert();
final contact = await FlutterContacts.openExternalInsert();
if (kDebugMode) {
print('Contact added: ${contact?.id}');
}
break;
case 'Insert external (prepopulated)':
FlutterContacts.openExternalInsert(
final contact = await FlutterContacts.openExternalInsert(
Contact(
name: Name(first: 'John', last: 'Doe'),
phones: [Phone('+1 555-123-4567')],
Expand All @@ -131,6 +135,9 @@ class _ContactListPageState extends State<ContactListPage>
],
),
);
if (kDebugMode) {
print('Contact added: ${contact?.id}');
}
break;
default:
log('Unknown overflow menu item: $value');
Expand Down

0 comments on commit 019da7e

Please sign in to comment.