Android:无法在 HTC 上查询 ContactsContract.Directory

2023-12-09

我编写了一个示例应用程序,它从 GAL(公司目录,在“帐户”中定义为 Exchange ActiveSync)返回联系人数据。同一个应用程序在一堆不同的设备上运行得很好,但在我测试过的 HTC 上却不行(One X+ 与 Android 4.1.1 和 One VX 与 4.0.4)。
基本上,对 ContactsContract.Directory.CONTENT_URI 的查询仅返回 ID 为 Directory.DEFAULT 和 Directory.LOCAL_INVISIBLE 的目录。在其他设备上,这会添加 id=5 和类型 com.android.exchange。原生“People”应用程序的搜索也适用于 HTC。

这是两个类的完整代码清单
主要活动

package com.example.galcontactssearch;

import com.example.galcontactssearch.CursorQueryWrapper.CursorResultIterator;

import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Directory;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.HashSet;

public class MainActivity extends ActionBarActivity {
    public static final String TAG = "SEARCH_IN_GAL";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.container, new PlaceholderFragment())
                    .commit();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * A placeholder fragment containing a simple view.
     */
    public static class PlaceholderFragment extends Fragment {

        private ArrayList<Long> dirIds;
        private String[] projection;

        public PlaceholderFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_main, container, false);
            final Context context = getActivity();
            String app_ver = null;
            try
            {
                app_ver =context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
            }
            catch (NameNotFoundException e)
            {
                Log.e(TAG, "Cannot find version name", e);
            }

            Button searchBtn = (Button) rootView.findViewById(R.id.button1);
            if(app_ver!=null){
                searchBtn.setText(searchBtn.getText() + " v." + app_ver);
            }
            final EditText text = (EditText) rootView.findViewById(R.id.editText1);
            final TextView resultsView = (TextView) rootView.findViewById(R.id.resultsView);
            searchBtn.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    final String searchStr = text.getText().toString();

                     new Thread(new Runnable() {
                            @Override
                            public void run() {
                                final String result;
                                if (TextUtils.isEmpty(searchStr)) {
                                    result = "No input";
                                } else {
                                    result = search(searchStr);
                                }
                                resultsView.post(new Runnable() {
                                    @Override
                                    public void run() {
                                        resultsView.setText(result);
                                    }
                                });
                            }
                        }).start();
                }
            });

            CursorQueryWrapper wrapper = new CursorQueryWrapper(TAG);
            dirIds = new ArrayList<Long>();
            wrapper.query(getActivity(), ContactsContract.Directory.CONTENT_URI, new String[] {
                    Directory._ID, Directory.ACCOUNT_NAME, Directory.ACCOUNT_TYPE
            }, null, null, null,
                    new CursorResultIterator() {
                        @Override
                        public void iterate(Cursor cursor) throws Exception {
                            long id = cursor.getLong(0);
                            if (Directory.DEFAULT != id && Directory.LOCAL_INVISIBLE != id) {
                                dirIds.add(id);
                                Log.d(TAG, "Account: id="+id + " name="+cursor.getString(1) +" type="+cursor.getString(2));
                            }
                        }
                    });
            if (dirIds.isEmpty()) {
                String result = "Cannot find additional accounts";
                Log.e(TAG, result);
                searchBtn.setEnabled(false);
                resultsView.setText(result);
            }else{
                HashSet<String> projSet = new HashSet<String>();
                projSet.add(StructuredName.DISPLAY_NAME);
                projSet.add(StructuredName.GIVEN_NAME);
                projSet.add(StructuredName.FAMILY_NAME);
                projSet.add(Email.ADDRESS);
                projSet.add(Phone.NUMBER);
                projSet.add(Contacts.Data.MIMETYPE);
                projSet.add(Email.TYPE);
                projSet.add(Phone.TYPE);
                projection = projSet.toArray(new String[projSet.size()]);
            }

            return rootView;
        }

        private String search(final String searchString) {
            final StringBuilder bld = new StringBuilder();
            CursorQueryWrapper wrapper = new CursorQueryWrapper(TAG);
            final Context context = getActivity();
            for (Long id : dirIds) {
                final String idStr = String.valueOf(id);
                Uri uri = ContactsContract.Contacts.CONTENT_FILTER_URI.buildUpon().appendEncodedPath(searchString)
                        .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY, idStr).build();

                final ArrayList<String> lookupKeys = new ArrayList<String>();
                wrapper.query(context, uri, new String[] {
                    Contacts.LOOKUP_KEY
                }, null, null, null, new CursorResultIterator() {
                    @Override
                    public void iterate(Cursor cursor) throws Exception {
                        lookupKeys.add(cursor.getString(0));
                    }
                });
                if (lookupKeys.isEmpty()) {
                    continue;
                }

                for (String lookupKey : lookupKeys) {
                    uri = ContactsContract.Contacts.CONTENT_LOOKUP_URI.buildUpon().appendEncodedPath(lookupKey)
                            .appendPath(Contacts.Entity.CONTENT_DIRECTORY)
                            .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY, idStr).build();
                    wrapper.query(context, uri, projection, null, null, null, new CursorResultIterator() {
                        @Override
                        public void iterate(Cursor cursor) throws Exception {
                            String mime = cursor.getString(cursor.getColumnIndex(Contacts.Data.MIMETYPE));
                            if (StructuredName.CONTENT_ITEM_TYPE.equals(mime)) {
                                String result = "Given name:"
                                        + cursor.getString(cursor.getColumnIndex(StructuredName.GIVEN_NAME))
                                        + " Family name:"
                                        + cursor.getString(cursor.getColumnIndex(StructuredName.FAMILY_NAME))
                                        + " Display name:"
                                        + cursor.getString(cursor.getColumnIndex(StructuredName.DISPLAY_NAME));
                                Log.d(TAG, result);
                                bld.append(result).append('\n');
                            } else if (Email.CONTENT_ITEM_TYPE.equals(mime)) {
                                String result = "Email address:"
                                        + cursor.getString(cursor.getColumnIndex(Email.ADDRESS))
                                        + " with type:"
                                        + Email.getTypeLabel(context.getResources(), cursor.getInt(cursor
                                                .getColumnIndex(Email.TYPE)), null);
                                Log.d(TAG, result);
                                bld.append(result).append('\n');
                            }
                            else if (Phone.CONTENT_ITEM_TYPE.equals(mime)) {
                                String result = "Phone num:"
                                        + cursor.getString(cursor.getColumnIndex(Phone.NUMBER))
                                        + " with type:"
                                        + Phone.getTypeLabel(context.getResources(), cursor.getInt(cursor
                                                .getColumnIndex(Phone.TYPE)), null);
                                Log.d(TAG, result);
                                bld.append(result).append('\n');
                            }
                        }
                    });
                    String result = "*************************************";
                    Log.d(TAG, result);
                    bld.append(result).append('\n');
                }
            }
            if (bld.length() == 0) {
                String result = "Cannot find matching contacts for the string '" + searchString + "'";
                Log.d(TAG, result);
                return result;
            }
            return bld.toString();
        }
    }

}

