ক্যালেন্ডার প্রদানকারীর ওভারভিউ

ক্যালেন্ডার প্রদানকারী একটি ব্যবহারকারীর ক্যালেন্ডার ইভেন্টগুলির জন্য একটি সংগ্রহস্থল। ক্যালেন্ডার প্রোভাইডার API আপনাকে ক্যালেন্ডার, ইভেন্ট, অংশগ্রহণকারী, অনুস্মারক ইত্যাদিতে কোয়েরি সঞ্চালন, সন্নিবেশ, আপডেট এবং ক্রিয়াকলাপ মুছে ফেলার অনুমতি দেয়।

ক্যালেন্ডার প্রদানকারী API অ্যাপ্লিকেশন এবং সিঙ্ক অ্যাডাপ্টার দ্বারা ব্যবহার করা যেতে পারে। কি ধরনের প্রোগ্রাম কল করছে তার উপর নির্ভর করে নিয়ম পরিবর্তিত হয়। এই নথিটি প্রাথমিকভাবে একটি অ্যাপ্লিকেশন হিসাবে ক্যালেন্ডার প্রদানকারী API ব্যবহার করার উপর ফোকাস করে৷ সিঙ্ক অ্যাডাপ্টারগুলি কীভাবে আলাদা তা আলোচনার জন্য, সিঙ্ক অ্যাডাপ্টারগুলি দেখুন।

সাধারণত, ক্যালেন্ডারের ডেটা পড়তে বা লিখতে, একটি অ্যাপ্লিকেশনের ম্যানিফেস্টে অবশ্যই ব্যবহারকারীর অনুমতিগুলিতে বর্ণিত যথাযথ অনুমতিগুলি অন্তর্ভুক্ত করতে হবে৷ সাধারণ ক্রিয়াকলাপগুলিকে সহজতর করার জন্য, ক্যালেন্ডার প্রদানকারী ক্যালেন্ডার ইন্টেন্টে বর্ণিত ইন্টেন্টগুলির একটি সেট অফার করে। ইভেন্টগুলি সন্নিবেশ, দেখতে এবং সম্পাদনা করতে এই উদ্দেশ্যগুলি ব্যবহারকারীদের ক্যালেন্ডার অ্যাপ্লিকেশনে নিয়ে যায়। ব্যবহারকারী ক্যালেন্ডার অ্যাপ্লিকেশনের সাথে ইন্টারঅ্যাক্ট করে এবং তারপরে আসল অ্যাপ্লিকেশনে ফিরে আসে। এইভাবে আপনার অ্যাপ্লিকেশনটির অনুমতির অনুরোধ করার প্রয়োজন নেই, বা ইভেন্টগুলি দেখতে বা তৈরি করার জন্য এটি একটি ব্যবহারকারী ইন্টারফেস প্রদানের প্রয়োজন নেই।

বেসিক

বিষয়বস্তু প্রদানকারীরা ডেটা সঞ্চয় করে এবং এটিকে অ্যাপ্লিকেশনগুলিতে অ্যাক্সেসযোগ্য করে তোলে। অ্যান্ড্রয়েড প্ল্যাটফর্ম (ক্যালেন্ডার প্রদানকারী সহ) দ্বারা অফার করা সামগ্রী প্রদানকারীরা সাধারণত একটি রিলেশনাল ডাটাবেস মডেলের উপর ভিত্তি করে টেবিলের একটি সেট হিসাবে ডেটা প্রকাশ করে, যেখানে প্রতিটি সারি একটি রেকর্ড এবং প্রতিটি কলাম একটি নির্দিষ্ট ধরণের এবং অর্থের ডেটা। ক্যালেন্ডার প্রোভাইডার API-এর মাধ্যমে, অ্যাপ্লিকেশন এবং সিঙ্ক অ্যাডাপ্টারগুলি ব্যবহারকারীর ক্যালেন্ডার ডেটা ধারণ করে এমন ডাটাবেস টেবিলগুলিতে পঠন/লেখার অ্যাক্সেস পেতে পারে।

প্রতিটি বিষয়বস্তু প্রদানকারী একটি সর্বজনীন URI প্রকাশ করে (একটি Uri অবজেক্ট হিসাবে মোড়ানো) যা অনন্যভাবে তার ডেটা সেট সনাক্ত করে। একটি বিষয়বস্তু প্রদানকারী যেটি একাধিক ডেটা সেট নিয়ন্ত্রণ করে (একাধিক টেবিল) প্রতিটির জন্য একটি পৃথক URI প্রকাশ করে৷ প্রদানকারীদের জন্য সমস্ত URI স্ট্রিং "content://" দিয়ে শুরু হয়। এটি একটি বিষয়বস্তু প্রদানকারী দ্বারা নিয়ন্ত্রিত হিসাবে ডেটা চিহ্নিত করে৷ ক্যালেন্ডার প্রদানকারী তার প্রতিটি ক্লাসের (টেবিল) জন্য URI-এর জন্য ধ্রুবক সংজ্ঞায়িত করে। এই URI-এর বিন্যাস আছে <class> .CONTENT_URI । উদাহরণস্বরূপ, Events.CONTENT_URI

চিত্র 1 ক্যালেন্ডার প্রদানকারী ডেটা মডেলের একটি গ্রাফিক্যাল উপস্থাপনা দেখায়। এটি প্রধান টেবিল এবং ক্ষেত্রগুলি দেখায় যা তাদের একে অপরের সাথে লিঙ্ক করে।

ক্যালেন্ডার প্রদানকারী ডেটা মডেল

চিত্র 1. ক্যালেন্ডার প্রদানকারী ডেটা মডেল।

একজন ব্যবহারকারীর একাধিক ক্যালেন্ডার থাকতে পারে এবং বিভিন্ন ক্যালেন্ডার বিভিন্ন ধরনের অ্যাকাউন্টের সাথে যুক্ত হতে পারে (গুগল ক্যালেন্ডার, এক্সচেঞ্জ, এবং তাই)।

CalendarContract ক্যালেন্ডার এবং ইভেন্ট সম্পর্কিত তথ্যের ডেটা মডেলকে সংজ্ঞায়িত করে। এই তথ্য নীচে তালিকাভুক্ত, টেবিলের একটি সংখ্যা সংরক্ষণ করা হয়.

টেবিল (শ্রেণী) বর্ণনা

CalendarContract.Calendars

এই টেবিলে ক্যালেন্ডার-নির্দিষ্ট তথ্য রয়েছে। এই টেবিলের প্রতিটি সারিতে একটি একক ক্যালেন্ডারের বিশদ বিবরণ রয়েছে, যেমন নাম, রঙ, সিঙ্ক তথ্য ইত্যাদি।
CalendarContract.Events এই টেবিলটি ইভেন্ট-নির্দিষ্ট তথ্য ধারণ করে। এই টেবিলের প্রতিটি সারিতে একটি একক ইভেন্টের তথ্য রয়েছে—উদাহরণস্বরূপ, ইভেন্টের শিরোনাম, অবস্থান, শুরুর সময়, শেষের সময় এবং আরও অনেক কিছু। ঘটনাটি একবার ঘটতে পারে বা একাধিকবার পুনরাবৃত্তি হতে পারে। অংশগ্রহণকারী, অনুস্মারক এবং বর্ধিত বৈশিষ্ট্য পৃথক টেবিলে সংরক্ষণ করা হয়। তাদের প্রত্যেকের একটি EVENT_ID আছে যা ইভেন্ট টেবিলে _ID উল্লেখ করে।
CalendarContract.Instances এই টেবিলটি একটি ইভেন্টের প্রতিটি ঘটনার জন্য শুরু এবং শেষ সময় ধারণ করে। এই টেবিলের প্রতিটি সারি একটি একক ইভেন্ট ঘটনা প্রতিনিধিত্ব করে। এক-সময়ের ইভেন্টগুলির জন্য ইভেন্টগুলির উদাহরণগুলির একটি 1:1 ম্যাপিং রয়েছে৷ পুনরাবৃত্ত ইভেন্টগুলির জন্য, একাধিক সারি স্বয়ংক্রিয়ভাবে তৈরি হয় যা সেই ইভেন্টের একাধিক ঘটনার সাথে মিলে যায়।
CalendarContract.Attendees এই টেবিলে ইভেন্টের অংশগ্রহণকারী (অতিথি) তথ্য রয়েছে। প্রতিটি সারি একটি ইভেন্টের একক অতিথিকে প্রতিনিধিত্ব করে। এটি অতিথির ধরন এবং অনুষ্ঠানের জন্য অতিথির উপস্থিতির প্রতিক্রিয়া নির্দিষ্ট করে৷
CalendarContract.Reminders এই টেবিলটি সতর্কতা/বিজ্ঞপ্তি ডেটা ধারণ করে। প্রতিটি সারি একটি ইভেন্টের জন্য একটি একক সতর্কতা উপস্থাপন করে। একটি ইভেন্ট একাধিক অনুস্মারক থাকতে পারে। প্রতি ইভেন্টে অনুস্মারকের সর্বাধিক সংখ্যা MAX_REMINDERS এ নির্দিষ্ট করা হয়েছে, যা প্রদত্ত ক্যালেন্ডারের মালিক সিঙ্ক অ্যাডাপ্টার দ্বারা সেট করা হয়েছে৷ অনুস্মারকগুলি ইভেন্টের কয়েক মিনিট আগে নির্দিষ্ট করা হয় এবং একটি পদ্ধতি রয়েছে যা নির্ধারণ করে কিভাবে ব্যবহারকারীকে সতর্ক করা হবে।

