cloud9_note

cloud9に限らないメモ

View on GitHub

Androidで同じ電話番号のはずなのに片方しか取得できない

回答

Androidの電話番号検索(たとえば

Uri lookupUri = Uri.withAppendedPath(
    ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
    Uri.encode(phoneNumber)
);
Cursor c = getContentResolver().query(lookupUri, );

を使った場合)の内部挙動は、以下のようになっています。

  1. 入力番号がE.164形式(「+81…」)か否かで検索対象カラムが変わる

    • +818012345678 のように「+(国番号付き)」と認識される番号を渡すと、実装上は normalized_number カラムだけを完全一致検索します。
    • 一方、先頭が 0 の「08012345678」のような国内形式を渡すと、normalized_number カラムへの一致検索に加え、末尾数桁(デフォルト7桁)でのサフィックス一致検索(LIKE '%…')も行います。 このロジックは ContactsProvider のソース中 appendPhoneLookupSelection メソッドで定義されています(Android Gooblesource)。
  2. そのため、異なるフォーマットで保存された番号はお互いにヒットしない

    • 「08012345678」で検索 → 生番号(numberカラム)/サフィックス一致 or normalized_number(一致)で、080登録のレコードにマッチ(+81登録のレコードはサフィックス一致しても、実装上 raw 検索はスキップされる場合あり)
    • 「+818012345678」で検索 → normalized_number カラムのみを検索し、+81登録のレコードにマッチ(080登録のレコードは raw number にしか保存されておらず normalized_number が空または別扱いになる場合あり) この動作はバグとも言われており、PhoneLookup フィルタが入力の “正規化済み判定” によって検索対象を切り替えてしまうためです(Stack Overflow)。

まとめ