游标查询包装器

package com.example.galcontactssearch;

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

public class CursorQueryWrapper {

    private final String tag;
    private QueryInterface queryInterface;

    public static class CursorIteratonInterrupt extends Exception {
        private static final long serialVersionUID = -1124533346986767621L;
    }

    public static abstract class CursorResultIterator {
        public void iterate(Cursor cursor) throws Exception {
        }

        public boolean shouldIterate() {
            return true;
        }

        public void prepareForIterations(Cursor cursor) {
        }
    }

    public interface QueryInterface {
        Cursor query(Context context, Uri uri, String[] projection,
                String selection, String[] selectionArgs, String sortOrder);
    }

    public static class ContextQuery implements QueryInterface {

        @Override
        public Cursor query(Context context, Uri uri, String[] projection, String selection, String[] selectionArgs,
                String sortOrder) {
            return context.getContentResolver()
                    .query(uri, projection, selection, selectionArgs, sortOrder);
        }

    }

    public CursorQueryWrapper(final String tag) {
        this(tag, null);
    }

    public CursorQueryWrapper(final String tag, QueryInterface queryInterface) {
        this.tag = tag;
        this.queryInterface = queryInterface == null ? new ContextQuery() : queryInterface;
    }

    public boolean query(Context context, Uri uri, String[] projection,
            String selection, String[] selectionArgs, String sortOrder, CursorResultIterator iterator) {
        Cursor cursor = null;
        Log.d(tag, "Starting query");
        try {
            StringBuilder bld = new StringBuilder(
                    "Running query");
            bld.append("\nUri: ").append(uri.toString());
            bld.append("\nProjection: ").append(projection == null ? "null" : TextUtils.join(", ", projection));
            bld.append("\nSelection: ").append(selection);
            bld.append("\nSelectionArgs: ").append(
                    selectionArgs == null ? "null" : TextUtils.join(", ", selectionArgs));
            bld.append("\nSortOrder: ").append(sortOrder);
            Log.d(tag, bld.toString());
            cursor = queryInterface.query(context, uri, projection, selection, selectionArgs, sortOrder);
            if (cursor == null) {
                Log.e(tag, "Cannot process the query. The cursor is null as a result of some error.");
                return false;
            }
            Log.d(tag, "Cursor's count is " + cursor.getCount());
            iterator.prepareForIterations(cursor);
            if (iterator.shouldIterate()) {
                while (cursor.moveToNext()) {
                    iterator.iterate(cursor);
                }
            }
        } catch (Exception e) {
            if (!(e instanceof CursorIteratonInterrupt)) {
                Log.e(tag,
                        "Cannot process the query.", e);
                return false;
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        Log.d(tag, "The query is ended successfully");
        return true;
    }

}

此外,还有这个应用程序,“真实联系人”,这本质上只是最新的 ICS 联系人应用程序编译的股票。例如,它可以在 Samsung Galaxy S3 上完美搜索 GAL,但不能在 HTC 上搜索。有人可以解释一下这个问题吗?


None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android:无法在 HTC 上查询 ContactsContract.Directory 的相关文章

随机推荐

  • Xcode 8 二进制文件未在 itunesconnect 上显示以供审核

    我已经从 Xcode 8 制作了二进制文件并通过 Application Loader 3 6 上传到 App Store 也提交成功并弹出 但是二进制文件没有在 iTunesConnect 中显示 因为它超过了 19 小时 但它没有在 i
  • 斐波那契函数的问题。 C++

    应该返回n数组的位置 但我只得到 0 而不是值 int fibonacci int n int f 100 f 0 0 f 1 1 for int i 2 i
  • 拉取 microsoft/nanoserver 容器时出现错误“Failed to OpenForBackup failed in Win32”

    尝试提取 microsoft nanoserver 映像时遇到以下错误 下载成功 提取图像期间会出现此错误 482ab31872a2 下载完成 注册层失败 重新执行错误 退出状态 1 输出 无法 OpenForBackup 在 Win32
  • 现有对象的向量

    我有一些对象 在本例中它们是向量 我希望它们存储在向量中 但不知道如何正确声明它 我的代码是 vector
  • 控制 WinForms 中的嵌套限制

    我正在运行时创建表单的控件 出于某种原因 我需要深度超过 49 个嵌套控件 即控件包含在另一个控件中 但出现以下错误 如何添加更多相互嵌套的控件 这是一段可能会重现该错误的代码 public partial class Form1 Form
  • 在 Struts2 中实现

    我目前正在处理一个项目 我的应用程序中有多个选择框 每个值应根据第一个列表中选择的先前值进行更改 这是我的代码 我没有获得第二个选择列表 这是我的jsp
  • Django FilteredSelectMultiple 未在页面上呈现

    我目前使用的是 Django 版本 1 11 2 并且想在管理页面之外使用 FilteredSelectMultiple 小部件 这是我的 forms py class TBDAuthGroupManageForm forms Form p
  • UPDATE count=count+1 是否存在并发?

    我想知道 我会遇到并发问题吗 这不在交易中 这段代码是为了Sqlite prototype 但我计划将它与 MySql 或来自 MS 的 SQL 一起使用 command CommandText UPDATE tag name SET co
  • 如何使用 Verilog 宏模拟 $display?

    我想创建一个具有多个参数的宏 就像 display 一样 我的代码看起来像这样 但它不起作用 define format macro A write s sformatf A 这就是我调用 format macro 的方式 format m
  • 如何创建自定义 UIAlertView

    我们正在创建一个沉浸式应用程序 它需要具有类似于UIAlertView 但我们不希望它看起来像一个系统对话框 我们想使用我们自己的图形 我已经完成了大部分工作 但遇到了一些障碍 如何使 UIView 显示在状态栏上方 以便我可以变暗 就像U
  • 删除“联合”非连续范围

    我不能使用rng EntireRow Delete当范围不连续时 并且范围是由 Union 构建的 我知道我可以使用排序和自动筛选根据条件删除多行 我想学习新东西 我对向后删除或使用循环不感兴趣 这太耗时了 当范围 usun 不连续时 代码
  • 使用终结器清理弱引用缓存?

    假设我有一个由弱引用或软引用组成的缓存 这些弱 软引用需要在某个时候关闭 理想情况下 一旦 GC 从缓存中删除对象 就应该关闭这些对象 使用终结器 清理器来关闭这些资源 同时仍然在程序末尾循环缓存并手动关闭它们是否合适 public voi
  • WinRT XAML 中的 Flyout 控件在哪里?

    JavaScript 中的 Flyout 控件对于 设置 窗格和按钮 Flyout 扩展非常方便 但是 WinRT XAML 的 Flyout 控件在哪里 您正在寻找的控件在 XAML 中称为 Popup 与 Flyout 的 JavaSc
  • PARTIAL_STATE_SAVING 是否应该设置为 false?

    今天 2012 年 4 月 MyFaces 和 Mojarra 的 JSF 2 1 实现似乎都在部分状态保存方面存在缺陷 并且 PARTIAL STATE SAVING 应设置为 false 这是真的 是否应该将 PARTIAL STATE
  • 从 Postman 的 API 连接对象存储时出现未经授权的错误

    我正在尝试使用邮递员中提供的 API 获取对象存储容器详细信息 但我收到未经授权的错误 API 信息可在http developer openstack org api ref object storage index html expan
  • SAPUI5中的“apply()”函数是什么

    我知道这是一个愚蠢的问题 但我在很多地方看到了以下声明 something apply this arguments 有人可以向我解释一下这个函数的使用或者给我指出某种文档吗 apply 是 javascript 函数的方法 请参阅文档ap
  • 无法搁置 VS2012 中对 TFS2010 的更改

    我们正在使用 TFS2010 仅用于源代码控制 直到最近每个人都在使用 VS2010 我们的开发人员刚刚安装了VS2012 在 Visual Studio 中下拉代码效果很好 当您转到团队资源管理器中的 待处理更改 时 我们会看到TF201
  • Windows运行时:如何在椭圆形按钮中设置图像?

  • 计划任务未运行 - Coldfusion 服务器管理

    我有一系列计划任务 这些任务都在一天中的不同时间运行 自从 Coldfusion 版本 7 迁移到 10 以来 这些任务已停止运行 当我选中将结果输出到文件的框时 我得到一个文本文件 其中仅显示 连接失败 我已经尝试了有关该任务的用户名和密
  • Android:无法在 HTC 上查询 ContactsContract.Directory

    我编写了一个示例应用程序 它从 GAL 公司目录 在 帐户 中定义为 Exchange ActiveSync 返回联系人数据 同一个应用程序在一堆不同的设备上运行得很好 但在我测试过的 HTC 上却不行 One X 与 Android 4