ক্যালেন্ডার প্রদানকারী API নমনীয় এবং শক্তিশালী হতে ডিজাইন করা হয়েছে। একই সময়ে, একটি ভাল শেষ ব্যবহারকারীর অভিজ্ঞতা প্রদান করা এবং ক্যালেন্ডার এবং এর ডেটার অখণ্ডতা রক্ষা করা গুরুত্বপূর্ণ৷ এই লক্ষ্যে, API ব্যবহার করার সময় এখানে কিছু বিষয় মাথায় রাখতে হবে:

  • ক্যালেন্ডার ইভেন্টগুলি ঢোকানো, আপডেট করা এবং দেখা৷ ক্যালেন্ডার প্রদানকারী থেকে ইভেন্টগুলি সরাসরি সন্নিবেশ, সংশোধন এবং পড়তে, আপনার উপযুক্ত অনুমতি প্রয়োজন৷ যাইহোক, আপনি যদি একটি পূর্ণাঙ্গ ক্যালেন্ডার অ্যাপ্লিকেশন বা সিঙ্ক অ্যাডাপ্টার তৈরি না করেন, তাহলে এই অনুমতিগুলির অনুরোধ করার প্রয়োজন নেই৷ আপনি পরিবর্তে সেই অ্যাপ্লিকেশনটিতে পড়া এবং লেখার ক্রিয়াকলাপগুলি হস্তান্তর করতে অ্যান্ড্রয়েডের ক্যালেন্ডার অ্যাপ্লিকেশন দ্বারা সমর্থিত উদ্দেশ্যগুলি ব্যবহার করতে পারেন৷ আপনি যখন অভিপ্রায় ব্যবহার করেন, তখন আপনার অ্যাপ্লিকেশনটি ব্যবহারকারীদেরকে ক্যালেন্ডার অ্যাপ্লিকেশনে পাঠায় যাতে পূর্বে ভরা ফর্মে কাঙ্খিত অপারেশন করা যায়। সেগুলি সম্পন্ন করার পরে, সেগুলি আপনার আবেদনে ফেরত দেওয়া হবে৷ ক্যালেন্ডারের মাধ্যমে সাধারণ ক্রিয়াকলাপগুলি সম্পাদন করার জন্য আপনার অ্যাপ্লিকেশনটি ডিজাইন করে, আপনি ব্যবহারকারীদের একটি সামঞ্জস্যপূর্ণ, শক্তিশালী ইউজার ইন্টারফেস প্রদান করেন। এটি সুপারিশকৃত পদ্ধতি। আরও তথ্যের জন্য, ক্যালেন্ডার ইন্টেন্টস দেখুন।
  • অ্যাডাপ্টার সিঙ্ক করুন। একটি সিঙ্ক অ্যাডাপ্টার অন্য সার্ভার বা ডেটা উত্সের সাথে ব্যবহারকারীর ডিভাইসে ক্যালেন্ডার ডেটা সিঙ্ক্রোনাইজ করে। CalendarContract.Calendars এবং CalendarContract.Events টেবিলে, সিঙ্ক অ্যাডাপ্টার ব্যবহারের জন্য সংরক্ষিত কলাম রয়েছে৷ প্রদানকারী এবং অ্যাপ্লিকেশন তাদের সংশোধন করা উচিত নয়. প্রকৃতপক্ষে, তারা দৃশ্যমান হয় না যদি না তারা একটি সিঙ্ক অ্যাডাপ্টার হিসাবে অ্যাক্সেস করা হয়। সিঙ্ক অ্যাডাপ্টার সম্পর্কে আরও তথ্যের জন্য, সিঙ্ক অ্যাডাপ্টার দেখুন।

ব্যবহারকারীর অনুমতি

ক্যালেন্ডার ডেটা পড়তে, একটি অ্যাপ্লিকেশনকে অবশ্যই তার ম্যানিফেস্ট ফাইলে READ_CALENDAR অনুমতি অন্তর্ভুক্ত করতে হবে৷ ক্যালেন্ডার ডেটা মুছে ফেলা, সন্নিবেশ করা বা আপডেট করার জন্য এটিতে অবশ্যই WRITE_CALENDAR অনুমতি অন্তর্ভুক্ত থাকতে হবে:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"...>
    <uses-sdk android:minSdkVersion="14" />
    <uses-permission android:name="android.permission.READ_CALENDAR" />
    <uses-permission android:name="android.permission.WRITE_CALENDAR" />
    ...
</manifest>

ক্যালেন্ডার টেবিল

CalendarContract.Calendars টেবিলে স্বতন্ত্র ক্যালেন্ডারের বিবরণ রয়েছে। নিম্নলিখিত ক্যালেন্ডার কলামগুলি একটি অ্যাপ্লিকেশন এবং একটি সিঙ্ক অ্যাডাপ্টার উভয় দ্বারা লেখার যোগ্য৷ সমর্থিত ক্ষেত্রগুলির সম্পূর্ণ তালিকার জন্য, CalendarContract.Calendars রেফারেন্স দেখুন।

ধ্রুবক বর্ণনা
NAME ক্যালেন্ডারের নাম।
CALENDAR_DISPLAY_NAME এই ক্যালেন্ডারের নাম যা ব্যবহারকারীর কাছে প্রদর্শিত হয়।
VISIBLE একটি বুলিয়ান নির্দেশ করে যে ক্যালেন্ডারটি প্রদর্শনের জন্য নির্বাচিত হয়েছে কিনা। 0 এর মান নির্দেশ করে যে এই ক্যালেন্ডারের সাথে সম্পর্কিত ইভেন্টগুলি দেখানো উচিত নয়৷ 1 এর মান নির্দেশ করে যে এই ক্যালেন্ডারের সাথে সম্পর্কিত ইভেন্টগুলি দেখানো উচিত। এই মান CalendarContract.Instances টেবিলে সারি তৈরিকে প্রভাবিত করে।
SYNC_EVENTS একটি বুলিয়ান নির্দেশ করে যে ক্যালেন্ডারটি সিঙ্ক করা উচিত এবং ডিভাইসে এর ইভেন্টগুলি সংরক্ষণ করা উচিত কিনা৷ 0 এর মান বলছে এই ক্যালেন্ডার সিঙ্ক করবেন না বা ডিভাইসে এর ইভেন্টগুলি সঞ্চয় করবেন না৷ 1 এর মান বলছে এই ক্যালেন্ডারের জন্য ইভেন্টগুলি সিঙ্ক করুন এবং ডিভাইসে এর ইভেন্টগুলি সঞ্চয় করুন৷

সমস্ত ক্রিয়াকলাপের জন্য একটি অ্যাকাউন্টের ধরন অন্তর্ভুক্ত করুন

