الثلاثاء، 26 نوفمبر 2019

مزودات المحتوى في برمجة الأندرويد Android Devloper Content Providers#

مزودات المحتوى في برمجة الأندرويد 

Android Devloper  Content Providers# 

مزودات المحتوى في برمجة الأندرويد Android Devloper  Content Providers# 

يوفر مكون موفر المحتوى البيانات من تطبيق إلى آخر عند الطلب.  تتم معالجة هذه الطلبات بواسطة أساليب فئة ContentResolver.  يمكن لمزود المحتوى استخدام طرق مختلفة لتخزين بياناته ويمكن تخزين البيانات في قاعدة بيانات أو في ملفات أو حتى عبر شبكة.
في بعض الأحيان يكون مطلوبًا مشاركة البيانات عبر التطبيقات.  هذا هو المكان الذي يصبح فيه مزودو المحتوى مفيدًا للغاية.
 يتيح لك موفرو المحتوى تركيز المحتوى في مكان واحد والحصول على العديد من التطبيقات المختلفة للوصول إليه حسب الحاجة.  يتصرف موفر المحتوى تمامًا مثل قاعدة البيانات حيث يمكنك الاستعلام عنها ، وتحرير محتواها ، وكذلك إضافة أو حذف المحتوى باستخدام طرق الإدراج () ، التحديث () ، الحذف () ، والاستعلام ().  في معظم الحالات ، يتم تخزين هذه البيانات في قاعدة بيانات SQlite.

 يتم تطبيق موفر المحتوى كفئة فرعية من فئة ContentProvider ويجب أن يقوم بتطبيق مجموعة قياسية من واجهات برمجة التطبيقات التي تمكن التطبيقات الأخرى من إجراء المعاملات.


public class My Application extends  ContentProvider {
}

Content URIs

للاستعلام عن مزود محتوى ، يمكنك تحديد سلسلة الاستعلام في شكل URI الذي له التنسيق التالي -
:////

هنا تفاصيل أجزاء مختلفة من URI -
المسلسلالوصف والجزء
1
prefix
يتم ضبط هذا دائمًا على المحتوى: //
2
authority
يحدد هذا اسم موفر المحتوى ، على سبيل المثال جهات الاتصال ، المتصفح ، إلخ. بالنسبة لموفري المحتوى من الأطراف الثالثة ، قد يكون هذا هو الاسم المؤهل بالكامل ، مثل com.ahmedalmahallawi.statusprovider
3
data_type
يشير هذا إلى نوع البيانات التي يوفرها هذا الموفر المعين.  على سبيل المثال ، إذا كنت تحصل على جميع جهات الاتصال من موفر محتوى جهات الاتصال ، فسيكون مسار البيانات هو الأشخاص وسيظهر URI كهذا المحتوى: // جهات الاتصال / الأشخاص
4
id
يحدد هذا السجل المحدد المطلوب.  على سبيل المثال ، إذا كنت تبحث عن رقم جهة الاتصال 5 في موفر محتوى جهات الاتصال ، فسيبدو URI مثل هذا المحتوى: // contacts / people / 5.

إنشاء مزود المحتوى
 يتضمن هذا عددًا من الخطوات البسيطة لإنشاء موفر المحتوى الخاص بك.

 بادئ ذي بدء ، تحتاج إلى إنشاء فئة موفر محتوى يمتد فئة ContentProviderbaseclass.

 ثانياً ، تحتاج إلى تحديد عنوان URI لموفر المحتوى الخاص بك والذي سيتم استخدامه للوصول إلى المحتوى.

 بعد ذلك ستحتاج إلى إنشاء قاعدة بيانات خاصة بك للحفاظ على المحتوى.  عادة ، يستخدم Android قاعدة بيانات SQLite ويحتاج إطار العمل إلى تجاوز أسلوب onCreate () الذي سيستخدم أسلوب SQLite Open Helper لإنشاء أو فتح قاعدة بيانات الموفر.  عند بدء تشغيل التطبيق الخاص بك ، يتم استدعاء معالج onCreate () لكل من موفري المحتوى الخاص به على مؤشر ترابط التطبيق الرئيسي.

 بعد ذلك ، سيتعين عليك تنفيذ استعلامات موفر المحتوى لتنفيذ عمليات مختلفة لقاعدة البيانات.

 أخيرًا ، سجّل مزود المحتوى الخاص بك في ملف نشاطك باستخدام علامة .

 فيما يلي قائمة بالطرق التي تحتاج إلى تجاوزها في فئة موفر المحتوى حتى يعمل موفر المحتوى الخاص بك -
onCreate () تسمى هذه الطريقة عند بدء تشغيل الموفر.

 query () تتلقى هذه الطريقة طلبًا من عميل.  يتم إرجاع النتيجة ككائن المؤشر.

 insert () تقوم هذه الطريقة بإدراج سجل جديد في موفر المحتوى.

 delete () هذه الطريقة تحذف سجلًا حاليًا من موفر المحتوى.

 update () تقوم هذه الطريقة بتحديث سجل موجود من موفر المحتوى.

 getType () تقوم هذه الطريقة بإرجاع نوع MIME من البيانات في URI المحدد.

 مثال
 يوضح هذا المثال كيفية إنشاء ContentProvider الخاص بك.  لذلك دعونا نتبع الخطوات التالية على غرار الخطوات التي اتبعناها أثناء إنشاء Hello World مثال 

التسلسلالوصف
1ستستخدم Android StudioIDE لإنشاء تطبيق Android وتسميته كتطبيقي ضمن حزمة com.example.MyApplication ، مع نشاط فارغ.
2تعديل ملف النشاط الرئيسي MainActivity.java لإضافة طريقتين جديدتين onClickAddName () و onClickRetrieveStudents ().
3قم بإنشاء ملف java جديد يسمى StudentsProvider.java ضمن الحزمة com.example.MyApplication لتحديد الموفر الفعلي والأساليب المرتبطة به.
4قم بتسجيل موفر المحتوى الخاص بك في ملف AndroidManifest.xml الخاص بك باستخدام العلامة
5قم بتعديل المحتوى الافتراضي لملف res / layout / activity_main.xml لتضمين واجهة المستخدم الرسومية الصغيرة لإضافة سجلات الطلاب.
6لا حاجة لتغيير string.xml.Android studio تهتم بملف string.xml.
7قم بتشغيل التطبيق لتشغيل محاكي Android والتحقق من نتيجة التغييرات التي تمت في التطبيق.

فيما يلي محتوى ملف النشاط الرئيسي المعدل src / com.example.MyApplication / MainActivity.java.  يمكن أن يشمل هذا الملف كل من طرق دورة الحياة الأساسية.  لقد أضفنا طريقتين جديدتين على onClickAddName () و onClickRetrieveStudents () للتعامل مع تفاعل المستخدم مع التطبيق.


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());
      }
   }
}
قم بإنشاء ملف جديد StudentsProvider.java ضمن حزمة com.example.MyApplication وما يلي هو محتوى src / com.example.MyApplication / StudentsProvider.java -
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);
      }
   }
}


فيما يلي المحتوى المعدل لملف AndroidManifest.xml.  هنا أضفنا علامة لتضمين مزود المحتوى الخاص بنا:
xml version="1.0" encoding="utf-8"?>
 xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.MyApplication">

   
      android:allowBackup="true"
      android:icon="@mipmap/ic_launcher"
      android:label="@string/app_name"
      android:supportsRtl="true"
      android:theme="@style/AppTheme">
          android:name=".MainActivity">
            
                android:name="android.intent.action.MAIN" />
                android:name="android.intent.category.LAUNCHER" />
            



التسميات: