در قسمت چهارم آموزش اندروید مبحث Content Provider ها یا تامین کننده محتوی را آموزش میدهیم.اگر بخواهیم تعریف کوتاهی برای این مبحث در نظر بگیریم میتوان گفت مانند یک پایگاه داده است که میتوان اطلاعات یک برنامه را درآنجا متمرکز کرده و چهار عمل اصلی را برروی آن انجام داد.
مبحث دیگر در بانک اطلاعاتی نحوه به اشتراک گذاری اطلاعات است چون تنها برنامه ای که بانک را ایجاد کرده اجازه دسترسی به بانک را دارد. به همین دلیل برنامه نویسان از تکنیکی به نام تامین کننده محتوی استفاده میکنند.میتوان گفت تامین کننده محتوی درواقع شبیه به یک منبع اطلاعاتی است و ذخیره سازی اطلاعات ربطی به نحوه استفاده و استفاده کننده ندارد.
چیزی که اینجا اهمیت پیدا میکند نحوه دسترسی برنامه های مختلف به تامین کننده محتوی است.تامین کننده محتوی شباهت زیادی به بانک اطلاعاتی دارد چرا که میتوان از آن اطلاعات را دریافت وحتی اقداماتی چون ویرایش و حذف و اضافه را نیز انجام داد.
اندروید خود دارای چندین تامین کننده محتوی پیش فرض میباشد مانند:
علاوه بر تامین کننده های خود اندروید میتوانید خود یک تامین کننده ایجاد کنید.
نحوه فراخوانی یا آدرس دهی نیز بسیار مهم است که به صورت زیر نوشته میشود
<standard_prefix>://<authority>/<data_path>/<id>
پروژه جدیدی با نام دلخواه ایجاد میکنیم و در فایل xml آن تنها یک TextView به صورت زیر ایجاد میکنیم
<TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="127dp" android:gravity="center" android:text="TextView" />
حال در فایل جاوا برنامه نیز چنین کدنویسی میکنیم
package com.example.contentproviderprj; import android.app.Activity; import android.content.ContentResolver; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.provider.ContactsContract; import android.support.v4.content.CursorLoader; import android.widget.TextView; public class MainActivity extends Activity { TextView txt; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); txt=(TextView)findViewById(R.id.textView1); fetchcontacts(); } public void fetchcontacts() { String phonenum=null; String email=null; Uri CONTENT_URI=ContactsContract.Contacts.CONTENT_URI; String _ID=ContactsContract.Contacts._ID; String DISPLAY_NAME=ContactsContract.Contacts.DISPLAY_NAME; String HAS_PHONE_NUM=ContactsContract.Contacts.HAS_PHONE_NUMBER; Uri PhoneCONTENT_URI=ContactsContract.CommonDataKinds.Phone.CONTENT_URI; String PhoneCONTACT_ID=ContactsContract.CommonDataKinds.Phone.CONTACT_ID; String NUMBER=ContactsContract.CommonDataKinds.Phone.NUMBER; Uri EmailCONTENT_URI=ContactsContract.CommonDataKinds.Email.CONTENT_URI; String EmailCONTACT_ID=ContactsContract.CommonDataKinds.Email.CONTACT_ID; String DATA=ContactsContract.CommonDataKinds.Email.DATA; StringBuffer output=new StringBuffer(); ContentResolver cr=getContentResolver(); Cursor cursor=cr.query(CONTENT_URI, null, null, null,null); //loop for every contact in the phone if(cursor.getCount() > 0){ while(cursor.moveToNext()){ String contact_id=cursor.getString(cursor.getColumnIndex(_ID)); String name=cursor.getString(cursor.getColumnIndex(DISPLAY_NAME)); int hasphonenum= Integer.parseInt(cursor.getString(cursor.getColumnIndex(HAS_PHONE_NUM))); if(hasphonenum > 0){ output.append("\n First Name:" + name); //query and loop for every phone number of contact Cursor phonecr=cr.query(PhoneCONTENT_URI, null, PhoneCONTACT_ID + " =?", new String[] {contact_id}, null); while(phonecr.moveToNext()){ phonenum= phonecr.getString(phonecr.getColumnIndex(NUMBER)); output.append("\n Phone number : " + phonenum); } phonecr.close(); //query and loop for every email of the contact Cursor emailcr=cr.query( EmailCONTENT_URI, null, EmailCONTACT_ID + " =?", new String[] {contact_id}, null); while(emailcr.moveToNext()){ email =emailcr.getString(emailcr.getColumnIndex(DATA)); output.append("\n Email : " + email); } emailcr.close(); } output.append("\n"); } txt.setText(output); } } }
دستورات فایل جاوا را اگربخواهیم قابل فهم تر کنیم میتوان گفت در onCreate برنامه که هنگام ایجاد برنامه فراخوانی میشود متد fetchconacts راصدا زدیم و خارج از بلاک onCreate آن را تعریف کرده ایم.
درون این متد ابتدا دو متغیر phonenum و email را تعریف میکنیم که در ادامه برای مقداردهی شماره و ایمیلی که از conacts استخراج میشود استفاده خواهیم کرد. وهمچنین شی CONTACT_URI که آدرس Contacts را درون خود جا داده ب استفاده از ثابت های از پیش تعریف شده نکته قابل توجه این است که عبارت ContactsContract.Contacts.CONTENT_URI برابر با مقدار content://contacts/people است اما در اندروید ۲ به بعد از ثابت ها بجای آدرس دهی دستی استفاده میشود. مقدار CONTACT_URI از نوع URI است چون در واقع یک آدرس Uri را برمیگرداند در حالی که مقادیر ID , DISPLAY_NAME , HAS_PHONE_NUM چون مقادیر شماره و نام و ای دی را برمیگردانند از نوع رشته ای است.
</span></p> String phonenum=null; String email=null; Uri CONTENT_URI=ContactsContract.Contacts.CONTENT_URI; String _ID=ContactsContract.Contacts._ID; String DISPLAY_NAME=ContactsContract.Contacts.DISPLAY_NAME; String HAS_PHONE_NUM=ContactsContract.Contacts.HAS_PHONE_NUMBER;
*برای تامین کننده های توکار دیگر نیز به صورت زیر مینویسیم
در ادامه برای شماره تلفن و ایمیل نیز به همین صورت متغیر هارا تعریف میکنیم.
سپس Buffer و CuntentResolver را بصورت زیر تعریف میکنیم.Buffer همانطور که قبلا بارها درباره اش گفته ایم به عنوان ظرفی برای نگهداری نتایج عمل میکند تا در انتها این نتایج را در محلی نمایش دهد.ContentResolver نیز میتوان گفت اجرا کننده ContentProvider ها میباشد و دستورات را بااستفاده از متد query این شی به تامین کننده محتوی اعمال میکنیم.
StringBuffer output=new StringBuffer(); ContentResolver cr=getContentResolver(); Cursor cursor=cr.query(CONTENT_URI, null, null, null,null);
Cursor یا اشاره گر نیز شامل نتیجه کوری خواهد بود. شکل کلی متد query بصورت زیر است
>query(uri, projection, selection, selectionArgs, sortOrder)
پارامترهای این متد نیز به شرح زیر است :
Uri : مقدار URI مربوط به دستورات است.
Projection : مشخص کننده ستون هایی است که باید استخراج شود.
Selection , selectionArgs : با استفاده از این دو آرگومان میتوان از دستور where استفاده کرد و شرطی لحاظ کرد و selectionArgs نیز مقداری است که در شرط باید در نظر گرفته شود.
setOrder :آخرین آرگومان نیز مربوط به مرتب سازی است.
سپس مقدار cursor را چک میکند و درصورتی که مخاطبی وجود داشت بااستفاده از دستور while تازمانی که به انتها مخاطبین برسد مقادیر ای دی و نام و شماره را درون متغیر ها قرار میدهد.
if(cursor.getCount() > 0){ while(cursor.moveToNext()){ String contact_id=cursor.getString(cursor.getColumnIndex(_ID)); String name=cursor.getString(cursor.getColumnIndex(DISPLAY_NAME)); int hasphonenum= Integer.parseInt(cursor.getString(cursor.getColumnIndex(HAS_PHONE_NUM)));
و در ادامه اگر تعداد شماره موبایل ها بیش از ۰ بود آنگاه مقدار نام ثبت شده را درون متغیر buffer قرار میدهد و با استفاده از یک کوری دیگر که اینبار Uri مروبط به Phone و شرطی که براساس contact_id اداره میشود مقادیر شماره تلفن های مربوط به هرای دی را استخراج کرده و درون متغیر phonecr قرار میدهد در ادامه با شرط while شماره تلفن های هر آیدی را در شی بافر قرار میدهد.
<pre class="lang:default decode:true">if(hasphonenum > 0){ output.append("\n First Name:" + name); //query and loop for every phone number of contact Cursor phonecr=cr.query(PhoneCONTENT_URI, null, PhoneCONTACT_ID + " =?", new String[] {contact_id}, null); while(phonecr.moveToNext()){ phonenum= phonecr.getString(phonecr.getColumnIndex(NUMBER)); output.append("\n Phone number : " + phonenum); } phonecr.close();
برای آیتم ایمیل نیز به همین صورت کدنویسی میکنیم و در انتها نیز شی بافر را درون TextView خود قرار میدهیم.
txt.setText(output);
حال وارد شبیه ساز خود شده و ابتدا چند contact وارد دستگاه کنید سپس برنامه را اجرا کنید و نتیجه را به صورت زیر ببینید