আপনি যদি একটি Calendars.ACCOUNT_NAME এ প্রশ্ন করেন, তাহলে আপনাকে অবশ্যই নির্বাচনের মধ্যে Calendars.ACCOUNT_TYPE অন্তর্ভুক্ত করতে হবে৷ কারণ একটি প্রদত্ত অ্যাকাউন্ট শুধুমাত্র তার ACCOUNT_NAME এবং ACCOUNT_TYPE উভয় ক্ষেত্রেই অনন্য বলে বিবেচিত হয়। ACCOUNT_TYPE হল অ্যাকাউন্ট প্রমাণীকরণকারীর সাথে সম্পর্কিত একটি স্ট্রিং যা অ্যাকাউন্টটি AccountManager নিবন্ধিত হওয়ার সময় ব্যবহৃত হয়েছিল। ACCOUNT_TYPE_LOCAL নামে একটি বিশেষ ধরনের অ্যাকাউন্ট রয়েছে যেটি ক্যালেন্ডারগুলির জন্য ডিভাইস অ্যাকাউন্টের সাথে যুক্ত নয়৷ ACCOUNT_TYPE_LOCAL অ্যাকাউন্টগুলি সিঙ্ক করা হয় না৷

একটি ক্যালেন্ডার জিজ্ঞাসা করুন

এখানে একটি উদাহরণ রয়েছে যা দেখায় যে কীভাবে একটি নির্দিষ্ট ব্যবহারকারীর মালিকানাধীন ক্যালেন্ডারগুলি পেতে হয়৷ সরলতার জন্য, এই উদাহরণে ক্যোয়ারী অপারেশনটি ইউজার ইন্টারফেস থ্রেডে ("প্রধান থ্রেড") দেখানো হয়েছে। অনুশীলনে, এটি মূল থ্রেডের পরিবর্তে একটি অ্যাসিঙ্ক্রোনাস থ্রেডে করা উচিত। আরও আলোচনার জন্য, লোডার দেখুন। আপনি যদি কেবল ডেটা পড়ছেন না তবে এটি সংশোধন করছেন, AsyncQueryHandler দেখুন।

কোটলিন

// Projection array. Creating indices for this array instead of doing
// dynamic lookups improves performance.
private val EVENT_PROJECTION: Array<String> = arrayOf(
        CalendarContract.Calendars._ID,                     // 0
        CalendarContract.Calendars.ACCOUNT_NAME,            // 1
        CalendarContract.Calendars.CALENDAR_DISPLAY_NAME,   // 2
        CalendarContract.Calendars.OWNER_ACCOUNT            // 3
)

// The indices for the projection array above.
private const val PROJECTION_ID_INDEX: Int = 0
private const val PROJECTION_ACCOUNT_NAME_INDEX: Int = 1
private const val PROJECTION_DISPLAY_NAME_INDEX: Int = 2
private const val PROJECTION_OWNER_ACCOUNT_INDEX: Int = 3

জাভা

// Projection array. Creating indices for this array instead of doing
// dynamic lookups improves performance.
public static final String[] EVENT_PROJECTION = new String[] {
    Calendars._ID,                           // 0
    Calendars.ACCOUNT_NAME,                  // 1
    Calendars.CALENDAR_DISPLAY_NAME,         // 2
    Calendars.OWNER_ACCOUNT                  // 3
};

// The indices for the projection array above.
private static final int PROJECTION_ID_INDEX = 0;
private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1;
private static final int PROJECTION_DISPLAY_NAME_INDEX = 2;
private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3;

উদাহরণের পরবর্তী অংশে, আপনি আপনার ক্যোয়ারী তৈরি করেন। নির্বাচন প্রশ্নের জন্য মানদণ্ড নির্দিষ্ট করে। এই উদাহরণে ক্যোয়ারী এমন ক্যালেন্ডারের সন্ধান করছে যেগুলিতে ACCOUNT_NAME "hera@example.com", ACCOUNT_TYPE "com.example" এবং OWNER_ACCOUNT "hera@example.com" আছে৷ আপনি যদি একজন ব্যবহারকারী দেখেছেন এমন সমস্ত ক্যালেন্ডার দেখতে চান, শুধুমাত্র ব্যবহারকারীর মালিকানাধীন ক্যালেন্ডার নয়, OWNER_ACCOUNT বাদ দিন। ক্যোয়ারীটি একটি Cursor অবজেক্ট প্রদান করে যা আপনি ডাটাবেস ক্যোয়ারী দ্বারা প্রত্যাবর্তিত ফলাফল সেটটি অতিক্রম করতে ব্যবহার করতে পারেন। বিষয়বস্তু প্রদানকারীদের মধ্যে প্রশ্নগুলি ব্যবহার করার বিষয়ে আরও আলোচনার জন্য, সামগ্রী প্রদানকারী দেখুন৷

কোটলিন

// Run query
val uri: Uri = CalendarContract.Calendars.CONTENT_URI
val selection: String = "((${CalendarContract.Calendars.ACCOUNT_NAME} = ?) AND (" +
        "${CalendarContract.Calendars.ACCOUNT_TYPE} = ?) AND (" +
        "${CalendarContract.Calendars.OWNER_ACCOUNT} = ?))"
val selectionArgs: Array<String> = arrayOf("hera@example.com", "com.example", "hera@example.com")
val cur: Cursor = contentResolver.query(uri, EVENT_PROJECTION, selection, selectionArgs, null)

জাভা

// Run query
Cursor cur = null;
ContentResolver cr = getContentResolver();
Uri uri = Calendars.CONTENT_URI;
String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND ("
                        + Calendars.ACCOUNT_TYPE + " = ?) AND ("
                        + Calendars.OWNER_ACCOUNT + " = ?))";
String[] selectionArgs = new String[] {"hera@example.com", "com.example",
        "hera@example.com"};
// Submit the query and get a Cursor object back.
cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);

এই পরবর্তী বিভাগটি ফলাফল সেটের মাধ্যমে ধাপে ধাপে কার্সার ব্যবহার করে। এটি প্রতিটি ক্ষেত্রের মান ফেরাতে উদাহরণের শুরুতে সেট আপ করা ধ্রুবকগুলি ব্যবহার করে।

কোটলিন

// Use the cursor to step through the returned records
while (cur.moveToNext()) {
    // Get the field values
    val calID: Long = cur.getLong(PROJECTION_ID_INDEX)
    val displayName: String = cur.getString(PROJECTION_DISPLAY_NAME_INDEX)
    val accountName: String = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX)
    val ownerName: String = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX)
    // Do something with the values...
}

জাভা

// Use the cursor to step through the returned records
while (cur.moveToNext()) {
    long calID = 0;
    String displayName = null;
    String accountName = null;
    String ownerName = null;

    // Get the field values
    calID = cur.getLong(PROJECTION_ID_INDEX);
    displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX);
    accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX);
    ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX);

    // Do something with the values...

   ...
}

একটি ক্যালেন্ডার পরিবর্তন করুন

একটি ক্যালেন্ডারের আপডেট করার জন্য, আপনি ক্যালেন্ডারের _ID প্রদান করতে পারেন Uri-তে একটি সংযুক্ত ID হিসাবে ( withAppendedId() ) বা প্রথম নির্বাচন আইটেম হিসাবে। নির্বাচন "_id=?" দিয়ে শুরু হওয়া উচিত? , এবং প্রথম selectionArg ক্যালেন্ডারের _ID হওয়া উচিত। আপনি URI-তে আইডি এনকোড করেও আপডেট করতে পারেন। এই উদাহরণটি ( withAppendedId() ) পদ্ধতি ব্যবহার করে একটি ক্যালেন্ডারের প্রদর্শন নাম পরিবর্তন করে:

কোটলিন

const val DEBUG_TAG: String = "MyActivity"
...
val calID: Long = 2
val values = ContentValues().apply {
    // The new display name for the calendar
    put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, "Trevor's Calendar")
}
val updateUri: Uri = ContentUris.withAppendedId(CalendarContract.Calendars.CONTENT_URI, calID)
val rows: Int = contentResolver.update(updateUri, values, null, null)
Log.i(DEBUG_TAG, "Rows updated: $rows")

জাভা

private static final String DEBUG_TAG = "MyActivity";
...
long calID = 2;
ContentValues values = new ContentValues();
// The new display name for the calendar
values.put(Calendars.CALENDAR_DISPLAY_NAME, "Trevor's Calendar");
Uri updateUri = ContentUris.withAppendedId(Calendars.CONTENT_URI, calID);
int rows = getContentResolver().update(updateUri, values, null, null);
Log.i(DEBUG_TAG, "Rows updated: " + rows);

একটি ক্যালেন্ডার ঢোকান

ক্যালেন্ডারগুলি প্রাথমিকভাবে একটি সিঙ্ক অ্যাডাপ্টার দ্বারা পরিচালিত হওয়ার জন্য ডিজাইন করা হয়েছে, তাই আপনার শুধুমাত্র একটি সিঙ্ক অ্যাডাপ্টার হিসাবে নতুন ক্যালেন্ডারগুলি সন্নিবেশ করা উচিত৷ বেশিরভাগ ক্ষেত্রে, অ্যাপ্লিকেশনগুলি শুধুমাত্র ক্যালেন্ডারে অতিমাত্রায় পরিবর্তন করতে পারে, যেমন প্রদর্শনের নাম পরিবর্তন করা। যদি একটি অ্যাপ্লিকেশনের একটি স্থানীয় ক্যালেন্ডার তৈরি করতে হয়, তাহলে এটি ACCOUNT_TYPE_LOCAL এর একটি ACCOUNT_TYPE ব্যবহার করে একটি সিঙ্ক অ্যাডাপ্টার হিসাবে ক্যালেন্ডার সন্নিবেশ সম্পাদন করে এটি করতে পারে। ACCOUNT_TYPE_LOCAL ক্যালেন্ডারগুলির জন্য একটি বিশেষ অ্যাকাউন্টের ধরন যা একটি ডিভাইস অ্যাকাউন্টের সাথে যুক্ত নয়৷ এই ধরনের ক্যালেন্ডার একটি সার্ভারে সিঙ্ক করা হয় না. সিঙ্ক অ্যাডাপ্টারের আলোচনার জন্য, সিঙ্ক অ্যাডাপ্টার দেখুন।

ইভেন্ট টেবিল

CalendarContract.Events টেবিলে পৃথক ইভেন্টের বিবরণ রয়েছে। ইভেন্টগুলি যোগ করতে, আপডেট করতে বা মুছতে, একটি অ্যাপ্লিকেশনকে অবশ্যই তার ম্যানিফেস্ট ফাইলে WRITE_CALENDAR অনুমতি অন্তর্ভুক্ত করতে হবে৷

নিম্নলিখিত ইভেন্ট কলামগুলি একটি অ্যাপ্লিকেশন এবং একটি সিঙ্ক অ্যাডাপ্টার উভয় দ্বারা লেখার যোগ্য৷ সমর্থিত ক্ষেত্রগুলির একটি সম্পূর্ণ তালিকার জন্য, CalendarContract.Events রেফারেন্স দেখুন।

ধ্রুবক বর্ণনা
CALENDAR_ID ইভেন্টটি যে ক্যালেন্ডারের _ID
ORGANIZER অনুষ্ঠানের আয়োজক (মালিক) এর ইমেল।
TITLE অনুষ্ঠানের শিরোনাম।
EVENT_LOCATION যেখানে ঘটনাটি ঘটে।
DESCRIPTION ঘটনার বর্ণনা।
DTSTART যুগ থেকে UTC মিলিসেকেন্ডে ইভেন্ট শুরু হওয়ার সময়।
DTEND যুগের পর থেকে UTC মিলিসেকেন্ডে ইভেন্টটি শেষ হওয়ার সময়।
EVENT_TIMEZONE ইভেন্টের জন্য সময় অঞ্চল।
EVENT_END_TIMEZONE ইভেন্টের শেষ সময়ের জন্য সময় অঞ্চল।
DURATION RFC5545 বিন্যাসে ইভেন্টের সময়কাল। উদাহরণ স্বরূপ, "PT1H" এর একটি মান বলে যে ইভেন্টটি এক ঘন্টা স্থায়ী হওয়া উচিত এবং "P2W" এর মান 2 সপ্তাহের সময়কাল নির্দেশ করে৷
ALL_DAY 1 এর মান নির্দেশ করে যে এই ইভেন্টটি স্থানীয় সময় অঞ্চল দ্বারা সংজ্ঞায়িত হিসাবে সমগ্র দিনটি দখল করে। 0 এর মান নির্দেশ করে যে এটি একটি নিয়মিত ইভেন্ট যা দিনের যেকোনো সময় শুরু এবং শেষ হতে পারে।
RRULE ইভেন্ট বিন্যাসের জন্য পুনরাবৃত্তি নিয়ম। উদাহরণস্বরূপ, "FREQ=WEEKLY;COUNT=10;WKST=SU" । আপনি এখানে আরো উদাহরণ খুঁজে পেতে পারেন.
RDATE ঘটনার পুনরাবৃত্তির তারিখ। আপনি সাধারণত পুনরাবৃত্তি সংঘটনের একটি সামগ্রিক সেট সংজ্ঞায়িত করতে RRULE এর সাথে RDATE ব্যবহার করেন। আরও আলোচনার জন্য, RFC5545 বিশেষত্ব দেখুন।
AVAILABILITY যদি এই ইভেন্টটি ব্যস্ত সময় হিসাবে গণনা করা হয় বা অবসর সময় যা নির্ধারিত করা যেতে পারে।
GUESTS_CAN_MODIFY অতিথিরা ইভেন্টটি পরিবর্তন করতে পারে কিনা।
GUESTS_CAN_INVITE_OTHERS অতিথিরা অন্য অতিথিদের আমন্ত্রণ জানাতে পারেন কিনা৷
GUESTS_CAN_SEE_GUESTS অতিথিরা উপস্থিতদের তালিকা দেখতে পারেন কিনা৷

ঘটনা যোগ করুন

যখন আপনার অ্যাপ্লিকেশান একটি নতুন ইভেন্ট সন্নিবেশ করে, তখন আমরা সুপারিশ করি যে আপনি একটি INSERT ইন্টেন্ট ব্যবহার করুন, যেমনটি একটি ইভেন্ট সন্নিবেশ করার জন্য একটি অভিপ্রায় ব্যবহার করাতে বর্ণিত হয়েছে৷ যাইহোক, যদি আপনার প্রয়োজন হয়, আপনি সরাসরি ইভেন্ট সন্নিবেশ করতে পারেন। এই বিভাগে এটি কিভাবে করতে হবে তা বর্ণনা করে।

এখানে একটি নতুন ইভেন্ট সন্নিবেশ করার নিয়ম আছে:

  • আপনাকে অবশ্যই CALENDAR_ID এবং DTSTART অন্তর্ভুক্ত করতে হবে।
  • আপনাকে অবশ্যই একটি EVENT_TIMEZONE অন্তর্ভুক্ত করতে হবে। সিস্টেমের ইনস্টল করা সময় অঞ্চল আইডিগুলির একটি তালিকা পেতে, getAvailableIDs() ব্যবহার করুন। মনে রাখবেন যে আপনি যদি INSERT ইন্টেন্টের মাধ্যমে একটি ইভেন্ট সন্নিবেশ করেন তবে এই নিয়মটি প্রযোজ্য হবে না, একটি ইভেন্ট সন্নিবেশ করার জন্য একটি অভিপ্রায় ব্যবহার করার মধ্যে বর্ণিত - সেই পরিস্থিতিতে, একটি ডিফল্ট সময় অঞ্চল সরবরাহ করা হয়৷
  • অ-পুনরাবৃত্ত ইভেন্টগুলির জন্য, আপনাকে অবশ্যই DTEND অন্তর্ভুক্ত করতে হবে।
  • পুনরাবৃত্ত ইভেন্টগুলির জন্য, আপনাকে অবশ্যই RRULE বা RDATE এর সাথে একটি DURATION অন্তর্ভুক্ত করতে হবে। মনে রাখবেন যে আপনি যদি INSERT ইন্টেন্টের মাধ্যমে একটি ইভেন্ট সন্নিবেশ করেন তবে এই নিয়মটি প্রযোজ্য হবে না, একটি ইভেন্ট সন্নিবেশ করার জন্য একটি অভিপ্রায় ব্যবহার করার মধ্যে বর্ণিত — সেই পরিস্থিতিতে, আপনি DTSTART এবং DTEND এর সাথে একটি RRULE ব্যবহার করতে পারেন এবং ক্যালেন্ডার অ্যাপ্লিকেশনটি রূপান্তরিত হয় এটি স্বয়ংক্রিয়ভাবে একটি সময়কাল পর্যন্ত।

এখানে একটি ঘটনা সন্নিবেশ একটি উদাহরণ. এটি সরলতার জন্য UI থ্রেডে সঞ্চালিত হচ্ছে। অনুশীলনে, ক্রিয়াটিকে একটি ব্যাকগ্রাউন্ড থ্রেডে সরানোর জন্য একটি অ্যাসিঙ্ক্রোনাস থ্রেডে সন্নিবেশ এবং আপডেট করা উচিত। আরও তথ্যের জন্য, AsyncQueryHandler দেখুন।

