我想从手机中获取所有联系人,只需在android ListView
中显示,而不在数据库中存储,目的是当用户点击按钮"同步所有联系人"然后应该获取所有联系人并显示在ListView
中。这是主要的活动类我也创建了带有变量contacts_name
和phone_no
以及CustomAdapter
类
public class MainActivity extends AppCompatActivity {
ListView listView;
Button sync;
ArrayList<newlist> listitem;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listitem = new ArrayList<newlist>();
listView = (ListView) findViewById(R.id.listViewID);
registerForContextMenu(listView);
sync= (Button) findViewById(R.id.syncID);
sync.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//what method will be used here for sync contacts and display in listview
}
});
}
}
请任何帮助将不胜感激。
答案 0 :(得分:1)
尝试使用此库,您可以轻松获得所有联系人。
https://github.com/EverythingMe/easy-content-providers
对于ListView
,您需要编写自定义适配器,您还可以在互联网上找到很多示例。这只是一个样本。
public class CustomListViewAdapter extends ArrayAdapter<Person> {
private final LayoutInflater inflater;
private final Context context;
private ViewHolder holder;
private final ArrayList<Person> persons;
public CustomListViewAdapter(Context context, ArrayList<Person> persons) {
super(context,0, persons);
this.context = context;
this.persons = persons;
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return persons.size();
}
@Override
public Person getItem(int position) {
return persons.get(position);
}
@Override
public long getItemId(int position) {
return persons.get(position).hashCode();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.list_view_item, null);
holder = new ViewHolder();
holder.personImage = (ImageView) convertView.findViewById(R.id.person_image);
holder.personNameLabel = (TextView) convertView.findViewById(R.id.person_name_label);
holder.personAddressLabel = (TextView) convertView.findViewById(R.id.person_address_label);
convertView.setTag(holder);
}
else{
//Get viewholder we already created
holder = (ViewHolder)convertView.getTag();
}
Person person = persons.get(position);
if(person != null){
holder.personImage.setImageResource(person.getPhotoId());
holder.personNameLabel.setText(person.getName());
holder.personAddressLabel.setText(person.getAddress());
}
return convertView;
}
//View Holder Pattern for better performance
private static class ViewHolder {
TextView personNameLabel;
TextView personAddressLabel;
ImageView personImage;
}
}
在 onCreate 中阅读图书馆的文档,并尝试弄清楚如何获取联系人。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// GET CONTACTS DATA
initialize();
}
private void initialize() {
persons = new ArrayList<Person>();
listView = (ListView) findViewById(R.id.person_list_view);
listViewAdapter = new CustomListViewAdapter(MainActivity.this,persons);
listView.setAdapter(listViewAdapter);
}
答案 1 :(得分:1)
<强>权限强>
首先,在清单中设置权限:
<uses-permission android:name="android.permission.READ_CONTACTS"/>
注意:从Marshmallow开始,权限模型已更改。如果您的targetSdkVersion&gt; = 23且您在Marshmallow(或更高版本)设备上运行,则可能需要启用运行时权限才能获得 READ_CONTACTS 权限。您还可以在此处阅读有关运行时权限更改的更多信息。
构建SimpleCursorAdapter
SimpleCursorAdapter是一个适配器,它将ListView绑定到Cursor数据集,该数据集将结果集显示为列表中的行。我们可以在接收游标之前通过构造如下来创建适配器:
public class SampleActivity extends AppCompatActivity {
// ... existing code ...
private SimpleCursorAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
setupCursorAdapter();
}
// Create simple cursor adapter to connect the cursor dataset we load with a ListView
private void setupCursorAdapter() {
// Column data from cursor to bind views from
String[] uiBindFrom = { ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.PHOTO_URI };
// View IDs which will have the respective column data inserted
int[] uiBindTo = { R.id.tvName, R.id.ivImage };
// Create the simple cursor adapter to use for our list
// specifying the template to inflate (item_contact),
adapter = new SimpleCursorAdapter(
this, R.layout.item_contact,
null, uiBindFrom, uiBindTo,
0);
}
}
请注意,如果要使用更复杂的自定义布局,则应构建自定义CursorAdapter以替换上面显示的SimpleCursorAdapter。
连接ListView
一旦我们定义了游标适配器,我们就可以在名为R.id.lvContacts的活动中添加一个ListView,它将包含从内容提供者加载的联系人列表。一旦我们在布局XML中定义了ListView,我们就可以将列表绑定到我们的适配器:
public class SampleActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
setupCursorAdapter();
// Find list and bind to adapter
ListView lvContacts = (ListView) findViewById(R.id.lvContacts);
lvContacts.setAdapter(adapter);
}
}
现在,一旦我们从Contacts ContentProvider加载Cursor,我们就可以将数据集插入适配器,列表将自动填充。
使用CursorLoader查询ContentProvider
每当我们想要从已注册的ContactProvider加载数据时,我们都希望异步执行查询以避免阻止UI。执行此查询的最简单方法是使用CursorLoader,它在后台针对ContentProvider运行异步查询,并将结果返回给我们的Activity。
要向我们的联系人提供程序执行请求,我们需要定义加载程序将用于创建请求并处理结果的回调。这些回调的类型为LoaderCallbacks,可以定义如下:
public class SampleActivity extends AppCompatActivity {
// ... existing code
// Defines the asynchronous callback for the contacts data loader
private LoaderManager.LoaderCallbacks<Cursor> contactsLoader =
new LoaderManager.LoaderCallbacks<Cursor>() {
// Create and return the actual cursor loader for the contacts data
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// Define the columns to retrieve
String[] projectionFields = new String[] { ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,
ContactsContract.Contacts.PHOTO_URI };
// Construct the loader
CursorLoader cursorLoader = new CursorLoader(SampleActivity.this,
ContactsContract.Contacts.CONTENT_URI, // URI
projectionFields, // projection fields
null, // the selection criteria
null, // the selection args
null // the sort order
);
// Return the loader for use
return cursorLoader;
}
// When the system finishes retrieving the Cursor through the CursorLoader,
// a call to the onLoadFinished() method takes place.
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
// The swapCursor() method assigns the new Cursor to the adapter
adapter.swapCursor(cursor);
}
// This method is triggered when the loader is being reset
// and the loader data is no longer available. Called if the data
// in the provider changes and the Cursor becomes stale.
@Override
public void onLoaderReset(Loader<Cursor> loader) {
// Clear the Cursor we were using with another call to the swapCursor()
adapter.swapCursor(null);
}
};
}
现在,当结果返回到定义的回调时,适配器将绑定到游标。通过指定加载程序回调,我们现在可以设置加载程序并执行对内容提供程序的异步请求:
public class SampleActivity extends AppCompatActivity {
// ... existing code
// Defines the id of the loader for later reference
public static final int CONTACT_LOADER_ID = 78; // From docs: A unique identifier for this loader. Can be whatever you want.
@Override
protected void onCreate(Bundle savedInstanceState) {
// Bind adapter to list
setupCursorAdapter();
// Initialize the loader with a special ID and the defined callbacks from above
getSupportLoaderManager().initLoader(CONTACT_LOADER_ID,
new Bundle(), contactsLoader);
}
}
现在我们已经完成了使用CursorLoader查询ContactProvider并将生成的Cursor加载到CursorAdapter中将联系人加载到列表中的过程。我们现在应该看到我们联系人姓名的列表。
您可以参考此link
答案 2 :(得分:1)
使用以下方法从手机数据库中提取联系人(根据您的要求更新方法,目前只提取联系人号码)。
List<Integer> fetchContacts() {
final String[] projection = new String[]{
ContactsContract.CommonDataKinds.Phone.NUMBER,
};
final Cursor phone = context.getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
projection, null, null, null);
List<Integer> contacts = new ArrayList<>();
while(phone.moveToNext()){
contacts.add(phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER););
}
phone.close();
return contacts;
}
之后,您可以将此联系人列表传递给适配器,并在适配器上调用notifyDataSetChanged()
以反映列表视图中的更改。
此外,您需要为清单文件中的联系人权限声明uses-permission
,如此
<uses-permission android:name="android.permission.READ_CONTACTS"/>