Android笔记----Android手势和ContentProvider
来源:互联网 发布:阿里二手域名 编辑:程序博客网 时间:2024/06/14 06:04
手势(Gesture)
ContentProvider简介
操作系统的ContentProvider
实现ContentProvider
监听ContentProvider的数据改变
手势(Gesture)
所谓手势,指用户手指或触摸笔在触摸屏上的连续触碰行为。手势这种连续的触碰会形成某个方向上的移动趋势,也会形成一个不规则的几何图形。
Android对两种手势行为都提供了支持:
第一种手势行为而言,Android提供了手势检测,并为手势提供相应的监听器。
对于第二种手势行为,Android允许开发者添加手势,并提供相应的API。
1.1 手势检测
GestureDetector是一个手势检测器,创建GestureDetector时需要传入一个GestureDetector.OnGestureListener实例, 负责对用户的手势行为提供响应。GestureDetector包含的事件处理方法如下:
boolean onDown(MotionEvent e):当触碰事件按下时触发该方法。
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) :在触摸屏上拖过时触发该方法。
void onLongPress(MotionEvent e):当用户在屏幕上长按时触发该方法。
boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY):当用户在屏幕上”滚动”时触发该方法。
void onShowPress(MotionEvent e) :当用户在触摸屏上按下、而且还未移动和松开时触发该方法。
boolean onSingleTapConfirmed(MotionEvent e)
boolean onSingleTapUp(MotionEvent e):用户在屏幕上的轻击事件将会触发该方法。
使用Android手势检测只需要两个步骤:
创建一个GestureDetector对象,创建该对象时必须实现GestureDetector.OnGestureListener监听器实例。
为应用程序的Activity的TouchEvent事件绑定监听器,在事件处理中指定把Activity上的TouchEvent事件交给GestureDetector处理。
例:手势动作测试:
手势动作测试
GestureTest.java
public class GestureTest extends Activityimplements OnGestureListener{// 定义手势检测器实例GestureDetector detector;@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);//创建手势检测器detector = new GestureDetector(this);}//将该Activity上的触碰事件交给GestureDetector处理@Overridepublic boolean onTouchEvent(MotionEvent me){return detector.onTouchEvent(me);}@Overridepublic boolean onDown(MotionEvent arg0){Toast.makeText(this,"onDown" , 8000).show();return false;}@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY){Toast.makeText(this , "onFling" , 8000).show();return false;}@Overridepublic void onLongPress(MotionEvent e){Toast.makeText(this ,"onLongPress" , 8000).show();}@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,float distanceY){Toast.makeText(this ,"onScroll" , 8000).show();return false;}@Overridepublic void onShowPress(MotionEvent e){Toast.makeText(this ,"onShowPress" , 8000).show();}@Overridepublic boolean onSingleTapUp(MotionEvent e){Toast.makeText(this ,"onSingleTapUp" , 8000).show();return false;}}
例:手势实现翻页效果:
GestureFlip.java
public class GestureFlip extends Activityimplements OnGestureListener{// ViewFlipper实例ViewFlipper flipper;// 定义手势检测器实例GestureDetector detector;//定义一个动画数组,用于为ViewFlipper指定切换动画效果Animation[] animations = new Animation[4];//定义手势动作两点之间的最小距离final int FLIP_DISTANCE = 50;@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);//创建手势检测器detector = new GestureDetector(this);// 获得ViewFlipper实例flipper = (ViewFlipper) this.findViewById(R.id.flipper);// 为ViewFlipper添加5个ImageView组件flipper.addView(addImageView(R.drawable.java));flipper.addView(addImageView(R.drawable.ee));flipper.addView(addImageView(R.drawable.ajax));flipper.addView(addImageView(R.drawable.xml));flipper.addView(addImageView(R.drawable.classic));//初始化Animation数组animations[0] = AnimationUtils.loadAnimation(this, R.anim.left_in);animations[1] = AnimationUtils.loadAnimation(this, R.anim.left_out);animations[2] = AnimationUtils.loadAnimation(this, R.anim.right_in);animations[3] = AnimationUtils.loadAnimation(this, R.anim.right_out);}// 定义添加ImageView的工具方法private View addImageView(int resId){ImageView imageView = new ImageView(this);imageView.setImageResource(resId);imageView.setScaleType(ImageView.ScaleType.CENTER);return imageView;}@Overridepublic boolean onFling(MotionEvent event1, MotionEvent event2,float velocityX, float velocityY){/* * 如果第一个触点事件的X座标大于第二个触点事件的X座标超过FLIP_DISTANCE * 也就是手势从右向左滑。 */if (event1.getX() - event2.getX() > FLIP_DISTANCE){// 为flipper设置切换的的动画效果flipper.setInAnimation(animations[0]);flipper.setOutAnimation(animations[1]);flipper.showPrevious();return true;}/* * 如果第二个触点事件的X座标大于第一个触点事件的X座标超过FLIP_DISTANCE * 也就是手势从右向左滑。 */else if (event2.getX() - event1.getX() > FLIP_DISTANCE){// 为flipper设置切换的的动画效果flipper.setInAnimation(animations[2]);flipper.setOutAnimation(animations[3]);flipper.showNext();return true;}return false;}@Overridepublic boolean onTouchEvent(MotionEvent event){//将该Activity上的触碰事件交给GestureDetector处理return detector.onTouchEvent(event);}@Overridepublic boolean onDown(MotionEvent arg0){return false;}@Overridepublic void onLongPress(MotionEvent event){}@Overridepublic boolean onScroll(MotionEvent event1, MotionEvent event2,float arg2, float arg3){return false;}@Overridepublic void onShowPress(MotionEvent event){}@Overridepublic boolean onSingleTapUp(MotionEvent event){return false;}}
Main.xm
<?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="fill_parent" android:orientation="vertical" > <!-- 定义ViewFlipper组件 --> <ViewFlipper android:id="@+id/flipper" android:layout_width="fill_parent" android:layout_height="fill_parent" /></LinearLayout>
1.2 增加手势
Android除了手势检测外,还允许应用程序把用户手势添加到指定文件,以备以后使用,如果程序需要,当用户下次再次画出该手势,系统将可识别该手势。
Android使用GestureLibrary来代表手势库,并提供GestureLibraries工具类来创建手势库,添加手势库的方法如下:
static GestureLibraryfromFile(File path):从path代表的文件中加载手势库。
static GestureLibraryfromFile(String path):从path代表的文件中加载手势库。
static GestureLibraryfromPrivateFile(Context context, String name):从指定的应用程序的数据文件中name文件中加载手势库。
static GestureLibraryfromRawResource(Context context, int resourceId):从resourceId所代表的资源中加载手势库。
一旦程序中获得了GestureLibrary对象后,该对象提供了如下方法来添加手势、识别手势。
例:增加手势:
AddGesture.java
public class AddGesture extends Activity{EditText editText;GestureOverlayView gestureView;@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);// 获取文本编辑框editText = (EditText) findViewById(R.id.gesture_name);// 获取手势编辑视图gestureView = (GestureOverlayView) findViewById(R.id.gesture);// 设置手势的绘制颜色gestureView.setGestureColor(Color.RED);// 设置手势的绘制宽度gestureView.setGestureStrokeWidth(4);// 为gesture的手势完成事件绑定事件监听器gestureView.addOnGesturePerformedListener(new OnGesturePerformedListener(){@Overridepublic void onGesturePerformed(GestureOverlayView overlay,final Gesture gesture){//加载save.xml界面布局代表的视图View saveDialog = getLayoutInflater().inflate(R.layout.save, null);// 获取saveDialog里的show组件ImageView imageView = (ImageView) saveDialog.findViewById(R.id.show);// 获取saveDialog里的gesture_name组件final EditText gestureName = (EditText) saveDialog.findViewById(R.id.gesture_name);// 根据Gesture包含的手势创建一个位图Bitmap bitmap = gesture.toBitmap(128, 128, 10, 0xFFFF0000);imageView.setImageBitmap(bitmap);//使用对话框显示saveDialog组件new AlertDialog.Builder(AddGesture.this).setView(saveDialog).setPositiveButton("保存", new OnClickListener(){@Overridepublic void onClick(DialogInterface dialog,int which){// 获取指定文件对应的手势库GestureLibrary gestureLib = GestureLibraries.fromFile("/sdcard/mygestures");// 添加手势gestureLib.addGesture(gestureName.getText().toString(),gesture);// 保存手势库gestureLib.save();}}).setNegativeButton("取消", null).show();}});}}
Main.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent"android:gravity="center_horizontal"><TextViewandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:text="请在下面屏幕上绘制手势"/><!-- 使用手势绘制组件 --><android.gesture.GestureOverlayViewandroid:id="@+id/gesture"android:layout_width="fill_parent"android:layout_height="fill_parent"android:gestureStrokeType="multiple" /></LinearLayout>
save.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent"><LinearLayoutandroid:orientation="horizontal"android:layout_width="fill_parent"android:layout_height="wrap_content"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginRight="8dip"android:text="@string/gesture_name" /><!-- 定义一个文本框来让用户输入手势名 --> <EditTextandroid:id="@+id/gesture_name"android:layout_width="fill_parent"android:layout_height="wrap_content"/></LinearLayout><!-- 定义一个图片框来显示手势 --> <ImageViewandroid:id="@+id/show"android:layout_width="128dp"android:layout_height="128dp"android:layout_marginTop="10dp" /></LinearLayout>
ContentProvider简介
为了在应用程序之间交换数据,Android提供了ContentProvider,它提供了不同应用程序之间交换数据的标准API,当一个应用程序需要把自己的数据暴露给其他应用程序使用时,该应用程序通过提供ContentProvider来实现其他应用程序可通过ContentResolver来操作ContentProvider暴露的数据。
ContentProvider是四大组件之一,也需要在AndroidManifest.xml文件中进行配置。
2.1共享数据标准: ContentProvider简介
ContentProvider提供了数据访问的接口,以某种Uri的形式对外提供数据,允许其他应用访问或修改数据;其他应用程序使用ContentResolver根据Uri去访问操作指定的数据。
开发一个ContentProvider的步骤如下:
定义ContentProvider类,该类需要继承ContentProvider基类。
在AndroidManifest.xml文件中配置该ContentProvider。
一个ContentProvider类除了继承ContentProvider基类外,还需要提供的方法如下:
onCreate():ContentProvider在其它应用第一次访问时才会被创建。
insert ():用于供外部应用往ContentProvider添加数据。
delete ():用于供外部应用从ContentProvider删除数据。
update():用于供外部应用更新ContentProvider中的数据
query():用于供外部应用从ContentProvider中获取数据。
对于ContentProvider而言,都是以Uri形式对外提供数据,Uri形如:
content://www.abc/words/2
content:这部分是Android所规定的。
com.boby.providers.dictprovider:这部分是ContentProvider的authority。
words:资源部分,当访问不同资源时,这部分是动态变化的。
2:ID部分
其他应用程序使用ContentResolver根据Uri去访问指定数据。可以通过getContentResolver()方法来获得该对象。获得ContentResolver对象后,就可以利用如下方法操作数据。
insert(Uri uri,ContentValues values):向Uri对应的ContentProvider中插入values对应的数据。
delete(Uri uri,String where, String[] selectionArgs):删除Uri对应的ContentProvider中where提交匹配的数据。
update(Uri uri,ContentValues values,String where, String[] selectionArgs):更新Uri对应的ContentProvider中where提交匹配的数据。
query (Uri uri,String[] projection,String selection, String[] selectionArgs,String sortOrder):查询Uri对应的ContentProvider中where提交匹配数据。
操作系统的ContentProvider
使用ContentResolver操作数据的步骤很简单如下所示:
调用Activity的getContentResolver()获取ContentResolver()对象。
根据需要调用ContentResolver的insert()、delete()、update()和query方法。
Android系统中提供了Contacts应用程序来管理联系人,而且Android系统中还为联系人管理提供了ContentProvider,这就允许其他应用程序ContentResolver来管理联系人数据。
Android系统对联系人管理ContentProvider的几个Uri如下:
ContactsContract.Contacts.CONTENT_URI:管理联系人的Uri。
ContactsContract.CommonDataKinds.Phone.CONTENT_URI:管理联系人电话的Uri。
ContactsContract.CommonDataKinds.Email.CONTENT_URI:管理联系人Email的Uri。
例:
ContactProviderTest.java
public class ContactProviderTest extends Activity{Button search;Button add;@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);// 获取系统界面中查找、添加两个按钮search = (Button) findViewById(R.id.search);add = (Button) findViewById(R.id.add);search.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View source){// 定义两个List来封装系统的联系人信息、指定联系人的电话号码、Email等详情final ArrayList<String> names = new ArrayList<String>();final ArrayList<ArrayList<String>> details= new ArrayList<ArrayList<String>>();// 使用ContentResolver查找联系人数据Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);// 遍历查询结果,获取系统中所有联系人while (cursor.moveToNext()){// 获取联系人IDString contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));// 获取联系人的名字String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));names.add(name);// 使用ContentResolver查找联系人的电话号码Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null, null);ArrayList<String> detail = new ArrayList<String>();// 遍历查询结果,获取该联系人的多个电话号码while (phones.moveToNext()){// 获取查询结果中电话号码列中数据。String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));detail.add("电话号码:" + phoneNumber); }phones.close();// 使用ContentResolver查找联系人的Email地址Cursor emails = getContentResolver().query(ContactsContract.CommonDataKinds.Email.CONTENT_URI,null,ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = " + contactId, null, null);// 遍历查询结果,获取该联系人的多个Email地址while (emails.moveToNext()){// 获取查询结果中Email地址列中数据。String emailAddress = emails.getString(emails.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA));detail.add("邮件地址:" + emailAddress); }emails.close();details.add(detail);}cursor.close();//加载result.xml界面布局代表的视图View resultDialog = getLayoutInflater().inflate(R.layout.result, null);// 获取resultDialog中ID为list的ExpandableListViewExpandableListView list = (ExpandableListView)resultDialog.findViewById(R.id.list);//创建一个ExpandableListAdapter对象ExpandableListAdapter adapter = new BaseExpandableListAdapter(){//获取指定组位置、指定子列表项处的子列表项数据@Overridepublic Object getChild(int groupPosition, int childPosition){return details.get(groupPosition).get(childPosition);}@Overridepublic long getChildId(int groupPosition, int childPosition){return childPosition;}@Overridepublic int getChildrenCount(int groupPosition){return details.get(groupPosition).size();}private TextView getTextView(){AbsListView.LayoutParams lp = new AbsListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, 64);TextView textView = new TextView(ContactProviderTest.this);textView.setLayoutParams(lp);textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);textView.setPadding(36, 0, 0, 0);textView.setTextSize(20);return textView;}// 该方法决定每个子选项的外观@Overridepublic View getChildView(int groupPosition, int childPosition,boolean isLastChild, View convertView, ViewGroup parent){TextView textView = getTextView();textView.setText(getChild(groupPosition, childPosition).toString());return textView;}//获取指定组位置处的组数据@Overridepublic Object getGroup(int groupPosition){return names.get(groupPosition);}@Overridepublic int getGroupCount(){return names.size();}@Overridepublic long getGroupId(int groupPosition){return groupPosition;}//该方法决定每个组选项的外观@Overridepublic View getGroupView(int groupPosition, boolean isExpanded,View convertView, ViewGroup parent){TextView textView = getTextView();textView.setText(getGroup(groupPosition).toString());return textView;}@Overridepublic boolean isChildSelectable(int groupPosition, int childPosition){return true;}@Overridepublic boolean hasStableIds(){return true;}};// 为ExpandableListView设置Adapter对象list.setAdapter(adapter);// 使用对话框来显示查询结果。new AlertDialog.Builder(ContactProviderTest.this).setView(resultDialog).setPositiveButton("确定" , null).show();}});// 为add按钮的单击事件绑定监听器add.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v){// 获取程序界面中的3个文本框String name = ((EditText)findViewById(R.id.name)).getText().toString();String phone = ((EditText)findViewById(R.id.phone)).getText().toString();String email = ((EditText)findViewById(R.id.email)).getText().toString();// 创建一个空的ContentValuesContentValues values = new ContentValues();// 向RawContacts.CONTENT_URI执行一个空值插入,// 目的是获取系统返回的rawContactId Uri rawContactUri = getContentResolver().insert(RawContacts.CONTENT_URI, values);long rawContactId = ContentUris.parseId(rawContactUri);values.clear();values.put(Data.RAW_CONTACT_ID, rawContactId); // 设置内容类型values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);// 设置联系人名字values.put(StructuredName.GIVEN_NAME, name);// 向联系人URI添加联系人名字getContentResolver().insert(android.provider.ContactsContract.Data.CONTENT_URI, values);values.clear();values.put(Data.RAW_CONTACT_ID, rawContactId);values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);// 设置联系人的电话号码values.put(Phone.NUMBER, phone);// 设置电话类型values.put(Phone.TYPE, Phone.TYPE_MOBILE);// 向联系人电话号码URI添加电话号码getContentResolver().insert(android.provider.ContactsContract.Data.CONTENT_URI, values);values.clear();values.put(Data.RAW_CONTACT_ID, rawContactId);values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);// 设置联系人的Email地址values.put(Email.DATA, email);// 设置该电子邮件的类型values.put(Email.TYPE, Email.TYPE_WORK);// 向联系人Email URI添加Email数据getContentResolver().insert(android.provider.ContactsContract.Data.CONTENT_URI, values);Toast.makeText(ContactProviderTest.this, "联系人数据添加成功" , 8000).show();}});}}
main.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent"><LinearLayout android:orientation="horizontal"android:layout_width="fill_parent"android:layout_height="wrap_content"android:gravity="center_horizontal"><Button android:id="@+id/search"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/search"/><Button android:id="@+id/add"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/add"/></LinearLayout><TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/name"/><EditTextandroid:id="@+id/name"android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/input"/><TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/phone"/><EditTextandroid:id="@+id/phone"android:layout_width="fill_parent" android:layout_height="wrap_content" android:phoneNumber="true"android:hint="@string/input"/><TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/email"/><EditTextandroid:id="@+id/email"android:layout_width="fill_parent" android:layout_height="wrap_content"android:hint="@string/input"/></LinearLayout>
result.xml
<?xml version="1.0" encoding="UTF-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent"><ExpandableListViewandroid:id="@+id/list"android:layout_width="fill_parent" android:layout_height="wrap_content" android:childIndicator="@drawable/icon"/></LinearLayout>
前面是如何使用ContentResolver来操作系统的ContentProvider提供的数据。下面介绍如何开发自己的ContentProvider。
4.1 创建ContentProvider的步骤:
开发一个ContentProvider子类,该子类需要实现增、删、改、查等方法。
在AndroidManifest.xml文件中注册该ContentProvider。
为了确定该ContentProvider实际能匹配的Uri,以及确定每个方法中Uri参数所操作的数据,Android系统中提供了UriMatcher工具类,提供了以下两个方法:
void addURI(String quthority,String path,int code):该方法用于向UriMatcher对象注册Uri。
int match(Uri uri):根据前面注册的Uri来判断指定Uri对应的标识码。
实现ContentProvider
Android还提供了ContentUris工具类,它是一个Uri字符串的工具类,它提供了如下两个工具方法。
withAppendedId(uri, id):用于为路径加上ID部分。
parseId(uri):用于从指定Uri中解析出所包含的ID值。
监听ContentProvider的数据改变
当ContentProvider将数据共享出来以后,ContentResolver会根据业务需要主动查询ContentProvider所共享数据;在有些时候,应用程序需要实时监听ContentProvider所共享数据的改变。并随着ContentProvider的数据改变而提供响应,这就需要利用ContentObserver了。
5.1 ContentObserver简介
ContentProvider 发生数据变化时,调用getContentResolver().notifyChange(uri, null)来通知注册在此URI上的访问者
访问者使用ContentObserver对数据(数据采用uri描述)进行监听,当监听到数据变化通知时,系统就会调用ContentObserver的onChange()方法 。
ContentResolver提供了如下方法来注册监听器:registerContentObserver(Uri uri,boolean notifyForDescendents , ContentObserver observer)
uri:该监听器所监听的ContentProvider的Uri。
notifyForDescendents:如果该参数设为true,假如注册监听的Uri为content://abc,那么Uri为content://abc/xyz的数据改变时也会触发该监听器。如果该参数设为false,只有content://abc的数据发生改变时会触发该监听器。
observer:监听器实例。
例:监听发出的短信:
MonitorSms.java
public class MonitorSms extends Activity{@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);//为content://sms的数据改变注册监听器getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, new SmsObserver(new Handler()));}// 提供自定义的ContentObserver监听器类private final class SmsObserver extends ContentObserver{public SmsObserver(Handler handler){super(handler);}public void onChange(boolean selfChange){// 查询发送箱中的短信(处于正在发送状态的短信放在发送箱)Cursor cursor = getContentResolver().query(Uri.parse("content://sms/outbox"), null, null, null, null);// 遍历查询得到的结果集,即可获取用户正在发送的短信while (cursor.moveToNext()){StringBuilder sb = new StringBuilder();// 获取短信的发送地址sb.append("address=").append(cursor.getString(cursor.getColumnIndex("address")));// 获取短信的标题sb.append(";subject=").append(cursor.getString(cursor.getColumnIndex("subject")));// 获取短信的内容sb.append(";body=").append(cursor.getString(cursor.getColumnIndex("body")));// 获取短信的发送时间sb.append(";time=").append(cursor.getLong(cursor.getColumnIndex("date")));System.out.println("Has Sent SMS:::" + sb.toString());}}}}
注意添加权限:
<!-- 授予读联系人ContentProvider的权限 --><uses-permission android:name="android.permission.READ_SMS"/>
- Android笔记----Android手势和ContentProvider
- Android课堂笔记—SQLite3和ContentProvider
- android学习笔记---contentProvider
- Android学习笔记-ContentProvider
- Android学习笔记ContentProvider
- Android学习笔记ContentProvider
- Android学习笔记ContentProvider
- Android ContentProvider和getContentResolver
- Android ContentProvider和getContentResolver
- Android ContentProvider和Uri
- android学习笔记之ContentProvider
- android学习笔记之ContentProvider
- Android学习笔记 ContentProvider (转)
- Android学习笔记----自定义ContentProvider
- android进阶:ContentProvider使用方法笔记
- Android学习笔记8---ContentProvider
- Android手势和shape
- Android学习笔记(十八)ContentProvider和Uri详解
- 线性表的链式存储
- Java 面试准备
- Android SDK下载异常(hostname in certificate didn't match)
- Java 面试准备[二]
- 判断当月一号是周几
- Android笔记----Android手势和ContentProvider
- 超实用PHP函数总结整理
- 《Android 4 高级编程》学习笔记
- 正则单行和多行处理
- 优化网站设计(二十二):避免404错误
- complex类
- android方向传感器(SENSOR_TYPE_ORIENTATION)
- iOS之UIStepper微调器的使用
- appium nodejs