閱讀242 返回首頁    go 阿裏雲 go 技術社區[雲棲]


手機衛士08-獲取手機聯係人

首先,我把把昨天忘記了的兩張設置向導的圖片放出來先

   


我們從上麵的第一張圖片可以看到,我們有一個選擇聯係人這一操作,那麼怎樣才能獲取到手機裏麵的聯係人呢,其實方法有很多的,現在我們來講一下我們這個項目裏麵用到的方法

其實要想知道怎樣獲取手機裏麵的聯係人,去看一下Android自己的源碼就知道的了

我們隻要把platform/packages/providers/ContactsProvider這一部分的內容下載下來看看就可以的啦

下麵是我下載之後,打開裏麵的AndroidManifest的內容

  1. <manifest xmlns:andro
  2.         package="com.android.providers.contacts"
  3.         android:sharedUserId="android.uid.shared"
  4.         android:sharedUserLabel="@string/sharedUserLabel">

  5.     <permission
  6.             android:name="com.android.voicemail.permission.READ_WRITE_ALL_VOICEMAIL"
  7.             android:label="@string/read_write_all_voicemail_label"
  8.             android:description="@string/read_write_all_voicemail_description"
  9.             android:permissionGroup="android.permission-group.PERSONAL_INFO"
  10.             android:protectionLevel="signature"
  11.             />

  12.     <uses-permission android:name="android.permission.READ_CONTACTS" />
  13.     <uses-permission android:name="android.permission.WRITE_CONTACTS" />
  14.     <uses-permission android:name="android.permission.GET_ACCOUNTS" />
  15.     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  16.     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  17.     <uses-permission android:name="android.permission.BIND_DIRECTORY_SEARCH" />
  18.     <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
  19.     <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
  20.     <uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" />
  21.     <uses-permission android:name="com.android.voicemail.permission.READ_WRITE_ALL_VOICEMAIL" />

  22.     <application android:process="android.process.acore"
  23.         android:label="@string/app_label"
  24.         android:icon="@drawable/app_icon"
  25.         android:allowBackup="false">

  26.         <provider android:name="ContactsProvider2"
  27.             android:authorities="contacts;com.android.contacts"
  28.             android:label="@string/provider_label"
  29.             android:multiprocess="false"
  30.             android:exported="true"
  31.             android:readPermission="android.permission.READ_CONTACTS"
  32.             android:writePermission="android.permission.WRITE_CONTACTS">
  33.             <path-permission
  34.                     android:pathPrefix="/search_suggest_query"
  35.                     android:readPermission="android.permission.GLOBAL_SEARCH" />
  36.             <path-permission
  37.                     android:pathPrefix="/search_suggest_shortcut"
  38.                     android:readPermission="android.permission.GLOBAL_SEARCH" />
  39.             <path-permission
  40.                     android:pathPattern="/contacts/.*/photo"
  41.                     android:readPermission="android.permission.GLOBAL_SEARCH" />
  42.             <grant-uri-permission android:pathPattern=".*" />
  43.         </provider>

  44.         <provider android:name="CallLogProvider"
  45.             android:authorities="call_log"
  46.             android:syncable="false" android:multiprocess="false"
  47.             android:exported="true"
  48.             android:readPermission="android.permission.READ_CALL_LOG"
  49.             android:writePermission="android.permission.WRITE_CALL_LOG">
  50.         </provider>

  51.         <provider android:name="VoicemailContentProvider"
  52.             android:authorities="com.android.voicemail"
  53.             android:syncable="false" android:multiprocess="false"
  54.             android:exported="true"
  55.             android:permission="com.android.voicemail.permission.ADD_VOICEMAIL">
  56.         </provider>

  57.         <!-- Handles database upgrades after OTAs, then disables itself -->
  58.         <receiver android:name="ContactsUpgradeReceiver">
  59.             <!-- This broadcast is sent after the core system has finished
  60.                  booting, before the home app is launched or BOOT_COMPLETED
  61.                  is sent. -->
  62.             <intent-filter>
  63.                 <action android:name="android.intent.action.PRE_BOOT_COMPLETED"/>
  64.             </intent-filter>
  65.         </receiver>

  66.         <receiver android:name="PackageIntentReceiver">
  67.             <intent-filter>
  68.                 <action android:name="android.intent.action.PACKAGE_ADDED" />
  69.                 <data android:scheme="package" />
  70.             </intent-filter>
  71.             <intent-filter>
  72.                 <action android:name="android.intent.action.PACKAGE_REPLACED" />
  73.                 <data android:scheme="package" />
  74.             </intent-filter>
  75.             <intent-filter>
  76.                 <action android:name="android.intent.action.PACKAGE_REMOVED" />
  77.                 <data android:scheme="package" />
  78.             </intent-filter>
  79.             <intent-filter>
  80.                 <action android:name="android.intent.action.PACKAGE_CHANGED" />
  81.                 <data android:scheme="package" />
  82.             </intent-filter>
  83.         </receiver>

  84.         <receiver android:name="LocaleChangeReceiver">
  85.             <intent-filter>
  86.                 <action android:name="android.intent.action.LOCALE_CHANGED"/>
  87.             </intent-filter>
  88.         </receiver>

  89.         <service android:name="VoicemailCleanupService"/>

  90.         <activity android:name=".debug.ContactsDumpActivity"
  91.                 android:label="@string/debug_dump_title"
  92.                 android:theme="@android:style/Theme.Holo.Dialog"
  93.                 >
  94.             <intent-filter>
  95.                 <action android:name="com.android.providers.contacts.DUMP_DATABASE"/>
  96.                 <category android:name="android.intent.category.DEFAULT"/>
  97.             </intent-filter>
  98.         </activity>

  99.         <provider android:name=".debug.DumpFileProvider"
  100.             android:authorities="com.android.contacts.dumpfile"
  101.             android:exported="true">
  102.         </provider>

  103.     </application>
  104. </manifest>
