【问题标题】:How do I get more than 500 contact lists on Android?如何在 Android 上获得超过 500 个联系人列表?
【发布时间】:2019-08-17 12:01:28
【问题描述】:

我想在 Android 6.0 及更高版本中获取超过 500 个联系人列表作为字符串。下面是一个完美运行的代码。但如果联系人列表超过 100,应用程序就会挂起。当我想获得 500 个联系人列表时,我可以在 logcat 上看到人。但是,用户不能在应用程序中做任何事情。并且应用程序可能会崩溃。我认为这与草料有关。我已经处理这个问题五天了。但我没有得到任何性能结果。任何帮助,我将不胜感激。

我的活动;

public class MainActivity extends Activity {

    Cursor cursor;
    ArrayList<String> vCard;
    String vfile;

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

        vfile = "Contacts" + System.currentTimeMillis() +".vcf";

        getVcardString();
}

private void getVcardString() {

        vCard = new ArrayList<String>();

        cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);

        if(cursor!=null&&cursor.getCount()>0){

            cursor.moveToFirst();
            for(int i =0;i<cursor.getCount();i++){


                try {
                    get(cursor);
                } catch (IOException e) {
                    e.printStackTrace();
                }

                cursor.moveToNext();
            }
            cursor.close();
        }
        else{

            ViewAlertDashboard02();
        }

    }

    public void get(Cursor cursor) throws IOException {

        String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
        Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_VCARD_URI, lookupKey);

        AssetFileDescriptor fd = getBaseContext().getContentResolver().openAssetFileDescriptor(uri, "r");
        FileInputStream fis = fd.createInputStream();

        byte[] buf = readBytes(fis);

        try {

            fis.read(buf);

            vcardstring = new String(buf);
            vCard.add(vcardstring);

            Log.d("Vcard",vcardstring);


        } catch (Exception e1){

            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }

    public byte[] readBytes(InputStream inputStream) throws IOException {
        // this dynamically extends to take the bytes you read
        ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();

        // this is storage overwritten on each iteration with bytes
        int bufferSize = 1024;
        byte[] buffer = new byte[bufferSize];

        // we need to know how may bytes were read to write them to the byteBuffer
        int len = 0;
        while ((len = inputStream.read(buffer)) != -1) {
            byteBuffer.write(buffer, 0, len);
        }

        // and then we can return your byte array.
        return byteBuffer.toByteArray();
    }
}

我的日志猫;

    >     08-17 14:56:44.984 3530-3289/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.024 3530-32650/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.054 3530-4755/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.084 3530-4546/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.124 3530-4513/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.154 3530-4517/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.184 3530-7059/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.204 3530-3548/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.234 3530-13626/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.264 3530-3290/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.284 3530-3289/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.314 3530-3291/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.334 3530-3550/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.364 3530-3882/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.384 3530-32650/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.424 3530-3292/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.454 3530-4755/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.484 3530-26421/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.504 3530-4546/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.534 3530-3293/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.554 3530-4513/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.584 3530-4517/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.604 3530-7059/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.634 3530-3548/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.664 3530-13626/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.684 3530-3290/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.714 3530-3289/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.744 3530-3291/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.764 3530-3550/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.794 3530-3882/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.814 3530-32650/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.844 3530-3292/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.864 3530-4755/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.894 3530-26421/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.924 3530-4546/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.944 3530-3293/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.974 3530-4513/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:45.994 3530-4517/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.024 3530-7059/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.064 3530-3548/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.094 3530-13626/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.134 3530-3290/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.164 3530-3289/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.204 3530-3291/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.264 3530-3550/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.294 3530-3882/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.314 3530-3292/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.334 3530-4755/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.364 3530-26421/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.384 3530-4546/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.404 3530-3293/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.434 3530-4513/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.464 3530-3548/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.484 3530-13626/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.514 3530-7059/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.544 3530-32650/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.564 3530-4517/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.594 3530-3882/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.614 3530-4755/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.644 3530-3289/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.674 3530-4546/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.714 3530-3293/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.744 3530-3291/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.784 3530-3290/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.814 3530-3292/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.844 3530-26421/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.874 3530-3550/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.904 3530-4513/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.924 3530-3548/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.954 3530-13626/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:46.974 3530-7059/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.014 3530-32650/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.044 3530-4517/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.064 3530-3882/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.094 3530-4755/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.114 3530-3289/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.144 3530-4546/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.174 3530-3293/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.204 3530-3291/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.234 3530-3290/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.264 3530-3292/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.284 3530-26421/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.324 3530-3550/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.354 3530-4513/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.394 3530-3548/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.424 3530-13626/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.464 3530-7059/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.494 3530-32650/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.524 3530-4517/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.564 3530-3882/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.594 3530-4755/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.644 3530-3289/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.694 3530-4546/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.724 3530-3293/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.784 3530-3291/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.814 3530-3290/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.854 3530-3292/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.914 3530-26421/? E/VCardComposer: Cursor#moveToNext() returned false
    >     08-17 14:56:47.954 3530-3550/? E/VCardComposer: Cursor#moveToNext() returned false

