استفاده از Content Provider در اندروید

یکشنبه 18 بهمن 1394

برای ذخیره کردن اطلاعات و اشتراک گذاری اطلاعات داخل یک مخزن از content provider استفاده می شود، معمولا برای ذخیره اطلاعات و اشتراک گذاری اطلاعات به صورت پنهان و کاربردی از content provider استفاده می شود، اما در اکثر موارد ما از دیتابیس sqlite استفاده می نماییم.و کمتر از content proider استفاده خواهد شد.

استفاده از Content Provider در اندروید

یک پروژه ی جدید ایجاد نمایید به صورت زیر:

یک activity جدید ایجاد نمایید:

در مرحله ی بعدی انتخاب آیکون است که می توانید یک آیکون به صورت دلخواه انتخاب نمایید.

در مرحله ی بعدی یک activity خالی ایجاد نمایید:

داخل پوشه ی res یک activity جدید ایجاد نمایید به صورت زیر:

روی پکیج مورد نظر راست کلیک نمایید و یک کلاس جدید داخل پکیج ایجاد نمایید.

کلاسی که ایجاد می نمایید یک زیر کلاس از کلاس contentprovider است، و باید یک uri را تولید نماییم، که شکل فرمت آن به گونه ی زیر است:

content://<authority>/<path>

تگ بالا نام provider مربوطه در آن قرار می گیرد، <path> مسیر ذخیره شدن اطلاعات وارد شده، ما یک id به تمام رکوردهای ذخیره شده در پایان تگ content uri اضافه می نماییم.

همان طور که می دانید برای استفاده از sqlitehelper ما از کلاس databasehelper استفاده می کردیم، هم چنین ما از کلاس urimatcher استفاده می نماییم که با الگوی خاص داخل محتوای uri قرار می گیرد.

هم چنین ما می خواهیم content provider مان با prpperty کار نماید نیاز داریم که تابع های oncreate و query,insert,delete,gettype را ایجاد نماییم.داخل کلاس birthprovider:

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;
import android.util.Log;

public class BirthProvider extends ContentProvider {
	 // fields for my content provider
	 static final String PROVIDER_NAME = "com.javacodegeeks.provider.BirthdayProv";
	 static final String URL = "content://" + PROVIDER_NAME + "/friends";
	 static final Uri CONTENT_URI = Uri.parse(URL);
	   
	 // fields for the database
	 static final String ID = "id";
	 static final String NAME = "name";
	 static final String BIRTHDAY = "birthday";
	 
	 // integer values used in content URI
	 static final int FRIENDS = 1;
	 static final int FRIENDS_ID = 2;
	 
	 DBHelper dbHelper;
	   
	 // projection map for a query
	 private static HashMap<String, String> BirthMap;
	 
	 // maps content URI "patterns" to the integer values that were set above
	 static final UriMatcher uriMatcher;
	   static{
	      uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
	      uriMatcher.addURI(PROVIDER_NAME, "friends", FRIENDS);
	      uriMatcher.addURI(PROVIDER_NAME, "friends/#", FRIENDS_ID);
	   }
	   
	   // database declarations
	   private SQLiteDatabase database;
	   static final String DATABASE_NAME = "BirthdayReminder";
	   static final String TABLE_NAME = "birthTable";
	   static final int DATABASE_VERSION = 1;
	   static final String CREATE_TABLE = 
	      " CREATE TABLE " + TABLE_NAME +
	      " (id INTEGER PRIMARY KEY AUTOINCREMENT, " + 
	      " name TEXT NOT NULL, " +
	      " birthday TEXT NOT NULL);";
	 
	   
	   // class that creates and manages the provider's database 
	   private static class DBHelper extends SQLiteOpenHelper {