複製代碼
我們可以看一下第一個provider,裏麵就有我們想要的uri還有它已經寫好了的類了,各位有興趣的可以去看一下是如何實現的, 其實我們要獲取的東西,都是存放在一個數據庫裏麵的,我們不妨把那個數據庫拿出來看一下,拿到那個數據庫也很簡單,隻要在Eclipse裏麵的ddms界麵裏麵,在右上邊  那個contacts2.db就是我們想要的東西啦我們可以把它導出來,然後用SQLite Database browser來打開它  獲取手機裏麵的聯係人,我們隻要關注三個表就可以啦,一個是raw_contacts   data還有一個mime_type這三個表就行啦mime_type存放的就是一些類型,是電話,還是短信,還是E-mail這些data就是存放一些數據的東西raw_contacts就是存放一些命名什麼的這三個表的關係就是下麵一樣的啦 從上麵的可以看到,我們可以通過raw_contacts拿到那個id還有display_name然後就去data那裏找到對應的raw_contact_id,這樣就可以獲得對應的數據啦,然後還可以通過mimetype_id在mime_type表裏麵找出想要的類型好啦,原理就是這樣啦,下麵我們來看一下代碼怎麼寫我們先要用一個model類來存放我們的數據com.xiaobin.security.domain.ContactInfo
  1. package com.xiaobin.security.domain;

  2. public class ContactInfo
  3. {
  4.         private String name;
  5.         private String phone;
  6.         
  7.         public String getName()
  8.         {
  9.                 return name;
  10.         }
  11.         public void setName(String name)
  12.         {
  13.                 this.name = name;
  14.         }
  15.         public String getPhone()
  16.         {
  17.                 return phone;
  18.         }
  19.         public void setPhone(String phone)
  20.         {
  21.                 this.phone = phone;
  22.         }
  23.         
  24. }
複製代碼
然後呢,我們就可以寫我們獲得手機聯係人的代碼啦新建一個類com.xiaobin.security.engine.ContactInfoService
  1. package com.xiaobin.security.engine;

  2. import java.util.ArrayList;
  3. import java.util.List;

  4. import android.content.ContentResolver;
  5. import android.content.Context;
  6. import android.database.Cursor;
  7. import android.net.Uri;

  8. import com.xiaobin.security.domain.ContactInfo;

  9. public class ContactInfoService
  10. {
  11.         private Context context;
  12.         
  13.         public ContactInfoService(Context context)
  14.         {
  15.                 this.context = context;
  16.         }
  17.         
  18.         public List<ContactInfo> getContactInfos()
  19.         {
  20.                 List<ContactInfo> infos = new ArrayList<ContactInfo>();
  21.                 ContactInfo info;
  22.                 
  23.                 ContentResolver contentResolver = context.getContentResolver();
  24.                 //在源碼的AndroidManifest裏麵可以看到這些uri
  25.                 Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
  26.                 Uri dataUri = Uri.parse("content://com.android.contacts/data");
  27.                 Cursor cursor = contentResolver.query(uri, null, null, null, null);
  28.                 while(cursor.moveToNext())
  29.                 {
  30.                         info = new ContactInfo();
  31.                         String id = cursor.getString(cursor.getColumnIndex("_id"));
  32.                         String name = cursor.getString(cursor.getColumnIndex("display_name"));
  33.                         info.setName(name);
  34.                         //通過raw_contacts裏麵的id拿到data裏麵對應的數據
  35.                         Cursor dataCursor = contentResolver.query(dataUri, null, "raw_contact_id = ? ", new String[] {id}, null);
  36.                         while(dataCursor.moveToNext())
  37.                         {
  38.                                 String type = dataCursor.getString(dataCursor.getColumnIndex("mimetype"));
  39.                                 //根據類型,隻要電話這種類型的數據
  40.                                 if(type.equals("vnd.android.cursor.item/phone_v2"))
  41.                                 {
  42.                                         String number = dataCursor.getString(dataCursor.getColumnIndex("data1"));//拿到數據
  43.                                         info.setPhone(number);
  44.                                 }
  45.                         }
  46.                         dataCursor.close();
  47.                         infos.add(info);
  48.                         info = null;
  49.                 }
  50.                 cursor.close();
  51.                 return infos;
  52.         }

  53. }
複製代碼
因為我們是點擊按鈕,然後打開一個activity,然後選擇好了之後,再把值返回到原來的activity那裏的,所以我們就要用到startActivityForResult這個方法啦好,我們來看一下setup_guide3這個向導頁麵的邏輯是怎樣寫的com.xiaobin.security.ui.SetupGuide3Activity
  1. package com.xiaobin.security.ui;

  2. import android.app.Activity;
  3. import android.content.Context;
  4. import android.content.Intent;
  5. import android.content.SharedPreferences;
  6. import android.content.SharedPreferences.Editor;
  7. import android.os.Bundle;
  8. import android.view.View;
  9. import android.view.View.OnClickListener;
  10. import android.widget.Button;
  11. import android.widget.EditText;
  12. import android.widget.Toast;

  13. import com.xiaobin.security.R;

  14. public class SetupGuide3Activity extends Activity implements OnClickListener
  15. {
  16.         private Button bt_next;
  17.         private Button bt_pervious;
  18.         private Button bt_select;
  19.         private EditText et_phoneNumber;
  20.         private SharedPreferences sp;
  21.         
  22.         @Override
  23.         protected void onCreate(Bundle savedInstanceState)
  24.         {
  25.                 super.onCreate(savedInstanceState);
  26.                 setContentView(R.layout.setup_guide3);
  27.                 
  28.                 sp = getSharedPreferences("config", Context.MODE_PRIVATE);
  29.                 
  30.                 bt_next = (Button) findViewById(R.id.bt_guide_next);
  31.                 bt_pervious = (Button) findViewById(R.id.bt_guide_pervious);
  32.                 bt_select = (Button) findViewById(R.id.bt_guide_select);
  33.                 bt_next.setOnClickListener(this);
  34.                 bt_pervious.setOnClickListener(this);
  35.                 bt_select.setOnClickListener(this);
  36.                 
  37.                 et_phoneNumber = (EditText) findViewById(R.id.et_guide_phoneNumber);
  38.         }
  39.         
  40.         //重寫這個方法,從acitivty裏麵拿到數據
  41.         @Override
  42.         protected void onActivityResult(int requestCode, int resultCode, Intent data)
  43.         {
  44.                 super.onActivityResult(requestCode, resultCode, data);
  45.                 //resultCode是乃至區分拿到的activity是從那一個activity裏麵拿到的
  46.                 
  47.                 if(data != null)
  48.                 {
  49.                         String number = data.getStringExtra("number");
  50.                         et_phoneNumber.setText(number);
  51.                 }
  52.         }

  53.         @Override
  54.         public void onClick(View v)
  55.         {
  56.                 switch(v.getId())
  57.                 {
  58.                         case R.id.bt_guide_select : 
  59.                                 Intent selectIntent = new Intent(this, SelectContactActivity.class);
  60.                                 //啟動一個activity來獲取數據,獲取到的數據是在重寫的onActivityResult這個方法裏麵拿到的
  61.                                 startActivityForResult(selectIntent, 1);
  62.                                 break;
  63.                                 
  64.                         case R.id.bt_guide_next : 
  65.                                 String number = et_phoneNumber.getText().toString().trim();
  66.                                 if(number.equals(""))
  67.                                 {
  68.                                         Toast.makeText(this, "安全號碼不能為空", Toast.LENGTH_SHORT).show();
  69.                                 }
  70.                                 else
  71.                                 {
  72.                                         Editor editor = sp.edit();
  73.                                         editor.putString("number", number);
  74.                                         editor.commit();
  75.                                         
  76.                                         Intent intent = new Intent(this, SetupGuide4Activity.class);
  77.                                         finish();
  78.                                         startActivity(intent);
  79.                                         //這個是定義activity切換時的動畫效果的
  80.                                         overridePendingTransition(R.anim.translate_in, R.anim.translate_out);
  81.                                 }
  82.                                 break;
  83.                         case R.id.bt_guide_pervious : 
  84.                                 
  85.                                 Intent i = new Intent(this, SetupGuide2Activity.class);
  86.                                 finish();
  87.                                 startActivity(i);
  88.                                 //這個是定義activity切換時的動畫效果的
  89.                                 overridePendingTransition(R.anim.alpha_in, R.anim.alpha_out);
  90.                                 break;
  91.                                 
  92.                         default : 
  93.                                 break;
  94.                 }
  95.         }

  96. }
