পরিচিতি সরবরাহকারী হল একটি শক্তিশালী এবং নমনীয় Android কম্পোনেন্ট যা ডিভাইসের লোকজনের ডেটার সেন্ট্রাল রিপোজিটরি ম্যানেজ করে। পরিচিতি সরবরাহকারী হল ডেটার সোর্স যা আপনি ডিভাইসের পরিচিতি অ্যাপ্লিকেশনে দেখতে পান এবং আপনি নিজের অ্যাপ্লিকেশনেও এর ডেটা অ্যাক্সেস করতে পারেন এবং ডিভাইস ও অনলাইন পরিষেবার মধ্যে ডেটা ট্রান্সফার করতে পারেন। প্রদানকারী বিভিন্ন ধরনের ডেটা সোর্স ব্যবহার করে এবং প্রতিটি ব্যক্তির জন্য যতটা সম্ভব ডেটা ম্যানেজ করার চেষ্টা করে, যার ফলে এর সংগঠন জটিল হয়ে পড়ে। এই কারণে, প্রদানকারীর API-তে কনট্র্যাক্ট ক্লাস ও ইন্টারফেসের একটি বিস্তৃত সেট অন্তর্ভুক্ত থাকে যা ডেটা রিট্রিভ ও পরিবর্তন, দুটিই সহজ করে তোলে।
এই নির্দেশিকায় নিম্নলিখিত বিষয়গুলি বর্ণনা করা হয়েছে:
- প্রোভাইডারের বেসিক স্ট্রাকচার।
- পরিষেবা প্রদানকারীর থেকে কীভাবে ডেটা ফিরিয়ে আনা যায়।
- প্রোভাইডারে ডেটা কীভাবে পরিবর্তন করবেন।
- আপনার সার্ভার থেকে পরিচিতি সরবরাহকারীতে ডেটা সিঙ্ক করার জন্য কীভাবে সিঙ্ক অ্যাডাপ্টার লিখবেন।
এই গাইড ধরে নেয় যে আপনি Android কন্টেন্ট প্রোভাইডার সম্পর্কে প্রাথমিক তথ্য জানেন। Android কন্টেন্ট প্রোভাইডার সম্পর্কে আরও জানতে, কন্টেন্ট প্রোভাইডার সংক্রান্ত প্রাথমিক তথ্য গাইড পড়ুন।
পরিচিতি সরবরাহকারী সংস্থা
পরিচিতি সরবরাহকারী হল Android কন্টেন্ট প্রোভাইডার কম্পোনেন্ট। এটি কোনও ব্যক্তির সম্পর্কে তিন ধরনের ডেটা মেইনটেইন করে, যার প্রতিটি প্রদানকারীর অফার করা টেবিলের সাথে সম্পর্কিত, যেমন ছবি ১-এ দেখানো হয়েছে:
ছবি ১. পরিচিতি সরবরাহকারী টেবিল স্ট্রাকচার।
তিনটি টেবিলকে সাধারণত তাদের কনট্র্যাক্ট ক্লাসের নাম দ্বারা উল্লেখ করা হয়। ক্লাসগুলি টেবিল দ্বারা ব্যবহৃত কন্টেন্ট URI, কলামের নাম এবং কলামের মানের জন্য ধ্রুবক সংজ্ঞায়িত করে:
-
ContactsContract.Contactsটি সারণী - র কন্ট্যাক্ট সারির অ্যাগ্রিগেশনের উপর ভিত্তি করে বিভিন্ন ব্যক্তিকে উপস্থাপনকারী সারি।
-
ContactsContract.RawContactsটি সারণী - ব্যবহারকারীর অ্যাকাউন্ট ও ধরন অনুযায়ী কোনও ব্যক্তির ডেটার সারসংক্ষেপ সহ সারি।
-
ContactsContract.Dataটি সারণী - র কন্ট্যাক্টের বিবরণ সহ সারি, যেমন ইমেল আইডি বা ফোন নম্বর।
ContactsContract-এ কনট্র্যাক্ট ক্লাস দ্বারা উপস্থাপিত অন্যান্য টেবিলগুলি
হল সহায়ক টেবিল যা পরিচিতি সরবরাহকারী তার ক্রিয়াকলাপগুলি পরিচালনা করতে বা ডিভাইসের পরিচিতি বা টেলিফোনি অ্যাপ্লিকেশনগুলিতে নির্দিষ্ট ফাংশনগুলিকে সমর্থন করতে
ব্যবহার করে।
র কন্ট্যাক্ট
র কন্ট্যাক্ট হল কোনও ব্যক্তির ডেটা যা একটি অ্যাকাউন্টের ধরন ও অ্যাকাউন্টের নাম থেকে আসে। যেহেতু পরিচিতি সরবরাহকারী কোনও ব্যক্তির ডেটার সোর্স হিসেবে একাধিক অনলাইন পরিষেবার অনুমতি দেয়, তাই পরিচিতি সরবরাহকারী একই ব্যক্তির জন্য একাধিক র কন্ট্যাক্টের অনুমতি দেয়। একাধিক র কন্ট্যাক্ট একজন ব্যবহারকারীকে একই ধরনের একাধিক অ্যাকাউন্ট থেকে কোনও ব্যক্তির ডেটা একত্রিত করার অনুমতি দেয়।
র কন্ট্যাক্টের বেশিরভাগ ডেটা
ContactsContract.RawContacts টেবিলে সেভ করা হয় না। পরিবর্তে, এটি ContactsContract.Data টেবিলের এক বা একাধিক
সারিতে স্টোর করা হয়। প্রতিটি ডেটা সারিতে একটি কলাম
Data.RAW_CONTACT_ID থাকে
যেটিতে তার পেরেন্ট ContactsContract.RawContacts সারির
RawContacts._ID ভ্যালু
থাকে।
গুরুত্বপূর্ণ র কন্ট্যাক্ট কলাম
ContactsContract.RawContacts টেবিলের গুরুত্বপূর্ণ কলামগুলি
টেবিল ১-এ তালিকাভুক্ত করা হয়েছে। টেবিলের নিচে দেওয়া নোটগুলি পড়তে ভুলবেন না:
সারণী ১. গুরুত্বপূর্ণ র কন্ট্যাক্ট কলাম।
| কলামের নাম | ব্যবহার করুন | নোট |
|---|---|---|
ACCOUNT_NAME
|
এই র কন্ট্যাক্টের সোর্স যে অ্যাকাউন্টের ধরন, তার অ্যাকাউন্টের নাম।
যেমন, Google অ্যাকাউন্টের নাম হল ডিভাইস মালিকের Gmail
আইডি। আরও তথ্যের জন্য
ACCOUNT_TYPE-এর পরবর্তী এন্ট্রি
দেখুন।
|
এই নামের ফর্ম্যাটটি অ্যাকাউন্টের ধরন অনুযায়ী নির্দিষ্ট করা হয়। এটি যে ইমেল আইডিই হতে হবে এমন কোনও বাধ্যবাধকতা নেই। |
ACCOUNT_TYPE
|
এই র কন্ট্যাক্টের সোর্স হল অ্যাকাউন্টের ধরন। যেমন, Google অ্যাকাউন্টের
অ্যাকাউন্টের ধরন হল com.google। আপনার মালিকানাধীন বা নিয়ন্ত্রণাধীন ডোমেনের জন্য ডোমেন শনাক্তকারীর সাহায্যে
সবসময় আপনার অ্যাকাউন্টের ধরন যাচাই করুন। এটি করলে আপনার অ্যাকাউন্টের ধরন
অনন্য হবে।
|
যে অ্যাকাউন্টের ধরন পরিচিতি ডেটা অফার করে, সেটির সাথে সাধারণত একটি সিঙ্ক অ্যাডাপ্টার থাকে যা পরিচিতি সরবরাহকারীর সাথে সিঙ্ক করে। |
DELETED
|
র কন্ট্যাক্টের জন্য "মুছে ফেলা হয়েছে" ফ্ল্যাগ। | এই ফ্ল্যাগ, সিঙ্ক অ্যাডাপ্টার তার সার্ভার থেকে সারি মুছে না দেওয়া পর্যন্ত, পরিচিতি সরবরাহকারীকে ইন্টার্নালি সারি বজায় রাখতে দেয় এবং তারপর অবশেষে রিপোজিটরি থেকে সারি মুছে দেয়। |
নোট
ContactsContract.RawContacts টেবিল সম্পর্কে
গুরুত্বপূর্ণ তথ্য নিচে দেওয়া হল:
-
ContactsContract.RawContacts-এর সংশ্লিষ্ট সারিতে র কন্ট্যাক্টের নাম সেভ করা নেই। পরিবর্তে, এটিContactsContract.DataটেবিলেরContactsContract.CommonDataKinds.StructuredNameসারিতে স্টোর করা হয়।ContactsContract.Dataটেবিলে এই ধরনের র কন্ট্যাক্টের শুধুমাত্র একটি সারি থাকে। -
সতর্কতা: র কন্ট্যাক্ট সারিতে আপনার নিজের অ্যাকাউন্ট ডেটা ব্যবহার করতে, এটি প্রথমে
AccountManager-এর সাথে রেজিস্টার করতে হবে। এটি করতে, ব্যবহারকারীদের অ্যাকাউন্টের তালিকায় অ্যাকাউন্টের ধরন ও তাদের অ্যাকাউন্টের নাম যোগ করার জন্য প্রম্পট করুন। আপনি এটি না করলে, পরিচিতি সরবরাহকারী অটোমেটিক আপনার র কন্ট্যাক্ট সারি মুছে দেবে।যেমন, আপনি যদি চান যে আপনার অ্যাপ
com.example.dataserviceডোমেন সহ আপনার ওয়েব-ভিত্তিক পরিষেবার জন্য পরিচিতির ডেটা বজায় রাখুক এবং আপনার পরিষেবার জন্য ব্যবহারকারীর অ্যাকাউন্টbecky.sharp@dataservice.example.comহয়, তাহলে আপনার অ্যাপ র কন্ট্যাক্ট সারি যোগ করার আগে ব্যবহারকারীকে প্রথমে অ্যাকাউন্টের "ধরন" (com.example.dataservice) এবং অ্যাকাউন্টের "নাম" (becky.smart@dataservice.example.com) যোগ করতে হবে। আপনি ডকুমেন্টেশনে ব্যবহারকারীকে এই প্রয়োজনীয়তা ব্যাখ্যা করতে পারেন, অথবা আপনি ব্যবহারকারীকে ধরন এবং নাম বা উভয়ই যোগ করার জন্য প্রম্পট করতে পারেন। অ্যাকাউন্টের ধরন ও অ্যাকাউন্টের নাম পরবর্তী বিভাগে আরও বিস্তারিতভাবে বর্ণনা করা হয়েছে।
র কন্ট্যাক্ট ডেটার সোর্স
র কন্ট্যাক্ট কীভাবে কাজ করে তা বুঝতে, "Emily Dickinson" ব্যবহারকারীর কথা ভাবুন, যার ডিভাইসে নিম্নলিখিত তিনটি ব্যবহারকারীর অ্যাকাউন্ট আছে:
emily.dickinson@gmail.comemilyd@gmail.com- "belle_of_amherst" Twitter অ্যাকাউন্ট
এই ব্যবহারকারী অ্যাকাউন্ট সেটিংস থেকে এই তিনটি অ্যাকাউন্টের জন্যই পরিচিতি সিঙ্ক করুন বিকল্প চালু করেছেন।
ধরা যাক, Emily Dickinson একটি ব্রাউজার উইন্ডো খুলে,
emily.dickinson@gmail.com হিসেবে Gmail-এ লগ-ইন করে,
Contacts খুলে, "Thomas Higginson"-কে যোগ করে। পরে, তিনি emilyd@gmail.com হিসেবে Gmail-এ লগ-ইন করেন এবং "Thomas Higginson"-কে ইমেল পাঠান, যা অটোমেটিক তাকে পরিচিতি হিসেবে যোগ করে। এছাড়াও, তিনি Twitter-এ "colonel_tom" (Thomas Higginson-এর Twitter ID) ফলো করেন।
এই কাজের ফলে পরিচিতি সরবরাহকারী তিনটি র কন্ট্যাক্ট তৈরি করে:
-
emily.dickinson@gmail.com-এর সাথে যুক্ত "Thomas Higginson"-এর জন্য একটি র কন্ট্যাক্ট। ব্যবহারকারীর অ্যাকাউন্টের ধরন হল Google। -
emilyd@gmail.com-এর সাথে যুক্ত "Thomas Higginson"-এর জন্য দ্বিতীয় র কন্ট্যাক্ট। ব্যবহারকারীর অ্যাকাউন্টের ধরনও Google। আগের নামের সাথে একই নাম হওয়া সত্ত্বেও দ্বিতীয় র কন্ট্যাক্ট আছে, কারণ অন্য ব্যবহারকারীর অ্যাকাউন্টের জন্য ব্যক্তিকে যোগ করা হয়েছে। - "belle_of_amherst"-এর সাথে যুক্ত "Thomas Higginson"-এর জন্য তৃতীয় র কন্ট্যাক্ট। ব্যবহারকারীর অ্যাকাউন্টের ধরন হল Twitter।
ডেটা
আগে যেমন উল্লেখ করা হয়েছে, র কন্ট্যাক্টের ডেটা
ContactsContract.Data সারিতে স্টোর করা হয় যা র কন্ট্যাক্টের
_ID ভ্যালুর সাথে লিঙ্ক করা থাকে। এটি একটি র কন্ট্যাক্টকে একই ধরনের ডেটার একাধিক ইনস্ট্যান্স রাখার অনুমতি দেয়,
যেমন ইমেল আইডি বা ফোন নম্বর। যেমন, emilyd@gmail.com-এর জন্য
"Thomas Higginson"-এর (Google অ্যাকাউন্ট emilyd@gmail.com-এর সাথে যুক্ত
Thomas Higginson-এর র কন্ট্যাক্ট সারি) বাড়ির ইমেল আইডি
thigg@gmail.com এবং অফিসের ইমেল আইডি
thomas.higginson@gmail.com হলে, পরিচিতি সরবরাহকারী দুটি ইমেল আইডির সারি স্টোর করে
এবং দুটিকেই র কন্ট্যাক্টের সাথে লিঙ্ক করে।
লক্ষ্য করুন যে এই একটি টেবিলে বিভিন্ন ধরনের ডেটা স্টোর করা আছে। যে নাম দেখানো হবে,
ফোন নম্বর, ইমেল, পোস্টাল ঠিকানা, ফটো এবং ওয়েবসাইট বিবরণের সারিগুলি সবই
ContactsContract.Data টেবিলে পাওয়া যাবে। এটি ম্যানেজ করতে সাহায্য করার জন্য,
ContactsContract.Data টেবিলে কিছু কলামের বর্ণনামূলক নাম আছে,
এবং অন্যদের সাধারণ নাম আছে। বর্ণনামূলক-নাম কলামের কন্টেন্টের অর্থ একই থাকে,
তা সারিতে থাকা ডেটার ধরন যাই হোক না কেন, যেখানে সাধারণ-নাম কলামের কন্টেন্টের অর্থ
ডেটার ধরনের উপর নির্ভর করে আলাদা হয়।
কলামের নাম বিশদে ব্যাখ্যা করা
বর্ণনামূলক কলামের নামের কিছু উদাহরণ হল:
-
RAW_CONTACT_ID -
এই ডেটার জন্য র কন্ট্যাক্টের
_IDকলামের ভ্যালু। -
MIMETYPE -
এই সারিতে স্টোর করা ডেটার ধরন, কাস্টম MIME টাইপ হিসেবে প্রকাশ করা হয়েছে। পরিচিতি সরবরাহকারী
ContactsContract.CommonDataKinds-এর সাবক্লাসে সংজ্ঞায়িত MIME-এর প্রকার ব্যবহার করে। এই MIME-এর প্রকারগুলি ওপেন সোর্স, এবং পরিচিতি সরবরাহকারীর সাথে কাজ করে এমন যেকোনও অ্যাপ্লিকেশন বা সিঙ্ক অ্যাডাপ্টার দ্বারা ব্যবহার করা যেতে পারে। -
IS_PRIMARY -
কোনও র কন্ট্যাক্টের জন্য এই ধরনের ডেটা সারি একাধিকবার দেখা গেলে,
IS_PRIMARYকলাম সেই ডেটা সারিকে ফ্ল্যাগ করে যাতে এই ধরনের ডেটার জন্য প্রাথমিক ডেটা থাকে। যেমন, ব্যবহারকারী কোনও পরিচিতির ফোন নম্বরে বেশিক্ষণ প্রেস করে ডিফল্ট হিসেবে সেট করুন বিকল্প বেছে নিলে, সেই নম্বর সহContactsContract.DataসারিরIS_PRIMARYকলামের মান শূন্য ছাড়া অন্য কিছুতে সেট করা হয়।
জেনেরিক কলামের নাম
DATA1 থেকে DATA15 পর্যন্ত ১৫টি জেনেরিক কলাম আছে যা সাধারণত উপলভ্য থাকে এবং আরও চারটি জেনেরিক কলাম SYNC1 থেকে SYNC4 পর্যন্ত আছে যা শুধুমাত্র সিঙ্ক অ্যাডাপ্টারের ব্যবহার করা উচিত। রোতে যে ধরনের ডেটাই থাকুক না কেন, জেনেরিক কলামের নামের কনস্ট্যান্ট সবসময়
কাজ করে।
DATA1 কলামটি ইন্ডেক্স করা হয়েছে। পরিচিতি সরবরাহকারী সবসময় এই কলামটি সেই ডেটার জন্য ব্যবহার করে
যেটি সরবরাহকারী আশা করে যে কোনও কোয়েরির সবচেয়ে ঘন ঘন টার্গেট হবে। যেমন,
ইমেল সারিতে, এই কলামে আসল ইমেল আইডি থাকে।
প্রথাগতভাবে, DATA15 কলামটি ফটো থাম্বনেলের মতো বাইনারি লার্জ অবজেক্ট
(BLOB) ডেটা স্টোর করার জন্য সংরক্ষিত থাকে।
ধরন-নির্দিষ্ট কলামের নাম
নির্দিষ্ট ধরনের সারির কলামের সাথে কাজ করার সুবিধা দিতে, Contacts Provider
টাইপ-নির্দিষ্ট কলামের নাম কনস্ট্যান্টও প্রদান করে, যা
ContactsContract.CommonDataKinds-এর সাবক্লাসে সংজ্ঞায়িত করা হয়েছে। কনস্ট্যান্ট একই কলামের নামের জন্য একটি
আলাদা কনস্ট্যান্ট নাম দেয়, যা আপনাকে নির্দিষ্ট ধরনের একটি সারিতে ডেটা অ্যাক্সেস করতে
সাহায্য করে।
যেমন, ContactsContract.CommonDataKinds.Email ক্লাস, ContactsContract.Data সারির জন্য
টাইপ-নির্দিষ্ট কলামের নাম কনস্ট্যান্টকে সংজ্ঞায়িত করে
যার MIME টাইপ হল
Email.CONTENT_ITEM_TYPE। ক্লাসে ইমেল আইডি কলামের জন্য
ADDRESS কনস্ট্যান্ট
আছে। ADDRESS-এর আসল ভ্যালু হল
"data1", যা কলামের
সাধারণ নামের মতোই।
সতর্কতা: প্রোভাইডারের আগে থেকে নির্ধারিত MIME টাইপ আছে এমন সারি ব্যবহার করে
ContactsContract.Data টেবিলে আপনার নিজস্ব কাস্টম ডেটা
যোগ করবেন না। আপনি যদি তা করেন, তাহলে আপনি ডেটা হারাতে পারেন বা প্রদানকারীর
ত্রুটি হতে পারে। যেমন, DATA1 কলামে ইমেল আইডির পরিবর্তে ইউজারনেম আছে এমন
Email.CONTENT_ITEM_TYPE MIME টাইপ সহ কোনও সারি যোগ করা উচিত নয়। আপনি যদি সারির জন্য নিজের কাস্টম MIME-এর প্রকার ব্যবহার করেন, তাহলে আপনি নিজের প্রকার-নির্দিষ্ট কলামের নাম
সংজ্ঞায়িত করতে এবং আপনার ইচ্ছামতো কলাম ব্যবহার করতে পারবেন।
ছবি ২-এ দেখানো হয়েছে যে কীভাবে বর্ণনামূলক কলাম এবং ডেটা কলাম একটি
ContactsContract.Data সারিতে দেখা যায় এবং কীভাবে ধরন-নির্দিষ্ট কলামের নাম জেনেরিক কলামের নামের উপর "ওভারলে" করে
ছবি ২. টাইপ-নির্দিষ্ট কলামের নাম এবং সাধারণ কলামের নাম।
টাইপ-নির্দিষ্ট কলামের নামের ক্লাস
সারণী ২-এ সবচেয়ে বেশি ব্যবহৃত ধরন-নির্দিষ্ট কলামের নামের ক্লাস তালিকাভুক্ত করা হয়েছে:
টেবিল ২. টাইপ-নির্দিষ্ট কলামের নামের ক্লাস
| ম্যাপিং ক্লাস | ডেটার ধরন | নোট |
|---|---|---|
ContactsContract.CommonDataKinds.StructuredName |
এই ডেটা সারির সাথে যুক্ত র কন্ট্যাক্টের নামের ডেটা। | র কন্ট্যাক্টে এই ধরনের একটিই সারি থাকে। |
ContactsContract.CommonDataKinds.Photo |
এই ডেটা সারির সাথে যুক্ত র কন্ট্যাক্টের মূল ফটো। | র কন্ট্যাক্টে এই ধরনের একটিই সারি থাকে। |
ContactsContract.CommonDataKinds.Email |
এই ডেটা সারির সাথে যুক্ত র কন্ট্যাক্টের ইমেল আইডি। | একটি র কন্ট্যাক্টে একাধিক ইমেল আইডি থাকতে পারে। |
ContactsContract.CommonDataKinds.StructuredPostal |
এই ডেটা সারির সাথে যুক্ত র কন্ট্যাক্টের ডাক ঠিকানা। | একটি র কন্ট্যাক্টে একাধিক ডাক ঠিকানা থাকতে পারে। |
ContactsContract.CommonDataKinds.GroupMembership |
একটি শনাক্তকারী যা র কন্ট্যাক্টকে পরিচিতি সরবরাহকারীর কোনও একটি গ্রুপের সাথে লিঙ্ক করে। | গ্রুপ হল অ্যাকাউন্টের ধরন ও অ্যাকাউন্টের নামের একটি ঐচ্ছিক ফিচার। পরিচিতি গ্রুপ বিভাগে এই বিষয়ে আরও বিস্তারিতভাবে বর্ণনা করা হয়েছে। |
পরিচিতি
পরিচিতি সরবরাহকারী সব ধরনের অ্যাকাউন্ট ও অ্যাকাউন্টের নাম জুড়ে র কন্ট্যাক্ট সারি একত্রিত করে পরিচিতি তৈরি করে। এটি কোনও ব্যক্তির জন্য ব্যবহারকারীর সংগ্রহ করা সমস্ত ডেটা প্রদর্শন এবং সংশোধন করার সুবিধা প্রদান করে। পরিচিতি সরবরাহকারী নতুন পরিচিতির সারি তৈরি করা এবং আগে থেকে থাকা পরিচিতির সারির সাথে র কন্ট্যাক্ট একত্রিত করার বিষয়টি ম্যানেজ করে। অ্যাপ্লিকেশন বা সিঙ্ক অ্যাডাপ্টার, কোনওটিকেই পরিচিতি যোগ করার অনুমতি দেওয়া হয় না এবং পরিচিতির সারির কিছু কলাম শুধুমাত্র পড়ার জন্য।
মনে রাখবেন: আপনি যদি
insert() সহ Contacts Provider-এ কোনও পরিচিতি যোগ করার চেষ্টা করেন, তাহলে
আপনি একটি UnsupportedOperationException ব্যতিক্রম পাবেন। আপনি যদি "শুধুমাত্র-পড়ার জন্য" হিসেবে তালিকাভুক্ত
কোনও কলাম আপডেট করার চেষ্টা করেন, তাহলে আপডেটটি উপেক্ষা করা হবে।
নতুন র কন্ট্যাক্ট যোগ করার উত্তরে Contacts Provider একটি নতুন পরিচিতি তৈরি করে যা আগে থেকে থাকা কোনও পরিচিতির সাথে মেলে না। এছাড়াও, কোনও আগে থেকে থাকা র কন্ট্যাক্টের ডেটা এমনভাবে পরিবর্তিত হলে, যা আগে যে কন্ট্যাক্টের সাথে অ্যাটাচ করা ছিল তার সাথে আর মেলে না, সেক্ষেত্রেও প্রোভাইডার এটি করে। কোনও অ্যাপ্লিকেশন বা সিঙ্ক অ্যাডাপ্টার যদি এমন একটি নতুন র কন্ট্যাক্ট তৈরি করে যা আগে থেকে থাকা কোনও পরিচিতির সাথে মিলে যায়, তাহলে নতুন র কন্ট্যাক্টটি আগে থেকে থাকা পরিচিতির সাথে যোগ করা হয়।
পরিচিতি সরবরাহকারী, পরিচিতি সারিকে তার র কন্ট্যাক্ট সারির সাথে লিঙ্ক করে, যেখানে পরিচিতি সারির
_ID কলাম Contacts
টেবিলে থাকে। র কন্ট্যাক্ট টেবিলের CONTACT_ID কলামে
ContactsContract.RawContacts-এ প্রতিটি র কন্ট্যাক্ট সারির সাথে সম্পর্কিত
কন্ট্যাক্ট সারির জন্য _ID ভ্যালু থাকে।
ContactsContract.Contacts টেবিলে LOOKUP_KEY কলামও আছে
যা পরিচিতির সারির সাথে
"স্থায়ী" লিঙ্ক। পরিচিতি সরবরাহকারী অটোমেটিক পরিচিতি ম্যানেজ করে বলে, এটি অ্যাগ্রিগেশন বা সিঙ্কের উত্তরে পরিচিতির সারির _ID ভ্যালু
পরিবর্তন করতে পারে। এমনকি এটি ঘটলেও, কন্টেন্ট URI
CONTENT_LOOKUP_URI-এর সাথে
পরিচিতির LOOKUP_KEY এখনও
পরিচিতির সারি দেখাবে, তাই আপনি
LOOKUP_KEY
ব্যবহার করে "পছন্দের" পরিচিতির লিঙ্ক বজায় রাখতে পারবেন এবং আরও অনেক কিছু করতে পারবেন। এই কলামের নিজস্ব ফর্ম্যাট আছে যা
_ID কলামের ফর্ম্যাটের সাথে সম্পর্কিত নয়।
তিনটি প্রধান টেবিল কীভাবে একে অপরের সাথে সম্পর্কিত তা চিত্র ৩-এ দেখানো হয়েছে।
ছবি ৩. পরিচিতি, র কন্ট্যাক্ট এবং বিবরণ টেবিল সম্পর্ক।
সতর্কতা: আপনি যদি Google Play Store-এ আপনার অ্যাপ প্রকাশ করেন অথবা আপনার অ্যাপটি Android 10 (API লেভেল ২৯) বা তার পরবর্তী ভার্সনে চলা কোনও ডিভাইসে থাকে, তাহলে মনে রাখবেন যে পরিচিতি ডেটা ফিল্ড এবং পদ্ধতির একটি সীমিত সেট বাতিল করা হয়েছে।
উল্লেখ করা শর্ত অনুযায়ী, সিস্টেম নির্দিষ্ট সময় অন্তর এইসব ডেটা ফিল্ডে লেখা যেকোনও ভ্যালু মুছে দেয়:
-
ContactsContract.ContactOptionsColumns.LAST_TIME_CONTACTED -
ContactsContract.ContactOptionsColumns.TIMES_CONTACTED -
ContactsContract.DataUsageStatColumns.LAST_TIME_USED -
ContactsContract.DataUsageStatColumns.TIMES_USED
পূর্ববর্তী ডেটা ফিল্ড সেট করতে ব্যবহৃত API-ও বাতিল করা হয়েছে:
এছাড়াও, নিম্নলিখিত ফিল্ডগুলি ঘন ঘন যোগাযোগ করা পরিচিতি আর দেখায় না। মনে রাখবেন যে, এই ফিল্ডগুলির মধ্যে কিছু ফিল্ড পরিচিতির র্যাঙ্কিংকে তখনই প্রভাবিত করে যখন পরিচিতিগুলি একটি নির্দিষ্ট ডেটার ধরনের অংশ হয়।
-
ContactsContract.Contacts.CONTENT_FREQUENT_URI -
ContactsContract.Contacts.CONTENT_STREQUENT_URI -
ContactsContract.Contacts.CONTENT_STREQUENT_FILTER_URI -
CONTENT_FILTER_URI(শুধুমাত্র ইমেল, ফোন, কল করা যাবে, এবং যোগাযোগ করা যাবে ডেটার ধরনের উপর প্রভাব ফেলে) -
ENTERPRISE_CONTENT_FILTER_URI(শুধুমাত্র ইমেল, ফোন, এবং কল করা যাবে এই ধরনের ডেটাকে প্রভাবিত করে)
আপনার অ্যাপ এইসব ফিল্ড বা API অ্যাক্সেস বা আপডেট করলে, বিকল্প পদ্ধতি ব্যবহার করুন। যেমন, আপনি ব্যক্তিগত কন্টেন্ট প্রোভাইডার বা আপনার অ্যাপ বা ব্যাকএন্ড সিস্টেমে স্টোর করা অন্যান্য ডেটা ব্যবহার করে নির্দিষ্ট কিছু ব্যবহারের ক্ষেত্রে পূরণ করতে পারেন।
এই পরিবর্তনের ফলে আপনার অ্যাপের কার্যকারিতা প্রভাবিত হয়নি তা যাচাই করতে, আপনি ম্যানুয়ালি এইসব ডেটা ফিল্ড মুছে দিতে পারেন। এটি করতে, Android 4.1 (API লেভেল 16) বা তার পরবর্তী যেকোনও ভার্সনে চলা ডিভাইসে নিম্নলিখিত ADB কমান্ড রান করুন:
adb shell content delete \ --uri content://com.android.contacts/contacts/delete_usage
সিঙ্ক অ্যাডাপ্টার থেকে পাওয়া ডেটা
ব্যবহারকারীরা সরাসরি ডিভাইসে পরিচিতি ডেটা লেখেন, তবে ডেটা সিঙ্ক অ্যাডাপ্টারের মাধ্যমে ওয়েব পরিষেবা থেকে পরিচিতি
সরবরাহকারীতেও প্রবাহিত হয়, যা ডিভাইস এবং পরিষেবার মধ্যে ডেটা স্থানান্তর
অটোমেট করে। সিঙ্ক অ্যাডাপ্টার ব্যাকগ্রাউন্ডে সিস্টেমের নিয়ন্ত্রণে
রান করে এবং ডেটা ম্যানেজ করার জন্য
ContentResolver মেথড কল করে।
Android-এ, সিঙ্ক অ্যাডাপ্টার যে ওয়েব পরিষেবার সাথে কাজ করে তা অ্যাকাউন্টের ধরন দ্বারা শনাক্ত করা হয়। প্রতিটি সিঙ্ক অ্যাডাপ্টার একটি অ্যাকাউন্টের ধরনের সাথে কাজ করে, তবে এটি সেই ধরনের জন্য একাধিক অ্যাকাউন্টের নাম সমর্থন করতে পারে। অ্যাকাউন্টের ধরন ও অ্যাকাউন্টের নাম সম্পর্কে র কন্ট্যাক্ট ডেটার সোর্স বিভাগে সংক্ষেপে বর্ণনা করা হয়েছে। নিম্নলিখিত সংজ্ঞাগুলি আরও বিশদ বিবরণ প্রদান করে এবং অ্যাকাউন্টের ধরন এবং নাম কীভাবে সিঙ্ক অ্যাডাপ্টার এবং পরিষেবার সাথে সম্পর্কিত তা বর্ণনা করে।
- অ্যাকাউন্টের ধরন
-
এমন একটি পরিষেবা শনাক্ত করে যেখানে ব্যবহারকারী ডেটা স্টোর করেছেন। বেশিরভাগ সময়, ব্যবহারকারীকে পরিষেবার মাধ্যমে
যাচাইকরণ করতে হয়। যেমন, Google Contacts হল একটি অ্যাকাউন্টের ধরন, যা
google.comকোড দ্বারা শনাক্ত করা হয়। এই ভ্যালুAccountManager-এর ব্যবহার করা অ্যাকাউন্টের ধরনের সাথে সম্পর্কিত। - অ্যাকাউন্টের নাম
- অ্যাকাউন্টের ধরন অনুযায়ী নির্দিষ্ট অ্যাকাউন্ট বা লগ-ইন শনাক্ত করে। Google Contacts অ্যাকাউন্ট Google অ্যাকাউন্টের মতোই, যার অ্যাকাউন্টের নাম হিসেবে ইমেল আইডি থাকে। অন্যান্য পরিষেবা এক শব্দের ইউজারনেম বা সংখ্যাসূচক আইডি ব্যবহার করতে পারে।
অ্যাকাউন্টের ধরন অনন্য হতে হবে না। একজন ব্যবহারকারী একাধিক Google Contacts অ্যাকাউন্ট কনফিগার করতে এবং Contacts Provider-এ তাদের ডেটা ডাউনলোড করতে পারেন; ব্যবহারকারীর ব্যক্তিগত অ্যাকাউন্টের নামের জন্য ব্যক্তিগত পরিচিতির একটি সেট এবং কাজের জন্য আরেকটি সেট থাকলে এটি হতে পারে। অ্যাকাউন্টের নাম সাধারণত অনন্য হয়। একসাথে, তারা পরিচিতি সরবরাহকারী এবং একটি বাহ্যিক পরিষেবার মধ্যে একটি নির্দিষ্ট ডেটা ফ্লো শনাক্ত করে।
আপনি যদি আপনার পরিষেবার ডেটা পরিচিতি সরবরাহকারীতে ট্রান্সফার করতে চান, তাহলে আপনাকে নিজের সিঙ্ক অ্যাডাপ্টার লিখতে হবে। পরিচিতি সরবরাহকারী সিঙ্ক অ্যাডাপ্টার বিভাগে এটি আরও বিস্তারিতভাবে বর্ণনা করা হয়েছে।
ছবি ৪-এ দেখানো হয়েছে যে কীভাবে পরিচিতি সরবরাহকারী লোকজনের ডেটার ফ্লোতে ফিট করে। "সিঙ্ক অ্যাডাপ্টার" হিসেবে চিহ্নিত বক্সে, প্রতিটি অ্যাডাপ্টারকে তার অ্যাকাউন্টের ধরন অনুযায়ী লেবেল করা হয়।
ছবি ৪. পরিচিতি সরবরাহকারীর ডেটা ফ্লো।
প্রয়োজনীয় অনুমতি
যেসব অ্যাপ্লিকেশন Contacts Provider অ্যাক্সেস করতে চায়, সেগুলিকে নিম্নলিখিত অনুমতিগুলির জন্য অনুরোধ করতে হবে:
- এক বা একাধিক টেবিল পড়ার অ্যাক্সেস
-
READ_CONTACTS, যাAndroidManifest.xml-এ<uses-permission>এলিমেন্টের সাথে<uses-permission android:name="android.permission.READ_CONTACTS">হিসেবে উল্লেখ করা হয়েছে। - এক বা একাধিক টেবিলে লেখার অ্যাক্সেস
-
WRITE_CONTACTS, যাAndroidManifest.xml-এ<uses-permission>এলিমেন্টের সাথে<uses-permission android:name="android.permission.WRITE_CONTACTS">হিসেবে উল্লেখ করা হয়েছে।
এইসব অনুমতি ব্যবহারকারীর প্রোফাইল ডেটার ক্ষেত্রে প্রযোজ্য নয়। ব্যবহারকারীর প্রোফাইল এবং এর প্রয়োজনীয় অনুমতিগুলি নিম্নলিখিত বিভাগে আলোচনা করা হয়েছে, ব্যবহারকারীর প্রোফাইল।
মনে রাখবেন যে ব্যবহারকারীর পরিচিতি ডেটা ব্যক্তিগত এবং সংবেদনশীল। ব্যবহারকারীরা তাদের গোপনীয়তা নিয়ে চিন্তিত, তাই তারা চান না যে অ্যাপ্লিকেশন তাদের বা তাদের পরিচিতি সম্পর্কে ডেটা সংগ্রহ করুক। আপনার কেন তাদের পরিচিতির ডেটা অ্যাক্সেস করার অনুমতি প্রয়োজন তা যদি স্পষ্ট না হয়, তাহলে তারা আপনার অ্যাপ্লিকেশনকে কম রেটিং দিতে পারে বা এটি ইনস্টল করতে অস্বীকার করতে পারে।
ব্যবহারকারীর প্রোফাইল
ContactsContract.Contacts টেবিলে একটি মাত্র সারি আছে যাতে
ডিভাইসের ব্যবহারকারীর প্রোফাইল ডেটা আছে। এই ডেটা ব্যবহারকারীর কোনও পরিচিতির পরিবর্তে
ডিভাইসের user বর্ণনা করে। প্রোফাইল ব্যবহার করে এমন প্রতিটি সিস্টেমের জন্য প্রোফাইল পরিচিতি সারিটি একটি র
পরিচিতি সারির সাথে লিঙ্ক করা হয়।
প্রতিটি প্রোফাইল র কন্ট্যাক্ট সারিতে একাধিক ডেটা সারি থাকতে পারে। ব্যবহারকারীর প্রোফাইল অ্যাক্সেস করার জন্য কনস্ট্যান্ট
ContactsContract.Profile ক্লাসে উপলভ্য।
ব্যবহারকারীর প্রোফাইল অ্যাক্সেস করার জন্য বিশেষ অনুমতি প্রয়োজন। রিড ও রাইট করার জন্য প্রয়োজনীয়
READ_CONTACTS এবং
WRITE_CONTACTS অনুমতি ছাড়াও, ব্যবহারকারীর প্রোফাইল অ্যাক্সেস করার জন্য
যথাক্রমে রিড ও রাইট অ্যাক্সেসের জন্য android.Manifest.permission#READ_PROFILE এবং
android.Manifest.permission#WRITE_PROFILE অনুমতি প্রয়োজন।
মনে রাখবেন, ব্যবহারকারীর প্রোফাইলকে সংবেদনশীল হিসেবে বিবেচনা করা উচিত। android.Manifest.permission#READ_PROFILE অনুমতি আপনাকে ডিভাইস ব্যবহারকারীর ব্যক্তিগতভাবে শনাক্তকরণযোগ্য ডেটা অ্যাক্সেস করতে দেয়। আপনার অ্যাপ্লিকেশনের বিবরণে ব্যবহারকারীকে অবশ্যই জানান যে কেন আপনার ব্যবহারকারীর প্রোফাইল অ্যাক্সেস করার অনুমতি প্রয়োজন।
ব্যবহারকারীর প্রোফাইল আছে এমন পরিচিতির সারি ফিরিয়ে আনতে,
ContentResolver.query()-এ কল করুন। কন্টেন্ট URI
CONTENT_URI-এ সেট করুন এবং কোনও
বাছাইয়ের মাপকাঠি প্রদান করবেন না। এছাড়াও, আপনি এই কন্টেন্ট URI-কে প্রোফাইলের জন্য র কন্ট্যাক্ট বা ডেটা ফিরিয়ে আনার জন্য
বেস URI হিসেবে ব্যবহার করতে পারেন। যেমন, এই স্নিপেট প্রোফাইলের জন্য ডেটা ফিরিয়ে আনে:
Kotlin
// Sets the columns to retrieve for the user profile projection = arrayOf( ContactsContract.Profile._ID, ContactsContract.Profile.DISPLAY_NAME_PRIMARY, ContactsContract.Profile.LOOKUP_KEY, ContactsContract.Profile.PHOTO_THUMBNAIL_URI ) // Retrieves the profile from the Contacts Provider profileCursor = contentResolver.query( ContactsContract.Profile.CONTENT_URI, projection, null, null, null )
জাভা
// Sets the columns to retrieve for the user profile projection = new String[] { Profile._ID, Profile.DISPLAY_NAME_PRIMARY, Profile.LOOKUP_KEY, Profile.PHOTO_THUMBNAIL_URI }; // Retrieves the profile from the Contacts Provider profileCursor = getContentResolver().query( Profile.CONTENT_URI, projection , null, null, null);
মনে রাখবেন: আপনি একাধিক পরিচিতির সারি ফিরিয়ে আনলে এবং সেগুলির মধ্যে কোনও একটি ব্যবহারকারীর প্রোফাইল কিনা তা নির্ধারণ করতে চাইলে,
সারির IS_USER_PROFILE কলামটি
পরীক্ষা করুন। পরিচিতিটি ব্যবহারকারীর প্রোফাইল হলে,
এই কলামটি "১" হিসেবে সেট করা হয়।
পরিচিতি সরবরাহকারী মেটাডেটা
পরিচিতি সরবরাহকারী এমন ডেটা ম্যানেজ করে যা রিপোজিটরিতে পরিচিতি ডেটার স্ট্যাটাস ট্র্যাক করে। রিপোজিটরি সংক্রান্ত এই মেটাডেটা বিভিন্ন জায়গায় স্টোর করা হয়, যার মধ্যে রয়েছে
র কন্ট্যাক্ট, ডেটা এবং পরিচিতি টেবিলের সারি,
ContactsContract.Settings টেবিল এবং
ContactsContract.SyncState টেবিল। নিম্নলিখিত সারণীতে এই প্রতিটি মেটাডেটার
প্রভাব দেখানো হয়েছে:
সারণী ৩. পরিচিতি সরবরাহকারীতে মেটাডেটা
| টেবিল | কলাম | মান | অর্থ |
|---|---|---|---|
ContactsContract.RawContacts |
DIRTY |
"0" - শেষবার সিঙ্ক করার পর থেকে পরিবর্তন করা হয়নি। |
ডিভাইসে পরিবর্তন করা হয়েছে এবং সার্ভারে আবার সিঙ্ক করতে হবে এমন র কন্ট্যাক্ট চিহ্নিত করে।
Android অ্যাপ্লিকেশন কোনও সারি আপডেট করলে, Contacts Provider অটোমেটিক ভ্যালু সেট করে।
যেসব সিঙ্ক অ্যাডাপ্টার র কন্ট্যাক্ট বা ডেটা টেবিল পরিবর্তন করে, সেগুলি সবসময়
ব্যবহার করা কন্টেন্ট URI-তে
|
| "১" - শেষবার সিঙ্ক করার পর থেকে পরিবর্তন করা হয়েছে, সার্ভারে আবার সিঙ্ক করতে হবে। | |||
ContactsContract.RawContacts |
VERSION |
এই সারির ভার্সন নম্বর। | যখনই সারি বা এর সাথে সম্পর্কিত ডেটা পরিবর্তিত হয়, তখনই পরিচিতি সরবরাহকারী অটোমেটিক এই মান বৃদ্ধি করে। |
ContactsContract.Data |
DATA_VERSION |
এই সারির ভার্সন নম্বর। | ডেটা সারি পরিবর্তন করা হলে, পরিচিতি সরবরাহকারী অটোমেটিক এই ভ্যালু বৃদ্ধি করে। |
ContactsContract.RawContacts |
SOURCE_ID |
একটি স্ট্রিং ভ্যালু যা এই র কন্ট্যাক্টকে অনন্যভাবে শনাক্ত করে সেই অ্যাকাউন্টে যেখানে এটি তৈরি করা হয়েছে। |
সিঙ্ক অ্যাডাপ্টার নতুন র কন্ট্যাক্ট তৈরি করলে, এই কলামটি র কন্ট্যাক্টের জন্য
সার্ভারের অনন্য আইডিতে সেট করা উচিত। কোনও Android অ্যাপ্লিকেশন নতুন র কন্ট্যাক্ট তৈরি করলে, অ্যাপ্লিকেশনটির এই কলাম খালি রাখা উচিত। এটি সিঙ্ক অ্যাডাপ্টারকে
সিগন্যাল দেয় যে সার্ভারে নতুন র কন্ট্যাক্ট তৈরি করতে হবে এবং
SOURCE_ID-এর জন্য ভ্যালু পেতে হবে।
বিশেষ করে, প্রতিটি অ্যাকাউন্টের ধরনের জন্য সোর্স আইডি অনন্য হতে হবে এবং সিঙ্ক করার সময় এটি পরিবর্তন করা যাবে না:
|
ContactsContract.Groups |
GROUP_VISIBLE |
"0" - এই গ্রুপের পরিচিতি Android অ্যাপ্লিকেশন UI-তে দেখা যাবে না। | এই কলামটি এমন সার্ভারের সাথে মানানসই যা ব্যবহারকারীকে নির্দিষ্ট গ্রুপে পরিচিতি লুকাতে অনুমতি দেয়। |
| "১" - এই গ্রুপের পরিচিতিগুলি অ্যাপ্লিকেশন UI-তে দেখার অনুমতি দেওয়া হয়েছে। | |||
ContactsContract.Settings |
UNGROUPED_VISIBLE |
"0" - এই অ্যাকাউন্ট এবং অ্যাকাউন্টের ধরনের জন্য, কোনও গ্রুপের অন্তর্গত নয় এমন পরিচিতিগুলি Android অ্যাপ্লিকেশন UI-তে দেখা যায় না। |
ডিফল্ট হিসেবে, কোনও র কন্ট্যাক্ট কোনও গ্রুপের অন্তর্ভুক্ত না হলে, কন্ট্যাক্টগুলি অদৃশ্য থাকে
(র কন্ট্যাক্টের জন্য গ্রুপ মেম্বারশিপ এক বা একাধিক
ContactsContract.CommonDataKinds.GroupMembership সারি
দ্বারা ContactsContract.Data টেবিলে নির্দেশিত হয়)।
অ্যাকাউন্টের ধরন ও অ্যাকাউন্টের জন্য ContactsContract.Settings টেবিল সারিতে
এই ফ্ল্যাগ সেট করে, আপনি গ্রুপ ছাড়া পরিচিতিগুলিকে দেখতে বাধ্য করতে পারেন।
এই ফ্ল্যাগ ব্যবহার করার একটি উদ্দেশ্য হল, গ্রুপ ব্যবহার করে না এমন সার্ভার থেকে পরিচিতি দেখানো।
|
| "১" - এই অ্যাকাউন্ট এবং অ্যাকাউন্টের ধরনের জন্য, কোনও গ্রুপের অন্তর্ভুক্ত নয় এমন পরিচিতি অ্যাপ্লিকেশন UI-তে দেখা যায়। | |||
ContactsContract.SyncState |
(সব) | আপনার সিঙ্ক অ্যাডাপ্টারের জন্য মেটাডেটা স্টোর করতে এই টেবিল ব্যবহার করুন। | এই টেবিলের সাহায্যে আপনি ডিভাইসে সিঙ্ক স্ট্যাটাস এবং সিঙ্ক-সম্পর্কিত অন্যান্য ডেটা স্থায়ীভাবে স্টোর করতে পারবেন। |
পরিচিতি সরবরাহকারী অ্যাক্সেস
এই বিভাগে Contacts Provider থেকে ডেটা অ্যাক্সেস করার নির্দেশিকা বর্ণনা করা হয়েছে, যার মধ্যে নিম্নলিখিত বিষয়গুলি ফোকাস করা হয়েছে:
- এন্টিটি কোয়েরি।
- ব্যাচ সংক্রান্ত পরিবর্তন।
- ইনটেন্ট সহ রিট্রিভাল ও পরিবর্তন।
- ডেটা ইন্টিগ্রিটি।
সিঙ্ক অ্যাডাপ্টার থেকে পরিবর্তন করার বিষয়টিও পরিচিতি সরবরাহকারী সিঙ্ক অ্যাডাপ্টার বিভাগে আরও বিস্তারিতভাবে কভার করা হয়েছে।
এন্টিটি কোয়েরি করা হচ্ছে
পরিচিতি সরবরাহকারী টেবিলগুলি একটি হায়ারার্কিতে সাজানো থাকে, তাই প্রায়শই একটি সারি এবং এটির সাথে লিঙ্ক করা সমস্ত "চাইল্ড" সারি
পুনরুদ্ধার করা কার্যকর হয়। যেমন, কোনও ব্যক্তির সব তথ্য
দেখানোর জন্য, আপনি হয়ত একটি
ContactsContract.Contacts সারির জন্য সব
ContactsContract.RawContacts সারি অথবা একটি
ContactsContract.RawContacts সারির জন্য সব
ContactsContract.CommonDataKinds.Email সারি ফিরিয়ে আনতে চাইবেন। এটি সহজ করতে, Contacts
Provider entity কনস্ট্রাক্ট অফার করে, যা টেবিলের মধ্যে
ডেটাবেস জয়েনের মতো কাজ করে।
এন্টিটি হল একটি টেবিলের মতো যা পেরেন্ট টেবিল এবং তার চাইল্ড টেবিল থেকে বেছে নেওয়া কলাম নিয়ে গঠিত।
আপনি কোনও এন্টিটি কোয়েরি করলে, এন্টিটিতে উপলভ্য কলামের ভিত্তিতে আপনি একটি প্রোজেকশন ও সার্চের মাপকাঠি
প্রদান করেন। ফলাফল হল একটি Cursor যাতে
প্রতিটি চাইল্ড টেবিল রোয়ের জন্য একটি রো থাকে যা ফিরিয়ে আনা হয়েছে। যেমন, আপনি যদি
ContactsContract.Contacts.Entity-এ কোনও পরিচিতির নাম
এবং সেই নামের সব র কন্ট্যাক্টের জন্য
সব ContactsContract.CommonDataKinds.Email সারি কোয়েরি করেন, তাহলে আপনি প্রতিটি ContactsContract.CommonDataKinds.Email সারির জন্য
একটি সারি সহ Cursor ফেরত পাবেন।
এন্টিটি কোয়েরি সহজ করে তোলে। কোনও এন্টিটি ব্যবহার করে, আপনি একটি পরিচিতি বা র কন্ট্যাক্টের জন্য সমস্ত পরিচিতি ডেটা একবারে পুনরুদ্ধার করতে পারেন, প্রথমে একটি আইডি পেতে পেরেন্ট টেবিল কোয়েরি করার পরিবর্তে, এবং তারপর সেই আইডি দিয়ে চাইল্ড টেবিল কোয়েরি করতে হবে। এছাড়াও, পরিচিতি সরবরাহকারী একটি এন্টিটির বিরুদ্ধে একটি ট্রানজ্যাকশনে একটি কোয়েরি প্রসেস করে, যা নিশ্চিত করে যে প্রাপ্ত ডেটা অভ্যন্তরীণভাবে সামঞ্জস্যপূর্ণ।
মনে রাখবেন: সাধারণত কোনও এন্টিটিতে পেরেন্ট ও চাইল্ড টেবিলের সব কলাম থাকে না এবং
থাকে না। আপনি যদি এমন কোনও কলামের নাম নিয়ে কাজ করার চেষ্টা করেন যা এন্টিটির জন্য কলামের নামের
ধ্রুবকের তালিকায় নেই, তাহলে আপনি Exception পাবেন।
কোনও পরিচিতির জন্য সব র কন্ট্যাক্ট সারি কীভাবে ফিরিয়ে আনা যায় তা নিম্নলিখিত স্নিপেট থেকে জানা যায়। স্ন্যাপশটটি
একটি বড় অ্যাপ্লিকেশনের অংশ যার দুটি অ্যাক্টিভিটি আছে, "প্রধান" এবং "বিস্তারিত"। মূল অ্যাক্টিভিটি
পরিচিতির সারির তালিকা দেখায়; ব্যবহারকারী একটি বেছে নিলে, অ্যাক্টিভিটি তার আইডি বিস্তারিত
অ্যাক্টিভিটিতে পাঠায়। বিস্তারিত অ্যাক্টিভিটি ContactsContract.Contacts.Entity ব্যবহার করে
বেছে নেওয়া পরিচিতির সাথে যুক্ত সব র কন্ট্যাক্ট থেকে সব ডেটা সারি
দেখায়।
এই স্নিপেট "বিস্তারিত" অ্যাক্টিভিটি থেকে নেওয়া হয়েছে:
Kotlin
... /* * Appends the entity path to the URI. In the case of the Contacts Provider, the * expected URI is content://com.google.contacts/#/entity (# is the ID value). */ contactUri = Uri.withAppendedPath( contactUri, ContactsContract.Contacts.Entity.CONTENT_DIRECTORY ) // Initializes the loader identified by LOADER_ID. loaderManager.initLoader( LOADER_ID, // The identifier of the loader to initialize null, // Arguments for the loader (in this case, none) this // The context of the activity ) // Creates a new cursor adapter to attach to the list view cursorAdapter = SimpleCursorAdapter( this, // the context of the activity R.layout.detail_list_item, // the view item containing the detail widgets mCursor, // the backing cursor fromColumns, // the columns in the cursor that provide the data toViews, // the views in the view item that display the data 0) // flags // Sets the ListView's backing adapter. rawContactList.adapter = cursorAdapter ... override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor> { /* * Sets the columns to retrieve. * RAW_CONTACT_ID is included to identify the raw contact associated with the data row. * DATA1 contains the first column in the data row (usually the most important one). * MIMETYPE indicates the type of data in the data row. */ val projection: Array<String> = arrayOf( ContactsContract.Contacts.Entity.RAW_CONTACT_ID, ContactsContract.Contacts.Entity.DATA1, ContactsContract.Contacts.Entity.MIMETYPE ) /* * Sorts the retrieved cursor by raw contact id, to keep all data rows for a single raw * contact collated together. */ val sortOrder = "${ContactsContract.Contacts.Entity.RAW_CONTACT_ID} ASC" /* * Returns a new CursorLoader. The arguments are similar to * ContentResolver.query(), except for the Context argument, which supplies the location of * the ContentResolver to use. */ return CursorLoader( applicationContext, // The activity's context contactUri, // The entity content URI for a single contact projection, // The columns to retrieve null, // Retrieve all the raw contacts and their data rows. null, // sortOrder // Sort by the raw contact ID. ) }
জাভা
... /* * Appends the entity path to the URI. In the case of the Contacts Provider, the * expected URI is content://com.google.contacts/#/entity (# is the ID value). */ contactUri = Uri.withAppendedPath( contactUri, ContactsContract.Contacts.Entity.CONTENT_DIRECTORY); // Initializes the loader identified by LOADER_ID. getLoaderManager().initLoader( LOADER_ID, // The identifier of the loader to initialize null, // Arguments for the loader (in this case, none) this); // The context of the activity // Creates a new cursor adapter to attach to the list view cursorAdapter = new SimpleCursorAdapter( this, // the context of the activity R.layout.detail_list_item, // the view item containing the detail widgets mCursor, // the backing cursor fromColumns, // the columns in the cursor that provide the data toViews, // the views in the view item that display the data 0); // flags // Sets the ListView's backing adapter. rawContactList.setAdapter(cursorAdapter); ... @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { /* * Sets the columns to retrieve. * RAW_CONTACT_ID is included to identify the raw contact associated with the data row. * DATA1 contains the first column in the data row (usually the most important one). * MIMETYPE indicates the type of data in the data row. */ String[] projection = { ContactsContract.Contacts.Entity.RAW_CONTACT_ID, ContactsContract.Contacts.Entity.DATA1, ContactsContract.Contacts.Entity.MIMETYPE }; /* * Sorts the retrieved cursor by raw contact id, to keep all data rows for a single raw * contact collated together. */ String sortOrder = ContactsContract.Contacts.Entity.RAW_CONTACT_ID + " ASC"; /* * Returns a new CursorLoader. The arguments are similar to * ContentResolver.query(), except for the Context argument, which supplies the location of * the ContentResolver to use. */ return new CursorLoader( getApplicationContext(), // The activity's context contactUri, // The entity content URI for a single contact projection, // The columns to retrieve null, // Retrieve all the raw contacts and their data rows. null, // sortOrder); // Sort by the raw contact ID. }
লোড করা হয়ে গেলে, LoaderManager, onLoadFinished()-এ
কলব্যাক ইনভোক করে। এই পদ্ধতিতে ইনকামিং আর্গুমেন্টের মধ্যে একটি হল
Cursor, যার মধ্যে কোয়েরির ফলাফল থাকে। আপনার নিজের অ্যাপে, আপনি এই Cursor থেকে ডেটা পেতে পারেন
যাতে এটি দেখানো যায় বা এটি নিয়ে আরও কাজ করা যায়।
ব্যাচ সংক্রান্ত পরিবর্তন
সম্ভব হলে, ContentProviderOperation অবজেক্টের ArrayList তৈরি করে এবং
applyBatch() কল করে,
"ব্যাচ মোডে" পরিচিতি সরবরাহকারীতে ডেটা যোগ, আপডেট এবং মুছে ফেলা উচিত। কারণ
পরিচিতি সরবরাহকারী একটি
applyBatch()-এ একটি ট্রানজ্যাকশনে সমস্ত অপারেশন
সম্পাদন করে, আপনার পরিবর্তনগুলি কখনই পরিচিতি রিপোজিটরিকে একটি অসঙ্গতিপূর্ণ
অবস্থায় ছেড়ে যাবে না। ব্যাচ মডিফিকেশন একই সাথে র কন্ট্যাক্ট ও তার বিস্তারিত ডেটা যোগ করার সুবিধা প্রদান করে।
মনে রাখবেন: একটি র কন্ট্যাক্ট পরিবর্তন করতে, আপনার অ্যাপে পরিবর্তন ম্যানেজ করার পরিবর্তে ডিভাইসের কন্ট্যাক্ট অ্যাপ্লিকেশনে ইনটেন্ট পাঠানোর কথা বিবেচনা করুন। এটি করার পদ্ধতি সম্পর্কে আরও বিস্তারিত বিবরণ ইনটেন্টের মাধ্যমে পুনরুদ্ধার ও পরিবর্তন বিভাগে দেওয়া আছে।
ইল্ড পয়েন্ট
অনেকগুলি অপারেশন সহ ব্যাচ মডিফিকেশন অন্যান্য প্রসেস ব্লক করতে পারে,
যার ফলে ব্যবহারকারীর সামগ্রিক অভিজ্ঞতা খারাপ হতে পারে। আপনি যত কম সম্ভব আলাদা আলাদা তালিকায় যেসব পরিবর্তন করতে চান, সেগুলি সাজাতে এবং একই সাথে সিস্টেমকে ব্লক করা থেকে আটকাতে, আপনাকে এক বা একাধিক অপারেশনের জন্য ইল্ড পয়েন্ট সেট করতে হবে।
ইল্ড পয়েন্ট হল একটি ContentProviderOperation অবজেক্ট যার
isYieldAllowed() ভ্যালু
true-এ সেট করা আছে। পরিচিতি সরবরাহকারী ইল্ড পয়েন্টের সম্মুখীন হলে, এটি অন্যান্য প্রসেস চালানোর জন্য
এর কাজ পজ করে এবং বর্তমান ট্রানজ্যাকশন বন্ধ করে দেয়। প্রোভাইডার আবার শুরু করলে, এটি
ArrayList-এ পরবর্তী অপারেশন চালিয়ে যায় এবং নতুন
ট্রানজ্যাকশন শুরু করে।
ইল্ড পয়েন্টের ফলে applyBatch()-এ প্রতি কলে একাধিক ট্রানজ্যাকশন হয়। এই কারণে, সম্পর্কিত সারির সেটের জন্য শেষ অপারেশনে আপনাকে ইল্ড পয়েন্ট সেট করতে হবে।
যেমন, কোনও সেটের শেষ অপারেশনের জন্য আপনাকে ইল্ড পয়েন্ট সেট করতে হবে যা র কন্ট্যাক্ট সারি এবং
তার সাথে সম্পর্কিত ডেটা সারি যোগ করে অথবা কোনও একটি কন্ট্যাক্টের সাথে সম্পর্কিত সারির সেটের
শেষ অপারেশন।
ইল্ড পয়েন্ট হল অ্যাটমিক অপারেশনের ইউনিট। দুটি ইল্ড পয়েন্টের মধ্যে সব অ্যাক্সেস একটি ইউনিট হিসেবে হয় সফল হবে অথবা ব্যর্থ হবে। আপনি কোনও ইল্ড পয়েন্ট সেট না করলে, সবচেয়ে ছোট অ্যাটমিক অপারেশন হল অপারেশনের সম্পূর্ণ ব্যাচ। আপনি ইল্ড পয়েন্ট ব্যবহার করলে, অপারেশন যাতে সিস্টেমের পারফর্ম্যান্স খারাপ না করে তা আটকাতে পারবেন এবং একই সাথে অপারেশনের সাবসেট অ্যাটমিক কিনা তা নিশ্চিত করতে পারবেন।
পরিবর্তন সংক্রান্ত ব্যাক রেফারেন্স
আপনি যখন একটি নতুন র কন্ট্যাক্ট সারি এবং এর সাথে সম্পর্কিত ডেটা সারিগুলি
ContentProviderOperation অবজেক্টের সেট হিসেবে যোগ করছেন, তখন আপনাকে ডেটা সারিগুলিকে
র কন্ট্যাক্ট সারির সাথে লিঙ্ক করতে হবে। এর জন্য র কন্ট্যাক্টের
_ID ভ্যালু
RAW_CONTACT_ID ভ্যালু হিসেবে যোগ করতে হবে। তবে, আপনি ডেটা সারির জন্য ContentProviderOperation
তৈরি করার সময় এই ভ্যালু উপলভ্য থাকে না, কারণ আপনি এখনও
র কন্ট্যাক্ট সারির জন্য ContentProviderOperation
প্রয়োগ করেননি। এই সমস্যার সমাধান করতে,
ContentProviderOperation.Builder ক্লাসে
withValueBackReference() পদ্ধতি আছে।
এই পদ্ধতির মাধ্যমে আপনি আগের অপারেশনের ফলাফল সহ
কলাম যোগ বা পরিবর্তন করতে পারবেন।
withValueBackReference()
পদ্ধতিতে দুটি আর্গুমেন্ট আছে:
-
key - কী-ভ্যালু পেয়ারের কী। এই আর্গুমেন্টের ভ্যালু, আপনি যে টেবিলটি পরিবর্তন করছেন সেটির কলামের নাম হতে হবে।
-
previousResult -
applyBatch()থেকেContentProviderResultঅবজেক্টের অ্যারেতে কোনও ভ্যালুর ০-ভিত্তিক ইনডেক্স। ব্যাচ অপারেশন প্রয়োগ করা হলে, প্রতিটি অপারেশনের ফলাফল ফলাফলের একটি অন্তর্বর্তী অ্যারেতে স্টোর করা হয়।previousResultভ্যালু হল এইসব ফলাফলের মধ্যে একটির ইন্ডেক্স, যাkeyভ্যালুর সাথে উদ্ধার ও স্টোর করা হয়। এটি আপনাকে একটি নতুন র কন্ট্যাক্ট রেকর্ড যোগ করতে এবং এর_IDভ্যালু ফেরত পেতে দেয়, তারপর আপনি একটিContactsContract.Dataসারি যোগ করার সময় ভ্যালুতে একটি "ব্যাক রেফারেন্স" তৈরি করে।আপনি প্রথমবার
applyBatch()কল করলে, সম্পূর্ণ ফলাফল অ্যারে তৈরি হয়, যার সাইজ আপনার দেওয়াContentProviderOperationঅবজেক্টেরArrayList-এর সাইজের সমান হয়। তবে, ফলাফল অ্যারের সব এলিমেন্টnull-এ সেট করা হয় এবং আপনি যদি এমন কোনও অপারেশনের ফলাফলের ব্যাক রেফারেন্স করার চেষ্টা করেন যা এখনও প্রয়োগ করা হয়নি,withValueBackReference()তাহলেExceptionথ্রো করে।
নিচের স্নিপেট থেকে জানা যাবে যে কীভাবে ব্যাচে নতুন র কন্ট্যাক্ট ও ডেটা যোগ করতে হয়। এতে এমন কোড থাকে যা ইল্ড পয়েন্ট তৈরি করে এবং ব্যাক রেফারেন্স ব্যবহার করে।
প্রথম স্নিপেট UI থেকে পরিচিতির ডেটা ফিরিয়ে আনে। এই পর্যায়ে, ব্যবহারকারী আগে থেকেই সেই অ্যাকাউন্ট বেছে নিয়েছেন যার জন্য নতুন র কন্ট্যাক্ট যোগ করা উচিত।
Kotlin
// Creates a contact entry from the current UI values, using the currently-selected account. private fun createContactEntry() { /* * Gets values from the UI */ val name = contactNameEditText.text.toString() val phone = contactPhoneEditText.text.toString() val email = contactEmailEditText.text.toString() val phoneType: String = contactPhoneTypes[mContactPhoneTypeSpinner.selectedItemPosition] val emailType: String = contactEmailTypes[mContactEmailTypeSpinner.selectedItemPosition]
জাভা
// Creates a contact entry from the current UI values, using the currently-selected account. protected void createContactEntry() { /* * Gets values from the UI */ String name = contactNameEditText.getText().toString(); String phone = contactPhoneEditText.getText().toString(); String email = contactEmailEditText.getText().toString(); int phoneType = contactPhoneTypes.get( contactPhoneTypeSpinner.getSelectedItemPosition()); int emailType = contactEmailTypes.get( contactEmailTypeSpinner.getSelectedItemPosition());
পরবর্তী স্নিপেট ContactsContract.RawContacts টেবিলে র কন্ট্যাক্ট সারি যোগ করার জন্য একটি অপারেশন তৈরি করে:
Kotlin
/* * Prepares the batch operation for inserting a new raw contact and its data. Even if * the Contacts Provider does not have any data for this person, you can't add a Contact, * only a raw contact. The Contacts Provider will then add a Contact automatically. */ // Creates a new array of ContentProviderOperation objects. val ops = arrayListOf<ContentProviderOperation>() /* * Creates a new raw contact with its account type (server type) and account name * (user's account). Remember that the display name is not stored in this row, but in a * StructuredName data row. No other data is required. */ var op: ContentProviderOperation.Builder = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, selectedAccount.name) .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, selectedAccount.type) // Builds the operation and adds it to the array of operations ops.add(op.build())
জাভা
/* * Prepares the batch operation for inserting a new raw contact and its data. Even if * the Contacts Provider does not have any data for this person, you can't add a Contact, * only a raw contact. The Contacts Provider will then add a Contact automatically. */ // Creates a new array of ContentProviderOperation objects. ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>(); /* * Creates a new raw contact with its account type (server type) and account name * (user's account). Remember that the display name is not stored in this row, but in a * StructuredName data row. No other data is required. */ ContentProviderOperation.Builder op = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI) .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, selectedAccount.getType()) .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, selectedAccount.getName()); // Builds the operation and adds it to the array of operations ops.add(op.build());
এরপর, কোডটি ডিসপ্লে নাম, ফোন এবং ইমেল সারির জন্য ডেটা সারি তৈরি করে।
প্রতিটি অপারেশন বিল্ডার অবজেক্ট
withValueBackReference()
ব্যবহার করে
RAW_CONTACT_ID
পাওয়ার জন্য। রেফারেন্সটি
প্রথম অপারেশন থেকে ContentProviderResult অবজেক্টে ফিরে যায়,
যা র কন্ট্যাক্ট সারি যোগ করে এবং এর নতুন _ID
ভ্যালু ফিরিয়ে দেয়।
এর ফলে, প্রতিটি ডেটা সারি অটোমেটিক তার
RAW_CONTACT_ID
দ্বারা নতুন ContactsContract.RawContacts সারির সাথে লিঙ্ক করা হয় যার সাথে এটি সম্পর্কিত।
ContentProviderOperation.Builder অবজেক্ট যা ইমেল রো যোগ করে সেটি
withYieldAllowed() দিয়ে ফ্ল্যাগ করা হয়, যা ইল্ড পয়েন্ট সেট করে:
Kotlin
// Creates the display name for the new raw contact, as a StructuredName data row. op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) /* * withValueBackReference sets the value of the first argument to the value of * the ContentProviderResult indexed by the second argument. In this particular * call, the raw contact ID column of the StructuredName data row is set to the * value of the result returned by the first operation, which is the one that * actually adds the raw contact row. */ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) // Sets the data row's MIME type to StructuredName .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) // Sets the data row's display name to the name in the UI. .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name) // Builds the operation and adds it to the array of operations ops.add(op.build()) // Inserts the specified phone number and type as a Phone data row op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) /* * Sets the value of the raw contact id column to the new raw contact ID returned * by the first operation in the batch. */ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) // Sets the data row's MIME type to Phone .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) // Sets the phone number and type .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone) .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType) // Builds the operation and adds it to the array of operations ops.add(op.build()) // Inserts the specified email and type as a Phone data row op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) /* * Sets the value of the raw contact id column to the new raw contact ID returned * by the first operation in the batch. */ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) // Sets the data row's MIME type to Email .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) // Sets the email address and type .withValue(ContactsContract.CommonDataKinds.Email.ADDRESS, email) .withValue(ContactsContract.CommonDataKinds.Email.TYPE, emailType) /* * Demonstrates a yield point. At the end of this insert, the batch operation's thread * will yield priority to other threads. Use after every set of operations that affect a * single contact, to avoid degrading performance. */ op.withYieldAllowed(true) // Builds the operation and adds it to the array of operations ops.add(op.build())
জাভা
// Creates the display name for the new raw contact, as a StructuredName data row. op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) /* * withValueBackReference sets the value of the first argument to the value of * the ContentProviderResult indexed by the second argument. In this particular * call, the raw contact ID column of the StructuredName data row is set to the * value of the result returned by the first operation, which is the one that * actually adds the raw contact row. */ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) // Sets the data row's MIME type to StructuredName .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE) // Sets the data row's display name to the name in the UI. .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name); // Builds the operation and adds it to the array of operations ops.add(op.build()); // Inserts the specified phone number and type as a Phone data row op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) /* * Sets the value of the raw contact id column to the new raw contact ID returned * by the first operation in the batch. */ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) // Sets the data row's MIME type to Phone .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) // Sets the phone number and type .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone) .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, phoneType); // Builds the operation and adds it to the array of operations ops.add(op.build()); // Inserts the specified email and type as a Phone data row op = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI) /* * Sets the value of the raw contact id column to the new raw contact ID returned * by the first operation in the batch. */ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0) // Sets the data row's MIME type to Email .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) // Sets the email address and type .withValue(ContactsContract.CommonDataKinds.Email.ADDRESS, email) .withValue(ContactsContract.CommonDataKinds.Email.TYPE, emailType); /* * Demonstrates a yield point. At the end of this insert, the batch operation's thread * will yield priority to other threads. Use after every set of operations that affect a * single contact, to avoid degrading performance. */ op.withYieldAllowed(true); // Builds the operation and adds it to the array of operations ops.add(op.build());
শেষ স্নিপেটটি
applyBatch()-এ কল দেখায় যা
নতুন র কন্ট্যাক্ট এবং ডেটা সারি যোগ করে।
Kotlin
// Ask the Contacts Provider to create a new contact Log.d(TAG, "Selected account: ${mSelectedAccount.name} (${mSelectedAccount.type})") Log.d(TAG, "Creating contact: $name") /* * Applies the array of ContentProviderOperation objects in batch. The results are * discarded. */ try { contentResolver.applyBatch(ContactsContract.AUTHORITY, ops) } catch (e: Exception) { // Display a warning val txt: String = getString(R.string.contactCreationFailure) Toast.makeText(applicationContext, txt, Toast.LENGTH_SHORT).show() // Log exception Log.e(TAG, "Exception encountered while inserting contact: $e") } }
জাভা
// Ask the Contacts Provider to create a new contact Log.d(TAG,"Selected account: " + selectedAccount.getName() + " (" + selectedAccount.getType() + ")"); Log.d(TAG,"Creating contact: " + name); /* * Applies the array of ContentProviderOperation objects in batch. The results are * discarded. */ try { getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops); } catch (Exception e) { // Display a warning Context ctx = getApplicationContext(); CharSequence txt = getString(R.string.contactCreationFailure); int duration = Toast.LENGTH_SHORT; Toast toast = Toast.makeText(ctx, txt, duration); toast.show(); // Log exception Log.e(TAG, "Exception encountered while inserting contact: " + e); } }
এছাড়াও, ব্যাচ অপারেশন আপনাকে অপ্টিমিস্টিক কনকারেন্সি কন্ট্রোল প্রয়োগ করতে দেয়, এটি হল অন্তর্নিহিত রিপোজিটরি লক না করেই মডিফিকেশন ট্রানজ্যাকশন প্রয়োগ করার একটি পদ্ধতি। এই পদ্ধতি ব্যবহার করতে, আপনি ট্রানজ্যাকশন প্রয়োগ করেন এবং তারপরে একই সময়ে করা হতে পারে এমন অন্যান্য পরিবর্তন চেক করেন। আপনি যদি দেখেন যে কোনও অসঙ্গতিপূর্ণ পরিবর্তন ঘটেছে, তাহলে আপনার ট্রানজ্যাকশন রোল ব্যাক করুন এবং আবার চেষ্টা করুন।
অপ্টিমিস্টিক কনকারেন্সি কন্ট্রোল মোবাইল ডিভাইসের জন্য উপযোগী, যেখানে একবারে একজন ব্যবহারকারীই থাকেন এবং ডেটা রিপোজিটরিতে একই সাথে অ্যাক্সেস করার ঘটনা বিরল। লকিং ব্যবহার করা হয় না বলে, লক সেট করা বা অন্যান্য ট্রানজ্যাকশন থেকে লক রিলিজ হওয়ার জন্য অপেক্ষা করতে সময় নষ্ট হয় না।
একটি ContactsContract.RawContacts সারি আপডেট করার সময় অপ্টিমিস্টিক কনকারেন্সি কন্ট্রোল ব্যবহার করতে, এই ধাপগুলি অনুসরণ করুন:
-
আপনি যে অন্যান্য ডেটা ফিরিয়ে আনেন তার সাথে র কন্ট্যাক্টের
VERSIONকলাম ফিরিয়ে আনুন। -
newAssertQuery(Uri)পদ্ধতি ব্যবহার করে, বাধ্যবাধকতা প্রয়োগ করার জন্য উপযুক্তContentProviderOperation.Builderঅবজেক্ট তৈরি করুন। কন্টেন্ট URI-এর জন্য,RawContacts.CONTENT_URIব্যবহার করুন এবং এর সাথে র কন্ট্যাক্টের_IDযোগ করুন। -
ContentProviderOperation.Builderঅবজেক্টের জন্য,withValue()কল করুন যাতেVERSIONকলামের সাথে আপনার এইমাত্র পাওয়া ভার্সন নম্বরের তুলনা করা যায়। -
একই
ContentProviderOperation.Builder-এর জন্য,withExpectedCount()কল করুন যাতে এই অ্যাসারশনের মাধ্যমে শুধুমাত্র একটি সারি পরীক্ষা করা হয়। -
ContentProviderOperationঅবজেক্ট তৈরি করতেbuild()কল করুন, তারপর এই অবজেক্টকেArrayList-এ প্রথম অবজেক্ট হিসেবে যোগ করুন যা আপনিapplyBatch()-এ পাস করেন। - ব্যাচ ট্রানজ্যাকশন প্রয়োগ করুন।
আপনি র কন্ট্যাক্ট সারিটি পড়ার সময় এবং
এটি পরিবর্তন করার চেষ্টার সময়ের মধ্যে অন্য কোনও অপারেশনের মাধ্যমে সারিটি আপডেট করা হলে, "assert" ContentProviderOperation
ব্যর্থ হবে এবং অপারেশনের পুরো ব্যাচটি বাতিল করা হবে। আপনি তারপর ব্যাচটি আবার চেষ্টা করার জন্য বেছে নিতে পারেন
অথবা অন্য কোনও অ্যাকশন নিতে পারেন।
নিম্নলিখিত স্নিপেট থেকে বোঝা যায় যে, CursorLoader ব্যবহার করে
একটি র কন্ট্যাক্ট কোয়েরি করার পরে কীভাবে "assert"
ContentProviderOperation তৈরি করতে হয়:
Kotlin
/* * The application uses CursorLoader to query the raw contacts table. The system calls this method * when the load is finished. */ override fun onLoadFinished(loader: Loader<Cursor>, cursor: Cursor) { // Gets the raw contact's _ID and VERSION values rawContactID = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID)) mVersion = cursor.getInt(cursor.getColumnIndex(SyncColumns.VERSION)) } ... // Sets up a Uri for the assert operation val rawContactUri: Uri = ContentUris.withAppendedId( ContactsContract.RawContacts.CONTENT_URI, rawContactID ) // Creates a builder for the assert operation val assertOp: ContentProviderOperation.Builder = ContentProviderOperation.newAssertQuery(rawContactUri).apply { // Adds the assertions to the assert operation: checks the version withValue(SyncColumns.VERSION, mVersion) // and count of rows tested withExpectedCount(1) } // Creates an ArrayList to hold the ContentProviderOperation objects val ops = arrayListOf<ContentProviderOperation>() ops.add(assertOp.build()) // You would add the rest of your batch operations to "ops" here ... // Applies the batch. If the assert fails, an Exception is thrown try { val results: Array<ContentProviderResult> = contentResolver.applyBatch(AUTHORITY, ops) } catch (e: OperationApplicationException) { // Actions you want to take if the assert operation fails go here }
জাভা
/* * The application uses CursorLoader to query the raw contacts table. The system calls this method * when the load is finished. */ public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { // Gets the raw contact's _ID and VERSION values rawContactID = cursor.getLong(cursor.getColumnIndex(BaseColumns._ID)); mVersion = cursor.getInt(cursor.getColumnIndex(SyncColumns.VERSION)); } ... // Sets up a Uri for the assert operation Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactID); // Creates a builder for the assert operation ContentProviderOperation.Builder assertOp = ContentProviderOperation.newAssertQuery(rawContactUri); // Adds the assertions to the assert operation: checks the version and count of rows tested assertOp.withValue(SyncColumns.VERSION, mVersion); assertOp.withExpectedCount(1); // Creates an ArrayList to hold the ContentProviderOperation objects ArrayList ops = new ArrayList<ContentProviderOperation>; ops.add(assertOp.build()); // You would add the rest of your batch operations to "ops" here ... // Applies the batch. If the assert fails, an Exception is thrown try { ContentProviderResult[] results = getContentResolver().applyBatch(AUTHORITY, ops); } catch (OperationApplicationException e) { // Actions you want to take if the assert operation fails go here }
ইনটেন্টের মাধ্যমে রিট্রিভ ও পরিবর্তন করা
ডিভাইসের পরিচিতি অ্যাপ্লিকেশনে ইনটেন্ট পাঠানোর মাধ্যমে আপনি পরোক্ষভাবে পরিচিতি প্রদানকারী অ্যাক্সেস করতে পারবেন। ইনটেন্ট ডিভাইসের পরিচিতি অ্যাপ্লিকেশন UI শুরু করে, যেখানে ব্যবহারকারীরা পরিচিতি-সম্পর্কিত কাজ করতে পারেন। এই ধরনের অ্যাক্সেস থাকলে, ব্যবহারকারী এগুলি করতে পারবেন:
- তালিকা থেকে কোনও পরিচিতি বেছে নিন এবং পরবর্তী কাজের জন্য আপনার অ্যাপে সেটি ফিরিয়ে আনুন।
- আগে থেকে থাকা পরিচিতির ডেটা এডিট করুন।
- তার যেকোনও অ্যাকাউন্টের জন্য নতুন র কন্ট্যাক্ট যোগ করুন।
- একটি পরিচিতি বা পরিচিতির ডেটা মুছে দিন।
ব্যবহারকারী ডেটা যোগ বা আপডেট করলে, আপনি প্রথমে ডেটা সংগ্রহ করতে এবং ইনটেন্টের অংশ হিসেবে তা পাঠাতে পারবেন।
ডিভাইসের পরিচিতি অ্যাপ্লিকেশনের মাধ্যমে পরিচিতি সরবরাহকারী অ্যাক্সেস করার জন্য ইনটেন্ট ব্যবহার করলে, আপনাকে সরবরাহকারী অ্যাক্সেস করার জন্য নিজের UI বা কোড লিখতে হবে না। এছাড়াও, আপনাকে প্রোভাইডারের ডেটা পড়া বা লেখার জন্য অনুমতি চাইতে হবে না। ডিভাইসের পরিচিতি অ্যাপ্লিকেশন আপনাকে কোনও পরিচিতির জন্য রিড পার্মিশন প্রতিনিধি হিসেবে দিতে পারে এবং আপনি অন্য অ্যাপ্লিকেশনের মাধ্যমে প্রোভাইডারে পরিবর্তন করছেন বলে আপনার কাছে রাইট পার্মিশন থাকার প্রয়োজন নেই।
প্রোভাইডার অ্যাক্সেস করার জন্য ইনটেন্ট পাঠানোর সাধারণ প্রসেস
কন্টেন্ট প্রোভাইডার সংক্রান্ত প্রাথমিক তথ্য গাইডের "ইনটেন্ট ব্যবহার করে ডেটা অ্যাক্সেস" বিভাগে বিস্তারিতভাবে বর্ণনা করা হয়েছে। উপলভ্য টাস্কের জন্য আপনি যে অ্যাকশন,
MIME-এর প্রকার ও ডেটা ভ্যালু ব্যবহার করেন, সেগুলি সারণী ৪-এ সংক্ষেপে দেখানো হয়েছে, যেখানে
putExtra()-এর সাথে আপনি যেসব অতিরিক্ত ভ্যালু ব্যবহার করতে পারবেন, সেগুলি
ContactsContract.Intents.Insert-এর রেফারেন্স ডকুমেন্টেশনে তালিকাভুক্ত করা হয়েছে:
সারণী ৪. পরিচিতি সরবরাহকারী ইনটেন্ট।
| টাস্ক | অ্যাকশন | ডেটা | MIME-এর প্রকার | নোট |
|---|---|---|---|---|
| তালিকা থেকে কোনও পরিচিতি বেছে নেওয়া | ACTION_PICK |
এর মধ্যে একটি:
|
ব্যবহার করা হয়নি |
আপনার দেওয়া কন্টেন্ট URI-এর ধরনের উপর নির্ভর করে, র কন্ট্যাক্টের তালিকা বা র কন্ট্যাক্ট থেকে পাওয়া ডেটার তালিকা
দেখায়।
কল
|
| নতুন র কন্ট্যাক্ট যোগ করা | Insert.ACTION |
N/A |
RawContacts.CONTENT_TYPE, এক সেট র কন্ট্যাক্টের জন্য MIME-এর ধরন।
|
ডিভাইসের পরিচিতি অ্যাপ্লিকেশনের পরিচিতি যোগ করুন স্ক্রিন দেখায়। ইনটেন্টে
আপনার যোগ করা অতিরিক্ত ভ্যালু দেখানো হয়। startActivityForResult()-এর সাথে পাঠানো হলে,
নতুন যোগ করা র কন্ট্যাক্টের কন্টেন্ট URI আপনার অ্যাক্টিভিটির
onActivityResult()
কলব্যাক পদ্ধতিতে Intent আর্গুমেন্টে,
"ডেটা" ফিল্ডে ফেরত পাঠানো হয়। ভ্যালু পেতে, getData() কল করুন।
|
| পরিচিতি এডিট করুন | ACTION_EDIT |
পরিচিতির জন্য
CONTENT_LOOKUP_URI। এডিটর অ্যাক্টিভিটি ব্যবহারকারীকে এই পরিচিতির সাথে যুক্ত যেকোনও ডেটা এডিট করার অনুমতি দেবে।
|
Contacts.CONTENT_ITEM_TYPE, একটি পরিচিতি। |
পরিচিতি অ্যাপ্লিকেশনে পরিচিতি এডিট করার স্ক্রিন দেখায়। ইনটেন্টে আপনার যোগ করা অতিরিক্ত ভ্যালু দেখানো হয়। ব্যবহারকারী এডিট সেভ করতে হয়ে গেছে বিকল্পে ক্লিক করলে, আপনার অ্যাক্টিভিটি আবার ফোরগ্রাউন্ডে ফিরে আসে। |
| এমন একটি পিকার দেখান যা ডেটাও যোগ করতে পারে। | ACTION_INSERT_OR_EDIT |
N/A |
CONTENT_ITEM_TYPE
|
এই ইনটেন্ট সবসময় পরিচিতি অ্যাপের পিকার স্ক্রিন দেখায়। ব্যবহারকারী এডিট করার জন্য কোনও পরিচিতি বেছে নিতে পারেন
অথবা নতুন পরিচিতি যোগ করতে পারেন। ব্যবহারকারীর পছন্দ অনুযায়ী, এডিট বা যোগ করার স্ক্রিন
দেখা যায় এবং ইনটেন্টে আপনি যে অতিরিক্ত ডেটা পাস করেন
তা দেখানো হয়। আপনার অ্যাপ যদি ইমেল বা ফোন নম্বরের মতো পরিচিতির ডেটা দেখায়, তাহলে ব্যবহারকারীকে আগে থেকে থাকা পরিচিতিতে ডেটা যোগ করার অনুমতি দিতে
এই ইনটেন্ট ব্যবহার করুন।
পরিচিতি,
মনে রাখবেন: এই ইনটেন্টের অতিরিক্ত অংশে নামের ভ্যালু পাঠানোর প্রয়োজন নেই, কারণ ব্যবহারকারী সবসময় আগে থেকে থাকা নাম বেছে নেন বা নতুন নাম যোগ করেন। এছাড়াও, আপনি যদি কোনও নাম পাঠান এবং ব্যবহারকারী সেটি এডিট করতে চান, তাহলে পরিচিতি অ্যাপ আপনার পাঠানো নামটি দেখাবে এবং আগের নামটি ওভাররাইট করবে। ব্যবহারকারী এটি লক্ষ্য না করে এডিট সেভ করে ফেললে, পুরনো ভ্যালু হারিয়ে যায়। |
ডিভাইসের পরিচিতি অ্যাপ আপনাকে কোনও র কন্ট্যাক্ট বা তার কোনও ডেটা ইনটেন্টের মাধ্যমে মুছতে দেয় না। পরিবর্তে, র কন্ট্যাক্ট মুছতে,
ContentResolver.delete()
বা ContentProviderOperation.newDelete() ব্যবহার করুন।
নিচের স্নিপেট থেকে জানা যাবে যে কীভাবে একটি ইনটেন্ট তৈরি করে পাঠাতে হয় যা নতুন র কন্ট্যাক্ট ও ডেটা যোগ করে:
Kotlin
// Gets values from the UI val name = contactNameEditText.text.toString() val phone = contactPhoneEditText.text.toString() val email = contactEmailEditText.text.toString() val company = companyName.text.toString() val jobtitle = jobTitle.text.toString() /* * Demonstrates adding data rows as an array list associated with the DATA key */ // Defines an array list to contain the ContentValues objects for each row val contactData = arrayListOf<ContentValues>() /* * Defines the raw contact row */ // Sets up the row as a ContentValues object val rawContactRow = ContentValues().apply { // Adds the account type and name to the row put(ContactsContract.RawContacts.ACCOUNT_TYPE, selectedAccount.type) put(ContactsContract.RawContacts.ACCOUNT_NAME, selectedAccount.name) } // Adds the row to the array contactData.add(rawContactRow) /* * Sets up the phone number data row */ // Sets up the row as a ContentValues object val phoneRow = ContentValues().apply { // Specifies the MIME type for this data row (all data rows must be marked by their type) put(ContactsContract.Data.MIMETYPE,ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE) // Adds the phone number and its type to the row put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone) } // Adds the row to the array contactData.add(phoneRow) /* * Sets up the email data row */ // Sets up the row as a ContentValues object val emailRow = ContentValues().apply { // Specifies the MIME type for this data row (all data rows must be marked by their type) put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE) // Adds the email address and its type to the row put(ContactsContract.CommonDataKinds.Email.ADDRESS, email) } // Adds the row to the array contactData.add(emailRow) // Creates a new intent for sending to the device's contacts application val insertIntent = Intent(ContactsContract.Intents.Insert.ACTION).apply { // Sets the MIME type to the one expected by the insertion activity type = ContactsContract.RawContacts.CONTENT_TYPE // Sets the new contact name putExtra(ContactsContract.Intents.Insert.NAME, name) // Sets the new company and job title putExtra(ContactsContract.Intents.Insert.COMPANY, company) putExtra(ContactsContract.Intents.Insert.JOB_TITLE, jobtitle) /* * Adds the array to the intent's extras. It must be a parcelable object in order to * travel between processes. The device's contacts app expects its key to be * Intents.Insert.DATA */ putParcelableArrayListExtra(ContactsContract.Intents.Insert.DATA, contactData) } // Send out the intent to start the device's contacts app in its add contact activity. startActivity(insertIntent)
জাভা
// Gets values from the UI String name = contactNameEditText.getText().toString(); String phone = contactPhoneEditText.getText().toString(); String email = contactEmailEditText.getText().toString(); String company = companyName.getText().toString(); String jobtitle = jobTitle.getText().toString(); // Creates a new intent for sending to the device's contacts application Intent insertIntent = new Intent(ContactsContract.Intents.Insert.ACTION); // Sets the MIME type to the one expected by the insertion activity insertIntent.setType(ContactsContract.RawContacts.CONTENT_TYPE); // Sets the new contact name insertIntent.putExtra(ContactsContract.Intents.Insert.NAME, name); // Sets the new company and job title insertIntent.putExtra(ContactsContract.Intents.Insert.COMPANY, company); insertIntent.putExtra(ContactsContract.Intents.Insert.JOB_TITLE, jobtitle); /* * Demonstrates adding data rows as an array list associated with the DATA key */ // Defines an array list to contain the ContentValues objects for each row ArrayList<ContentValues> contactData = new ArrayList<ContentValues>(); /* * Defines the raw contact row */ // Sets up the row as a ContentValues object ContentValues rawContactRow = new ContentValues(); // Adds the account type and name to the row rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_TYPE, selectedAccount.getType()); rawContactRow.put(ContactsContract.RawContacts.ACCOUNT_NAME, selectedAccount.getName()); // Adds the row to the array contactData.add(rawContactRow); /* * Sets up the phone number data row */ // Sets up the row as a ContentValues object ContentValues phoneRow = new ContentValues(); // Specifies the MIME type for this data row (all data rows must be marked by their type) phoneRow.put( ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE ); // Adds the phone number and its type to the row phoneRow.put(ContactsContract.CommonDataKinds.Phone.NUMBER, phone); // Adds the row to the array contactData.add(phoneRow); /* * Sets up the email data row */ // Sets up the row as a ContentValues object ContentValues emailRow = new ContentValues(); // Specifies the MIME type for this data row (all data rows must be marked by their type) emailRow.put( ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE ); // Adds the email address and its type to the row emailRow.put(ContactsContract.CommonDataKinds.Email.ADDRESS, email); // Adds the row to the array contactData.add(emailRow); /* * Adds the array to the intent's extras. It must be a parcelable object in order to * travel between processes. The device's contacts app expects its key to be * Intents.Insert.DATA */ insertIntent.putParcelableArrayListExtra(ContactsContract.Intents.Insert.DATA, contactData); // Send out the intent to start the device's contacts app in its add contact activity. startActivity(insertIntent);
ডেটা ইন্টিগ্রিটি
পরিচিতি রিপোজিটরিতে গুরুত্বপূর্ণ ও সংবেদনশীল ডেটা থাকে যা ব্যবহারকারীরা সঠিক ও আপ-টু-ডেট রাখতে চান, তাই পরিচিতি সরবরাহকারীর কাছে ডেটা ইন্টিগ্রিটির জন্য সুনির্দিষ্ট নিয়ম থাকে। পরিচিতির ডেটা পরিবর্তন করার সময় এইসব নিয়ম মেনে চলার দায়িত্ব আপনার। গুরুত্বপূর্ণ নিয়মগুলি এখানে তালিকাভুক্ত করা হয়েছে:
-
আপনি যোগ করেন এমন প্রতিটি
ContactsContract.RawContactsসারির জন্য সবসময় একটিContactsContract.CommonDataKinds.StructuredNameসারি যোগ করুন। -
ContactsContract.DataটেবিলেContactsContract.CommonDataKinds.StructuredNameসারি ছাড়াContactsContract.RawContactsসারি থাকলে, অ্যাগ্রিগেশনের সময় সমস্যা হতে পারে। -
সবসময় নতুন
ContactsContract.Dataসারিকে তার মূলContactsContract.RawContactsসারির সাথে লিঙ্ক করুন। -
ContactsContract.Data-এর সাথে লিঙ্ক করা নেই এমনContactsContract.RawContactsসারি ডিভাইসের পরিচিতি অ্যাপ্লিকেশনে দেখা যাবে না এবং এর ফলে সিঙ্ক অ্যাডাপ্টারে সমস্যা হতে পারে। - শুধুমাত্র আপনার মালিকানাধীন র কন্ট্যাক্টের ডেটা পরিবর্তন করুন।
- মনে রাখবেন যে পরিচিতি সরবরাহকারী সাধারণত বিভিন্ন ধরনের অ্যাকাউন্ট/অনলাইন পরিষেবা থেকে ডেটা ম্যানেজ করে। আপনাকে নিশ্চিত করতে হবে যে আপনার অ্যাপ্লিকেশন শুধুমাত্র আপনার মালিকানাধীন সারির ডেটা পরিবর্তন বা মুছে দেয় এবং এটি শুধুমাত্র আপনার নিয়ন্ত্রণ করা অ্যাকাউন্টের ধরন এবং নাম সহ ডেটা যোগ করে।
-
কর্তৃপক্ষ, কন্টেন্ট URI, URI পাথ, কলামের নাম, MIME-এর প্রকার এবং
TYPEভ্যালুর জন্যContactsContractএবং এর সাবক্লাসে সংজ্ঞায়িত ধ্রুবকগুলি সর্বদা ব্যবহার করুন। - এইসব কনস্ট্যান্ট ব্যবহার করলে আপনি ভুল এড়াতে পারবেন। কোনও কনস্ট্যান্টের ব্যবহার বন্ধ করা হলে, আপনাকে কম্পাইলার সতর্কতা সহ বিজ্ঞপ্তি দেওয়া হবে।
কাস্টম ডেটা সারি
আপনার নিজস্ব কাস্টম MIME-এর প্রকার তৈরি ও ব্যবহার করে, আপনি ContactsContract.Data টেবিলে আপনার নিজস্ব ডেটা সারি যোগ, এডিট, মুছে ফেলতে এবং
পুনরুদ্ধার করতে পারবেন। আপনার সারি
ContactsContract.DataColumns-এ সংজ্ঞায়িত কলাম ব্যবহার করার মধ্যে সীমাবদ্ধ,
যদিও আপনি ডিফল্ট কলামের নামের সাথে আপনার নিজস্ব
ধরন-নির্দিষ্ট কলামের নাম ম্যাপ করতে পারেন। ডিভাইসের পরিচিতি অ্যাপ্লিকেশনে,
আপনার সারির ডেটা দেখানো হয় কিন্তু এডিট বা মুছে ফেলা যায় না এবং ব্যবহারকারীরা অতিরিক্ত ডেটা
যোগ করতে পারেন না। ব্যবহারকারীদের আপনার কাস্টম ডেটা সারি পরিবর্তন করার অনুমতি দিতে, আপনাকে অবশ্যই আপনার নিজস্ব অ্যাপ্লিকেশনে একটি এডিটর
অ্যাক্টিভিটি প্রদান করতে হবে।
আপনার কাস্টম ডেটা দেখাতে, একটি contacts.xml ফাইল প্রদান করুন যাতে একটি
<ContactsAccountType> এলিমেন্ট এবং এর এক বা একাধিক
<ContactsDataKind> চাইল্ড এলিমেন্ট থাকে। এটি <ContactsDataKind> element বিভাগে আরও বিস্তারিতভাবে
বর্ণনা করা হয়েছে।
কাস্টম MIME-এর প্রকার সম্পর্কে আরও জানতে, কন্টেন্ট প্রোভাইডার তৈরি করুন নির্দেশিকা পড়ুন।
পরিচিতি সরবরাহকারী সিঙ্ক অ্যাডাপ্টার
পরিচিতি সরবরাহকারীকে বিশেষভাবে ডিজাইন করা হয়েছে যাতে এটি কোনও ডিভাইস এবং অনলাইন পরিষেবার মধ্যে পরিচিতি ডেটার সিঙ্ক ম্যানেজ করতে পারে। এর ফলে ব্যবহারকারীরা নতুন ডিভাইসে আগে থেকে থাকা ডেটা ডাউনলোড করতে এবং নতুন অ্যাকাউন্টে আগে থেকে থাকা ডেটা আপলোড করতে পারবেন। এছাড়াও, সিঙ্ক করার ফলে ব্যবহারকারীর কাছে লেটেস্ট ডেটা থাকে, ডেটা কোথা থেকে যোগ করা হয়েছে বা পরিবর্তন করা হয়েছে তা নিয়ে চিন্তা করতে হয় না। সিঙ্ক করার আরেকটি সুবিধা হল, ডিভাইস নেটওয়ার্কের সাথে কানেক্ট করা না থাকলেও এটি পরিচিতির ডেটা উপলভ্য করে।
আপনি বিভিন্ন উপায়ে সিঙ্ক্রোনাইজেশন প্রয়োগ করতে পারলেও, Android সিস্টেম একটি প্লাগ-ইন সিঙ্ক্রোনাইজেশন ফ্রেমওয়ার্ক প্রদান করে যা নিম্নলিখিত টাস্ক অটোমেট করে:
- নেটওয়ার্কের উপলভ্যতা চেক করা হচ্ছে।
- ব্যবহারকারীর পছন্দ অনুযায়ী সিঙ্ক্রোনাইজেশন শিডিউল ও এক্সিকিউট করা।
- বন্ধ হয়ে যাওয়া সিঙ্ক করার প্রসেস আবার চালু করা হচ্ছে।
এই ফ্রেমওয়ার্ক ব্যবহার করতে, আপনাকে সিঙ্ক অ্যাডাপ্টার প্লাগ-ইন দিতে হবে। প্রতিটি সিঙ্ক অ্যাডাপ্টার একটি পরিষেবা এবং কন্টেন্ট প্রোভাইডারের জন্য অনন্য, তবে একই পরিষেবার জন্য একাধিক অ্যাকাউন্টের নাম ম্যানেজ করতে পারে। এছাড়াও, ফ্রেমওয়ার্ক একই পরিষেবা ও প্রোভাইডারের জন্য একাধিক সিঙ্ক অ্যাডাপ্টার ব্যবহারের অনুমতি দেয়।
সিঙ্ক অ্যাডাপ্টার ক্লাস ও ফাইল
আপনি AbstractThreadedSyncAdapter-এর সাবক্লাস হিসেবে সিঙ্ক অ্যাডাপ্টার প্রয়োগ করেন
এবং Android অ্যাপ্লিকেশনের অংশ হিসেবে
এটি ইনস্টল করেন। সিস্টেম আপনার অ্যাপ্লিকেশন ম্যানিফেস্টের এলিমেন্ট এবং ম্যানিফেস্টের মাধ্যমে নির্দেশিত একটি বিশেষ XML ফাইল থেকে
সিঙ্ক অ্যাডাপ্টার সম্পর্কে জানতে পারে। XML ফাইল অনলাইন পরিষেবার জন্য অ্যাকাউন্টের ধরন এবং কন্টেন্ট প্রোভাইডারের জন্য অথরিটি নির্ধারণ করে, যা একসাথে
অ্যাডাপ্টারকে অনন্যভাবে শনাক্ত করে। ব্যবহারকারী সিঙ্ক অ্যাডাপ্টারের অ্যাকাউন্টের ধরনের জন্য অ্যাকাউন্ট যোগ না করা এবং সিঙ্ক অ্যাডাপ্টার যে কন্টেন্ট প্রোভাইডারের সাথে সিঙ্ক করে তার জন্য সিঙ্ক্রোনাইজেশন চালু না করা পর্যন্ত সিঙ্ক অ্যাডাপ্টার অ্যাক্টিভ হয় না। সেই সময়, সিস্টেম অ্যাডাপ্টার ম্যানেজ করা শুরু করে,
কন্টেন্ট প্রোভাইডার ও সার্ভারের মধ্যে সিঙ্ক করার জন্য প্রয়োজন অনুযায়ী এটিকে কল করে।
মনে রাখবেন: সিঙ্ক অ্যাডাপ্টারের শনাক্তকরণের অংশ হিসেবে অ্যাকাউন্টের ধরন ব্যবহার করলে,
সিস্টেম একই সংস্থার বিভিন্ন পরিষেবা অ্যাক্সেস করে এমন সিঙ্ক অ্যাডাপ্টার শনাক্ত করতে এবং একসাথে গ্রুপ করতে পারে। যেমন, Google অনলাইন পরিষেবার জন্য সিঙ্ক অ্যাডাপ্টারের সবকটির একই
অ্যাকাউন্টের ধরন com.google আছে। ব্যবহারকারীরা তাদের ডিভাইসে Google অ্যাকাউন্ট যোগ করলে, Google পরিষেবার জন্য ইনস্টল করা সব
সিঙ্ক অ্যাডাপ্টার একসাথে তালিকাভুক্ত করা হয়; তালিকাভুক্ত প্রতিটি সিঙ্ক অ্যাডাপ্টার
ডিভাইসে একটি ভিন্ন কন্টেন্ট প্রোভাইডারের সাথে সিঙ্ক করে।
যেহেতু বেশিরভাগ পরিষেবার ক্ষেত্রে ডেটা অ্যাক্সেস করার আগে ব্যবহারকারীদের পরিচয় যাচাই করতে হয়, তাই Android সিস্টেম
একটি যাচাইকরণ ফ্রেমওয়ার্ক অফার করে যা সিঙ্ক অ্যাডাপ্টার ফ্রেমওয়ার্কের মতো এবং প্রায়শই
এর সাথে ব্যবহার করা হয়। যাচাইকরণ ফ্রেমওয়ার্ক
প্লাগ-ইন যাচাইকারী ব্যবহার করে যা
AbstractAccountAuthenticator-এর সাবক্লাস। একজন যাচাইকারী নিম্নলিখিত ধাপে
ব্যবহারকারীর পরিচয় যাচাই করেন:
- ব্যবহারকারীর নাম, পাসওয়ার্ড বা একই ধরনের তথ্য (ব্যবহারকারীর ক্রেডেনশিয়াল) সংগ্রহ করে।
- পরিষেবায় ক্রেডেনশিয়াল পাঠায়
- পরিষেবার উত্তর পরীক্ষা করে।
পরিষেবাটি ক্রেডেনশিয়াল গ্রহণ করলে, যাচাইকারী পরে ব্যবহারের জন্য
ক্রেডেনশিয়াল স্টোর করতে পারে। প্লাগ-ইন যাচাইকারী ফ্রেমওয়ার্কের কারণে,
AccountManager যেকোনও যাচাইকারী টোকেন অ্যাক্সেস করতে পারে যা যাচাইকারী
সমর্থন করে এবং প্রকাশ করার জন্য বেছে নেয়, যেমন OAuth2 যাচাইকারী টোকেন।
যদিও যাচাইকরণের প্রয়োজন নেই, বেশিরভাগ পরিচিতি পরিষেবা এটি ব্যবহার করে। তবে, যাচাইকরণের জন্য আপনাকে Android যাচাইকরণ ফ্রেমওয়ার্ক ব্যবহার করতে হবে না।
সিঙ্ক অ্যাডাপ্টার ইমপ্লিমেন্টেশন
পরিচিতি সরবরাহকারীর জন্য সিঙ্ক অ্যাডাপ্টার প্রয়োগ করতে, আপনি একটি Android অ্যাপ্লিকেশন তৈরি করে শুরু করেন যার মধ্যে নিম্নলিখিতগুলি থাকে:
-
একটি
Serviceকম্পোনেন্ট যা সিঙ্ক অ্যাডাপ্টারের সাথে বাইন্ড করার জন্য সিস্টেম থেকে আসা অনুরোধের উত্তর দেয়। -
সিস্টেম যখন সিঙ্ক করতে চায়, তখন এটি সিঙ্ক অ্যাডাপ্টারের জন্য
IBinderপেতে পরিষেবারonBind()মেথড কল করে। এটি সিস্টেমকে অ্যাডাপ্টারের পদ্ধতিতে ক্রস-প্রসেস কল করার অনুমতি দেয়। -
আসল সিঙ্ক অ্যাডাপ্টার,
AbstractThreadedSyncAdapter-এর কংক্রিট সাবক্লাস হিসেবে প্রয়োগ করা হয়েছে। -
এই ক্লাস সার্ভার থেকে ডেটা ডাউনলোড, ডিভাইস থেকে ডেটা আপলোড এবং
সমস্যা সমাধানের কাজ করে। অ্যাডাপ্টারের মূল কাজ
onPerformSync()পদ্ধতিতে করা হয়। এই ক্লাসটি অবশ্যই একটি সিঙ্গলটন হিসাবে ইনস্ট্যান্টিয়েট করতে হবে। -
Application-এর একটি সাবক্লাস। -
এই ক্লাসটি সিঙ্ক অ্যাডাপ্টার সিঙ্গলটনের জন্য ফ্যাক্টরি হিসেবে কাজ করে। সিঙ্ক অ্যাডাপ্টার ইনস্ট্যান্টিয়েট করতে
onCreate()পদ্ধতি ব্যবহার করুন এবং সিঙ্ক অ্যাডাপ্টারের পরিষেবারonBind()পদ্ধতিতে সিঙ্গলটন ফিরিয়ে দিতে স্ট্যাটিক "গেটার" পদ্ধতি প্রদান করুন। -
ঐচ্ছিক: একটি
Serviceকম্পোনেন্ট যা ব্যবহারকারী যাচাইকরণের জন্য সিস্টেম থেকে আসা অনুরোধের উত্তর দেয়। -
AccountManagerযাচাইকরণ প্রসেস শুরু করার জন্য এই পরিষেবা চালু করে। পরিষেবারonCreate()পদ্ধতি একটি যাচাইকরণ অবজেক্ট ইনস্ট্যান্টিয়েট করে। অ্যাপ্লিকেশনের সিঙ্ক অ্যাডাপ্টারের জন্য সিস্টেম যখন ব্যবহারকারীর অ্যাকাউন্ট যাচাই করতে চায়, তখন এটি যাচাইকারীর জন্যIBinderপেতে পরিষেবারonBind()পদ্ধতিকে কল করে। এটি সিস্টেমকে প্রমাণীকরণকারীর পদ্ধতিতে ক্রস-প্রসেস কল করার অনুমতি দেয়.. -
ঐচ্ছিক:
AbstractAccountAuthenticator-এর একটি কংক্রিট সাবক্লাস যা যাচাইকরণের জন্য অনুরোধ ম্যানেজ করে। -
এই ক্লাস এমন পদ্ধতি প্রদান করে যা
AccountManagerসার্ভারের সাথে ব্যবহারকারীর ক্রেডেনশিয়াল যাচাই করার জন্য কল করে। যাচাইকরণ প্রক্রিয়ার বিবরণ সার্ভার প্রযুক্তির উপর নির্ভর করে ব্যাপকভাবে পরিবর্তিত হয়। যাচাইকরণ সম্পর্কে আরও জানতে আপনার সার্ভার সফ্টওয়্যারের ডকুমেন্টেশন দেখুন। - XML ফাইল যা সিস্টেমে সিঙ্ক অ্যাডাপ্টার এবং যাচাইকরণকারীকে সংজ্ঞায়িত করে।
-
আগে বর্ণনা করা সিঙ্ক অ্যাডাপ্টার ও যাচাইকরণ পরিষেবা কম্পোনেন্ট
অ্যাপ্লিকেশন ম্যানিফেস্টে
<service>এলিমেন্টে সংজ্ঞায়িত করা হয়। এইসব এলিমেন্টে এমন<meta-data>চাইল্ড এলিমেন্ট থাকে যা সিস্টেমে নির্দিষ্ট ডেটা প্রদান করে:-
সিঙ্ক অ্যাডাপ্টার পরিষেবার জন্য
<meta-data>এলিমেন্টটি XML ফাইলres/xml/syncadapter.xml-এ পয়েন্ট করে। পরিবর্তে, এই ফাইলটি ওয়েব পরিষেবার জন্য একটি URI নির্দিষ্ট করে যা পরিচিতি সরবরাহকারীর সাথে সিঙ্ক করা হবে, এবং ওয়েব পরিষেবার জন্য একটি অ্যাকাউন্টের ধরন। -
ঐচ্ছিক:
<meta-data>এলিমেন্টটি প্রমাণীকরণের জন্য XML ফাইলres/xml/authenticator.xml-কে নির্দেশ করে। পরিবর্তে, এই ফাইলটি অ্যাকাউন্টের ধরন নির্দিষ্ট করে যা এই প্রমাণীকরণকারী সমর্থন করে, সেইসাথে UI রিসোর্স যা প্রমাণীকরণ প্রক্রিয়া চলাকালীন প্রদর্শিত হয়। এই এলিমেন্টে উল্লেখ করা অ্যাকাউন্টের ধরন সিঙ্ক অ্যাডাপ্টারের জন্য উল্লেখ করা অ্যাকাউন্টের ধরনের একই হতে হবে।
-
সিঙ্ক অ্যাডাপ্টার পরিষেবার জন্য
সোশ্যাল স্ট্রিম ডেটা
android.provider.ContactsContract.StreamItems এবং android.provider.ContactsContract.StreamItemPhotos টেবিল সামাজিক নেটওয়ার্কগুলি থেকে ইনকামিং ডেটা পরিচালনা করে। আপনি এমন একটি সিঙ্ক অ্যাডাপ্টার লিখতে পারেন যা আপনার নিজস্ব নেটওয়ার্ক থেকে এই টেবিলে স্ট্রিম ডেটা যোগ করে অথবা আপনি এই টেবিল থেকে স্ট্রিম ডেটা পড়তে এবং আপনার নিজস্ব অ্যাপ্লিকেশনে এটি প্রদর্শন করতে পারেন, অথবা দুটিই করতে পারেন। এইসব ফিচারের মাধ্যমে, আপনার সোশ্যাল নেটওয়ার্কিং পরিষেবা ও অ্যাপ্লিকেশন Android-এর সোশ্যাল নেটওয়ার্কিং অভিজ্ঞতার সাথে ইন্টিগ্রেট করা যেতে পারে।
সোশ্যাল স্ট্রিম টেক্সট
স্ট্রিম আইটেম সবসময় র কন্ট্যাক্টের সাথে যুক্ত থাকে। android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID,
র কন্ট্যাক্টের জন্য _ID ভ্যালুর সাথে লিঙ্ক করে। র কন্ট্যাক্টের অ্যাকাউন্টের ধরন ও অ্যাকাউন্টের নামও
স্ট্রিম আইটেম সারিতে স্টোর করা হয়।
আপনার স্ট্রিম থেকে ডেটা নিম্নলিখিত কলামে স্টোর করুন:
- android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_TYPE
- প্রয়োজনীয়। এই স্ট্রিম আইটেমের সাথে যুক্ত র কন্ট্যাক্টের জন্য ব্যবহারকারীর অ্যাকাউন্টের ধরন। স্ট্রিম আইটেম যোগ করার সময় এই ভ্যালু সেট করতে ভুলবেন না।
- android.provider.ContactsContract.StreamItemsColumns#ACCOUNT_NAME
- প্রয়োজনীয়। এই স্ট্রিম আইটেমের সাথে যুক্ত র কন্ট্যাক্টের জন্য ব্যবহারকারীর অ্যাকাউন্টের নাম। স্ট্রিম আইটেম যোগ করার সময় এই ভ্যালু সেট করতে ভুলবেন না।
- শনাক্তকারী কলাম
-
প্রয়োজনীয়। আপনি কোনও স্ট্রিম আইটেম যোগ করলে, আপনাকে অবশ্যই নিম্নলিখিত শনাক্তকারী কলাম যোগ করতে হবে:
- android.provider.ContactsContract.StreamItemsColumns#CONTACT_ID: এই স্ট্রিম আইটেমটি যে পরিচিতির সাথে যুক্ত তার android.provider.BaseColumns#_ID ভ্যালু।
- android.provider.ContactsContract.StreamItemsColumns#CONTACT_LOOKUP_KEY: এই স্ট্রিম আইটেমটি যে পরিচিতির সাথে যুক্ত, তার android.provider.ContactsContract.ContactsColumns#LOOKUP_KEY ভ্যালু।
- android.provider.ContactsContract.StreamItemsColumns#RAW_CONTACT_ID: এই স্ট্রিম আইটেমটি যে র কন্ট্যাক্টের সাথে যুক্ত, তার android.provider.BaseColumns#_ID ভ্যালু।
- android.provider.ContactsContract.StreamItemsColumns#COMMENTS
- ঐচ্ছিক। সারসংক্ষেপ সংক্রান্ত তথ্য স্টোর করে যা আপনি স্ট্রিম আইটেমের শুরুতে দেখাতে পারবেন।
- android.provider.ContactsContract.StreamItemsColumns#TEXT
-
স্ট্রিম আইটেমের টেক্সট, হয় আইটেমের সোর্স দ্বারা পোস্ট করা কন্টেন্ট,
অথবা স্ট্রিম আইটেম তৈরি করা কিছু অ্যাকশনের বিবরণ। এই কলামে যেকোনও ফর্ম্যাটিং এবং এম্বেড করা রিসোর্স ইমেজ থাকতে পারে যা
fromHtml()-এর মাধ্যমে রেন্ডার করা যেতে পারে। প্রদানকারী দীর্ঘ কন্টেন্ট ট্রাঙ্কেট বা এলিপসাইজ করতে পারে, তবে এটি ট্যাগ ভাঙা এড়ানোর চেষ্টা করবে। - android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP
- একটি টেক্সট স্ট্রিং যাতে স্ট্রিম আইটেম যোগ বা আপডেট করার সময় উল্লেখ করা থাকে, এটি যুগ থেকে মিলিসেকেন্ড হিসেবে দেখানো হয়। যেসব অ্যাপ্লিকেশন স্ট্রিম আইটেম যোগ বা আপডেট করে, সেগুলি এই কলামটি বজায় রাখার জন্য দায়ী; এটি পরিচিতি সরবরাহকারী দ্বারা অটোমেটিক বজায় রাখা হয় না।
আপনার স্ট্রিম আইটেমের জন্য শনাক্তকরণ তথ্য দেখাতে, আপনার অ্যাপ্লিকেশনে রিসোর্সের সাথে লিঙ্ক করতে android.provider.ContactsContract.StreamItemsColumns#RES_ICON, android.provider.ContactsContract.StreamItemsColumns#RES_LABEL এবং android.provider.ContactsContract.StreamItemsColumns#RES_PACKAGE ব্যবহার করুন।
android.provider.ContactsContract.StreamItems টেবিলে android.provider.ContactsContract.StreamItemsColumns#SYNC1 থেকে android.provider.ContactsContract.StreamItemsColumns#SYNC4 পর্যন্ত কলামও থাকে যা শুধুমাত্র সিঙ্ক অ্যাডাপ্টারের জন্য ব্যবহার করা হয়।
সোশ্যাল স্ট্রিম ফটো
android.provider.ContactsContract.StreamItemPhotos টেবিলে স্ট্রিম আইটেমের সাথে সম্পর্কিত ফটো
স্টোর করা হয়। টেবিলের
android.provider.ContactsContract.StreamItemPhotosColumns#STREAM_ITEM_ID কলাম
android.provider.ContactsContract.StreamItems টেবিলের
_ID কলামের মানের সাথে লিঙ্ক করে। ফটো রেফারেন্স
টেবিলের এই কলামে স্টোর করা হয়:
- android.provider.ContactsContract.StreamItemPhotos#PHOTO কলাম (একটি BLOB)।
- ফটোর একটি বাইনারি উপস্থাপনা, স্টোরেজ এবং ডিসপ্লের জন্য প্রদানকারী দ্বারা রিসাইজ করা হয়েছে। এই কলামটি Contacts Provider-এর আগের ভার্সনের সাথে ব্যাকওয়ার্ড কম্প্যাটিবিলিটির জন্য উপলভ্য, যা ফটো সেভ করার জন্য ব্যবহার করা হয়। তবে, বর্তমান ভার্সনে ফটো স্টোর করার জন্য আপনার এই কলাম ব্যবহার করা উচিত নয়। পরিবর্তে, ফাইলে ফটো সেভ করতে android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID অথবা android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI (দুটিই নিচের পয়েন্টে বর্ণনা করা হয়েছে) ব্যবহার করুন। এই কলামে এখন ফটোটির একটি থাম্বনেল রয়েছে, যা পড়ার জন্য উপলভ্য।
- android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_FILE_ID
-
র কন্ট্যাক্টের জন্য কোনও ফটোর সংখ্যাসূচক শনাক্তকারী। এই ভ্যালুটি কনস্ট্যান্টের সাথে যোগ করুন
DisplayPhoto.CONTENT_URIযাতে একটি ফটো ফাইলের দিকে পয়েন্ট করা কন্টেন্ট URI পাওয়া যায় এবং তারপরopenAssetFileDescriptor()কল করুন যাতে ফটো ফাইলের হ্যান্ডেল পাওয়া যায়। - android.provider.ContactsContract.StreamItemPhotosColumns#PHOTO_URI
-
এই সারিতে দেখানো ফটোর জন্য সরাসরি ফটো ফাইলকে পয়েন্ট করে এমন কন্টেন্ট URI।
ফটো ফাইলের হ্যান্ডেল পেতে এই URI সহ
openAssetFileDescriptor()-এ কল করুন।
সোশ্যাল স্ট্রিম টেবিল ব্যবহার করা
এই সারণীগুলি Contacts Provider-এর অন্যান্য প্রধান সারণীর মতোই কাজ করে, তবে নিম্নলিখিত ব্যতিক্রমগুলি রয়েছে:
- এইসব টেবিলের জন্য অতিরিক্ত অ্যাক্সেস সংক্রান্ত অনুমতি প্রয়োজন। সেগুলি থেকে পড়তে, আপনার অ্যাপ্লিকেশনের অবশ্যই android.Manifest.permission#READ_SOCIAL_STREAM অনুমতি থাকতে হবে। এগুলি পরিবর্তন করতে, আপনার অ্যাপ্লিকেশনের কাছে অবশ্যই android.Manifest.permission#WRITE_SOCIAL_STREAM অনুমতি থাকতে হবে।
-
android.provider.ContactsContract.StreamItems টেবিলের জন্য, প্রতিটি র কন্ট্যাক্টের জন্য
স্টোর করা সারির সংখ্যা সীমিত। এই সীমায় পৌঁছে গেলে,
পরিচিতি সরবরাহকারী সবচেয়ে পুরনো
android.provider.ContactsContract.StreamItemsColumns#TIMESTAMP সহ সারি অটোমেটিক মুছে দিয়ে
নতুন স্ট্রিম আইটেম সারির জন্য জায়গা করে দেয়। সীমা
জানতে, কন্টেন্ট URI
android.provider.ContactsContract.StreamItems#CONTENT_LIMIT_URI-তে কোয়েরি করুন। আপনি
null-এ সেট করা কন্টেন্ট URI ছাড়া অন্য সব আর্গুমেন্ট ছেড়ে দিতে পারেন। কোয়েরি একটি কার্সর রিটার্ন করে যাতে একটি সারি থাকে, সাথে একটি কলাম android.provider.ContactsContract.StreamItems#MAX_ITEMS থাকে।
android.provider.ContactsContract.StreamItems.StreamItemPhotos ক্লাসটি android.provider.ContactsContract.StreamItemPhotos-এর একটি সাব-টেবিলকে সংজ্ঞায়িত করে, যাতে একটি একক স্ট্রিম আইটেমের জন্য ফটো সারি থাকে।
সোশ্যাল স্ট্রিম ইন্টার্যাকশন
পরিচিতি সরবরাহকারীর দ্বারা পরিচালিত সোশ্যাল স্ট্রিম ডেটা, ডিভাইসের পরিচিতি অ্যাপ্লিকেশনের সাথে একযোগে, আপনার সোশ্যাল নেটওয়ার্কিং সিস্টেমকে বিদ্যমান পরিচিতির সাথে সংযুক্ত করার একটি শক্তিশালী উপায় অফার করে। নিম্নলিখিত ফিচারগুলি উপলভ্য:
- সিঙ্ক অ্যাডাপ্টারের মাধ্যমে আপনার সোশ্যাল নেটওয়ার্কিং পরিষেবা পরিচিতি সরবরাহকারীর সাথে সিঙ্ক করে, আপনি কোনও ব্যবহারকারীর পরিচিতির সাম্প্রতিক অ্যাক্টিভিটি ফিরিয়ে আনতে এবং পরে ব্যবহার করার জন্য android.provider.ContactsContract.StreamItems এবং android.provider.ContactsContract.StreamItemPhotos টেবিলে সেভ করতে পারবেন।
- নিয়মিত সিঙ্ক করার পাশাপাশি, ব্যবহারকারী কোনও পরিচিতি দেখার জন্য বেছে নিলে, অতিরিক্ত ডেটা উদ্ধার করার জন্য আপনি সিঙ্ক অ্যাডাপ্টার ট্রিগার করতে পারেন। এটি আপনার সিঙ্ক অ্যাডাপ্টারকে পরিচিতির জন্য হাই-রেজোলিউশন ফটো এবং সবচেয়ে সাম্প্রতিক স্ট্রিম আইটেমগুলি পুনরুদ্ধার করার অনুমতি দেয়।
- ডিভাইসের পরিচিতি অ্যাপ্লিকেশন এবং পরিচিতি প্রদানকারীর সাথে একটি বিজ্ঞপ্তি রেজিস্টার করে, আপনি কোনও পরিচিতি দেখার সময় একটি ইনটেন্ট পেতে পারেন এবং সেই সময়ে আপনার পরিষেবা থেকে পরিচিতির স্ট্যাটাস আপডেট করতে পারেন। এই পদ্ধতিটি সিঙ্ক অ্যাডাপ্টারের মাধ্যমে সম্পূর্ণ সিঙ্ক করার চেয়ে দ্রুত হতে পারে এবং কম ব্যান্ডউইথ ব্যবহার করতে পারে।
- ব্যবহারকারীরা ডিভাইসের পরিচিতি অ্যাপ্লিকেশনে পরিচিতি দেখার সময় আপনার সামাজিক নেটওয়ার্কিং পরিষেবাতে একটি পরিচিতি যোগ করতে পারেন। আপনি "পরিচিতিকে আমন্ত্রণ জানান" ফিচারের মাধ্যমে এটি চালু করেন, যা আপনি এমন একটি অ্যাক্টিভিটির সাথে চালু করেন যা আপনার নেটওয়ার্কে আগে থেকে থাকা পরিচিতিকে যোগ করে এবং একটি XML ফাইল যা ডিভাইসের পরিচিতি অ্যাপ্লিকেশন এবং পরিচিতি প্রদানকারীকে আপনার অ্যাপ্লিকেশনের বিবরণ প্রদান করে।
পরিচিতি সরবরাহকারীর সাথে স্ট্রিম আইটেমের নিয়মিত সিঙ্ক্রোনাইজেশন অন্যান্য সিঙ্ক্রোনাইজেশনের মতোই। সিঙ্ক্রোনাইজেশন সম্পর্কে আরও জানতে, পরিচিতি সরবরাহকারী সিঙ্ক অ্যাডাপ্টার বিভাগটি দেখুন। বিজ্ঞপ্তি রেজিস্টার করা এবং পরিচিতিদের আমন্ত্রণ জানানোর বিষয়টি পরবর্তী দুটি বিভাগে কভার করা হয়েছে।
সোশ্যাল নেটওয়ার্কিং ভিউ ম্যানেজ করার জন্য রেজিস্টার করা হচ্ছে
ব্যবহারকারী আপনার সিঙ্ক অ্যাডাপ্টারের মাধ্যমে ম্যানেজ করা কোনও পরিচিতি দেখলে বিজ্ঞপ্তি পাওয়ার জন্য আপনার সিঙ্ক অ্যাডাপ্টার রেজিস্টার করতে:
-
আপনার প্রোজেক্টের
res/xml/ডিরেক্টরিতেcontacts.xmlনামের একটি ফাইল তৈরি করুন। আপনার কাছে এই ফাইলটি আগে থেকেই থাকলে, আপনি এই ধাপটি এড়িয়ে যেতে পারেন। -
এই ফাইলে, এলিমেন্ট যোগ করুন
<ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android">. এই এলিমেন্ট আগে থেকেই থাকলে, আপনি এই ধাপটি এড়িয়ে যেতে পারেন। -
ব্যবহারকারী ডিভাইসের পরিচিতি অ্যাপ্লিকেশনে কোনও পরিচিতির বিবরণ পৃষ্ঠা খুললে,
বিজ্ঞপ্তি পাঠানো হয় এমন কোনও পরিষেবা রেজিস্টার করতে,
viewContactNotifyService="serviceclass"অ্যাট্রিবিউটটি এলিমেন্টে যোগ করুন, যেখানেserviceclassহল পরিষেবার সম্পূর্ণ-যোগ্য ক্লাসনেম যা ডিভাইসের পরিচিতি অ্যাপ্লিকেশন থেকে ইনটেন্ট গ্রহণ করবে। বিজ্ঞপ্তি পরিষেবা ব্যবহার করার জন্য, এমন ক্লাস ব্যবহার করুন যাIntentService-কে এক্সটেন্ড করে, যাতে পরিষেবাটি ইনটেন্ট গ্রহণ করতে পারে। ইনকামিং ইনটেন্টের ডেটাতে ব্যবহারকারীর ক্লিক করা র কন্ট্যাক্টের কন্টেন্ট URI থাকে। বিজ্ঞপ্তি পরিষেবা থেকে, আপনি র কন্ট্যাক্টের ডেটা আপডেট করার জন্য আপনার সিঙ্ক অ্যাডাপ্টারকে বাইন্ড করতে এবং তারপরে কল করতে পারেন।
ব্যবহারকারী কোনও স্ট্রিম আইটেম বা ফটো অথবা দুটিতেই ক্লিক করলে, কল করার জন্য কোনও অ্যাক্টিভিটি রেজিস্টার করতে:
-
আপনার প্রোজেক্টের
res/xml/ডিরেক্টরিতেcontacts.xmlনামের একটি ফাইল তৈরি করুন। আপনার কাছে এই ফাইলটি আগে থেকেই থাকলে, আপনি এই ধাপটি এড়িয়ে যেতে পারেন। -
এই ফাইলে, এলিমেন্ট যোগ করুন
<ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android">. এই এলিমেন্ট আগে থেকেই থাকলে, আপনি এই ধাপটি এড়িয়ে যেতে পারেন। -
ডিভাইসের পরিচিতি অ্যাপ্লিকেশনে কোনও স্ট্রিম আইটেমে ব্যবহারকারীর ক্লিক ম্যানেজ করার জন্য আপনার কোনও একটি অ্যাক্টিভিটি রেজিস্টার করতে, এলিমেন্টে
viewStreamItemActivity="activityclass"অ্যাট্রিবিউট যোগ করুন, যেখানেactivityclassহল অ্যাক্টিভিটির সম্পূর্ণ-যোগ্য ক্লাসনেম যা ডিভাইসের পরিচিতি অ্যাপ্লিকেশন থেকে ইনটেন্ট পাবে। -
ডিভাইসের পরিচিতি অ্যাপ্লিকেশনে ব্যবহারকারী কোনও স্ট্রিম ফটোতে ক্লিক করলে, আপনার কোনও একটি অ্যাক্টিভিটি রেজিস্টার করতে,
এলিমেন্টে
viewStreamItemPhotoActivity="activityclass"অ্যাট্রিবিউট যোগ করুন, যেখানেactivityclassহল অ্যাক্টিভিটির সম্পূর্ণ-যোগ্য ক্লাসনেম যা ডিভাইসের পরিচিতি অ্যাপ্লিকেশন থেকে ইনটেন্ট পাবে।
<ContactsAccountType> এলিমেন্টটি <ContactsAccountType> এলিমেন্ট বিভাগে আরও বিস্তারিতভাবে বর্ণনা করা হয়েছে।
ইনকামিং ইনটেন্টে ব্যবহারকারীর ক্লিক করা আইটেম বা ফটোর কন্টেন্ট URI থাকে। টেক্সট আইটেম ও ফটোর জন্য আলাদা অ্যাক্টিভিটি রাখতে, একই ফাইলে দুটি অ্যাট্রিবিউট ব্যবহার করুন।
আপনার সোশ্যাল নেটওয়ার্কিং পরিষেবার সাথে ইন্টার্যাক্ট করা
আপনার সোশ্যাল নেটওয়ার্কিং সাইটে কোনও পরিচিতিকে আমন্ত্রণ জানানোর জন্য ব্যবহারকারীকে ডিভাইসের পরিচিতি অ্যাপ্লিকেশন ছেড়ে যেতে হবে না। পরিবর্তে, আপনি ডিভাইসের পরিচিতি অ্যাপকে আপনার কোনও অ্যাক্টিভিটিতে পরিচিতিকে আমন্ত্রণ জানানোর জন্য একটি ইনটেন্ট পাঠাতে বলতে পারেন। এটি সেট-আপ করতে:
-
আপনার প্রোজেক্টের
res/xml/ডিরেক্টরিতেcontacts.xmlনামের একটি ফাইল তৈরি করুন। আপনার কাছে এই ফাইলটি আগে থেকেই থাকলে, আপনি এই ধাপটি এড়িয়ে যেতে পারেন। -
এই ফাইলে, এলিমেন্ট যোগ করুন
<ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android">. এই এলিমেন্ট আগে থেকেই থাকলে, আপনি এই ধাপটি এড়িয়ে যেতে পারেন। -
নিম্নলিখিত অ্যাট্রিবিউট যোগ করুন:
inviteContactActivity="activityclass"-
inviteContactActionLabel="@string/invite_action_label"
activityclassভ্যালু হল অ্যাক্টিভিটির সম্পূর্ণ-যোগ্য ক্লাসনেম যা ইন্টেন্ট গ্রহণ করবে।invite_action_labelভ্যালু হল একটি টেক্সট স্ট্রিং যা ডিভাইসের পরিচিতি অ্যাপ্লিকেশনের কানেকশন যোগ করুন মেনুতে দেখানো হয়।
মনে রাখবেন: ContactsSource হল ContactsAccountType-এর জন্য
বন্ধ হয়ে যাওয়া ট্যাগের নাম।
contacts.xml রেফারেন্স
contacts.xml ফাইলে XML এলিমেন্ট আছে যা পরিচিতি অ্যাপ্লিকেশন ও পরিচিতি প্রদানকারীর সাথে আপনার
সিঙ্ক অ্যাডাপ্টার ও অ্যাপ্লিকেশনের ইন্টার্যাকশন নিয়ন্ত্রণ করে। এইসব
এলিমেন্ট নিম্নলিখিত বিভাগে বর্ণনা করা হয়েছে।
<যোগাযোগের অ্যাকাউন্টের ধরণ> উপাদান
<ContactsAccountType> এলিমেন্ট আপনার অ্যাপ্লিকেশনের সাথে পরিচিতি অ্যাপ্লিকেশনের
ইন্টার্যাকশন নিয়ন্ত্রণ করে। এটির সিনট্যাক্স নিচে দেওয়া হল:
<ContactsAccountType xmlns:android="http://schemas.android.com/apk/res/android" inviteContactActivity="activity_name" inviteContactActionLabel="invite_command_text" viewContactNotifyService="view_notify_service" viewGroupActivity="group_view_activity" viewGroupActionLabel="group_action_text" viewStreamItemActivity="viewstream_activity_name" viewStreamItemPhotoActivity="viewphotostream_activity_name">
যেখানে আছে:
res/xml/contacts.xml
এতে এগুলি থাকতে পারে:
<ContactsDataKind>
বিবরণ:
Android কম্পোনেন্ট এবং UI লেবেল ঘোষণা করে যা ব্যবহারকারীদের তাদের পরিচিতিদের মধ্যে একজনকে একটি সোশ্যাল নেটওয়ার্কে আমন্ত্রণ জানাতে, তাদের সোশ্যাল নেটওয়ার্কিং স্ট্রিমগুলির মধ্যে একটি আপডেট হলে ব্যবহারকারীদের জানাতে এবং আরও অনেক কিছু করতে দেয়।
মনে রাখবেন যে <ContactsAccountType>-এর অ্যাট্রিবিউটের জন্য অ্যাট্রিবিউট প্রিফিক্স android:-এর
প্রয়োজন নেই।
অ্যাট্রিবিউট:
inviteContactActivity- আপনার অ্যাপ্লিকেশনের অ্যাক্টিভিটির সম্পূর্ণ-যোগ্য ক্লাস নাম যা আপনি অ্যাক্টিভেট করতে চান যখন ব্যবহারকারী ডিভাইসের পরিচিতি অ্যাপ্লিকেশন থেকে কানেকশন যোগ করুন বিকল্প বেছে নেন।
inviteContactActionLabel-
inviteContactActivity-এ নির্দিষ্ট করা অ্যাক্টিভিটির জন্য দেখানো টেক্সট স্ট্রিং, কানেকশন যোগ করুন মেনুতে। যেমন, আপনি "আমার নেটওয়ার্কে ফলো করুন" স্ট্রিং ব্যবহার করতে পারেন। এই লেবেলের জন্য আপনি স্ট্রিং রিসোর্স আইডেন্টিফায়ার ব্যবহার করতে পারবেন। viewContactNotifyService- আপনার অ্যাপ্লিকেশনের কোনও পরিষেবার সম্পূর্ণ-যোগ্য ক্লাস নাম যা ব্যবহারকারী কোনও পরিচিতি দেখলে বিজ্ঞপ্তি পাবে। এই বিজ্ঞপ্তি ডিভাইসের পরিচিতি অ্যাপ্লিকেশন পাঠায়; এটি আপনার অ্যাপ্লিকেশনকে ডেটা-ইনটেনসিভ অপারেশন স্থগিত করার অনুমতি দেয় যতক্ষণ না সেগুলির প্রয়োজন হয়। যেমন, আপনার অ্যাপ্লিকেশন এই বিজ্ঞপ্তির উত্তর দিতে পারে পরিচিতির হাই-রেজোলিউশন ফটো এবং সবচেয়ে সাম্প্রতিক সোশ্যাল স্ট্রিম আইটেম পড়ে এবং দেখিয়ে। এই ফিচারটি সোশ্যাল স্ট্রিম ইন্টার্যাকশন বিভাগে আরও বিস্তারিতভাবে বর্ণনা করা হয়েছে।
viewGroupActivity- আপনার অ্যাপ্লিকেশনের কোনও অ্যাক্টিভিটির সম্পূর্ণ-যোগ্য ক্লাস নাম যা গ্রুপের তথ্য দেখাতে পারে। ব্যবহারকারী ডিভাইসের পরিচিতি অ্যাপ্লিকেশনে গ্রুপ লেবেলে ক্লিক করলে, এই অ্যাক্টিভিটির UI দেখানো হয়।
viewGroupActionLabel-
UI কন্ট্রোলের জন্য পরিচিতি অ্যাপ্লিকেশন যে লেবেল দেখায়, যার মাধ্যমে
ব্যবহারকারী আপনার অ্যাপ্লিকেশনে গ্রুপ দেখতে পান।
এই অ্যাট্রিবিউটের জন্য স্ট্রিং রিসোর্স আইডেন্টিফায়ার অনুমোদিত।
viewStreamItemActivity- আপনার অ্যাপ্লিকেশনে কোনও অ্যাক্টিভিটির সম্পূর্ণ-যোগ্য ক্লাস নাম যা ডিভাইসের পরিচিতি অ্যাপ্লিকেশন চালু করে যখন ব্যবহারকারী কোনও র কন্ট্যাক্টের জন্য স্ট্রিম আইটেমে ক্লিক করেন।
viewStreamItemPhotoActivity- আপনার অ্যাপ্লিকেশনের কোনও অ্যাক্টিভিটির সম্পূর্ণ-যোগ্য ক্লাস নাম যা ডিভাইসের পরিচিতি অ্যাপ্লিকেশন চালু করে যখন ব্যবহারকারী র কন্ট্যাক্টের জন্য স্ট্রিম আইটেমে কোনও ফটোতে ক্লিক করেন।
<ContactsDataKind> এলিমেন্ট
<ContactsDataKind> এলিমেন্ট, পরিচিতি অ্যাপ্লিকেশনের UI-তে আপনার অ্যাপ্লিকেশনের
কাস্টম ডেটা রো-এর ডিসপ্লে নিয়ন্ত্রণ করে। এটির সিনট্যাক্স নিচে দেওয়া হল:
<ContactsDataKind android:mimeType="MIMEtype" android:icon="icon_resources" android:summaryColumn="column_name" android:detailColumn="column_name">
যেখানে আছে:
<ContactsAccountType>
বিবরণ:
র কন্ট্যাক্টের বিবরণের অংশ হিসেবে কাস্টম ডেটা সারির কন্টেন্ট পরিচিতি অ্যাপ্লিকেশনে দেখাতে
এই এলিমেন্ট ব্যবহার করুন। <ContactsAccountType>-এর প্রতিটি <ContactsDataKind> চাইল্ড এলিমেন্ট
কাস্টম ডেটা সারির ধরনকে দেখায় যা আপনার সিঙ্ক
অ্যাডাপ্টার ContactsContract.Data টেবিলে যোগ করে। আপনার ব্যবহার করা প্রতিটি কাস্টম MIME প্রকারের জন্য একটি
<ContactsDataKind> এলিমেন্ট যোগ করুন। আপনার কাছে যদি এমন কোনও কাস্টম ডেটা রো থাকে যার জন্য আপনি ডেটা দেখাতে চান না, তাহলে আপনাকে
এলিমেন্ট যোগ করতে হবে না।
অ্যাট্রিবিউট:
android:mimeType-
ContactsContract.Dataটেবিলে আপনার কাস্টম ডেটা সারি প্রকারের একটির জন্য আপনি যে কাস্টম MIME প্রকারটি সংজ্ঞায়িত করেছেন। যেমন,vnd.android.cursor.item/vnd.example.locationstatusভ্যালুটি কোনও ডেটা সারির জন্য কাস্টম MIME-এর প্রকার হতে পারে যা কোনও পরিচিতির শেষ জানা লোকেশন রেকর্ড করে। android:icon- একটি Android ড্রয়েবল রিসোর্স যা পরিচিতি অ্যাপ্লিকেশন আপনার ডেটার পাশে দেখায়। ব্যবহারকারীকে বোঝাতে এটি ব্যবহার করুন যে ডেটা আপনার পরিষেবা থেকে এসেছে।
android:summaryColumn-
ডেটা সারি থেকে পাওয়া দুটি ভ্যালুর মধ্যে প্রথমটির কলামের নাম। এই
ডেটা সারির এন্ট্রির প্রথম লাইন হিসেবে ভ্যালু দেখানো হয়। প্রথম লাইনটি
ডেটার সারসংক্ষেপ হিসেবে ব্যবহার করার জন্য, তবে এটি ঐচ্ছিক। এছাড়াও,
android:detailColumnদেখুন। android:detailColumn-
ডেটা সারি থেকে পাওয়া দুটি ভ্যালুর মধ্যে দ্বিতীয়টির কলামের নাম। এই ডেটা সারির জন্য এন্ট্রির দ্বিতীয় লাইন হিসেবে
ভ্যালু দেখানো হয়। এছাড়াও,
android:summaryColumnদেখুন।
পরিচিতি সরবরাহকারীর অতিরিক্ত ফিচার
আগের বিভাগে বর্ণনা করা প্রধান ফিচার ছাড়াও, পরিচিতি ডেটা নিয়ে কাজ করার জন্য পরিচিতি সরবরাহকারী এইসব উপযোগী ফিচার অফার করে:
- পরিচিতি গ্রুপ
- ফটো ফিচার
পরিচিতি গ্রুপ
পরিচিতি সরবরাহকারী, বিকল্প হিসেবে,
গ্রুপ ডেটার সাথে সম্পর্কিত পরিচিতির সংগ্রহে লেবেল যোগ করতে পারে। ব্যবহারকারীর অ্যাকাউন্টের সাথে যুক্ত সার্ভার
গ্রুপ বজায় রাখতে চাইলে, অ্যাকাউন্টের ধরনের জন্য সিঙ্ক অ্যাডাপ্টারকে পরিচিতি সরবরাহকারী ও সার্ভারের মধ্যে
গ্রুপ ডেটা ট্রান্সফার করতে হবে। ব্যবহারকারী সার্ভারে নতুন পরিচিতি যোগ করে
তারপর এই পরিচিতি নতুন গ্রুপে রাখলে, সিঙ্ক অ্যাডাপ্টারকে অবশ্যই নতুন গ্রুপটি
ContactsContract.Groups টেবিলে যোগ করতে হবে। র কন্ট্যাক্ট যে গ্রুপ বা গ্রুপগুলির
অন্তর্ভুক্ত, সেগুলি ContactsContract.CommonDataKinds.GroupMembership MIME টাইপ ব্যবহার করে
ContactsContract.Data টেবিলে স্টোর করা হয়।
আপনি যদি এমন একটি সিঙ্ক অ্যাডাপ্টার ডিজাইন করেন যা সার্ভার থেকে পরিচিতি সরবরাহকারীতে র কন্ট্যাক্ট ডেটা যোগ করবে
এবং আপনি গ্রুপ ব্যবহার করছেন না, তাহলে আপনার ডেটা দৃশ্যমান করার জন্য আপনাকে
সরবরাহকারীকে বলতে হবে। ব্যবহারকারী ডিভাইসে অ্যাকাউন্ট যোগ করার সময় যে কোডটি এক্সিকিউট করা হয়, সেটিতে ContactsContract.Settings
সারিটি আপডেট করুন যা পরিচিতি সরবরাহকারী অ্যাকাউন্টের জন্য যোগ করে। এই সারিতে,
Settings.UNGROUPED_VISIBLE কলামের ভ্যালু ১ হিসেবে সেট করুন। আপনি এটি করলে, পরিচিতি সরবরাহকারী সবসময়
আপনার পরিচিতি ডেটা দেখাবে, এমনকি আপনি গ্রুপ ব্যবহার না করলেও।
পরিচিতির ফটো
ContactsContract.Data টেবিলে MIME-এর প্রকার Photo.CONTENT_ITEM_TYPE সহ সারি হিসেবে ফটো স্টোর করা হয়। সারিটির
CONTACT_ID কলামটি র কন্ট্যাক্টের
_ID কলামের সাথে লিঙ্ক করা আছে।
ContactsContract.Contacts.Photo ক্লাসটি ContactsContract.Contacts-এর একটি সাব-টেবিলকে সংজ্ঞায়িত করে
যেটিতে কোনও পরিচিতির প্রাথমিক ফটোর জন্য ফটো সংক্রান্ত তথ্য থাকে, যা পরিচিতির প্রাথমিক র কন্ট্যাক্টের প্রাথমিক ফটো। একইভাবে,
ContactsContract.RawContacts.DisplayPhoto ক্লাসটি ContactsContract.RawContacts-এর একটি সাব-টেবিল
সংজ্ঞায়িত করে, যাতে র কন্ট্যাক্টের
প্রাথমিক ফটোর জন্য ফটো সংক্রান্ত তথ্য থাকে।
ContactsContract.Contacts.Photo এবং
ContactsContract.RawContacts.DisplayPhoto-এর রেফারেন্স ডকুমেন্টেশনে
ফটো সংক্রান্ত তথ্য ফিরিয়ে আনার উদাহরণ রয়েছে। র কন্ট্যাক্টের জন্য প্রাথমিক থাম্বনেল ফিরিয়ে আনার কোনও
সুবিধাজনক ক্লাস নেই, তবে আপনি র কন্ট্যাক্টের
_ID,
Photo.CONTENT_ITEM_TYPE এবং IS_PRIMARY
কলাম বেছে নিয়ে ContactsContract.Data টেবিলে কোয়েরি পাঠিয়ে
র কন্ট্যাক্টের প্রাথমিক ফটো রো খুঁজে পেতে পারেন।
কোনও ব্যক্তির সোশ্যাল স্ট্রিম ডেটাতে ফটোও অন্তর্ভুক্ত থাকতে পারে। এগুলি android.provider.ContactsContract.StreamItemPhotos টেবিলে স্টোর করা হয়, যা সোশ্যাল স্ট্রিম ফটো বিভাগে আরও বিস্তারিতভাবে বর্ণনা করা হয়েছে।