‏إظهار الرسائل ذات التسميات Android الاندرويد. إظهار كافة الرسائل
‏إظهار الرسائل ذات التسميات Android الاندرويد. إظهار كافة الرسائل

الفلاتر والمقاصد في برمجة الأندرويد Android Devlopement Intents and Filter#

الفلاتر والمقاصد في برمجة الأندرويد

 Android  Devlopement Intents and Filter# 

الفلاتر والمقاصد في برمجة الأندرويد Android  Devlopement Intents and Filter# 

المقصد intent هو كائن مراسلة يمكنك استخدامه لطلب إجراء من مكون تطبيق آخر.  على الرغم من أن المقاصد تسهل الاتصال بين المكونات بعدة طرق ، إلا أن هناك ثلاث حالات استخدام أساسية:

 بدء النشاط
 يمثل النشاط شاشة واحدة في التطبيق.  يمكنك بدء مثيل جديد للنشاط بتمرير نية إلى startActivity ().  تصف مقصد intent النشاط لبدء وتحميل أي بيانات ضرورية.

إذا كنت ترغب في تلقي نتيجة من النشاط عند انتهائه ، فاتصل بـ startActivityForResult ().  يتلقى نشاطك النتيجة ككائن هدف منفصل في رد الاتصال onActivityResult () لنشاطك.  لمزيد من المعلومات ، راجع دليل الأنشطة.

 بدء الخدمة Starting a service
 الخدمة عبارة عن مكون يقوم بإجراء عمليات في الخلفية بدون واجهة مستخدم.  باستخدام Android 5.0 (API المستوى 21) والإصدارات الأحدث ، يمكنك بدء تشغيل خدمة باستخدام JobScheduler.  لمزيد من المعلومات حول JobScheduler ، راجع وثائق مرجع API الخاصة به.


بالنسبة للإصدارات الأقدم من Android 5.0 (مستوى API 21) ، يمكنك بدء تشغيل الخدمة باستخدام أساليب فئة الخدمة.  يمكنك بدء خدمة لتنفيذ عملية لمرة واحدة (مثل تنزيل ملف) عن طريق تمرير  intent إلى startService ().  تصف ال intent الخدمة لبدء وتحمل أي بيانات ضرورية.

 إذا تم تصميم الخدمة بواجهة عميل خادم ، فيمكنك الربط بالخدمة من مكون آخر عن طريق تمرير مقصد intent إلى bindService ().  لمزيد من المعلومات ، راجع دليل الخدمات.

تسليم البث delivering broadcasts 
 البث هو رسالة يمكن لأي تطبيق استلامها.  يقدم النظام عمليات بث متعددة لأحداث النظام ، مثل عندما يرتفع النظام أو يبدأ الجهاز في الشحن.  يمكنك توصيل بث إلى تطبيقات أخرى عن طريق تمرير مقصد  sendBroadcast () أو sendOrderedBroadcast ().

 تشرح بقية هذه الصفحة كيفية عمل المقاصد intents وكيفية استخدامها.  للحصول على معلومات ذات صلة ، راجع التفاعل مع تطبيقات أخرى ومشاركة المحتوى

أنواع المقاصد intents types

هناك نوعان من المقاصد intent:

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


يوضح الشكل 1 كيف يتم استخدام المقصد عند بدء النشاط.  عندما يقوم كائن Intent بتسمية مكون نشاط معين بشكل صريح ، يبدأ النظام على الفور في تشغيل هذا المكون.


الشكل 1. كيف يتم تسليم المقصد الضمني من خلال النظام لبدء نشاط آخر: [1] يُنشئ النشاط "أ" هدفًا مع وصف للإجراء ويمرره إلى startActivity ().  [2] يبحث نظام Android عن جميع التطبيقات بحثًا عن مرشح نوايا يطابق المقصد intent.  عندما يتم العثور على تطابق ، [3] يبدأ النظام في نشاط المطابقة (النشاط B) من خلال استدعاء أسلوب onCreate () الخاص به وتمريره إلى النية.

 عند استخدام المقصد الضمني ، يجد نظام Android المكون المناسب للبدء بمقارنة القصد من النية بعوامل تصفية المقاصد المعلنة في ملف البيان للتطبيقات الأخرى على الجهاز.  إذا كانت المقصد  تتطابق مع مرشح المقاصد ، فإن النظام يبدأ هذا المكون ويسلم كائن المقاصد.  إذا كانت عوامل تصفية المقاصد المتعددة متوافقة ، يعرض النظام مربع حوار حتى يمكن للمستخدم اختيار التطبيق الذي تريد استخدامه.

عامل تصفية المقصد هو تعبير في ملف بيان التطبيق الذي يحدد نوع المقاصد intentsالتي يرغب المكون في تلقيها.  على سبيل المثال ، بإعلان مرشح فلتر النوايا او المقاصد intents لأحد الأنشطة ، يمكنك من تشغيل التطبيقات الأخرى نشاطك مباشرة بنوع معين من النوايا intents.  وبالمثل ، إذا لم تعلن عن أي مرشحات نية intent  للنشاط ، فيمكن البدء به فقط بقصد صريح.

بناء المقصد intent building 
 يحمل كائن Intent المعلومات التي يستخدمها نظام Android لتحديد أي مكون يتم تشغيله (مثل اسم المكون أو فئة المكون الذي يجب أن يستقبل القصد) ، بالإضافة إلى المعلومات التي يستخدمها مكون المستلم من أجل تنفيذ الإجراء بشكل صحيح (مثل  الإجراء الواجب اتخاذه والبيانات الواجب اتخاذها)

 المعلومات الأساسية الواردة في نية هي التالية:

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