複製代碼
我們還要新建一個類用來做為選擇的呢com.xiaobin.security.ui.SelectContactActivity
  1. package com.xiaobin.security.ui;

  2. import java.util.List;

  3. import android.app.Activity;
  4. import android.content.Intent;
  5. import android.os.Bundle;
  6. import android.view.View;
  7. import android.view.ViewGroup;
  8. import android.widget.AdapterView;
  9. import android.widget.AdapterView.OnItemClickListener;
  10. import android.widget.BaseAdapter;
  11. import android.widget.ListView;
  12. import android.widget.TextView;

  13. import com.xiaobin.security.R;
  14. import com.xiaobin.security.domain.ContactInfo;
  15. import com.xiaobin.security.engine.ContactInfoService;

  16. public class SelectContactActivity extends Activity
  17. {
  18.         private ListView lv;
  19.         private List<ContactInfo> infos;
  20.         
  21.         @Override
  22.         protected void onCreate(Bundle savedInstanceState)
  23.         {
  24.                 super.onCreate(savedInstanceState);
  25.                 setContentView(R.layout.select_contact);
  26.                 
  27.                 infos = new ContactInfoService(this).getContactInfos();
  28.                 
  29.                 lv = (ListView) findViewById(R.id.lv_select_contact);
  30.                 lv.setAdapter(new SelectContactAdapter());
  31.                 lv.setOnItemClickListener(new OnItemClickListener()
  32.                 {
  33.                         @Override
  34.                         public void onItemClick(AdapterView<?> parent, View view, int position, long id)
  35.                         {
  36.                                 String number = infos.get(position).getPhone();
  37.                                 Intent intent = new Intent();
  38.                                 intent.putExtra("number", number);
  39.                                 //把要返回的數據設置進去,便通過onActivityResult(int, int, Intent)拿到
  40.                                 setResult(1, intent);
  41.                                 finish();
  42.                         }
  43.                 });
  44.         }
  45.         
  46.         //=================================================================================
  47.         
  48.         private class SelectContactAdapter extends BaseAdapter
  49.         {

  50.                 @Override
  51.                 public int getCount()
  52.                 {
  53.                         return infos.size();
  54.                 }

  55.                 @Override
  56.                 public Object getItem(int position)
  57.                 {
  58.                         return infos.get(position);
  59.                 }

  60.                 @Override
  61.                 public long getItemId(int position)
  62.                 {
  63.                         return position;
  64.                 }

  65.                 @Override
  66.                 public View getView(int position, View convertView, ViewGroup parent)
  67.                 {
  68.                         ContactInfo info = infos.get(position);
  69.                         View view;
  70.                         ContactViews views;
  71.                         if(convertView == null)
  72.                         {
  73.                                 views = new ContactViews();
  74.                                 view = View.inflate(SelectContactActivity.this, R.layout.contact_item, null);
  75.                                 views.tv_name = (TextView) view.findViewById(R.id.tv_contact_name);
  76.                                 views.tv_number = (TextView) view.findViewById(R.id.tv_contact_number);
  77.                                 views.tv_name.setText("聯係人:" + info.getName());
  78.                                 views.tv_number.setText("聯係電話:" + info.getPhone());
  79.                                 
  80.                                 view.setTag(views);
  81.                         }
  82.                         else
  83.                         {
  84.                                 view = convertView;
  85.                         }
  86.                         return view;
  87.                 }
  88.                 
  89.         }
  90.         
  91.         private class ContactViews
  92.         {
  93.                 TextView tv_name;
  94.                 TextView tv_number;
  95.         }

  96. }