		public DBHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
			// TODO Auto-generated constructor stub
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			// TODO Auto-generated method stub
			 db.execSQL(CREATE_TABLE);
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			// TODO Auto-generated method stub
			Log.w(DBHelper.class.getName(),
			        "Upgrading database from version " + oldVersion + " to "
			            + newVersion + ". Old data will be destroyed");
			db.execSQL("DROP TABLE IF EXISTS " +  TABLE_NAME);
	        onCreate(db);
		}
		
	   }
	   
	@Override
	public boolean onCreate() {
		// TODO Auto-generated method stub
		Context context = getContext();
		dbHelper = new DBHelper(context);
		// permissions to be writable
		database = dbHelper.getWritableDatabase();

	    if(database == null)
	    	return false;
	    else
	    	return true;	
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		// TODO Auto-generated method stub
		 SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
		 // the TABLE_NAME to query on
		 queryBuilder.setTables(TABLE_NAME);
	      
	      switch (uriMatcher.match(uri)) {
	      // maps all database column names
	      case FRIENDS:
	    	  queryBuilder.setProjectionMap(BirthMap);
	         break;
	      case FRIENDS_ID:
	    	  queryBuilder.appendWhere( ID + "=" + uri.getLastPathSegment());
	         break;
	      default:
	         throw new IllegalArgumentException("Unknown URI " + uri);
	      }
	      if (sortOrder == null || sortOrder == ""){
	         // No sorting-> sort on names by default
	         sortOrder = NAME;
	      }
	      Cursor cursor = queryBuilder.query(database, projection, selection, 
	    		  selectionArgs, null, null, sortOrder);
	      /** 
	       * register to watch a content URI for changes
	       */
	      cursor.setNotificationUri(getContext().getContentResolver(), uri);

	      return cursor;
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		// TODO Auto-generated method stub
		long row = database.insert(TABLE_NAME, "", values);
	      
		// If record is added successfully
	      if(row > 0) {
	         Uri newUri = ContentUris.withAppendedId(CONTENT_URI, row);
	         getContext().getContentResolver().notifyChange(newUri, null);
	         return newUri;
	      }
	      throw new SQLException("Fail to add a new record into " + uri);
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		// TODO Auto-generated method stub
		 int count = 0;
	      
	      switch (uriMatcher.match(uri)){
	      case FRIENDS:
	         count = database.update(TABLE_NAME, values, selection, selectionArgs);
	         break;
	      case FRIENDS_ID:
	         count = database.update(TABLE_NAME, values, ID + 
	                 " = " + uri.getLastPathSegment() + 
	                 (!TextUtils.isEmpty(selection) ? " AND (" +
	                 selection + ')' : ""), selectionArgs);
	         break;
	      default: 
	         throw new IllegalArgumentException("Unsupported URI " + uri );
	      }
	      getContext().getContentResolver().notifyChange(uri, null);
	      return count;
	}
	
	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		// TODO Auto-generated method stub
		int count = 0;
		
		 switch (uriMatcher.match(uri)){
	      case FRIENDS:
	    	  // delete all the records of the table
	    	  count = database.delete(TABLE_NAME, selection, selectionArgs);
	    	  break;
	      case FRIENDS_ID:
	      	  String id = uri.getLastPathSegment();	//gets the id
	          count = database.delete( TABLE_NAME, ID +  " = " + id + 
	                (!TextUtils.isEmpty(selection) ? " AND (" + 
	                selection + ')' : ""), selectionArgs);
	          break;
	      default: 
	          throw new IllegalArgumentException("Unsupported URI " + uri);
	      }
	      
	      getContext().getContentResolver().notifyChange(uri, null);
	      return count;
		
		
	}

	@Override
	public String getType(Uri uri) {
		// TODO Auto-generated method stub
		switch (uriMatcher.match(uri)){
	      // Get all friend-birthday records 
	      case FRIENDS:
	         return "vnd.android.cursor.dir/vnd.example.friends";
	      // Get a particular friend 
	      case FRIENDS_ID:
	         return "vnd.android.cursor.item/vnd.example.friends";
	      default:
	         throw new IllegalArgumentException("Unsupported URI: " + uri);
	      }
	}


}

به جای متد delete و به جای حذف کردن داده ی ذخیره شده شما می توانید از یک sync adapter با یک flag استفاده نمایید.

با استفاده از sync adapter شما می توانید یک سطر از سرور ابتدا حذف نمایید و بعد از داخل adapter آن را حذف کنید.

داخل فایل androidmanifest نیاز است که provider مورد نظر را تعریف نمایید و دسترسی آن را برای خواندن و نوشتن بدهید.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.javacodegeeks.android.contentprovidertest"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/logo"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.javacodegeeks.android.contentprovidertest.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
         <provider android:name="BirthProvider" 
           	android:authorities="com.javacodegeeks.provider.BirthdayProv">
        </provider>
    </application>

</manifest>

