首先,我把把昨天忘记了的两张设置向导的图片放出来先
我们从上面的第一张图片可以看到,我们有一个选择联系人这一操作,那么怎样才能获取到手机里面的联系人呢,其实方法有很多的,现在我们来讲一下我们这个项目里面用到的方法
其实要想知道怎样获取手机里面的联系人,去看一下Android自己的源码就知道的了
我们只要把platform/packages/providers/ContactsProvider这一部分的内容下载下来看看就可以的啦
下面是我下载之后,打开里面的AndroidManifest的内容
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.providers.contacts"
- android:sharedUserId="android.uid.shared"
- android:sharedUserLabel="@string/sharedUserLabel">
- <permission
- android:name="com.android.voicemail.permission.READ_WRITE_ALL_VOICEMAIL"
- android:label="@string/read_write_all_voicemail_label"
- android:description="@string/read_write_all_voicemail_description"
- android:permissionGroup="android.permission-group.PERSONAL_INFO"
- android:protectionLevel="signature"
- />
- <uses-permission android:name="android.permission.READ_CONTACTS" />
- <uses-permission android:name="android.permission.WRITE_CONTACTS" />
- <uses-permission android:name="android.permission.GET_ACCOUNTS" />
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
- <uses-permission android:name="android.permission.BIND_DIRECTORY_SEARCH" />
- <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
- <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
- <uses-permission android:name="com.android.voicemail.permission.ADD_VOICEMAIL" />
- <uses-permission android:name="com.android.voicemail.permission.READ_WRITE_ALL_VOICEMAIL" />
- <application android:process="android.process.acore"
- android:label="@string/app_label"
- android:icon="@drawable/app_icon"
- android:allowBackup="false">
- <provider android:name="ContactsProvider2"
- android:authorities="contacts;com.android.contacts"
- android:label="@string/provider_label"
- android:multiprocess="false"
- android:exported="true"
- android:readPermission="android.permission.READ_CONTACTS"
- android:writePermission="android.permission.WRITE_CONTACTS">
- <path-permission
- android:pathPrefix="/search_suggest_query"
- android:readPermission="android.permission.GLOBAL_SEARCH" />
- <path-permission
- android:pathPrefix="/search_suggest_shortcut"
- android:readPermission="android.permission.GLOBAL_SEARCH" />
- <path-permission
- android:pathPattern="/contacts/.*/photo"
- android:readPermission="android.permission.GLOBAL_SEARCH" />
- <grant-uri-permission android:pathPattern=".*" />
- </provider>
- <provider android:name="CallLogProvider"
- android:authorities="call_log"
- android:syncable="false" android:multiprocess="false"
- android:exported="true"
- android:readPermission="android.permission.READ_CALL_LOG"
- android:writePermission="android.permission.WRITE_CALL_LOG">
- </provider>
- <provider android:name="VoicemailContentProvider"
- android:authorities="com.android.voicemail"
- android:syncable="false" android:multiprocess="false"
- android:exported="true"
- android:permission="com.android.voicemail.permission.ADD_VOICEMAIL">
- </provider>
- <!-- Handles database upgrades after OTAs, then disables itself -->
- <receiver android:name="ContactsUpgradeReceiver">
- <!-- This broadcast is sent after the core system has finished
- booting, before the home app is launched or BOOT_COMPLETED
- is sent. -->
- <intent-filter>
- <action android:name="android.intent.action.PRE_BOOT_COMPLETED"/>
- </intent-filter>
- </receiver>
- <receiver android:name="PackageIntentReceiver">
- <intent-filter>
- <action android:name="android.intent.action.PACKAGE_ADDED" />
- <data android:scheme="package" />
- </intent-filter>
- <intent-filter>
- <action android:name="android.intent.action.PACKAGE_REPLACED" />
- <data android:scheme="package" />
- </intent-filter>
- <intent-filter>
- <action android:name="android.intent.action.PACKAGE_REMOVED" />
- <data android:scheme="package" />
- </intent-filter>
- <intent-filter>
- <action android:name="android.intent.action.PACKAGE_CHANGED" />
- <data android:scheme="package" />
- </intent-filter>
- </receiver>
- <receiver android:name="LocaleChangeReceiver">
- <intent-filter>
- <action android:name="android.intent.action.LOCALE_CHANGED"/>
- </intent-filter>
- </receiver>
- <service android:name="VoicemailCleanupService"/>
- <activity android:name=".debug.ContactsDumpActivity"
- android:label="@string/debug_dump_title"
- android:theme="@android:style/Theme.Holo.Dialog"
- >
- <intent-filter>
- <action android:name="com.android.providers.contacts.DUMP_DATABASE"/>
- <category android:name="android.intent.category.DEFAULT"/>
- </intent-filter>
- </activity>
- <provider android:name=".debug.DumpFileProvider"
- android:authorities="com.android.contacts.dumpfile"
- android:exported="true">
- </provider>
- </application>
- </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
- package com.xiaobin.security.domain;
- public class ContactInfo
- {
- private String name;
- private String phone;
-
- public String getName()
- {
- return name;
- }
- public void setName(String name)
- {
- this.name = name;
- }
- public String getPhone()
- {
- return phone;
- }
- public void setPhone(String phone)
- {
- this.phone = phone;
- }
-
- }
复制代码
然后呢,我们就可以写我们获得手机联系人的代码啦新建一个类com.xiaobin.security.engine.ContactInfoService
- package com.xiaobin.security.engine;
- import java.util.ArrayList;
- import java.util.List;
- import android.content.ContentResolver;
- import android.content.Context;
- import android.database.Cursor;
- import android.net.Uri;
- import com.xiaobin.security.domain.ContactInfo;
- public class ContactInfoService
- {
- private Context context;
-
- public ContactInfoService(Context context)
- {
- this.context = context;
- }
-
- public List<ContactInfo> getContactInfos()
- {
- List<ContactInfo> infos = new ArrayList<ContactInfo>();
- ContactInfo info;
-
- ContentResolver contentResolver = context.getContentResolver();
- //在源码的AndroidManifest里面可以看到这些uri
- Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
- Uri dataUri = Uri.parse("content://com.android.contacts/data");
- Cursor cursor = contentResolver.query(uri, null, null, null, null);
- while(cursor.moveToNext())
- {
- info = new ContactInfo();
- String id = cursor.getString(cursor.getColumnIndex("_id"));
- String name = cursor.getString(cursor.getColumnIndex("display_name"));
- info.setName(name);
- //通过raw_contacts里面的id拿到data里面对应的数据
- Cursor dataCursor = contentResolver.query(dataUri, null, "raw_contact_id = ? ", new String[] {id}, null);
- while(dataCursor.moveToNext())
- {
- String type = dataCursor.getString(dataCursor.getColumnIndex("mimetype"));
- //根据类型,只要电话这种类型的数据
- if(type.equals("vnd.android.cursor.item/phone_v2"))
- {
- String number = dataCursor.getString(dataCursor.getColumnIndex("data1"));//拿到数据
- info.setPhone(number);
- }
- }
- dataCursor.close();
- infos.add(info);
- info = null;
- }
- cursor.close();
- return infos;
- }
- }
复制代码
因为我们是点击按钮,然后打开一个activity,然后选择好了之后,再把值返回到原来的activity那里的,所以我们就要用到startActivityForResult这个方法啦好,我们来看一下setup_guide3这个向导页面的逻辑是怎样写的com.xiaobin.security.ui.SetupGuide3Activity
- package com.xiaobin.security.ui;
- import android.app.Activity;
- import android.content.Context;
- import android.content.Intent;
- import android.content.SharedPreferences;
- import android.content.SharedPreferences.Editor;
- import android.os.Bundle;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.Toast;
- import com.xiaobin.security.R;
- public class SetupGuide3Activity extends Activity implements OnClickListener
- {
- private Button bt_next;
- private Button bt_pervious;
- private Button bt_select;
- private EditText et_phoneNumber;
- private SharedPreferences sp;
-
- @Override
- protected void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.setup_guide3);
-
- sp = getSharedPreferences("config", Context.MODE_PRIVATE);
-
- bt_next = (Button) findViewById(R.id.bt_guide_next);
- bt_pervious = (Button) findViewById(R.id.bt_guide_pervious);
- bt_select = (Button) findViewById(R.id.bt_guide_select);
- bt_next.setOnClickListener(this);
- bt_pervious.setOnClickListener(this);
- bt_select.setOnClickListener(this);
-
- et_phoneNumber = (EditText) findViewById(R.id.et_guide_phoneNumber);
- }
-
- //重写这个方法,从acitivty里面拿到数据
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data)
- {
- super.onActivityResult(requestCode, resultCode, data);
- //resultCode是乃至区分拿到的activity是从那一个activity里面拿到的
-
- if(data != null)
- {
- String number = data.getStringExtra("number");
- et_phoneNumber.setText(number);
- }
- }
- @Override
- public void onClick(View v)
- {
- switch(v.getId())
- {
- case R.id.bt_guide_select :
- Intent selectIntent = new Intent(this, SelectContactActivity.class);
- //启动一个activity来获取数据,获取到的数据是在重写的onActivityResult这个方法里面拿到的
- startActivityForResult(selectIntent, 1);
- break;
-
- case R.id.bt_guide_next :
- String number = et_phoneNumber.getText().toString().trim();
- if(number.equals(""))
- {
- Toast.makeText(this, "安全号码不能为空", Toast.LENGTH_SHORT).show();
- }
- else
- {
- Editor editor = sp.edit();
- editor.putString("number", number);
- editor.commit();
-
- Intent intent = new Intent(this, SetupGuide4Activity.class);
- finish();
- startActivity(intent);
- //这个是定义activity切换时的动画效果的
- overridePendingTransition(R.anim.translate_in, R.anim.translate_out);
- }
- break;
- case R.id.bt_guide_pervious :
-
- Intent i = new Intent(this, SetupGuide2Activity.class);
- finish();
- startActivity(i);
- //这个是定义activity切换时的动画效果的
- overridePendingTransition(R.anim.alpha_in, R.anim.alpha_out);
- break;
-
- default :
- break;
- }
- }
- }
复制代码
我们还要新建一个类用来做为选择的呢com.xiaobin.security.ui.SelectContactActivity
- package com.xiaobin.security.ui;
- import java.util.List;
- import android.app.Activity;
- import android.content.Intent;
- import android.os.Bundle;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.AdapterView;
- import android.widget.AdapterView.OnItemClickListener;
- import android.widget.BaseAdapter;
- import android.widget.ListView;
- import android.widget.TextView;
- import com.xiaobin.security.R;
- import com.xiaobin.security.domain.ContactInfo;
- import com.xiaobin.security.engine.ContactInfoService;
- public class SelectContactActivity extends Activity
- {
- private ListView lv;
- private List<ContactInfo> infos;
-
- @Override
- protected void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.select_contact);
-
- infos = new ContactInfoService(this).getContactInfos();
-
- lv = (ListView) findViewById(R.id.lv_select_contact);
- lv.setAdapter(new SelectContactAdapter());
- lv.setOnItemClickListener(new OnItemClickListener()
- {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id)
- {
- String number = infos.get(position).getPhone();
- Intent intent = new Intent();
- intent.putExtra("number", number);
- //把要返回的数据设置进去,便通过onActivityResult(int, int, Intent)拿到
- setResult(1, intent);
- finish();
- }
- });
- }
-
- //=================================================================================
-
- private class SelectContactAdapter extends BaseAdapter
- {
- @Override
- public int getCount()
- {
- return infos.size();
- }
- @Override
- public Object getItem(int position)
- {
- return infos.get(position);
- }
- @Override
- public long getItemId(int position)
- {
- return position;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent)
- {
- ContactInfo info = infos.get(position);
- View view;
- ContactViews views;
- if(convertView == null)
- {
- views = new ContactViews();
- view = View.inflate(SelectContactActivity.this, R.layout.contact_item, null);
- views.tv_name = (TextView) view.findViewById(R.id.tv_contact_name);
- views.tv_number = (TextView) view.findViewById(R.id.tv_contact_number);
- views.tv_name.setText("联系人:" + info.getName());
- views.tv_number.setText("联系电话:" + info.getPhone());
-
- view.setTag(views);
- }
- else
- {
- view = convertView;
- }
- return view;
- }
-
- }
-
- private class ContactViews
- {
- TextView tv_name;
- TextView tv_number;
- }
- }
复制代码
这个类是非常简单的,只有一个listView大家也可以看到,这个类里面有一个adapter,这个是为了方便,所以写在里面的,而且那个listview我们也用到了上一次的优化方法如果有什么不了解的,可以回去看一下我们前面的那个Android项目实战--手机卫士06--GridView的优化与修改Button的显示样式好啦,下面是activity的布局文件,还有listview的布局文件select_contact.xml
- <?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:background="@android:color/white"
- android:orientation="vertical" >
-
- <ListView
- android:id="@+id/lv_select_contact"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
- </LinearLayout>
复制代码
contact_item.xml
- <?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" >
-
- <TextView
- android:id="@+id/tv_contact_name"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
-
- <TextView
- android:id="@+id/tv_contact_number"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
- </LinearLayout>
复制代码
好啦,获取联系人的操作,我们也差不多完成的啦,现在还要加上两个权限
- <uses-permission android:name="android.permission.READ_CONTACTS" />
- <uses-permission android:name="android.permission.WRITE_CONTACTS"/>
复制代码
到现在为止,获取联系人的操作就完成的啦,因为之前都是清一色的切换效果,所以我现写多了两个切换效果,大家可以看看,也是很简单的至于怎么写那些效果,那就要看一下我们的前一篇文章啦translate_in.xml
- <?xml version="1.0" encoding="utf-8"?>
- <translate xmlns:android="http://schemas.android.com/apk/res/android"
- android:fromXDelta="100%p"
- android:toXDelta="0"
- android:duration="400" >
- <!-- 100%p是指从看不到的地方进入到0这个地方 -->
- </translate>
复制代码
translate_out.xml
- <?xml version="1.0" encoding="utf-8"?>
- <translate xmlns:android="http://schemas.android.com/apk/res/android"
- android:fromXDelta="0"
- android:toXDelta="-100%p"
- android:duration="400" >
- <!-- 100%p是指从看不到的地方进入到0这个地方 -->
- </translate>
复制代码
好啦,今天要说的基本上已经说完的啦如果有什么不明白的,或有什么指导的,欢迎留言 Security_08获取手机联系人.rar (641.15
KB, 下载次数: 116)
2013-10-9 15:24 上传
点击文件名下载附件
下载积分: 下载豆 -2
|