複製代碼
這個類是非常簡單的,隻有一個listView大家也可以看到,這個類裏麵有一個adapter,這個是為了方便,所以寫在裏麵的,而且那個listview我們也用到了上一次的優化方法如果有什麼不了解的,可以回去看一下我們前麵的那個Android項目實戰--手機衛士06--GridView的優化與修改Button的顯示樣式好啦,下麵是activity的布局文件,還有listview的布局文件select_contact.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:andro
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     android:background="@android:color/white"
  6.     android:orientation="vertical" >
  7.     
  8.     <ListView 
  9.         android:
  10.         android:layout_width="match_parent"
  11.         android:layout_height="match_parent" />

  12. </LinearLayout>
複製代碼
contact_item.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:andro
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     android:orientation="vertical" >
  6.     
  7.     <TextView 
  8.         android:
  9.         android:layout_width="match_parent"
  10.         android:layout_height="wrap_content"/>
  11.     
  12.     <TextView 
  13.         android:
  14.         android:layout_width="match_parent"
  15.         android:layout_height="wrap_content"/>

  16. </LinearLayout>
複製代碼
好啦,獲取聯係人的操作,我們也差不多完成的啦,現在還要加上兩個權限
  1.     <uses-permission android:name="android.permission.READ_CONTACTS" />
  2.     <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
複製代碼
到現在為止,獲取聯係人的操作就完成的啦,因為之前都是清一色的切換效果,所以我現寫多了兩個切換效果,大家可以看看,也是很簡單的至於怎麼寫那些效果,那就要看一下我們的前一篇文章啦translate_in.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <translate xmlns:andro
  3.     android:fromXDelta="100%p"
  4.     android:toXDelta="0"
  5.     android:duration="400" >
  6.     <!-- 100%p是指從看不到的地方進入到0這個地方 -->

  7. </translate>
複製代碼
translate_out.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <translate xmlns:andro
  3.     android:fromXDelta="0"
  4.     android:toXDelta="-100%p"
  5.     android:duration="400" >
  6.     <!-- 100%p是指從看不到的地方進入到0這個地方 -->

  7. </translate>
複製代碼
好啦,今天要說的基本上已經說完的啦如果有什麼不明白的,或有什麼指導的,歡迎留言  Security_08獲取手機聯係人.rar (641.15 KB, 下載次數: 116) 
2013-10-9 15:24 上傳
點擊文件名下載附件 
下載積分: 下載豆 -2



這裏是快速回複,趕緊試試哦

我知道了
   
 
   

該用戶從未簽到

0

主題

171

帖子

3341

積分

Android伯爵

積分
3341
沙發
 發表於 2013-10-9 22:08:37 | 隻看該作者
看了樓主的帖子,如沐春風






 
 
   

該用戶從未簽到

0

主題

16

帖子

46

積分

Android感染者

積分
46
地板
 發表於 2013-10-10 13:33:13 | 隻看該作者
上限是多少呢
 
 
   
TA的每日心情
難過
2013-10-12 14:19

簽到天數: 1 天

連續簽到: 1 天

[LV.1]初來乍到

0

主題

8

帖子

18

積分

Android感染者

菜鳥

積分
18

社區QQ達人

6#
 發表於 2013-10-12 14:13:36 | 隻看該作者
這東西真好
 
 
   
TA的每日心情
開心
昨天 10:21

簽到天數: 35 天

連續簽到: 2 天

[LV.5]常住居民I

1

主題

237

帖子

567

積分

Android男爵

積分
567
7#
 發表於 2013-10-13 09:58:08 | 隻看該作者
xue xi xue xi
 
 
   

該用戶從未簽到

0

主題

16

帖子

46

積分

Android感染者

積分
46
9#
 發表於 2013-10-14 09:58:55 | 隻看該作者
簡單的實現
 
 
   
{:6_160:} {:6_158:} {:6_157:} 最後更新:2017-04-03 14:54:25

  上一篇:go Java類集--Iterator接口、ListIterator接口、foreach及Enumeration接口
  下一篇:go 鎵嬫満鍗+07-璁劇疆鍚戝-鍗氬-浜戞爾紺懼尯-闃塊噷浜?