天冷了,老夫要把伙食搞上去,這不最近在軟件園二樓吃,伙食15塊,杠杠的。
創(chuàng)新互聯(lián)公司是一家專(zhuān)注于成都做網(wǎng)站、網(wǎng)站建設(shè)與策劃設(shè)計(jì),橋西網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)公司做網(wǎng)站,專(zhuān)注于網(wǎng)站建設(shè)十余年,網(wǎng)設(shè)計(jì)領(lǐng)域的專(zhuān)業(yè)建站公司;建站業(yè)務(wù)涵蓋:橋西等地區(qū)。橋西做網(wǎng)站價(jià)格咨詢(xún):18982081108
美包包,不說(shuō)了,進(jìn)入正題。今天老夫要講的是讀取聯(lián)系人,其實(shí)我做這個(gè)的初衷是想做一個(gè)短信攔截,電話(huà)攔截的功能。
我們先看一下界面,還是不錯(cuò)的,挺絢麗的。
OK,我們一看就知道,這又是一個(gè)ListView。目前的功能是當(dāng)你在復(fù)選框打鉤,點(diǎn)擊后面的撥號(hào)就會(huì)將電話(huà)打出去。如果不打鉤,電話(huà)則不會(huì)撥出去。OK,我們先看看頁(yè)面布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ListView android:id="@+id/contactListView" android:descendantFocusability="blocksDescendants" android:layout_width="fill_parent" android:layout_height="fill_parent" android:divider="@color/teal" android:dividerHeight="1dp"> </ListView> <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <Button android:id="@+id/btnSelAll" android:text="@string/btnSelAll" android:textColor="@color/teal" android:textSize="14dp" android:textStyle="bold" android:layout_weight="1" android:layout_width="fill_parent" android:layout_height="fill_parent"></Button> <Button android:id="@+id/btnInverseSel" android:text="@string/btnSelInverse" android:textColor="@color/teal" android:layout_marginLeft="1dp" android:layout_weight="1" android:textSize="14dp" android:textStyle="bold" android:layout_width="fill_parent" android:layout_height="fill_parent"></Button> <Button android:id="@+id/btnSet" android:text="@string/btnSet" android:layout_weight="1" android:textColor="@color/teal" android:layout_marginLeft="1dp" android:textSize="14dp" android:textStyle="bold" android:layout_width="fill_parent" android:layout_height="fill_parent"></Button> </LinearLayout> </LinearLayout>
我們?cè)倏纯碙istView要加載的模版
<?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="wrap_content" android:id="@+id/contactTemplate"> <TableLayout android:id="@+id/tabContatMain" android:layout_width="fill_parent" android:layout_height="wrap_content" android:stretchColumns="2" android:shrinkColumns="2" android:padding="3dip"> <TableRow> <CheckBox android:id="@+id/chkContactUser" android:layout_gravity="center_vertical"></CheckBox> <ImageView android:id="@+id/imgContactPhoto" android:layout_gravity="center_vertical" android:scaleType="fitCenter"></ImageView> <TextView android:id="@+id/txtContactName" android:layout_marginLeft="10dp" android:layout_gravity="center_vertical" android:textColor="@color/teal1"></TextView> <TextView android:id="@+id/txtContactTelNumber" android:layout_marginLeft="4dp" android:gravity="right" android:layout_gravity="center_vertical" android:textColor="@color/yellow"></TextView> <Button android:id="@+id/btnDail" android:text="@string/btnDail" android:textSize="10dp" android:layout_marginLeft="10dp" android:width="60dp" android:drawableRight="@drawable/dail" android:layout_gravity="center_vertical" android:textColor="@color/purplered"></Button> </TableRow> </TableLayout> </LinearLayout>
依然是TableLayout布局,我們?cè)O(shè)置它的收縮列為第二列,伸展列也是第二列。這樣如果第二列不夠顯示則會(huì)收縮。OK,我們看一下后臺(tái)代碼
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.punchinalarm); owner = this; btnSelAll = (Button) this.findViewById(R.id.btnSelAll); btnSelInverse = (Button) this.findViewById(R.id.btnInverseSel); btnSet = (Button) this.findViewById(R.id.btnSet); contactUserListView = (ListView) this .findViewById(R.id.contactListView); dataList = new ArrayList<Map<String, Object>>(); this.InitData(); }
在OnCreate方法中,我們初始化數(shù)據(jù)。
private void InitData() { String phoneUserName = null; String phoneNumber = null; Long contactId = null; Long photoId = null; Map<String, Object> dataMap = null; ContentResolver resolver = this.getApplicationContext() .getContentResolver(); /* * 獲取Sim卡聯(lián)系人 Uri uri = Uri.parse("content://icc/adn"); */ Cursor phoneCursor = resolver.query(Phone.CONTENT_URI, PHONE_PROJECTION, null, null, null); if (phoneCursor != null) { while (phoneCursor.moveToNext()) { dataMap = new HashMap<String, Object>(); phoneUserName = phoneCursor.getString(0); phoneNumber = phoneCursor.getString(1); photoId = phoneCursor.getLong(2); contactId = phoneCursor.getLong(3); if (phoneNumber == null || phoneNumber.trim().length() < 11) { continue; } Bitmap contactPhoto = null; if (photoId > 0) { Uri uri = ContentUris.withAppendedId( ContactsContract.Contacts.CONTENT_URI, contactId); InputStream input = ContactsContract.Contacts .openContactPhotoInputStream(resolver, uri); contactPhoto = BitmapFactory.decodeStream(input); } else { contactPhoto = BitmapFactory.decodeResource(getResources(), R.drawable.usersmall); } dataMap.put("UserName", phoneUserName); dataMap.put("UserPhoneNumber", phoneNumber); dataMap.put("UserPhoto", contactPhoto); dataList.add(dataMap); } if (dataList != null && dataList.size() > 0) { customAdapter simpleAdapter = new customAdapter(this, dataList, R.layout.contactdetailtemplate, new String[] { "UserPhoto", "UserName", "UserPhoneNumber" }, new int[] { R.id.chkContactUser, R.id.imgContactPhoto, R.id.txtContactName, R.id.txtContactTelNumber, R.id.btnDail }); this.contactUserListView.setAdapter(simpleAdapter); } } }
我們知道外界的程序通過(guò)ContentResolver接口可以訪問(wèn)ContentProvider提供的數(shù)據(jù),在Activity當(dāng)中通過(guò)getContentResolver()可以得到當(dāng)前應(yīng)用的 ContentResolver實(shí)例。因?yàn)橥ㄓ嶄浐投滔⒍伎梢酝ㄟ^(guò)接口訪問(wèn),所以我們就可以通過(guò)getContentResolver訪問(wèn)SIM卡和手機(jī)中的聯(lián)系人信息。
我們主要到下面的這句
Cursor phoneCursor = resolver.query(Phone.CONTENT_URI, PHONE_PROJECTION, null, null, null);
通過(guò)接口查詢(xún),我們會(huì)得到一個(gè)Cursor。通過(guò)查看Cursor的定義,我們發(fā)現(xiàn)它是個(gè)抽象類(lèi)
public abstract interface android.database.Cursor
我們發(fā)現(xiàn)它提供了一些方法,如下
由此可見(jiàn),它是一個(gè)既可以前進(jìn)又可以后退的無(wú)向游標(biāo),類(lèi)似于SqlServer中的游標(biāo)。這樣的話(huà)我們不論是讀取聯(lián)系人信息,還是讀取短消息,都可以隨時(shí)定位游標(biāo)。
在上面我們看到Query的幾個(gè)參數(shù),Phone.Content_URI,獲取聯(lián)系人的時(shí)候需要去這個(gè)URI去取數(shù)據(jù)。其實(shí)這里的Phone.Content_URI的值是content://com.android.contacts/contacts。它的定義如下
public static final android.net.Uri CONTENT_URI;
ok,我們拿到聯(lián)系人之后,我們進(jìn)行循環(huán),游標(biāo)下移,拿出所有的有電話(huà)號(hào)碼的聯(lián)系人的數(shù)據(jù)。因?yàn)槲覀儌魅氲腜HONE_PROJECTION的順序是姓名,電話(huà)號(hào)碼,照片ID,以及一個(gè)ContactID。所以我們看到取數(shù)據(jù)的順序如下
phoneUserName = phoneCursor.getString(0); phoneNumber = phoneCursor.getString(1); photoId = phoneCursor.getLong(2); contactId = phoneCursor.getLong(3);
拿到PhotoID之后,我們判斷是否大于0,如果大于0,我們會(huì)獲取用戶(hù)圖像。
獲取用戶(hù)圖像的時(shí)候,先通過(guò)下面的代碼將URI和參數(shù)連接起來(lái)
ContentUris.withAppendedId( ContactsContract.Contacts.CONTENT_URI, contactId)
其實(shí)這個(gè)類(lèi)似于Get方式的API,比如ContactUser/100,意思是獲取編號(hào)為100的人的信息。
OK,URI構(gòu)造好之后,我們獲取圖像
InputStream input = ContactsContract.Contacts .openContactPhotoInputStream(resolver, uri); contactPhoto = BitmapFactory.decodeStream(input);
最后加入List<Map<String,Object>>,對(duì)ListView運(yùn)用適配器。
class customAdapter extends BaseAdapter { private List<Map<String, Object>> dataList; private LayoutInflater mInflater; private Context context; private String[] keyString; private int[] valueViewID; Holder holder; public customAdapter(Context context, List<Map<String, Object>> dataList, int resource, String[] from, int[] to) { this.dataList = dataList; this.context = context; mInflater = (LayoutInflater) this.context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); keyString = new String[from.length]; valueViewID = new int[to.length]; System.arraycopy(from, 0, keyString, 0, from.length); System.arraycopy(to, 0, valueViewID, 0, to.length); } @Override public int getCount() { return dataList.size(); } @Override public Object getItem(int position) { return dataList.get(position); } @Override public long getItemId(int position) { return position; } public void removeItem(int position) { dataList.remove(position); this.notifyDataSetChanged(); } public View getView(int position, View convertView, ViewGroup parent) { if (convertView != null) { holder = (Holder) convertView.getTag(); } else { convertView = mInflater.inflate(R.layout.contactdetailtemplate, null); holder = new Holder(); holder.chkContactUser = (CheckBox) convertView .findViewById(valueViewID[0]); holder.imgUserPhoto = (ImageView) convertView .findViewById(valueViewID[1]); holder.labUserName = (TextView) convertView .findViewById(valueViewID[2]); holder.labPhoneNumber = (TextView) convertView .findViewById(valueViewID[3]); holder.btnDail = (Button) convertView .findViewById(valueViewID[4]); convertView.setTag(holder); } Map<String, Object> appInfo = dataList.get(position); if (appInfo != null) { String userName = appInfo.get(keyString[1]).toString(); String userPhoneNumber = appInfo.get(keyString[2]) == null ? "" : appInfo.get(keyString[2]).toString(); Bitmap userPhoto = (Bitmap) appInfo.get(keyString[0]); holder.labUserName.setText(userName); holder.labPhoneNumber.setText(userPhoneNumber); holder.imgUserPhoto.setImageBitmap(userPhoto); holder.btnDail.setOnClickListener(new ViewButtonListener( position, holder.chkContactUser)); } return convertView; } } class Holder { public TextView labUserName; public TextView labPhoneNumber; public ImageView imgUserPhoto; public Button btnDail; public CheckBox chkContactUser; }
這里,其實(shí)很簡(jiǎn)單,我們就是拿到控件,然后根據(jù)Position,拿到List中的某行數(shù)據(jù),然后賦值。
最后我們看看按鈕的Click事件,我們傳入了Position和每行的CheckBox。
class ViewButtonListener implements OnClickListener { private int position; Object phoneNumber; CheckBox chkContactUser; ViewButtonListener(int position,CheckBox chkContactUser) { this.position = position; this.phoneNumber = dataList.get(position).get("UserPhoneNumber"); this.chkContactUser= chkContactUser; } @Override public void onClick(View view) { int vid = view.getId(); if (vid == R.id.btnDail&&chkContactUser.isChecked()) { Intent dialIntent = new Intent(Intent.ACTION_CALL, Uri .parse("tel:" + phoneNumber)); startActivity(dialIntent); } } }
在OnClick中,我們判斷如果是撥號(hào)按鈕并且列頭的CheckBox是勾選的,則會(huì)撥號(hào),否則不會(huì)撥號(hào)。OK,最后我們希望在按回退鍵的時(shí)候,彈出是否退出的提示
ok,代碼如下
public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0)) { dialog(); return true; } return true; } protected void dialog() { AlertDialog.Builder builder = new Builder(punchinalarm.this); builder.setMessage("確定要退出嗎?"); builder.setTitle("提示"); builder.setPositiveButton("確認(rèn)", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); android.os.Process.killProcess(android.os.Process.myPid()); } }); builder.setNegativeButton("取消", new android.content.DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); builder.create().show(); }
最后,哥們的博客是貨真價(jià)實(shí),小米3測(cè)試機(jī)。
新聞標(biāo)題:Android切近實(shí)戰(zhàn)(八)
分享網(wǎng)址:http://aaarwkj.com/article8/igocip.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計(jì)、微信小程序、網(wǎng)站策劃、網(wǎng)站設(shè)計(jì)、軟件開(kāi)發(fā)、用戶(hù)體驗(yàn)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)