这段代码有两个问题。我的第一个问题是它不能很好地工作并且应用程序可能会崩溃。我的另一个问题是,如果我的联系人列表中有 500 人,它会显示更多。我认为这样做的原因是强制处理器。我认为它重复了一个过程。您的经验和知识可以成为我的解决方案。提前致谢。

注意:此代码可在 Android 4 及更高版本上无缝运行多达 100 个联系人列表,并支持最新版本的 android。你可以使用它。

【问题讨论】:

  • 首先将所有这些 I/O 移动到后台线程。
  • 只需使用后台线程获取联系。
  • 感谢您的 cmets。我创建了一个后台服务并在按下按钮时启动它。我试图在后台服务中获取联系人列表,但应用程序再次崩溃并且应用程序挂起。你能给我举个例子吗?我在哪里做错了? @CommonsWare
  • “我创建了一个后台服务并在按下按钮时启动它”——您不需要服务即可使用后台线程。 “但应用程序又崩溃了”——然后问一个单独的 Stack Overflow 问题,minimal reproducible example 显示崩溃的堆栈跟踪和触发崩溃的代码。您当前的问题是“应用程序可能崩溃”,但您没有显示堆栈跟踪,因此我们无法知道崩溃的原因和位置。例如,您可能会因为尝试一次将每个联系人的 vCard 数据加载到内存中而得到 OutOfMemoryError
  • 非常感谢。我只是在学习东西。我按照你说的方式尝试了后台线程。现在一切都好了。我将后台线程与后台服务混合在一起。谢谢你以这种方式向我展示。我学到了一些新东西并获得了经验。 :)

标签: android android-contacts


【解决方案1】:

你有两个大问题:

  1. 在 UI 线程上运行长时间运行的代码
  2. 混合查询Phone.CONTENT_URIContacts.CONTENT_URI

对于问题 #1,您可以将 onCreate 代码更改为以下内容:

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

    vfile = "Contacts" + System.currentTimeMillis() +".vcf";

    new Thread(new Runnable() {
            @Override
            public void run() {
                getVcardString();
            }
    }).start();
}

对于问题 #2,问题在于您的主要查询是获取数据库中的所有电话,然后逐个电话将与该电话相关的联系人转换为电子名片。因此,如果一个联系人有多个电话,您将多次添加同一个联系人。

我假设您只需要手机联系人,因此将您的主要查询更改为:

cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);

到:

String selection = ContactsContract.Contacts.HAS_PHONE_NUMBER + "=1";
cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, selection, null, null);

如果修复的代码仍然崩溃,可能是OutOfMemoryError在这里发布异常堆栈,有一些地方可以改进。

【讨论】:

  • 非常感谢您的回答。我能够纠正我的 #1 问题。第二个问题还在继续。我试过你的答案,但没有奏效。联系人列表看起来仍然很高。如果我的联系人列表中有 5 个人,它会显示大约两倍。你能建议另一个答案吗?为什么他长得这么像?
  • 有时您认为您有 5 个联系人,但实际上您可能有 10 个,您可以使用 Contacts._IDContacts.DISPLAY_NAME 为每个光标行添加一个日志,以检查哪些联系人是代码查找,并确保没有重复。您还可以将Contacts.IN_VISIBLE_GROUP + "=1" 添加到您的选择中,以仅过滤到可见的联系人
  • 谢谢你的回答,我试过了。但是联系人列表仍然看起来太多了。
  • 你添加日志了吗?您是否看到 10 个不同的联系人 ID 和 10 个不同的显示名称?
  • 另外,我建议从 for 循环切换到 while (cursor.moveToNext()) { ... } 循环(不需要 moveToFirst)
猜你喜欢
  • 1970-01-01
  • 2017-05-06
  • 1970-01-01
  • 1970-01-01
  • 2016-10-08
  • 1970-01-01
  • 2023-01-04
  • 2020-10-16
  • 2016-05-30
相关资源
最近更新 更多