Content Providers در اندروید
Content Provider یکی از قابلیت های جالب اندروید است که به یک برنامه اجازه می دهد تا داده های خود را با سایر برنامه های دیگر به اشتراگ بگذارد. یک Content Provider می تواند داده ها را به روش های مختلف از جمله فایل، دیتابیس و حتی روی شبکه ذخیره کند. گاهی اوقات لازم است تا داده ها را با برنامه مختلف به اشتراک بگذاریم. در این مواقع از Content Provider ها استفاده می شود.
Content Provider ها به شما اجازه می دهند تا محتوا را به شکل متمرکز در یک مکان ذخیره کنید تا در صورت نیاز به آن ها دسترسی داشته باشید. عملکر Content Provide ها بسیار شبیه به دیتابیس می باشد و می توانید عملیات های رایجی که بر روی دیتابیس انجام می دهید (پرس و جو، افزودن، حذف، ویرایش) را به راحتی و با استفاده از متدهای inserter، update، delete و query انجام دهید. در اکثر مواقع این داده های اشتراکی در دیتابیس SQLite نگه داری می شوند.
یک Content Provider از کلاس اصلی ContentProvider مشتق می شود و باید یک مجموعه استاندارد از PAPI ها را پیاده سازی کند تا سایر برنامه ها قادر به استفاده از داده های اشتراکی باشند.
1 2 3 | public class My Application extends ContentProvider { } |
آدرس محتوا (Content URLs)
به منظور دسترسی به داده هایی که یک Content Provider ارائه می کند، باید درخواست ها را در قالب یک URL و در فرمت زیر مشخص کرد:
1 | <prefix>://<authority>/<data_type>/<id> |
توضیح بخش های مختلف یک آدرس:
ردیف | توضیحات |
1 | prefix این بخش همیشه به صورت content:// تنظیم می شود. |
2 | authority این بخش نام Content Provider را مشخص می کند. برای مثال Contacts، Browser و غیره. بهتر است یک نام کامل مانند com.tutorialspoint.statusprovider برای آن تنظیم کنید. |
3 | data_type در این بخش از آدرس، نوع داده ای را که Content Provider ارائه می کند، مشخص می شود. برای نمونه، اگر شما بخواهید اطلاعات مخاطبین را توسط Content Provider دریافت کنید، باید از نوع people استفاده کنید که به صورت content://contacts/people می باشد. |
4 | id این بخش از آدرس id رکورد موجود در Content Provider را مشخص می کند. برای مثال زمانی که بخواهیم اطلاعات مربوط به مخاطب پنجم را دریافت کنیم، آدرس ما به صورت content://contacts/people/5 خواهد بود. |
ایجاد یک Content Provider
در زیر نحوه ایجاد یک Content Provider به صورت ساده توضیح داده شده است:
- اول از همه باید یک کلاس که از کلاس ContentProvider مشتق شده است، ایجاد کنید.
- در مرحله بعد باید آدرس دسترسی به Content Provider را طبق قالبی که در بخش بالا گفته شد، مشخص کنید.
- در محله بعد، باید داده ها را درون یک دیتابیس ذخیره کنید. اندروید معمولا از دیتابیس SQLite استفاده می کند.
- سپس باید توابع مختلفی که برای پرس و جو بر روی Content Provider لازم هستند را بازنویسی کنید.
- در نهایت Content Provider ایجاد شده را درون Activity مورد استفاده و درون تگ
معرفی می کنیم.
در زیر لیست توابعی که برای انجام عملیات های خاص باید باز نوشی شوند را مشاهده می کنید:
- onCreate() : این متد زمانی که Provider شروع شود، فراخوانی می شود.
- query() : این متد درخواست هایی که از طرف کلاینت می شود را دریافت می کند و به صورت یک شیء از نوع Cursor باز میگرداند.
- insert() : این متد به منظور افزودن یک رکورد جدید درون Content Provider استفاده می شود.
- delete() : این متد به منظور حذف یک رکورد موجود در Content Provider استفاده می شود.
- update() : این متد به منظور به روز رسانی یک رکورد موجود در Content Provider استفاده می شود.
- getType() : این تابع نوع داده ای را که از طریق آدرس بازگردانده می شود را مشخص می کند.
مثال
این مثال به شما نحوه ایجاد یک Content Provider را به صورت مرحله به مرحله توضیح می دهد.
مرحله | توضیحات |
1 | نرم افزار Android Studio را باز کرده و یک پروژه به صورت زیر ایجاد کنید: نام : My Application نام پکیج: com.example.MyApplication و یک Activity خالی |
2 | دو متد onClickAddName() و onClickRetrieveStudents() را به فایل MainActivity.java موجود در پروژه اضافه کنید. |
3 | یک فایل جدید با نام StudentsProvider.java و تحت پکیج com.example.MyApplication برای تعریف Content Provider و متدهای مربوط به آن ایجاد کنید. |
4 | Content Provider خود را با استفاده از تگ |
5 | محتوای پیش فرض فایل res/layout/activity_main.xml را برای ایجاد یک GUI کوچک تغییر دهید. |
6 | نیازی به تغییر فایل string.xml نیست. |
7 | برنامه را اجرا کنید تا شبیه ساز اندروید راه اندازی شود و نتیجه تغییرات ایجاد شده را مشاهده کنید. |
کد زیر محتوای تغییر یافته فایل src/com.example.MyApplication/MainActivity.java می باشد. ما دو متد onClickAddName و onClickRetrieveStudents را به منظور مدیریت تعاملات کاربر با برنامه به این فایل اضافه کرده ایم.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | package com.example.MyApplication; import android.net.Uri; import android.os.Bundle; import android.app.Activity; import android.content.ContentValues; import android.content.CursorLoader; import android.database.Cursor; import android.view.Menu; import android.view.View; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void onClickAddName(View view) { // Add a new student record ContentValues values = new ContentValues(); values.put(StudentsProvider.NAME, ((EditText)findViewById(R.id.editText2)).getText().toString()); values.put(StudentsProvider.GRADE, ((EditText)findViewById(R.id.editText3)).getText().toString()); Uri uri = getContentResolver().insert( StudentsProvider.CONTENT_URI, values); Toast.makeText(getBaseContext(), uri.toString(), Toast.LENGTH_LONG).show(); } public void onClickRetrieveStudents(View view) { // Retrieve student records String URL = "content://com.example.MyApplication.StudentsProvider"; Uri students = Uri.parse(URL); Cursor c = managedQuery(students, null, null, null, "name"); if (c.moveToFirst()) { do{ Toast.makeText(this, c.getString(c.getColumnIndex(StudentsProvider._ID)) + ", " + c.getString(c.getColumnIndex( StudentsProvider.NAME)) + ", " + c.getString(c.getColumnIndex( StudentsProvider.GRADE)), Toast.LENGTH_SHORT).show(); } while (c.moveToNext()); } } } |
یک فایل جدید به نام StudentProvider.java و تحت پکیج com.example.MyApplication به پروژه اضافه کنید و کد زیر را درون آن قرار دهید (src/com.example.MyApplication/StudentsProvider.java).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | package com.example.MyApplication; import java.util.HashMap; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.UriMatcher; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.text.TextUtils; public class StudentsProvider extends ContentProvider { static final String PROVIDER_NAME = "com.example.MyApplication.StudentsProvider"; static final String URL = "content://" + PROVIDER_NAME + "/students"; static final Uri CONTENT_URI = Uri.parse(URL); static final String _ID = "_id"; static final String NAME = "name"; static final String GRADE = "grade"; private static HashMap<String, String> STUDENTS_PROJECTION_MAP; static final int STUDENTS = 1; static final int STUDENT_ID = 2; static final UriMatcher uriMatcher; static{ uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(PROVIDER_NAME, "students", STUDENTS); uriMatcher.addURI(PROVIDER_NAME, "students/#", STUDENT_ID); } /** * Database specific constant declarations */ private SQLiteDatabase db; static final String DATABASE_NAME = "College"; static final String STUDENTS_TABLE_NAME = "students"; static final int DATABASE_VERSION = 1; static final String CREATE_DB_TABLE = " CREATE TABLE " + STUDENTS_TABLE_NAME + " (_id INTEGER PRIMARY KEY AUTOINCREMENT, " + " name TEXT NOT NULL, " + " grade TEXT NOT NULL);"; /** * Helper class that actually creates and manages * the provider's underlying data repository. */ private static class DatabaseHelper extends SQLiteOpenHelper { DatabaseHelper(Context context){ super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_DB_TABLE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS " + STUDENTS_TABLE_NAME); onCreate(db); } } @Override public boolean onCreate() { Context context = getContext(); DatabaseHelper dbHelper = new DatabaseHelper(context); /** * Create a write able database which will trigger its * creation if it doesn't already exist. */ db = dbHelper.getWritableDatabase(); return (db == null)? false:true; } @Override public Uri insert(Uri uri, ContentValues values) { /** * Add a new student record */ long rowID = db.insert( STUDENTS_TABLE_NAME, "", values); /** * If record is added successfully */ if (rowID > 0) { Uri _uri = ContentUris.withAppendedId(CONTENT_URI, rowID); getContext().getContentResolver().notifyChange(_uri, null); return _uri; } throw new SQLException("Failed to add a record into " + uri); } @Override public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); qb.setTables(STUDENTS_TABLE_NAME); switch (uriMatcher.match(uri)) { case STUDENTS: qb.setProjectionMap(STUDENTS_PROJECTION_MAP); break; case STUDENT_ID: qb.appendWhere( _ID + "=" + uri.getPathSegments().get(1)); break; default: } if (sortOrder == null || sortOrder == ""){ /** * By default sort on student names */ sortOrder = NAME; } Cursor c = qb.query(db, projection, selection, selectionArgs,null, null, sortOrder); /** * register to watch a content URI for changes */ c.setNotificationUri(getContext().getContentResolver(), uri); return c; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { int count = 0; switch (uriMatcher.match(uri)){ case STUDENTS: count = db.delete(STUDENTS_TABLE_NAME, selection, selectionArgs); break; case STUDENT_ID: String id = uri.getPathSegments().get(1); count = db.delete( STUDENTS_TABLE_NAME, _ID + " = " + id + (!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs); break; default: throw new IllegalArgumentException("Unknown URI " + uri); } getContext().getContentResolver().notifyChange(uri, null); return count; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int count = 0; switch (uriMatcher.match(uri)) { case STUDENTS: count = db.update(STUDENTS_TABLE_NAME, values, selection, selectionArgs); break; case STUDENT_ID: count = db.update(STUDENTS_TABLE_NAME, values, _ID + " = " + uri.getPathSegments().get(1) + (!TextUtils.isEmpty(selection) ? " AND (" +selection + ')' : ""), selectionArgs); break; default: throw new IllegalArgumentException("Unknown URI " + uri ); } getContext().getContentResolver().notifyChange(uri, null); return count; } @Override public String getType(Uri uri) { switch (uriMatcher.match(uri)){ /** * Get all student records */ case STUDENTS: return "vnd.android.cursor.dir/vnd.example.students"; /** * Get a particular student */ case STUDENT_ID: return "vnd.android.cursor.item/vnd.example.students"; default: throw new IllegalArgumentException("Unsupported URI: " + uri); } } } |
بعد از انجام مراحل بالا، باید Content Provider را درون فایل AndroidManifest.xml معرفی کنیم.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.MyApplication"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <provider android:name="StudentsProvider" android:authorities="com.example.MyApplication.StudentsProvider"/> </application> </manifest> |
کد زیر محتوای مربوط به فایل res/layout/activity_main.xml می باشد.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.MyApplication.MainActivity"> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Content provider" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:textSize="30dp" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Tutorials point " android:textColor="#ff87ff09" android:textSize="30dp" android:layout_below="@+id/textView1" android:layout_centerHorizontal="true" /> <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/imageButton" android:src="@drawable/abc" android:layout_below="@+id/textView2" android:layout_centerHorizontal="true" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/button2" android:text="Add Name" android:layout_below="@+id/editText3" android:layout_alignRight="@+id/textView2" android:layout_alignEnd="@+id/textView2" android:layout_alignLeft="@+id/textView2" android:layout_alignStart="@+id/textView2" android:onClick="onClickAddName"/> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/editText" android:layout_below="@+id/imageButton" android:layout_alignRight="@+id/imageButton" android:layout_alignEnd="@+id/imageButton" /> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/editText2" android:layout_alignTop="@+id/editText" android:layout_alignLeft="@+id/textView1" android:layout_alignStart="@+id/textView1" android:layout_alignRight="@+id/textView1" android:layout_alignEnd="@+id/textView1" android:hint="Name" android:textColorHint="@android:color/holo_blue_light" /> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/editText3" android:layout_below="@+id/editText" android:layout_alignLeft="@+id/editText2" android:layout_alignStart="@+id/editText2" android:layout_alignRight="@+id/editText2" android:layout_alignEnd="@+id/editText2" android:hint="Grade" android:textColorHint="@android:color/holo_blue_bright" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Retrive student" android:id="@+id/button" android:layout_below="@+id/button2" android:layout_alignRight="@+id/editText3" android:layout_alignEnd="@+id/editText3" android:layout_alignLeft="@+id/button2" android:layout_alignStart="@+id/button2" android:onClick="onClickRetrieveStudents"/> </RelativeLayout> |
مطمئن شوید که محتویات فایل res/values/strings.xml به صورت زیر باشد:
1 2 3 4 | <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">My Application</string> </resources>; |
اگر قبلا شبیه ساز خود را ایجاد کرده اید، بر روی دکمه Run کلیک کنید تا برنامه شما در شبیه ساز اجرا شود و نتیجه را مشاهده کنید. حال یک نام و یک رتبه نمونه در فیلد های مشخص شده وارد کنید و سپس دکمه Add Name را لمس کنید تا اطلاعات دانش آموز جدید در دیتابیس ثبت شود. به منظور افزودن یک رکورد جدید به دیتابیس از متد insert استفاده می شود. این روند را چند بار تکرار کنید تا تعداد دانش آموز در دیتابیس شما ثبت شود.
بعد از افزودن دانش آموزان به دیتابیس، حال می توانید با استفاده از دکمه Retrieve Student دانش آموزان ثبت شده را مشاهده کنید. این کار با استفاده از متد query انجام می شود. برای تمرین می توانید، قابلیت و ویرایش و حذف را هم به این برنامه اضافه کنید. برای این کار باید دو متدی که برای حذف و ویرایش لازم هستند را درون فایل MainActivity.java تعریف کنید و همچنین رابط کاربری برنامه را متناسب با قابلیت ها جدید تغییر دهید.
هیچ نظری ثبت نشده است