কোটলিন

val calID: Long = 3
val startMillis: Long = Calendar.getInstance().run {
    set(2012, 9, 14, 7, 30)
    timeInMillis
}
val endMillis: Long = Calendar.getInstance().run {
    set(2012, 9, 14, 8, 45)
    timeInMillis
}
...

val values = ContentValues().apply {
    put(CalendarContract.Events.DTSTART, startMillis)
    put(CalendarContract.Events.DTEND, endMillis)
    put(CalendarContract.Events.TITLE, "Jazzercise")
    put(CalendarContract.Events.DESCRIPTION, "Group workout")
    put(CalendarContract.Events.CALENDAR_ID, calID)
    put(CalendarContract.Events.EVENT_TIMEZONE, "America/Los_Angeles")
}
val uri: Uri = contentResolver.insert(CalendarContract.Events.CONTENT_URI, values)

// get the event ID that is the last element in the Uri
val eventID: Long = uri.lastPathSegment.toLong()
//
// ... do something with event ID
//
//

জাভা

long calID = 3;
long startMillis = 0;
long endMillis = 0;
Calendar beginTime = Calendar.getInstance();
beginTime.set(2012, 9, 14, 7, 30);
startMillis = beginTime.getTimeInMillis();
Calendar endTime = Calendar.getInstance();
endTime.set(2012, 9, 14, 8, 45);
endMillis = endTime.getTimeInMillis();
...

ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(Events.DTSTART, startMillis);
values.put(Events.DTEND, endMillis);
values.put(Events.TITLE, "Jazzercise");
values.put(Events.DESCRIPTION, "Group workout");
values.put(Events.CALENDAR_ID, calID);
values.put(Events.EVENT_TIMEZONE, "America/Los_Angeles");
Uri uri = cr.insert(Events.CONTENT_URI, values);

// get the event ID that is the last element in the Uri
long eventID = Long.parseLong(uri.getLastPathSegment());
//
// ... do something with event ID
//
//

দ্রষ্টব্য: ইভেন্ট তৈরি হওয়ার পরে এই উদাহরণটি কীভাবে ইভেন্ট আইডি ক্যাপচার করে তা দেখুন। এটি একটি ইভেন্ট আইডি পাওয়ার সবচেয়ে সহজ উপায়। অন্যান্য ক্যালেন্ডার ক্রিয়াকলাপগুলি সম্পাদন করতে আপনার প্রায়শই ইভেন্ট আইডির প্রয়োজন হয়—উদাহরণস্বরূপ, একটি ইভেন্টে অংশগ্রহণকারী বা অনুস্মারক যোগ করার জন্য।

ইভেন্ট আপডেট করুন

যখন আপনার অ্যাপ্লিকেশন ব্যবহারকারীকে একটি ইভেন্ট সম্পাদনা করার অনুমতি দিতে চায়, তখন আমরা সুপারিশ করি যে আপনি একটি EDIT ইন্টেন্ট ব্যবহার করুন, যেমনটি বর্ণনা করা হয়েছে একটি ইভেন্ট সম্পাদনা করার জন্য একটি অভিপ্রায় ব্যবহার করুন ৷ যাইহোক, যদি আপনার প্রয়োজন হয়, আপনি সরাসরি ইভেন্টগুলি সম্পাদনা করতে পারেন। একটি ইভেন্টের আপডেট করার জন্য, আপনি ইভেন্টের _ID প্রদান করতে পারেন Uri ( withAppendedId() ) বা প্রথম নির্বাচন আইটেম হিসাবে একটি সংযুক্ত ID হিসাবে। নির্বাচন "_id=?" দিয়ে শুরু হওয়া উচিত? , এবং প্রথম selectionArg ইভেন্টের _ID হওয়া উচিত। আপনি কোন আইডি ছাড়া একটি নির্বাচন ব্যবহার করে আপডেট করতে পারেন। এখানে একটি ইভেন্ট আপডেট করার একটি উদাহরণ। এটি withAppendedId() পদ্ধতি ব্যবহার করে ইভেন্টের শিরোনাম পরিবর্তন করে:

কোটলিন

val DEBUG_TAG = "MyActivity"
...
val eventID: Long = 188
...
val values = ContentValues().apply {
    // The new title for the event
    put(CalendarContract.Events.TITLE, "Kickboxing")
}
val updateUri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID)
val rows: Int = contentResolver.update(updateUri, values, null, null)
Log.i(DEBUG_TAG, "Rows updated: $rows")

জাভা

private static final String DEBUG_TAG = "MyActivity";
...
long eventID = 188;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
Uri updateUri = null;
// The new title for the event
values.put(Events.TITLE, "Kickboxing");
updateUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
int rows = cr.update(updateUri, values, null, null);
Log.i(DEBUG_TAG, "Rows updated: " + rows);

ইভেন্ট মুছুন

আপনি একটি ইভেন্ট মুছে ফেলতে পারেন তার _ID দ্বারা URI-তে একটি সংযুক্ত ID হিসাবে, অথবা আদর্শ নির্বাচন ব্যবহার করে। আপনি যদি একটি সংযুক্ত আইডি ব্যবহার করেন তবে আপনি একটি নির্বাচনও করতে পারবেন না। মুছে ফেলার দুটি সংস্করণ রয়েছে: একটি অ্যাপ্লিকেশন হিসাবে এবং একটি সিঙ্ক অ্যাডাপ্টার হিসাবে। একটি অ্যাপ্লিকেশন মুছে ফেলা মুছে ফেলা কলামটিকে 1 এ সেট করে। এই পতাকাটি সিঙ্ক অ্যাডাপ্টারকে বলে যে সারিটি মুছে ফেলা হয়েছে এবং এই মুছে ফেলা সার্ভারে প্রচার করা উচিত। একটি সিঙ্ক অ্যাডাপ্টার ডিলিট ডাটাবেস থেকে এর সমস্ত সম্পর্কিত ডেটা সহ ইভেন্টটিকে সরিয়ে দেয়। এখানে _ID এর মাধ্যমে একটি ইভেন্ট মুছে ফেলার অ্যাপ্লিকেশনের একটি উদাহরণ রয়েছে:

কোটলিন

val DEBUG_TAG = "MyActivity"
...
val eventID: Long = 201
...
val deleteUri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID)
val rows: Int = contentResolver.delete(deleteUri, null, null)
Log.i(DEBUG_TAG, "Rows deleted: $rows")

জাভা

private static final String DEBUG_TAG = "MyActivity";
...
long eventID = 201;
...
ContentResolver cr = getContentResolver();
Uri deleteUri = null;
deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
int rows = cr.delete(deleteUri, null, null);
Log.i(DEBUG_TAG, "Rows deleted: " + rows);

অংশগ্রহণকারীদের টেবিল

CalendarContract.Attendees টেবিলের প্রতিটি সারি একটি ইভেন্টের একক অংশগ্রহণকারী বা অতিথিকে প্রতিনিধিত্ব করে৷ কলিং query() প্রদত্ত EVENT_ID সহ ইভেন্টের অংশগ্রহণকারীদের একটি তালিকা প্রদান করে। এই EVENT_ID অবশ্যই একটি নির্দিষ্ট ইভেন্টের _ID সাথে মিলবে৷

নিম্নলিখিত সারণী লেখার যোগ্য ক্ষেত্রগুলির তালিকা করে। একটি নতুন অংশগ্রহণকারীকে সন্নিবেশ করার সময়, আপনাকে অবশ্যই ATTENDEE_NAME ব্যতীত তাদের সবাইকে অন্তর্ভুক্ত করতে হবে।

ধ্রুবক বর্ণনা
EVENT_ID অনুষ্ঠানের আইডি।
ATTENDEE_NAME অংশগ্রহণকারীর নাম।
ATTENDEE_EMAIL অংশগ্রহণকারীর ইমেল ঠিকানা।
ATTENDEE_RELATIONSHIP

অনুষ্ঠানে অংশগ্রহণকারীর সম্পর্ক। এর মধ্যে একটি:

ATTENDEE_TYPE

অংশগ্রহণকারীর ধরন। এর মধ্যে একটি:

ATTENDEE_STATUS

উপস্থিতির উপস্থিতি অবস্থা। এর মধ্যে একটি:

অংশগ্রহণকারীদের যোগ করুন

এখানে একটি উদাহরণ যা একটি ইভেন্টে একজন একক অংশগ্রহণকারীকে যোগ করে। মনে রাখবেন যে EVENT_ID প্রয়োজন:

কোটলিন

val eventID: Long = 202
...
val values = ContentValues().apply {
    put(CalendarContract.Attendees.ATTENDEE_NAME, "Trevor")
    put(CalendarContract.Attendees.ATTENDEE_EMAIL, "trevor@example.com")
    put(
        CalendarContract.Attendees.ATTENDEE_RELATIONSHIP,
        CalendarContract.Attendees.RELATIONSHIP_ATTENDEE
    )
    put(CalendarContract.Attendees.ATTENDEE_TYPE, CalendarContract.Attendees.TYPE_OPTIONAL)
    put(
        CalendarContract.Attendees.ATTENDEE_STATUS,
        CalendarContract.Attendees.ATTENDEE_STATUS_INVITED
    )
    put(CalendarContract.Attendees.EVENT_ID, eventID)
}
val uri: Uri = contentResolver.insert(CalendarContract.Attendees.CONTENT_URI, values)

জাভা

long eventID = 202;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(Attendees.ATTENDEE_NAME, "Trevor");
values.put(Attendees.ATTENDEE_EMAIL, "trevor@example.com");
values.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
values.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_OPTIONAL);
values.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_INVITED);
values.put(Attendees.EVENT_ID, eventID);
Uri uri = cr.insert(Attendees.CONTENT_URI, values);

অনুস্মারক টেবিল

CalendarContract.Reminders টেবিলের প্রতিটি সারি একটি ইভেন্টের জন্য একটি একক অনুস্মারক উপস্থাপন করে। কলিং query() প্রদত্ত EVENT_ID সহ ইভেন্টের জন্য অনুস্মারকগুলির একটি তালিকা প্রদান করে।

নিম্নলিখিত সারণী অনুস্মারকগুলির জন্য লেখার যোগ্য ক্ষেত্রগুলি তালিকাভুক্ত করে৷ একটি নতুন অনুস্মারক সন্নিবেশ করার সময় তাদের সব অন্তর্ভুক্ত করা আবশ্যক. মনে রাখবেন যে সিঙ্ক অ্যাডাপ্টারগুলি CalendarContract.Calendars টেবিলে যে ধরনের অনুস্মারক সমর্থন করে তা নির্দিষ্ট করে৷ বিস্তারিত জানার জন্য ALLOWED_REMINDERS দেখুন।

ধ্রুবক বর্ণনা
EVENT_ID অনুষ্ঠানের আইডি।
MINUTES ইভেন্টের আগের মিনিট যে অনুস্মারকটি ফায়ার করা উচিত।
METHOD

সার্ভারে সেট করা অ্যালার্ম পদ্ধতি। এর মধ্যে একটি:

অনুস্মারক যোগ করুন

এই উদাহরণটি একটি ইভেন্টে একটি অনুস্মারক যোগ করে৷ ইভেন্টের 15 মিনিট আগে অনুস্মারকটি জ্বলে ওঠে।

কোটলিন

val eventID: Long = 221
...
val values = ContentValues().apply {
    put(CalendarContract.Reminders.MINUTES, 15)
    put(CalendarContract.Reminders.EVENT_ID, eventID)
    put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT)
}
val uri: Uri = contentResolver.insert(CalendarContract.Reminders.CONTENT_URI, values)

জাভা

long eventID = 221;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(Reminders.MINUTES, 15);
values.put(Reminders.EVENT_ID, eventID);
values.put(Reminders.METHOD, Reminders.METHOD_ALERT);
Uri uri = cr.insert(Reminders.CONTENT_URI, values);

উদাহরণ টেবিল

CalendarContract.Instances টেবিল একটি ইভেন্টের ঘটনার শুরু এবং শেষ সময় ধারণ করে। এই টেবিলের প্রতিটি সারি একটি একক ইভেন্ট ঘটনা প্রতিনিধিত্ব করে। দৃষ্টান্ত সারণীটি লেখার যোগ্য নয় এবং শুধুমাত্র ইভেন্টের ঘটনার অনুসন্ধান করার একটি উপায় প্রদান করে।

নিম্নলিখিত সারণীতে আপনি একটি উদাহরণের জন্য অনুসন্ধান করতে পারেন এমন কিছু ক্ষেত্র তালিকাভুক্ত করে। মনে রাখবেন সময় অঞ্চল KEY_TIMEZONE_TYPE এবং KEY_TIMEZONE_INSTANCES দ্বারা সংজ্ঞায়িত করা হয়েছে।

ধ্রুবক বর্ণনা
BEGIN উদাহরণের শুরুর সময়, UTC মিলিসেকেন্ডে।
END উদাহরণের শেষ সময়, UTC মিলিসেকেন্ডে।
END_DAY ক্যালেন্ডারের সময় অঞ্চলের সাথে সম্পর্কিত উদাহরণের জুলিয়ান শেষ দিন।
END_MINUTE ক্যালেন্ডারের সময় অঞ্চলে মধ্যরাত থেকে পরিমাপ করা উদাহরণের শেষ মিনিট।
EVENT_ID এই উদাহরণের জন্য ইভেন্টের _ID
START_DAY ক্যালেন্ডারের সময় অঞ্চলের সাপেক্ষে উদাহরণের জুলিয়ান শুরুর দিন।
START_MINUTE ক্যালেন্ডারের সময় অঞ্চলের সাপেক্ষে মধ্যরাত থেকে পরিমাপ করা উদাহরণের শুরুর মিনিট।

দৃষ্টান্ত টেবিল জিজ্ঞাসা

ইনস্ট্যান্স সারণীটি অনুসন্ধান করতে, আপনাকে URI-তে প্রশ্নের জন্য একটি পরিসীমা সময় নির্দিষ্ট করতে হবে। এই উদাহরণে, CalendarContract.Instances CalendarContract.EventsColumns ইন্টারফেসের বাস্তবায়নের মাধ্যমে TITLE ক্ষেত্রে অ্যাক্সেস পায়। অন্য কথায়, TITLE একটি ডাটাবেস ভিউয়ের মাধ্যমে ফেরত দেওয়া হয়, কাঁচা CalendarContract.Instances টেবিলের অনুসন্ধানের মাধ্যমে নয়।

কোটলিন

const val DEBUG_TAG: String = "MyActivity"
val INSTANCE_PROJECTION: Array<String> = arrayOf(
        CalendarContract.Instances.EVENT_ID, // 0
        CalendarContract.Instances.BEGIN, // 1
        CalendarContract.Instances.TITLE // 2
)

// The indices for the projection array above.
const val PROJECTION_ID_INDEX: Int = 0
const val PROJECTION_BEGIN_INDEX: Int = 1
const val PROJECTION_TITLE_INDEX: Int = 2

// Specify the date range you want to search for recurring
// event instances
val startMillis: Long = Calendar.getInstance().run {
    set(2011, 9, 23, 8, 0)
    timeInMillis
}
val endMillis: Long = Calendar.getInstance().run {
    set(2011, 10, 24, 8, 0)
    timeInMillis
}

// The ID of the recurring event whose instances you are searching
// for in the Instances table
val selection: String = "${CalendarContract.Instances.EVENT_ID} = ?"
val selectionArgs: Array<String> = arrayOf("207")

// Construct the query with the desired date range.
val builder: Uri.Builder = CalendarContract.Instances.CONTENT_URI.buildUpon()
ContentUris.appendId(builder, startMillis)
ContentUris.appendId(builder, endMillis)

// Submit the query
val cur: Cursor = contentResolver.query(
        builder.build(),
        INSTANCE_PROJECTION,
        selection,
        selectionArgs, null
)
while (cur.moveToNext()) {
    // Get the field values
    val eventID: Long = cur.getLong(PROJECTION_ID_INDEX)
    val beginVal: Long = cur.getLong(PROJECTION_BEGIN_INDEX)
    val title: String = cur.getString(PROJECTION_TITLE_INDEX)

    // Do something with the values.
    Log.i(DEBUG_TAG, "Event: $title")
    val calendar = Calendar.getInstance().apply {
        timeInMillis = beginVal
    }
    val formatter = SimpleDateFormat("MM/dd/yyyy")
    Log.i(DEBUG_TAG, "Date: ${formatter.format(calendar.time)}")
}