المقصد او النية او النوايا او القصد هو intent.

هذا الحقل من Intent هو كائن ComponentName ، والذي يمكنك تحديده باستخدام اسم فئة مؤهل بالكامل للمكون الهدف ، بما في ذلك اسم حزمة التطبيق ، على سبيل المثال ، com.example.ExampleActivity.  يمكنك تعيين اسم المكون باستخدام setComponent () أو setClass () أو setClassName () أو مع مُنشئ Intent.

 عمل
 سلسلة تحدد الإجراء العام المراد تنفيذه (مثل العرض أو الانتقاء).
 في حالة وجود نية للبث ، هذا هو الإجراء الذي تم الإبلاغ عنه.  يحدد الإجراء إلى حد كبير كيفية تنظيم بقية النية - خاصة المعلومات الواردة في البيانات والإضافات.

 يمكنك تحديد الإجراءات الخاصة بك لاستخدامها من قبل النوايا داخل التطبيق الخاص بك (أو للاستخدام من قبل التطبيقات الأخرى لاستدعاء مكونات في التطبيق الخاص بك) ، ولكن عادة ما تحدد ثوابت الإجراءات المحددة بواسطة فئة Intent أو فئات إطار العمل الأخرى.  فيما يلي بعض الإجراءات الشائعة لبدء النشاط:

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

 يمكنك تحديد الإجراء لنية مع setAction () أو مع مُنشئ Intent.

 إذا قمت بتحديد الإجراءات الخاصة بك ، فتأكد من تضمين اسم حزمة التطبيق الخاص بك كبادئة ، كما هو موضح في المثال التالي:


static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";


البيانات
 URI (كائن Uri) الذي يشير إلى البيانات المطلوب التصرف عليها و / أو نوع MIME لتلك البيانات.  يتم تحديد نوع البيانات التي يتم توفيرها بشكل عام بواسطة إجراء النية.  على سبيل المثال ، إذا كان الإجراء ACTION_EDIT ، فيجب أن تحتوي البيانات على URI للوثيقة المراد تحريرها.
 عند إنشاء هدف ، غالبًا ما يكون من المهم تحديد نوع البيانات (نوع MIME) بالإضافة إلى URI الخاص به.  على سبيل المثال ، قد لا يتمكن أي نشاط قادر على عرض الصور من تشغيل ملف صوتي ، على الرغم من أن تنسيقات URI قد تكون متشابهة.  تحديد نوع MIME لبياناتك يساعد نظام Android في العثور على أفضل مكون لتلقي نيتك.  ومع ذلك ، يمكن في بعض الأحيان الاستدلال على نوع MIME من URI - خاصةً عندما تكون البيانات محتوى: URI.  المحتوى: يشير URI إلى أن البيانات موجودة على الجهاز ويتم التحكم فيها بواسطة ContentProvider ، مما يجعل نوع MIME للبيانات مرئيًا للنظام.

 لتعيين URI البيانات فقط ، استدعاء setData ().  لتعيين نوع MIME فقط ، قم باستدعاء setType ().  إذا لزم الأمر ...


الصنف category 
 سلسلة تحتوي على معلومات إضافية حول نوع المكون الذي يجب أن يعالج القصد.  يمكن وضع أي عدد من أوصاف الفئات في نية ، لكن معظم النوايا لا تتطلب فئة.  فيما يلي بعض الفئات الشائعة:
 CATEGORY_BROWSABLE
 يتيح النشاط المستهدف بدء تشغيله بواسطة مستعرض ويب لعرض البيانات المشار إليها بواسطة ارتباط ، مثل صورة أو رسالة بريد إلكتروني.
 CATEGORY_LAUNCHER
 النشاط هو النشاط الأولي للمهمة وهو مدرج في مشغل تطبيق النظام.
 راجع وصف فئة Intent للحصول على قائمة كاملة بالفئات.

 يمكنك تحديد فئة مع addCategory ().


إضافات extras
 أزواج القيمة الرئيسية التي تحمل معلومات إضافية مطلوبة لإنجاز الإجراء المطلوب.  مثلما تستخدم بعض الإجراءات أنواع معينة من URIs للبيانات ، تستخدم بعض الإجراءات أيضًا إضافات معينة.
 يمكنك إضافة بيانات إضافية بطرق مختلفة putExtra () ، كل منها يقبل معلمتين: اسم المفتاح والقيمة.  يمكنك أيضًا إنشاء كائن Bundle مع جميع البيانات الإضافية ، ثم إدراج Bundle في Intent باستخدام putExtras ().

 على سبيل المثال ، عند إنشاء نية لإرسال بريد إلكتروني مع ACTION_SEND ، يمكنك تحديد المستلم باستخدام مفتاح EXTRA_EMAIL ، وتحديد الموضوع باستخدام مفتاح EXTRA_SUBJECT.

 تحدد الفئة Intent العديد من الثوابت EXTRA_ * لأنواع البيانات القياسية.  إذا كنت بحاجة إلى الإعلان عن المفاتيح الإضافية الخاصة بك (للنوايا التي يستقبلها تطبيقك) ، فتأكد من تضمين اسم حزمة التطبيق الخاص بك كبادئة ، كما هو موضح في المثال التالي 
static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";


ماهو التجزئة او التقسيم Fragment في برمجة الأندرويد Android Fragment#

ماهو التجزئة او التقسيم Fragment في برمجة الأندرويد

 Android Fragment# 


مزودات المحتوى في برمجة الأندرويد 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" />