#android #android-contacts
#Android #android-контакты
Вопрос:
Я хочу получить как имя контактов, так и их тип в моем макете.Я предоставляю свои действия и файл макета.Я получаю недопустимое исключение типа столбца.любая помощь была бы весьма ощутимой.заранее спасибо.
TestActivity.class:
package application.test;
import android.app.ListActivity;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Data;
import android.view.LayoutInflater;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.content.ContentResolver;
import android.database.Cursor;
import android.database.SQLException;
public class TestActivity extends ListActivity
{
String name[];
String phoneType[];
ListView lview;
ListViewAdapter lviewAdapter;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);
LinearLayout mainLayout=new LinearLayout(this);
mainLayout.setOrientation(LinearLayout.VERTICAL);
LayoutInflater layoutInflater = getLayoutInflater();
mainLayout.addView(layoutInflater.inflate(R.layout.main,null));
mainLayout.addView(layoutInflater.inflate(R.layout.extra,null));
this.addContentView(mainLayout, params);
lview = (ListView) findViewById(android.R.id.list);
getContacts();
lviewAdapter=new ListViewAdapter(this, name, phoneType);
lview.setAdapter(lviewAdapter);
}//onCreate
public void getContacts(){
int i=0;
ContentResolver cr = getContentResolver();
String[] projection = new String[] { Data._ID,
ContactsContract.Contacts.DISPLAY_NAME, Phone.TYPE};
Cursor cur = cr.query(ContactsContract.Data.CONTENT_URI,
projection, null, null, null);
if (cur != null amp;amp; cur.moveToFirst()) {
try {
int indexID = cur.getColumnIndexOrThrow(ContactsContract.Contacts._ID);
int indexName = cur.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME);
int indexPhoneType = cur.getColumnIndexOrThrow(Phone.TYPE);
while (cur.moveToNext()) {
i ;
String id = cur.getString(indexID);
name[i] = cur.getString(indexName);
phoneType[i] = cur.getString(indexPhoneType);
}
} catch (SQLException sqle) {
sqle.printStackTrace();
} finally {
if (!cur.isClosed()) {
cur.close();
}
}
}
}
}
ListViewAdapter.class
package application.test;
import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
public class ListViewAdapter extends BaseAdapter {
Activity context;
String name[];
String phoneType[];
public ListViewAdapter(Activity context,String[] name,String[] phoneType){
super();
this.context=context;
this.name=name;
this.phoneType=phoneType;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return name.length;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
public class viewHolder {
TextView top;
TextView bottom;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
viewHolder holder;
if(convertView==null){
LayoutInflater inflator=context.getLayoutInflater();
convertView=inflator.inflate(R.layout.row,null);
holder=new viewHolder();
holder.top=(TextView)convertView.findViewById(R.id.toptext);
holder.bottom=(TextView)convertView.findViewById(R.id.bottomtext);
convertView.setTag(holder);
}else{
holder=(viewHolder)convertView.getTag();
}
holder.top.setText(name[position]);
holder.bottom.setText(phoneType[position]);
return convertView;
}
}
row.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="6dip">
<LinearLayout
android:orientation="vertical"
android:layout_width="0dip"
android:layout_weight="1"
android:layout_height="fill_parent">
<TextView
android:id="@ id/toptext"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:gravity="center_vertical"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:id="@ id/bottomtext"
android:singleLine="true"
android:ellipsize="marquee"
/>
</LinearLayout>
</LinearLayout>
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent" android:id="@ id/relativeLayout1"
android:layout_height="fill_parent">
<TextView android:id="@ id/textView1"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:text="All Contacts" android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"></TextView>
<TextView android:id="@ id/textView2"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_height="wrap_content" android:layout_width="wrap_content"
android:text="Search " android:layout_alignBaseline="@ id/editText1"
android:layout_alignBottom="@ id/editText1"
android:layout_alignParentLeft="true"></TextView>
<EditText android:layout_height="wrap_content" android:layout_width="180dp" android:id="@ id/editText1" android:layout_below="@ id/textView1" android:layout_toRightOf="@ id/textView2" android:layout_marginTop="18dp">
<requestFocus></requestFocus>
</EditText>
<Button android:layout_height="wrap_content"
android:text="Search" android:layout_width="wrap_content" android:id="@ id/button_searchContact"
android:layout_alignBottom="@ id/editText1" android:layout_toRightOf="@ id/editText1"></Button>
<ListView android:id="@android:id/list"
android:layout_height="wrap_content" android:layout_width="fill_parent"
android:layout_marginBottom="70dp"
android:layout_alignParentLeft="true" android:layout_below="@ id/editText1"></ListView>
</RelativeLayout>
extra.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:id="@ id/commonButtons"
android:gravity="bottom">
<ImageButton android:background="@drawable/favorite" android:layout_width="65dp" android:id="@ id/button_favorites" android:layout_height="50dp" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_marginBottom="20dp"></ImageButton>
<ImageButton android:background="@drawable/recents" android:layout_width="65dp" android:id="@ id/button_recent" android:layout_height="50dp" android:layout_alignTop="@ id/button_favorites" android:layout_toLeftOf="@ id/button_contacts"></ImageButton>
<ImageButton android:background="@drawable/contacts" android:layout_width="65dp" android:id="@ id/button_contacts" android:layout_height="50dp" android:layout_alignTop="@ id/button_recent" android:layout_centerHorizontal="true"></ImageButton>
<ImageButton android:background="@drawable/keypad" android:layout_width="65dp" android:id="@ id/button_keypad" android:layout_height="50dp" android:layout_alignTop="@ id/button_contacts" android:layout_toLeftOf="@ id/button_about"></ImageButton>
<ImageButton android:background="@drawable/about" android:layout_width="65dp" android:id="@ id/button_about" android:layout_height="50dp" android:layout_alignTop="@ id/button_keypad" android:layout_alignParentRight="true"></ImageButton>
<TextView android:layout_width="wrap_content" android:text="Favorites"
android:id="@ id/textView1" android:layout_height="wrap_content"
android:layout_below="@ id/button_recent" android:layout_toLeftOf="@ id/button_recent"></TextView>
<TextView android:layout_width="wrap_content" android:text="Contacts"
android:id="@ id/textView3" android:layout_height="wrap_content"
android:layout_alignBaseline="@ id/textView2"
android:layout_alignBottom="@ id/textView2" android:layout_toLeftOf="@ id/button_keypad" android:layout_alignLeft="@ id/button_contacts"></TextView>
<TextView android:layout_width="wrap_content" android:text=" Recents" android:id="@ id/textView2" android:layout_height="wrap_content" android:layout_below="@ id/button_recent" android:layout_toRightOf="@ id/button_favorites" android:layout_alignRight="@ id/button_recent"></TextView>
<TextView android:layout_width="wrap_content" android:text=" Keypad"
android:id="@ id/textView4" android:layout_height="wrap_content"
android:layout_alignParentBottom="true" android:layout_toRightOf="@ id/button_contacts"
android:layout_toLeftOf="@ id/button_about"></TextView>
<TextView android:layout_width="wrap_content" android:text=" About"
android:id="@ id/textView5" android:layout_height="wrap_content"
android:layout_alignParentBottom="true" android:layout_alignLeft="@ id/button_about"
android:layout_alignParentRight="true"></TextView>
</RelativeLayout>
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="application.test"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8"/>
<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".TestActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Комментарии:
1. Иисус, опубликуй свой полный код. Вы перемещаете курсор на первый элемент? Где ваша ПРОЕКЦИЯ?
Ответ №1:
Вот мой класс активности, с которым я тестировал код. Макет не важен, так как контактная информация печатается на стандартном выводе (посмотрите в DDMS).
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.database.SQLException;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts.Data;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
public final class ContactManager extends Activity {
public static final String TAG = "ContactManager";
@Override
public void onCreate(Bundle savedInstanceState)
{
Log.v(TAG, "Activity State: onCreate()");
super.onCreate(savedInstanceState);
setContentView(R.layout.contact_manager);
testGetContacts();
}
private void testGetContacts() {
ContentResolver cr = getContentResolver();
String[] projection = new String[] { Data._ID,
ContactsContract.Contacts.DISPLAY_NAME, Phone.TYPE};
Cursor cur = cr.query(ContactsContract.Data.CONTENT_URI,
projection, null, null, null);
if (cur != null amp;amp; cur.moveToFirst()) {
try {
int indexID = cur.getColumnIndexOrThrow(ContactsContract.Contacts._ID);
int indexName = cur.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME);
int indexPhoneType = cur.getColumnIndexOrThrow(Phone.TYPE);
while (cur.moveToNext()) {
String id = cur.getString(indexID);
String name = cur.getString(indexName);
String phoneType = cur.getString(indexPhoneType);
System.out.println(id "n");
System.out.println(name "n");
System.out.println(phoneType "n");
}
} catch (SQLException sqle) {
//handle exception here - like missing column name!
} finally { //close your cursor if it's not needed!
if (!cur.isClosed()) {
cur.close();
}
}
}
}
}
Ответ №2:
Предложения по улучшению кода:
0) Добавьте проекцию в свой код => получение всех столбцов неэффективно
String[] projection = new String[] { ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,ContactsContract.PhoneLookup.TYPE};
И затем добавьте проекцию в свой запрос:
Cursor cur = cr.query(ContactsContract.Data.CONTENT_URI,
projection, null, null, null);
1) В вашем цикле вы получаете индекс столбца на каждой итерации. В этом нет необходимости выводить cur.getColumnIndex из цикла.
2) При работе с курсором вы можете дополнить цикл for циклом while-condition. Вот предложение impl. вашего метода getContacts():
// A list of providers imports used!
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts.Data;
public void getContacts(){
ContentResolver cr = getContentResolver();
String[] projection = new String[] { Data._ID,
ContactsContract.Contacts.DISPLAY_NAME, Phone.TYPE};
Cursor cur = cr.query(ContactsContract.Data.CONTENT_URI,
projection, null, null, null);
// don't use this ContentProvider
// Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI,
// projection, null, null, null);
if (cur != null amp;amp; cur.moveToFirst()) {
try {
int indexID = cur.getColumnIndexOrThrow(ContactsContract.Contacts._ID);
int indexName = cur.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME);
int indexPhoneType = cur.getColumnIndexOrThrow(Phone.TYPE);
while (cur.moveToNext()) {
//do your logic here;
String id = cur.getString(indexID);
String name = cur.getString(indexName);
String phoneType = cur.getString(indexPhoneType);
}
} catch (SQLException sqle) {
//handle exception here - like missing column name!
} finally { //close your cursor if it's not needed!
if (!cur.isClosed()) {
cur.close();
}
}
}
}
Редактировать:
Используйте этот импорт:
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts.Data;
Используйте эту проекцию
String[] projection = new String[] { ContactsContract.Contacts._ID,
ContactsContract.Contacts.DISPLAY_NAME,ContactsContract.PhoneLookup.TYPE};
Используйте этот запрос:
Crsor cur = cr.query(ContactsContract.Data.CONTENT_URI,
projection, null, null, null);
Используйте имена столбцов:
int indexID = cur.getColumnIndexOrThrow(ContactsContract.Contacts._ID);
int indexName = cur.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME);
int indexPhoneType = cur.getColumnIndexOrThrow(Phone.TYPE);
Комментарии:
1. Это то, что я получаю после добавления проекции. (Исключение изменено на недопустимый тип столбца)…………………………
2. попробуйте ContactsContract.Data.DISPLAY_NAME вместо ContactsContract. Контакты. ИМЯ_СООБЩЕНИЯ. Какая строка выдает недопустимый тип столбца?
3. Я попытался отладить код .. вот два случая .. 1] если я добавлю столбец проекции не найден, появится ошибка [Cursor cur = cr.query(ContactsContract. Контакты. CONTENT_URI, проекция, нуль, null, null);] 2] если я не добавлю проекцию, то появится исключение (ошибка row0 col-1) .. есть идеи..
4. да — очевидно, что не все столбцы, которые вы ищете, предоставлены этим поставщиком контента. В первом случае запрос выдает исключение, поскольку мы запрашиваем определенный столбец, который не существует. Во втором случае ошибка возникает, когда мы пытаемся получить индекс столбца, который не существует. Итак, это та же проблема. ИДЕЯ: прокомментируйте проекцию на данный момент, выполните и посмотрите, в какой строке происходит сбой getColumnIndexOrThrow, чтобы мы знали, какой столбец не указан.
5. не могли бы вы предоставить код для получения имени и типа контактов, сохраненных в телефоне, и добавления их в соответствующие массивы .. любая помощь была бы заметна..