জাভা

private static final String DEBUG_TAG = "MyActivity";
public static final String[] INSTANCE_PROJECTION = new String[] {
    Instances.EVENT_ID,      // 0
    Instances.BEGIN,         // 1
    Instances.TITLE          // 2
  };

// The indices for the projection array above.
private static final int PROJECTION_ID_INDEX = 0;
private static final int PROJECTION_BEGIN_INDEX = 1;
private static final int PROJECTION_TITLE_INDEX = 2;
...

// Specify the date range you want to search for recurring
// event instances
Calendar beginTime = Calendar.getInstance();
beginTime.set(2011, 9, 23, 8, 0);
long startMillis = beginTime.getTimeInMillis();
Calendar endTime = Calendar.getInstance();
endTime.set(2011, 10, 24, 8, 0);
long endMillis = endTime.getTimeInMillis();

Cursor cur = null;
ContentResolver cr = getContentResolver();

// The ID of the recurring event whose instances you are searching
// for in the Instances table
String selection = Instances.EVENT_ID + " = ?";
String[] selectionArgs = new String[] {"207"};

// Construct the query with the desired date range.
Uri.Builder builder = Instances.CONTENT_URI.buildUpon();
ContentUris.appendId(builder, startMillis);
ContentUris.appendId(builder, endMillis);

// Submit the query
cur =  cr.query(builder.build(),
    INSTANCE_PROJECTION,
    selection,
    selectionArgs,
    null);

while (cur.moveToNext()) {
    String title = null;
    long eventID = 0;
    long beginVal = 0;

    // Get the field values
    eventID = cur.getLong(PROJECTION_ID_INDEX);
    beginVal = cur.getLong(PROJECTION_BEGIN_INDEX);
    title = cur.getString(PROJECTION_TITLE_INDEX);

    // Do something with the values.
    Log.i(DEBUG_TAG, "Event:  " + title);
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(beginVal);
    DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
    Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime()));
    }
 }

ক্যালেন্ডারের উদ্দেশ্য

ক্যালেন্ডার ডেটা পড়তে এবং লিখতে আপনার অ্যাপ্লিকেশনটির অনুমতির প্রয়োজন নেই৷ এটি পরিবর্তে সেই অ্যাপ্লিকেশনটিতে পড়া এবং লেখার ক্রিয়াকলাপগুলি হস্তান্তর করতে অ্যান্ড্রয়েডের ক্যালেন্ডার অ্যাপ্লিকেশন দ্বারা সমর্থিত উদ্দেশ্যগুলি ব্যবহার করতে পারে৷ নিম্নলিখিত সারণীতে ক্যালেন্ডার প্রদানকারী দ্বারা সমর্থিত উদ্দেশ্যগুলির তালিকা রয়েছে:

অ্যাকশন ইউআরআই বর্ণনা অতিরিক্ত

VIEW

content://com.android.calendar/time/<ms_since_epoch>

এছাড়াও আপনি CalendarContract.CONTENT_URI এর সাথে URI উল্লেখ করতে পারেন। এই অভিপ্রায় ব্যবহার করার একটি উদাহরণের জন্য, ক্যালেন্ডার ডেটা দেখতে ইন্টেন্ট ব্যবহার করা দেখুন।
<ms_since_epoch> দ্বারা নির্দিষ্ট সময়ে ক্যালেন্ডার খুলুন। কোনোটিই নয়।

VIEW

content://com.android.calendar/events/<event_id>

আপনি Events.CONTENT_URI এর সাথে URIও উল্লেখ করতে পারেন। এই অভিপ্রায় ব্যবহার করার একটি উদাহরণের জন্য, ক্যালেন্ডার ডেটা দেখতে ইন্টেন্ট ব্যবহার করা দেখুন।
<event_id> দ্বারা নির্দিষ্ট ইভেন্ট দেখুন। CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT

content://com.android.calendar/events/<event_id>

আপনি Events.CONTENT_URI এর সাথে URIও উল্লেখ করতে পারেন। এই অভিপ্রায় ব্যবহার করার একটি উদাহরণের জন্য, একটি ইভেন্ট সম্পাদনা করতে একটি অভিপ্রায় ব্যবহার করা দেখুন৷
<event_id> দ্বারা নির্দিষ্ট ইভেন্টটি সম্পাদনা করুন। CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT

INSERT

content://com.android.calendar/events

আপনি Events.CONTENT_URI এর সাথে URIও উল্লেখ করতে পারেন। এই উদ্দেশ্য ব্যবহার করার একটি উদাহরণের জন্য, একটি ইভেন্ট সন্নিবেশ করার জন্য একটি অভিপ্রায় ব্যবহার করা দেখুন।
একটি ইভেন্ট তৈরি করুন। নিচের সারণীতে তালিকাভুক্ত যে কোনো অতিরিক্ত।

নিম্নলিখিত সারণী ক্যালেন্ডার প্রদানকারী দ্বারা সমর্থিত অভিপ্রায় অতিরিক্তগুলি তালিকাভুক্ত করে:

অভিপ্রায় অতিরিক্ত বর্ণনা
Events.TITLE অনুষ্ঠানের নাম।
CalendarContract.EXTRA_EVENT_BEGIN_TIME ইভেন্টের সময়কাল থেকে মিলিসেকেন্ডে শুরু হয়।
CalendarContract.EXTRA_EVENT_END_TIME যুগ থেকে মিলিসেকেন্ডে ইভেন্টের শেষ সময়।
CalendarContract.EXTRA_EVENT_ALL_DAY একটি বুলিয়ান যা নির্দেশ করে যে একটি ইভেন্ট সারাদিন। মান true বা false হতে পারে।
Events.EVENT_LOCATION অনুষ্ঠানের অবস্থান।
Events.DESCRIPTION ঘটনার বিবরণ।
Intent.EXTRA_EMAIL একটি কমা-বিভক্ত তালিকা হিসাবে আমন্ত্রণ জানানোর জন্য তাদের ইমেল ঠিকানা।
Events.RRULE ঘটনার পুনরাবৃত্তির নিয়ম।
Events.ACCESS_LEVEL অনুষ্ঠানটি ব্যক্তিগত হোক বা সর্বজনীন।
Events.AVAILABILITY যদি এই ইভেন্টটি ব্যস্ত সময় হিসাবে গণনা করা হয় বা অবসর সময় যা নির্ধারিত করা যেতে পারে।

নিম্নলিখিত বিভাগগুলি কীভাবে এই উদ্দেশ্যগুলি ব্যবহার করতে হয় তা বর্ণনা করে৷

একটি ইভেন্ট সন্নিবেশ একটি অভিপ্রায় ব্যবহার করুন

INSERT ইন্টেন্ট ব্যবহার করে আপনার অ্যাপ্লিকেশনটি ইভেন্ট সন্নিবেশের কাজটি ক্যালেন্ডারে হস্তান্তর করতে দেয়। এই পদ্ধতির সাথে, আপনার অ্যাপ্লিকেশনটির ম্যানিফেস্ট ফাইলে অন্তর্ভুক্ত WRITE_CALENDAR অনুমতিরও প্রয়োজন নেই৷

যখন ব্যবহারকারীরা এই পদ্ধতি ব্যবহার করে এমন একটি অ্যাপ্লিকেশন চালান, তখন ইভেন্টটি যোগ করা শেষ করতে অ্যাপ্লিকেশনটি তাদের ক্যালেন্ডারে পাঠায়। INSERT অভিপ্রায় ক্যালেন্ডারে ইভেন্টের বিশদ বিবরণ সহ একটি ফর্ম প্রাক-পপুলেট করতে অতিরিক্ত ক্ষেত্র ব্যবহার করে। ব্যবহারকারীরা তারপর ইভেন্ট বাতিল করতে, প্রয়োজনে ফর্মটি সম্পাদনা করতে বা তাদের ক্যালেন্ডারে ইভেন্টটি সংরক্ষণ করতে পারে।

এখানে একটি কোড স্নিপেট রয়েছে যা 19 জানুয়ারী, 2012 তারিখে একটি ইভেন্ট নির্ধারণ করে, যা সকাল 7:30 থেকে সকাল 8:30 পর্যন্ত চলে এই কোড স্নিপেট সম্পর্কে নিম্নলিখিতগুলি নোট করুন:

  • এটি Events.CONTENT_URI Uri হিসাবে নির্দিষ্ট করে৷
  • এটি CalendarContract.EXTRA_EVENT_BEGIN_TIME ব্যবহার করে। EXTRA_EVENT_BEGIN_TIME এবং CalendarContract.EXTRA_EVENT_END_TIME অতিরিক্ত ক্ষেত্রগুলি ইভেন্টের সময়ের সাথে ফর্মটিকে প্রাক-পপুলেট করতে। এই সময়ের জন্য মান যুগ থেকে UTC মিলিসেকেন্ডে হতে হবে।
  • এটি ইমেল ঠিকানা দ্বারা নির্দিষ্ট আমন্ত্রিতদের একটি কমা দ্বারা পৃথক তালিকা প্রদান করতে Intent.EXTRA_EMAIL অতিরিক্ত ক্ষেত্র ব্যবহার করে৷

কোটলিন

val startMillis: Long = Calendar.getInstance().run {
    set(2012, 0, 19, 7, 30)
    timeInMillis
}
val endMillis: Long = Calendar.getInstance().run {
    set(2012, 0, 19, 8, 30)
    timeInMillis
}
val intent = Intent(Intent.ACTION_INSERT)
        .setData(CalendarContract.Events.CONTENT_URI)
        .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, startMillis)
        .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endMillis)
        .putExtra(CalendarContract.Events.TITLE, "Yoga")
        .putExtra(CalendarContract.Events.DESCRIPTION, "Group class")
        .putExtra(CalendarContract.Events.EVENT_LOCATION, "The gym")
        .putExtra(CalendarContract.Events.AVAILABILITY, CalendarContract.Events.AVAILABILITY_BUSY)
        .putExtra(Intent.EXTRA_EMAIL, "rowan@example.com,trevor@example.com")
startActivity(intent)

জাভা

Calendar beginTime = Calendar.getInstance();
beginTime.set(2012, 0, 19, 7, 30);
Calendar endTime = Calendar.getInstance();
endTime.set(2012, 0, 19, 8, 30);
Intent intent = new Intent(Intent.ACTION_INSERT)
        .setData(Events.CONTENT_URI)
        .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis())
        .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis())
        .putExtra(Events.TITLE, "Yoga")
        .putExtra(Events.DESCRIPTION, "Group class")
        .putExtra(Events.EVENT_LOCATION, "The gym")
        .putExtra(Events.AVAILABILITY, Events.AVAILABILITY_BUSY)
        .putExtra(Intent.EXTRA_EMAIL, "rowan@example.com,trevor@example.com");
startActivity(intent);

একটি ইভেন্ট সম্পাদনা করতে একটি অভিপ্রায় ব্যবহার করুন

আপডেট করা ইভেন্টে বর্ণিত হিসাবে আপনি সরাসরি একটি ইভেন্ট আপডেট করতে পারেন। কিন্তু EDIT ইন্টেন্ট ব্যবহার করে এমন একটি অ্যাপ্লিকেশনকে অনুমতি দেয় যার ক্যালেন্ডার অ্যাপ্লিকেশনে ইভেন্ট সম্পাদনা করার অনুমতি নেই। যখন ব্যবহারকারীরা ক্যালেন্ডারে তাদের ইভেন্ট সম্পাদনা শেষ করে, তখন তারা আসল অ্যাপ্লিকেশনে ফিরে আসে।

এখানে একটি উদ্দেশ্যের একটি উদাহরণ যা একটি নির্দিষ্ট ইভেন্টের জন্য একটি নতুন শিরোনাম সেট করে এবং ব্যবহারকারীদের ক্যালেন্ডারে ইভেন্টটি সম্পাদনা করতে দেয়৷

কোটলিন

val eventID: Long = 208
val uri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID)
val intent = Intent(Intent.ACTION_EDIT)
        .setData(uri)
        .putExtra(CalendarContract.Events.TITLE, "My New Title")
startActivity(intent)

জাভা

long eventID = 208;
Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
Intent intent = new Intent(Intent.ACTION_EDIT)
    .setData(uri)
    .putExtra(Events.TITLE, "My New Title");
startActivity(intent);

ক্যালেন্ডার ডেটা দেখতে ইন্টেন্ট ব্যবহার করুন

ক্যালেন্ডার প্রদানকারী VIEW ইন্টেন্ট ব্যবহার করার দুটি ভিন্ন উপায় অফার করে:

  • একটি নির্দিষ্ট তারিখে ক্যালেন্ডার খুলতে।
  • একটি ঘটনা দেখতে.

এখানে একটি উদাহরণ রয়েছে যা দেখায় কিভাবে একটি নির্দিষ্ট তারিখে ক্যালেন্ডার খুলতে হয়:

কোটলিন

val startMillis: Long
...
val builder: Uri.Builder = CalendarContract.CONTENT_URI.buildUpon()
        .appendPath("time")
ContentUris.appendId(builder, startMillis)
val intent = Intent(Intent.ACTION_VIEW)
        .setData(builder.build())
startActivity(intent)

জাভা

// A date-time specified in milliseconds since the epoch.
long startMillis;
...
Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon();
builder.appendPath("time");
ContentUris.appendId(builder, startMillis);
Intent intent = new Intent(Intent.ACTION_VIEW)
    .setData(builder.build());
startActivity(intent);

এখানে একটি উদাহরণ রয়েছে যা দেখায় কিভাবে একটি ইভেন্ট দেখার জন্য খুলতে হয়:

কোটলিন

val eventID: Long = 208
...
val uri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID)
val intent = Intent(Intent.ACTION_VIEW).setData(uri)
startActivity(intent)

জাভা

long eventID = 208;
...
Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
Intent intent = new Intent(Intent.ACTION_VIEW)
   .setData(uri);
startActivity(intent);

অ্যাডাপ্টার সিঙ্ক করুন

একটি অ্যাপ্লিকেশন এবং একটি সিঙ্ক অ্যাডাপ্টার কীভাবে ক্যালেন্ডার প্রদানকারীকে অ্যাক্সেস করে তার মধ্যে সামান্য পার্থক্য রয়েছে:

  • একটি সিঙ্ক অ্যাডাপ্টারকে CALLER_IS_SYNCADAPTER true সেট করে এটি একটি সিঙ্ক অ্যাডাপ্টার নির্দিষ্ট করতে হবে।
  • একটি সিঙ্ক অ্যাডাপ্টারকে URI-তে ক্যোয়ারী প্যারামিটার হিসাবে একটি ACCOUNT_NAME এবং একটি ACCOUNT_TYPE প্রদান করতে হবে৷
  • একটি সিঙ্ক অ্যাডাপ্টারের একটি অ্যাপ্লিকেশন বা উইজেটের চেয়ে বেশি কলামে লেখার অ্যাক্সেস রয়েছে৷ উদাহরণস্বরূপ, একটি অ্যাপ্লিকেশন শুধুমাত্র একটি ক্যালেন্ডারের কয়েকটি বৈশিষ্ট্য পরিবর্তন করতে পারে, যেমন এর নাম, প্রদর্শনের নাম, দৃশ্যমানতা সেটিং এবং ক্যালেন্ডারটি সিঙ্ক হয়েছে কিনা। তুলনা করে, একটি সিঙ্ক অ্যাডাপ্টার শুধুমাত্র সেই কলামগুলিই নয়, অন্যান্য অনেকগুলি যেমন ক্যালেন্ডারের রঙ, সময় অঞ্চল, অ্যাক্সেস স্তর, অবস্থান ইত্যাদি অ্যাক্সেস করতে পারে৷ যাইহোক, একটি সিঙ্ক অ্যাডাপ্টার এটি নির্দিষ্ট করা ACCOUNT_NAME এবং ACCOUNT_TYPE তে সীমাবদ্ধ।

এখানে একটি সহায়ক পদ্ধতি রয়েছে যা আপনি একটি সিঙ্ক অ্যাডাপ্টারের সাথে ব্যবহারের জন্য একটি URI ফেরত দিতে ব্যবহার করতে পারেন:

কোটলিন

fun asSyncAdapter(uri: Uri, account: String, accountType: String): Uri {
    return uri.buildUpon()
            .appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
            .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, account)
            .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, accountType).build()
}

জাভা

static Uri asSyncAdapter(Uri uri, String account, String accountType) {
    return uri.buildUpon()
        .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,"true")
        .appendQueryParameter(Calendars.ACCOUNT_NAME, account)
        .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
 }