زمانی که application  ما می خواهد به داده های ما دسترسی پیدا کند ما از contentprovider استفاده می نماییم، این درخواست ها به وسیله ی شی objectresolver مدیریت می شوند، در مثال زیر ما 3 تابع داریم که این تابع ها می توانند یک provider اضافه، حذف و یا نمایش اطلاعات استفاده شود.

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.ContentValues;
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);
	}
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	public void deleteAllBirthdays (View view) {
		// delete all the records and the table of the database provider
		String URL = "content://com.javacodegeeks.provider.BirthdayProv/friends";
	    Uri friends = Uri.parse(URL);
		int count = getContentResolver().delete(
				 friends, null, null);
		String countNum = "Javacodegeeks: "+ count +" records are deleted.";
		Toast.makeText(getBaseContext(), 
			      countNum, Toast.LENGTH_LONG).show();
		
	}
	 public void addBirthday(View view) {
	      // Add a new birthday record
	      ContentValues values = new ContentValues();

	      values.put(BirthProvider.NAME, 
	      ((EditText)findViewById(R.id.name)).getText().toString());
	      
	      values.put(BirthProvider.BIRTHDAY, 
	      ((EditText)findViewById(R.id.birthday)).getText().toString());

	      Uri uri = getContentResolver().insert(
	    	BirthProvider.CONTENT_URI, values);
	      
	      Toast.makeText(getBaseContext(), 
	    	"Javacodegeeks: " + uri.toString() + " inserted!", Toast.LENGTH_LONG).show();
	   }
	   public void showAllBirthdays(View view) {
	      // Show all the birthdays sorted by friend's name
	      String URL = "content://com.javacodegeeks.provider.BirthdayProv/friends";
	      Uri friends = Uri.parse(URL);
	      Cursor c = getContentResolver().query(friends, null, null, null, "name");
	      String result = "Javacodegeeks Results:";
	      
	      if (!c.moveToFirst()) {
	    	  Toast.makeText(this, result+" no content yet!", Toast.LENGTH_LONG).show();
	      }else{
	    	  do{
	            result = result + "\n" + c.getString(c.getColumnIndex(BirthProvider.NAME)) + 
	    	            " with id " +  c.getString(c.getColumnIndex(BirthProvider.ID)) + 
	    	            " has birthday: " + c.getString(c.getColumnIndex(BirthProvider.BIRTHDAY));
	          } while (c.moveToNext());
	    	  Toast.makeText(this, result, Toast.LENGTH_LONG).show();
	      }
	     
	   }
}

برای user interface پروژه ی خود از از edittext و button استفاده می نماییم.

به صورت زیر خواهد بود:

<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=".MainActivity" >

    <EditText
		android:id="@+id/name"
	    android:layout_width="fill_parent"
	    android:layout_height="wrap_content"
	    android:ems="10" 
	    android:hint="نام" />
        
     <EditText
	 	android:id="@+id/birthday"
	 	android:layout_width="fill_parent"
	    android:layout_height="wrap_content"
	    android:layout_alignLeft="@+id/name"
	    android:layout_below="@+id/name"
	    android:ems="10"
	    android:hint="تاریخ تولد" />
     
     <Button
         android:id="@+id/btnAdd"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:onClick="addBirthday"
         android:layout_alignLeft="@+id/birthday"
         android:layout_below="@+id/birthday"
         android:layout_marginTop="30dp"
         android:text="افزودن تاریخ تولد جدید" />
     
     <Button
         android:id="@+id/btnShow"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:layout_alignLeft="@+id/btnAdd"
         android:layout_below="@+id/btnAdd"
         android:layout_marginTop="20dp"
         android:onClick="showAllBirthdays"
         android:text="نمایش تمام تاریخ تولد ها" />

     <Button
         android:id="@+id/btnDelete"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:layout_below="@+id/btnShow"
         android:layout_alignLeft="@+id/btnShow"
         android:layout_marginTop="20dp"
         android:onClick="deleteAllBirthdays"
         android:text="حذف تمام تاریخ تولدها" />
     
</RelativeLayout>

داخل string پروژه ی خود هم می توانید نام پروژه و و منو و نام ابزار هایی را که استفاده کرده اید را داخل آن تغییر نام دهید.

<resources>
    <string name="app_name">ContentProviderTest</string>
    <string name="action_settings">Settings</string>
    <string name="birthday">Birthday</string>
    <string name="name">Name</string>
    <string name="add">Add a new Birthday</string>
    <string name="show">Show all the Birthdays</string>
    <string name="delete">Delete all the Birthdays</string>
</resources>

زمانی که پروژه را run نمایید به صورت زیر خواهد بود:

فایل های ضمیمه

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید