কীভাবে করবেন
উপস্থাপন করা হচ্ছে Cahier: বড় স্ক্রিনে কর্মদক্ষতা ও সৃজনশীলতার জন্য একটি নতুন অ্যান্ড্রয়েড গিটহাব স্যাম্পল
১১ মিনিটের পাঠ

ইঙ্ক এপিআই এখন বিটা পর্যায়ে রয়েছে এবং আপনার অ্যাপে ইন্টিগ্রেট করার জন্য প্রস্তুত। ডেভেলপারদের মূল্যবান মতামতের ফলেই এই মাইলফলকটি অর্জন করা সম্ভব হয়েছে, যার ফলস্বরূপ এপিআই-এর পারফরম্যান্স, স্থিতিশীলতা এবং ভিজ্যুয়াল কোয়ালিটিতে ক্রমাগত উন্নতি সাধিত হয়েছে।
গুগল অ্যাপস, যেমন গুগল ডক্স , পিক্সেল স্টুডিও , গুগল ফটোস , ক্রোম পিডিএফ , ইউটিউব ইফেক্ট মেকার, এবং অ্যান্ড্রয়েডের অনন্য ফিচার যেমন সার্কেল টু সার্চ— এই সবই সর্বশেষ এপিআই ব্যবহার করে।
এই মাইলফলকটি উদযাপন উপলক্ষে, আমরা Cahier চালু করার ঘোষণা দিতে পেরে আনন্দিত। এটি একটি পূর্ণাঙ্গ নোট-নেওয়ার অ্যাপের নমুনা, যা সব আকারের অ্যান্ড্রয়েড ডিভাইস, বিশেষ করে ট্যাবলেট এবং ফোল্ডেবল ফোনের জন্য অপ্টিমাইজ করা হয়েছে।
Cahier কী?
Cahier (ফরাসি ভাষায় যার অর্থ "নোটবুক") হলো একটি নমুনা অ্যাপ, যা দেখানোর জন্য ডিজাইন করা হয়েছে যে কীভাবে এমন একটি অ্যাপ্লিকেশন তৈরি করা যায়, যা ব্যবহারকারীদের লেখা, অঙ্কন এবং ছবির সমন্বয়ে তাদের চিন্তাভাবনা লিপিবদ্ধ ও সংগঠিত করতে সক্ষম করে।
বড় স্ক্রিনে ব্যবহারকারীর কর্মক্ষমতা ও সৃজনশীলতা বাড়ানোর জন্য এই স্যাম্পলটি একটি নির্ভরযোগ্য রেফারেন্স হিসেবে কাজ করতে পারে। এটি এই ধরনের অভিজ্ঞতা তৈরির সেরা পদ্ধতিগুলো তুলে ধরে, যা ডেভেলপারদের সংশ্লিষ্ট শক্তিশালী এপিআই এবং কৌশলগুলো বুঝতে ও গ্রহণ করতে সাহায্য করে। এই পোস্টে Cahier-এর মূল বৈশিষ্ট্য, প্রধান এপিআই এবং সেইসব আর্কিটেকচারাল সিদ্ধান্তগুলো সম্পর্কে বিস্তারিত আলোচনা করা হয়েছে, যা এই স্যাম্পলটিকে আপনার নিজের অ্যাপের জন্য একটি চমৎকার রেফারেন্স হিসেবে তৈরি করেছে।
নমুনাটিতে প্রদর্শিত প্রধান বৈশিষ্ট্যগুলো হলো:
- বহুমুখী নোট তৈরি: এখানে দেখানো হয়েছে কীভাবে একটি নমনীয় কন্টেন্ট তৈরির সিস্টেম বাস্তবায়ন করতে হয়, যা একটি নোটের মধ্যেই টেক্সট, ফ্রিফর্ম ড্রয়িং এবং ছবি সংযুক্তি সহ একাধিক ফরম্যাট সমর্থন করে।
- ক্রিয়েটিভ ইঙ্কিং টুলস : ইঙ্ক এপিআই (Ink API) ব্যবহার করে একটি উচ্চ পারফরম্যান্স ও কম ল্যাটেন্সির ড্রয়িং অভিজ্ঞতা প্রদান করে। এই স্যাম্পলটিতে বিভিন্ন ব্রাশ, একটি কালার পিকার, আনডু/রিডু কার্যকারিতা এবং একটি ইরেজার টুল সমন্বিত করার একটি বাস্তব উদাহরণ দেওয়া হয়েছে।
- ড্র্যাগ অ্যান্ড ড্রপের মাধ্যমে সাবলীল কন্টেন্ট ইন্টিগ্রেশন : ড্র্যাগ অ্যান্ড ড্রপ ব্যবহার করে কীভাবে ইনকামিং এবং আউটগোয়িং উভয় কন্টেন্ট পরিচালনা করা যায় তা দেখানো হয়েছে। এর মধ্যে রয়েছে অন্য অ্যাপ থেকে ড্রপ করা ছবি গ্রহণ করা এবং নির্বিঘ্নে শেয়ার করার জন্য ব্যবহারকারীদের আপনার অ্যাপের বাইরে কন্টেন্ট ড্র্যাগ করে নিয়ে যাওয়ার সুবিধা দেওয়া।
- নোটের বিন্যাস : দ্রুত অ্যাক্সেসের জন্য নোটগুলিকে পছন্দের তালিকায় যুক্ত করুন। সবকিছু গুছিয়ে রাখতে ভিউটি ফিল্টার করুন।
- অফলাইন ফার্স্ট আর্কিটেকচার: Room ব্যবহার করে অফলাইন ফার্স্ট আর্কিটেকচারে নির্মিত, যা নিশ্চিত করে যে সমস্ত ডেটা স্থানীয়ভাবে সংরক্ষিত থাকে এবং ইন্টারনেট সংযোগ ছাড়াই অ্যাপটি সম্পূর্ণ কার্যকর থাকে।
- শক্তিশালী মাল্টি-উইন্ডো এবং মাল্টি-ইনস্ট্যান্স সাপোর্ট : এটি দেখায় কীভাবে মাল্টি-ইনস্ট্যান্স সাপোর্ট করা যায়, যার ফলে আপনার অ্যাপটি একাধিক উইন্ডোতে চালু করা যায়। এতে ব্যবহারকারীরা পাশাপাশি বিভিন্ন নোটে কাজ করতে পারেন, যা বড় স্ক্রিনে উৎপাদনশীলতা এবং সৃজনশীলতা বাড়ায়।
- সকল স্ক্রিনের জন্য অভিযোজিত UI : ফোন, ট্যাবলেট এবং ফোল্ডেবল ডিভাইসে একটি সর্বোত্তম ব্যবহারকারীর অভিজ্ঞতা প্রদানের জন্য, ইউজার ইন্টারফেসটি ListDetailPaneScaffold এবং NavigationSuiteScaffold ব্যবহার করে বিভিন্ন স্ক্রিনের আকার ও ওরিয়েন্টেশনের সাথে নির্বিঘ্নে খাপ খাইয়ে নেয়।
- গভীর সিস্টেম ইন্টিগ্রেশন : সিস্টেমব্যাপী নোটস ইন্টেন্ট-এ সাড়া দিয়ে এবং বিভিন্ন সিস্টেম এন্ট্রি পয়েন্ট থেকে দ্রুত কন্টেন্ট ক্যাপচার সক্ষম করার মাধ্যমে, কীভাবে আপনার অ্যাপকে অ্যান্ড্রয়েড ১৪ এবং তার পরবর্তী সংস্করণগুলিতে ডিফল্ট নোট-টেকিং অ্যাপ হিসেবে সেট করা যায়, তার একটি নির্দেশিকা প্রদান করে।
বড় পর্দায় উৎপাদনশীলতা এবং সৃজনশীলতার জন্য নির্মিত
প্রাথমিক উন্মোচনের জন্য, আমরা এমন কয়েকটি মূল বৈশিষ্ট্যের ওপর ঘোষণাটি কেন্দ্রীভূত করছি, যা Cahier- কে কর্মদক্ষতা এবং সৃজনশীলতা—উভয় ক্ষেত্রেই একটি গুরুত্বপূর্ণ শিক্ষণীয় উপকরণ হিসেবে গড়ে তোলে।
অভিযোজনশীলতার একটি ভিত্তি
Cahier-কে একেবারে গোড়া থেকেই অভিযোজনযোগ্য করে তৈরি করা হয়েছে। এই স্যাম্পলটি material3-adaptive লাইব্রেরির ListDetailPaneScaffold এবং NavigationSuiteScaffold অংশ ব্যবহার করে, যা অ্যাপের লেআউটকে বিভিন্ন স্ক্রিনের আকার ও ওরিয়েন্টেশনের সাথে নির্বিঘ্নে খাপ খাইয়ে নেয়। এটি একটি আধুনিক অ্যান্ড্রয়েড অ্যাপের জন্য অত্যন্ত গুরুত্বপূর্ণ একটি উপাদান, এবং কীভাবে এটি কার্যকরভাবে প্রয়োগ করতে হয় তার একটি সুস্পষ্ট উদাহরণ Cahier প্রদান করে।

ম্যাটেরিয়াল ৩ অ্যাডাপ্টিভ লাইব্রেরি দিয়ে নির্মিত Cahier অ্যাডাপ্টিভ UI
মূল এপিআই এবং ইন্টিগ্রেশনগুলি প্রদর্শন করা হচ্ছে
এই নমুনাটির মূল উদ্দেশ্য হলো এমন কিছু শক্তিশালী প্রোডাক্টিভিটি এপিআই (API) প্রদর্শন করা, যা আপনি আপনার নিজের অ্যাপ্লিকেশনগুলিতে কাজে লাগাতে পারেন, যার মধ্যে রয়েছে:
মূল এপিআইগুলির একটি বিশদ পর্যালোচনা
চলুন, প্রথম শ্রেণীর নোট নেওয়ার অভিজ্ঞতা প্রদানের জন্য Cahier যে দুটি মূল API সংহত করে, সেগুলির বিষয়ে আরও গভীরভাবে আলোচনা করা যাক।
ইঙ্ক এপিআই দিয়ে প্রাকৃতিক ইঙ্কিং অভিজ্ঞতা তৈরি করা
স্টাইলাস ইনপুট বড় স্ক্রিনের ডিভাইসগুলোকে ডিজিটাল নোটবুক এবং স্কেচবুকে রূপান্তরিত করে। আপনাকে সাবলীল এবং স্বাভাবিক ইঙ্কিং অভিজ্ঞতা তৈরিতে সাহায্য করার জন্য, আমরা এই স্যাম্পলের ভিত্তি হিসেবে ইঙ্ক এপিআই (Ink API) তৈরি করেছি। ইঙ্ক এপিআই সেরা মানের স্বল্প ল্যাটেন্সির সাথে সুন্দর ইঙ্ক স্ট্রোক তৈরি, রেন্ডার এবং পরিচালনা করা সহজ করে তোলে।
ইঙ্ক এপিআই একটি মডিউলার আর্কিটেকচার প্রদান করে, ফলে আপনি এটিকে আপনার অ্যাপের নির্দিষ্ট স্ট্যাক এবং প্রয়োজন অনুযায়ী সাজিয়ে নিতে পারেন। এপিআই মডিউলগুলোর মধ্যে রয়েছে:
- অথরিং মডিউল ( কম্পোজ - ভিউ ): ডিভাইসের পক্ষে সম্ভব সর্বনিম্ন ল্যাটেন্সিতে মসৃণ স্ট্রোক তৈরি করতে রিয়েল-টাইম ইঙ্কিং ইনপুট পরিচালনা করে।
- DrawingSurface- এ, Cahier রিয়েল-টাইম স্টাইলাস বা টাচ ইনপুট পরিচালনা করার জন্য সদ্য প্রবর্তিত InProgressStrokes কম্পোজেবলটি ব্যবহার করে। এই মডিউলটি পয়েন্টার ইভেন্ট ক্যাপচার করা এবং সর্বনিম্ন সম্ভাব্য ল্যাটেন্সিতে ওয়েট ইঙ্ক স্ট্রোক রেন্ডার করার জন্য দায়ী।
- স্ট্রোকস মডিউল: এটি ইঙ্ক ইনপুট এবং তার ভিজ্যুয়াল উপস্থাপনাকে নির্দেশ করে। একজন ব্যবহারকারী একটি লাইন আঁকা শেষ করলে, onStrokesFinished কলব্যাকটি অ্যাপকে একটি চূড়ান্ত/শুকনো স্ট্রোক অবজেক্ট প্রদান করে। এই অপরিবর্তনীয় অবজেক্টটি, যা সম্পূর্ণ ইঙ্ক স্ট্রোককে নির্দেশ করে, পরবর্তীতে DrawingCanvasViewModel- এ পরিচালিত হয়।
- রেন্ডারিং মডিউল: দক্ষতার সাথে ইঙ্ক স্ট্রোক প্রদর্শন করে, যার ফলে এগুলোকে জেটপ্যাক কম্পোজ বা অ্যান্ড্রয়েড ভিউ-এর সাথে একত্রিত করা যায়।
- বিদ্যমান এবং সদ্য শুকানো উভয় স্ট্রোক প্রদর্শন করার জন্য, Cahier সক্রিয় ড্রয়িংয়ের ক্ষেত্রে DrawingSurface- এ এবং নোটটির একটি স্থির প্রিভিউ দেখানোর ক্ষেত্রে DrawingDetailPanePreview- তে CanvasStrokeRenderer ব্যবহার করে। এই মডিউলটি দক্ষতার সাথে একটি ক্যানভাসের উপর স্ট্রোক অবজেক্টগুলো অঙ্কন করে।
- ব্রাশ মডিউল ( কম্পোজ - ভিউ ): স্ট্রোকের ভিজ্যুয়াল স্টাইল নির্ধারণের জন্য একটি ডিক্লারেটিভ উপায় প্রদান করে। সাম্প্রতিক আপডেটগুলিতে (alpha03 রিলিজের পর থেকে) একটি নতুন ড্যাশড লাইন ব্রাশ অন্তর্ভুক্ত করা হয়েছে, যা ল্যাসো সিলেকশনের মতো ফিচারের জন্য বিশেষভাবে উপযোগী। DrawingCanvasViewModel বর্তমান ব্রাশের স্টেট ধারণ করে। DrawingCanvas- এর একটি টুলবক্স ব্যবহারকারীদের বিভিন্ন ব্রাশ ফ্যামিলি (যেমন StockBrushes.pressurePen() বা StockBrushes.highlighter() ) নির্বাচন করতে এবং রং পরিবর্তন করতে দেয়। ViewModel ব্রাশ অবজেক্টটি আপডেট করে, যা পরবর্তীতে নতুন স্ট্রোকের জন্য InProgressStrokes কম্পোজেবল দ্বারা ব্যবহৃত হয়।
- জ্যামিতি মডিউল ( কম্পোজ - ভিউ ): মোছা এবং নির্বাচন করার মতো বৈশিষ্ট্যগুলির জন্য স্ট্রোক পরিবর্তন ও বিশ্লেষণ করার সুবিধা।
- টুলবক্সের মধ্যে থাকা ইরেজার টুল এবং DrawingCanvasViewModel- এর কার্যকারিতা জিওমেট্রি মডিউলের উপর নির্ভর করে। যখন ইরেজারটি সক্রিয় থাকে, তখন এটি ব্যবহারকারীর জেসচারের পথের চারপাশে একটি MutableParallelogram তৈরি করে। এরপর কোন স্ট্রোকগুলো মুছতে হবে তা নির্ধারণ করার জন্য ইরেজারটি আকৃতি এবং বিদ্যমান স্ট্রোকগুলোর বাউন্ডিং বক্সের মধ্যে ছেদবিন্দু পরীক্ষা করে, যা ইরেজারটিকে স্বজ্ঞাত এবং নির্ভুল করে তোলে।
- স্টোরেজ মডিউল: এটি ইঙ্ক ডেটার জন্য কার্যকর সিরিয়ালাইজেশন এবং ডিসিরিয়ালাইজেশন সুবিধা প্রদান করে, যার ফলে ডিস্ক এবং নেটওয়ার্কের আকার উল্লেখযোগ্যভাবে সাশ্রয় হয়। ড্রয়িং সংরক্ষণ করার জন্য, Cahier তার Room ডেটাবেসে Stroke অবজেক্টগুলো সংরক্ষণ করে। Converters- এ, নমুনাটি স্টোরেজ মডিউলের encode ফাংশন ব্যবহার করে StrokeInputBatch (কাঁচা পয়েন্ট ডেটা)-কে একটি ByteArray- তে সিরিয়ালাইজ করে। বাইট অ্যারেটি, ব্রাশের বৈশিষ্ট্যসহ, একটি JSON স্ট্রিং হিসাবে সংরক্ষিত হয়। যখন একটি নোট লোড করা হয়, তখন স্ট্রোকগুলো পুনর্গঠন করতে decode ফাংশনটি ব্যবহৃত হয়।

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

ইঙ্ক এপিআই-এর কাস্টম ব্রাশ দিয়ে তৈরি রংধনু লেজার

ইঙ্ক এপিআই-এর কাস্টম ব্রাশ দিয়ে তৈরি মিউজিক ব্রাশ
- নেটিভ জেটপ্যাক কম্পোজ ইন্টারঅপারেবিলিটি মডিউলগুলো আরও স্বাভাবিক ও কার্যকর ডেভেলপমেন্ট অভিজ্ঞতার জন্য আপনার কম্পোজ UI-এর মধ্যেই সরাসরি ইঙ্কিং ফাংশনালিটির ইন্টিগ্রেশনকে সুবিন্যস্ত করে।
কাস্টম ইমপ্লিমেন্টেশনের তুলনায় প্রোডাক্টিভিটি এবং ক্রিয়েটিভিটি অ্যাপের জন্য ইঙ্ক এপিআই বেশ কিছু সুবিধা প্রদান করে, যা এটিকে একটি আদর্শ পছন্দ করে তোলে:
- ব্যবহারের সহজতা: ইঙ্ক এপিআই গ্রাফিক্স এবং জ্যামিতির জটিলতা দূর করে, যার ফলে আপনি ক্যাহিয়ারের মূল বৈশিষ্ট্যগুলিতে মনোযোগ দিতে পারেন।
- পারফরম্যান্স: অন্তর্নির্মিত লো ল্যাটেন্সি সাপোর্ট এবং অপ্টিমাইজড রেন্ডারিং একটি মসৃণ ও প্রতিক্রিয়াশীল ইঙ্কিং অভিজ্ঞতা নিশ্চিত করে।
- নমনীয়তা: মডিউলার ডিজাইনটি আপনাকে প্রয়োজনীয় উপাদানগুলো বেছে নেওয়ার সুযোগ দেয়, যা Cahier-এর আর্কিটেকচারে Ink API-এর নির্বিঘ্ন ইন্টিগ্রেশন সম্ভব করে তোলে।
ডকস-এ মার্কআপ এবং সার্কেল টু সার্চ-এর মতো অনেক গুগল অ্যাপের পাশাপাশি ওরিয়ন নোটস এবং পিডিএফ স্ক্যানার-এর মতো পার্টনার অ্যাপগুলোতেও ইঙ্ক এপিআই ইতিমধ্যেই গ্রহণ করা হয়েছে।
“সার্কেল-টু-সার্চ (CtS)-এর জন্য ইঙ্ক এপিআই (Ink API) ছিল আমাদের প্রথম পছন্দ। তাদের বিস্তৃত ডকুমেন্টেশন ব্যবহার করে ইঙ্ক এপিআই ইন্টিগ্রেট করা অত্যন্ত সহজ ছিল, যার ফলে আমরা মাত্র এক সপ্তাহের মধ্যে আমাদের প্রথম কার্যকরী প্রোটোটাইপ তৈরি করতে সক্ষম হই। ইঙ্ক-এর কাস্টম ব্রাশ টেক্সচার এবং অ্যানিমেশন সাপোর্ট আমাদের স্ট্রোক ডিজাইনে দ্রুত পরিবর্তন আনতে সাহায্য করেছে।” - জর্ডান কোমোডা, সফটওয়্যার ইঞ্জিনিয়ার - গুগল
নোটস রোলের সাথে ডিফল্ট নোটস অ্যাপ হয়ে ওঠা
নোট নেওয়া একটি মূল সক্ষমতা যা বড় স্ক্রিনের ডিভাইসে ব্যবহারকারীর কর্মদক্ষতা বাড়ায়। নোটস রোল ফিচারের মাধ্যমে, ব্যবহারকারীরা লক স্ক্রিন থেকে অথবা অন্যান্য অ্যাপ চালু থাকা অবস্থাতেও আপনার সামঞ্জস্যপূর্ণ অ্যাপগুলো অ্যাক্সেস করতে পারেন। এই ফিচারটি সিস্টেমব্যাপী ডিফল্ট নোট-নেওয়ার অ্যাপগুলোকে শনাক্ত করে ও সেট করে এবং কন্টেন্ট ক্যাপচার করার জন্য সেগুলোকে চালু করার অনুমতি প্রদান করে।
Cahier-এ বাস্তবায়ন
নোটস রোলটি বাস্তবায়নে কয়েকটি গুরুত্বপূর্ণ ধাপ রয়েছে, যেগুলোর সবগুলোই নমুনায় দেখানো হয়েছে:
- ম্যানিফেস্ট ঘোষণা : প্রথমে, অ্যাপটিকে নোট-নেওয়ার ইন্টেন্টগুলো পরিচালনা করার সক্ষমতা ঘোষণা করতে হবে। AndroidManifest.xml- এ, Cahier android.intent.action.CREATE_NOTE অ্যাকশনের জন্য একটি
<intent-filter>অন্তর্ভুক্ত করে। এটি সিস্টেমকে সংকেত দেয় যে অ্যাপটি নোটস রোলের জন্য একটি সম্ভাব্য প্রার্থী। - রোলের অবস্থা যাচাই করা : SettingsViewModel বর্তমান অবস্থা নির্ধারণ করতে অ্যান্ড্রয়েডের RoleManager ব্যবহার করে। SettingsViewModel যাচাই করে দেখে যে ডিভাইসে নোটস রোলটি উপলব্ধ আছে কিনা ( isRoleAvailable ) এবং Cahier বর্তমানে সেই রোলটি ধারণ করে আছে কিনা ( isRoleHeld )। এই অবস্থাটি Kotlin ফ্লো ব্যবহার করে UI-তে প্রকাশ করা হয়।
- রোলের জন্য অনুরোধ : Settings.kt ফাইলে, যদি রোলটি উপলব্ধ থাকে কিন্তু ব্যবহারকারী সেটি ধারণ না করে থাকেন, তবে তাকে একটি বাটন দেখানো হয়। বাটনটি ক্লিক করা হলে, এটি ViewModel-এর
requestNotesRoleফাংশনটিকে কল করে। এই ফাংশনটি ডিফল্ট অ্যাপ সেটিংস স্ক্রিন খোলার জন্য একটি ইন্টেন্ট তৈরি করে, যেখানে ব্যবহারকারী Cahier নির্বাচন করতে পারেন। এই প্রক্রিয়াটি rememberLauncherForActivityResult API ব্যবহার করে পরিচালিত হয়, যা ইন্টেন্টটি চালু করা এবং ফলাফল গ্রহণ করার কাজটি করে। - UI আপডেট করা : ব্যবহারকারী সেটিংস স্ক্রিন থেকে ফিরে আসার পর, ActivityResultLauncher কলব্যাকটি ViewModel-এর একটি ফাংশনকে ট্রিগার করে রোলের স্ট্যাটাস আপডেট করে, যা নিশ্চিত করে যে অ্যাপটি এখন ডিফল্ট কিনা তা UI-তে সঠিকভাবে প্রতিফলিত হচ্ছে।
আমাদের 'নোট-টেকিং অ্যাপ তৈরি করুন' গাইড থেকে জানুন, কীভাবে আপনার অ্যাপে নোটস রোলটি ইন্টিগ্রেট করবেন।

লেনোভো ট্যাবলেটে ডিফল্ট নোট-নেওয়ার অ্যাপ হিসেবে Cahier একটি ফ্লোটিং উইন্ডোতে চালু হয়েছে।
একটি বড় অগ্রগতি: লেনোভো নোটস রোল চালু করেছে
বড় স্ক্রিনের অ্যান্ড্রয়েড প্রোডাক্টিভিটির ক্ষেত্রে একটি বড় অগ্রগতির কথা ঘোষণা করতে পেরে আমরা অত্যন্ত আনন্দিত: লেনোভো অ্যান্ড্রয়েড ১৫ এবং তার পরবর্তী সংস্করণের ট্যাবলেটগুলিতে নোটস রোল (Notes Role) সাপোর্ট চালু করেছে! এই আপডেটের মাধ্যমে, আপনি এখন আপনার নোট-নেওয়ার অ্যাপগুলো আপডেট করতে পারবেন, যা সামঞ্জস্যপূর্ণ লেনোভো ডিভাইসের ব্যবহারকারীদের এটিকে ডিফল্ট হিসেবে সেট করার সুযোগ দেবে। এর ফলে লক স্ক্রিন থেকেই নির্বিঘ্নে অ্যাপটি ব্যবহার করা যাবে এবং সিস্টেম লেভেলের কন্টেন্ট ক্যাপচার ফিচারগুলোও আনলক হবে।
একটি শীর্ষস্থানীয় OEM-এর এই অঙ্গীকার অ্যান্ড্রয়েডে একটি সত্যিকারের সমন্বিত ও ফলপ্রসূ ব্যবহারকারীর অভিজ্ঞতা প্রদানে নোটস-এর ভূমিকার ক্রমবর্ধমান গুরুত্বকে তুলে ধরে।
মাল্টি-ইনস্ট্যান্স, মাল্টি-উইন্ডোইং এবং ডেস্কটপ উইন্ডোইং
বড় স্ক্রিনে প্রোডাক্টিভিটি বা উৎপাদনশীলতা মানেই হলো তথ্য এবং ওয়ার্কফ্লো দক্ষতার সাথে পরিচালনা করা। এই কারণেই Cahier-কে অ্যান্ড্রয়েডের উন্নত উইন্ডোইং ক্ষমতাকে পুরোপুরি কাজে লাগানোর জন্য তৈরি করা হয়েছে, যা ব্যবহারকারীর প্রয়োজন অনুযায়ী মানিয়ে নিতে পারে এমন একটি নমনীয় কর্মক্ষেত্র প্রদান করে। অ্যাপটি সমর্থন করে:
- মাল্টি-উইন্ডোয়িং : স্প্লিট-স্ক্রিন বা ফ্রি-ফর্ম মোডে অন্য কোনো অ্যাপের পাশাপাশি চলার মৌলিক ক্ষমতা। Cahier-এ নোট নেওয়ার সময় কোনো ওয়েব পেজ দেখার মতো কাজের জন্য এটি অপরিহার্য।
- মাল্টি-ইনস্ট্যান্স : এখানেই সত্যিকারের মাল্টিটাস্কিংয়ের আসল মজা। Cahier ব্যবহারকারীদের একই সাথে অ্যাপটির একাধিক, স্বাধীন উইন্ডো খোলার সুযোগ দেয়। কল্পনা করুন, আপনি পাশাপাশি দুটি ভিন্ন নোট তুলনা করছেন, অথবা একটি উইন্ডোতে কোনো টেক্সট নোট দেখার পাশাপাশি অন্যটিতে ছবি আঁকছেন। Cahier দেখায় কীভাবে এই পৃথক ইনস্ট্যান্সগুলোকে পরিচালনা করতে হয়, যার প্রত্যেকটির নিজস্ব অবস্থা থাকে, যা আপনার অ্যাপকে একটি শক্তিশালী, বহুমুখী টুলে পরিণত করে।
- ডেস্কটপ উইন্ডোইং : কোনো এক্সটার্নাল ডিসপ্লের সাথে সংযুক্ত হলে, অ্যান্ড্রয়েড ডেস্কটপ মোড একটি ট্যাবলেট বা ফোল্ডেবল ডিভাইসকে ওয়ার্কস্টেশনে রূপান্তরিত করে। যেহেতু Cahier একটি অ্যাডাপ্টিভ UI দিয়ে তৈরি এবং মাল্টি-ইনস্ট্যান্স সমর্থন করে, তাই এই পরিবেশে অ্যাপটি চমৎকারভাবে কাজ করে। ব্যবহারকারীরা একটি প্রচলিত ডেস্কটপের মতোই একাধিক Cahier উইন্ডো খুলতে, আকার পরিবর্তন করতে এবং অবস্থান ঠিক করতে পারেন, যা এমন সব জটিল ওয়ার্কফ্লো পরিচালনা করা সম্ভব করে তোলে যা আগে মোবাইল ডিভাইসে নাগালের বাইরে ছিল।

পিক্সেল ট্যাবলেটে ডেস্কটপ উইন্ডো মোডে Cahier চলছে
Cahier-এ আমরা এই বৈশিষ্ট্যগুলো যেভাবে বাস্তবায়ন করেছি তা নিচে দেওয়া হলো:
মাল্টি-ইনস্ট্যান্স সক্ষম করতে, প্রথমে AndroidManifest এ MainActivity এর ডিক্লারেশনে PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI প্রপার্টিটি যোগ করে সিস্টেমকে জানাতে হতো যে অ্যাপটি একাধিকবার চালু হওয়া সমর্থন করে।
<activity android:name="com.example.cahier.MainActivity" android:exported="true" android:label="@string/app_name" android:theme="@style/Theme.MyApplication" android:showWhenLocked="true" android:turnScreenOn="true" android:resizeableActivity="true" android:launchMode="singleInstancePerTask"> <property android:name="android.window.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI" android:value="true"/> ... </activity>
এরপর, আমরা অ্যাপটির একটি নতুন ইনস্ট্যান্স চালু করার লজিকটি প্রয়োগ করেছি। CahierHomeScreen.kt- এ, যখন কোনো ব্যবহারকারী একটি নোট নতুন উইন্ডোতে খোলার সিদ্ধান্ত নেন, তখন আমরা নির্দিষ্ট ফ্ল্যাগসহ একটি নতুন Intent তৈরি করি, যা সিস্টেমকে নির্দেশ দেয় নতুন অ্যাক্টিভিটিটি কীভাবে চালু করতে হবে। FLAG_ACTIVITY_NEW_TASK , FLAG_ACTIVITY_MULTIPLE_TASK , এবং FLAG_ACTIVITY_LAUNCH_ADJACENT এর সমন্বয় নিশ্চিত করে যে নোটটি বিদ্যমান উইন্ডোটির পাশাপাশি একটি নতুন, পৃথক উইন্ডোতে খুলবে।
fun openNewWindow(activity: Activity?, note: Note) {
val intent = Intent(activity, MainActivity::class.java)
intent.putExtra(AppArgs.NOTE_TYPE_KEY, note.type)
intent.putExtra(AppArgs.NOTE_ID_KEY, note.id)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK or
Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT
activity?.startActivity(intent)
} মাল্টি-উইন্ডো মোড সমর্থন করার জন্য, ম্যানিফেস্টের <activity> বা <application> এলিমেন্ট সেট করে সিস্টেমকে জানাতে হতো যে অ্যাপটি রিসাইজযোগ্যতা সমর্থন করে।
<activity android:name="com.example.cahier.MainActivity" android:resizeableActivity="true" ...> </activity>
ম্যাটেরিয়াল ৩ অ্যাডাপ্টিভ লাইব্রেরি দিয়ে ইউআইটি তৈরি হওয়ায়, এটি অ্যান্ড্রয়েডের স্প্লিট স্ক্রিন মোডের মতো একাধিক উইন্ডোর পরিস্থিতিতে নির্বিঘ্নে মানিয়ে নিতে পারে।
ব্যবহারকারীর অভিজ্ঞতা উন্নত করার জন্য, আমরা ড্র্যাগ অ্যান্ড ড্রপ সুবিধা যুক্ত করেছি। Cahier-এ আমরা কীভাবে এটি বাস্তবায়ন করেছি তা নিচে দেখুন।
ড্র্যাগ এবং ড্রপ
একটি সত্যিকারের কার্যকরী বা সৃজনশীল অ্যাপ বিচ্ছিন্নভাবে কাজ করে না; এটি ডিভাইসের বাকি ইকোসিস্টেমের সাথে নির্বিঘ্নে মিথস্ক্রিয়া করে। এই মিথস্ক্রিয়ার একটি মূল ভিত্তি হলো ড্র্যাগ অ্যান্ড ড্রপ, বিশেষ করে বড় স্ক্রিনে যেখানে ব্যবহারকারীরা প্রায়শই একাধিক অ্যাপ উইন্ডোতে কাজ করেন। Cahier কন্টেন্ট যোগ করা এবং শেয়ার করা উভয়ের জন্যই স্বজ্ঞাত ড্র্যাগ অ্যান্ড ড্রপ কার্যকারিতা প্রয়োগ করে এই বিষয়টিকে পুরোপুরি গ্রহণ করেছে।
- অনায়াস ইম্পোর্টিং : ব্যবহারকারীরা অন্যান্য অ্যাপ্লিকেশন—যেমন ওয়েব ব্রাউজার, ফটো গ্যালারি বা ফাইল ম্যানেজার—থেকে ছবি টেনে এনে সরাসরি একটি নোট ক্যানভাসে ফেলতে পারেন। এর জন্য, Cahier একটি ড্রপ জোন নির্ধারণ করতে, সামঞ্জস্যপূর্ণ কন্টেন্ট (যেমন
image/*) পরীক্ষা করতে এবং আগত URI প্রসেস করতে dragAndDropTarget মডিফায়ারটি ব্যবহার করে। - সহজ শেয়ারিং : Cahier-এর ভেতরের কন্টেন্ট অন্যান্য অ্যাপের কন্টেন্টের মতোই সহজে শেয়ার করা যায়। ব্যবহারকারীরা একটি টেক্সট নোটের মধ্যে থাকা কোনো ছবিতে লং-প্রেস করতে পারেন, অথবা একটি ড্রয়িং নোট ও ছবির সমন্বয়ে তৈরি সম্পূর্ণ ক্যানভাসে লং-প্রেস করে সেটিকে টেনে অন্য কোনো অ্যাপ্লিকেশনে নিয়ে যেতে পারেন।
প্রযুক্তিগত গভীর বিশ্লেষণ: ড্রয়িং ক্যানভাস থেকে টেনে বের করা
ড্রয়িং ক্যানভাসে ড্র্যাগ জেসচার প্রয়োগ করা একটি অনন্য চ্যালেঞ্জ। আমাদের DrawingSurface- এ, যে কম্পোজেবলগুলো লাইভ ড্রয়িং ইনপুট পরিচালনা করে (Ink API-এর InProgressStrokes ) এবং যে Box ড্র্যাগ শুরু করার জন্য লং-প্রেস জেসচার শনাক্ত করে, সেগুলো হলো সহোদর কম্পোজেবল ।
ডিফল্টরূপে, Jetpack Compose পয়েন্টার ইনপুট সিস্টেমটি এমনভাবে ডিজাইন করা হয়েছে যাতে শুধুমাত্র একটি সিibling composable —অর্থাৎ ডিক্লারেশন ক্রমে প্রথমটি যা টাচ লোকেশনকে ওভারল্যাপ করে—ইভেন্টটি গ্রহণ করে। Cahier-এর ক্ষেত্রে, আমরা চাই আমাদের ড্র্যাগ-অ্যান্ড-ড্রপ ইনপুট হ্যান্ডলিং লজিকটি চলার এবং সম্ভাব্য ইনপুটগুলো গ্রহণ করার সুযোগ পাক, InProgressStrokes composable-টি আঁকার জন্য সমস্ত অব্যবহৃত ইনপুট ব্যবহার করে ফেলার আগেই। যদি আমরা বিষয়গুলো সঠিক ক্রমে না সাজাই, তাহলে আমাদের Box ড্র্যাগ শুরু করার জন্য লং-প্রেস জেসচারটি শনাক্ত করতে পারবে না, অথবা InProgressStrokes আঁকার জন্য ইনপুট পাবে না।
এর সমাধান করতে, আমরা একটি কাস্টম pointerInputWithSiblingFallthrough মডিফায়ার তৈরি করেছি এবং কম্পোজেবল কোডে InProgressStrokes এর আগে আমাদের Box রেখেছি, যেটি এই মডিফায়ারটি ব্যবহার করে। এই ইউটিলিটিটি স্ট্যান্ডার্ড pointerInput সিস্টেমের একটি পাতলা র্যাপার, তবে এতে একটি গুরুত্বপূর্ণ পরিবর্তন রয়েছে: এটি sharePointerInputWithSiblings() ফাংশনটিকে ওভাররাইড করে true রিটার্ন করে। এটি কম্পোজ ফ্রেমওয়ার্ককে বলে দেয় যে, পয়েন্টার ইভেন্টগুলো কনজিউম হয়ে যাওয়ার পরেও যেন সিibling কম্পোজেবলগুলোতে পাস হতে পারে।
internal fun Modifier.pointerInputWithSiblingFallthrough(
pointerInputEventHandler: PointerInputEventHandler
) = this then PointerInputSiblingFallthroughElement(pointerInputEventHandler)
private class PointerInputSiblingFallthroughModifierNode(
pointerInputEventHandler: PointerInputEventHandler
) : PointerInputModifierNode, DelegatingNode() {
var pointerInputEventHandler: PointerInputEventHandler
get() = delegateNode.pointerInputEventHandler
set(value) {
delegateNode.pointerInputEventHandler = value
}
val delegateNode = delegate(
SuspendingPointerInputModifierNode(pointerInputEventHandler)
)
override fun onPointerEvent(
pointerEvent: PointerEvent,
pass: PointerEventPass,
bounds: IntSize
) {
delegateNode.onPointerEvent(pointerEvent, pass, bounds)
}
override fun onCancelPointerInput() {
delegateNode.onCancelPointerInput()
}
override fun sharePointerInputWithSiblings() = true
}
private data class PointerInputSiblingFallthroughElement(
val pointerInputEventHandler: PointerInputEventHandler
) : ModifierNodeElement<PointerInputSiblingFallthroughModifierNode>() {
override fun create() = PointerInputSiblingFallthroughModifierNode(pointerInputEventHandler)
override fun update(node: PointerInputSiblingFallthroughModifierNode) {
node.pointerInputEventHandler = pointerInputEventHandler
}
override fun InspectorInfo.inspectableProperties() {
name = "pointerInputWithSiblingFallthrough"
properties["pointerInputEventHandler"] = pointerInputEventHandler
}
} DrawingSurface এ এটি যেভাবে ব্যবহার করা হয় তা এখানে দেওয়া হলো:
Box(
modifier = Modifier
.fillMaxSize()
// Our custom modifier enables this gesture to coexist with the drawing input.
.pointerInputWithSiblingFallthrough {
detectDragGesturesAfterLongPress(
onDragStart = { onStartDrag() },
onDrag = { _, _ -> /* consume drag events */ },
onDragEnd = { /* No action needed */ }
)
}
)
// The Ink API's composable for live drawing sits here as a sibling.
InProgressStrokes(...) এর ফলে, সিস্টেমটি একই সাথে ড্রয়িং স্ট্রোক এবং লং-প্রেস ড্র্যাগ জেসচার উভয়ই সঠিকভাবে শনাক্ত করতে পারে। ড্র্যাগ শুরু হয়ে গেলে, আমরা FileProvider ব্যবহার করে একটি শেয়ারযোগ্য content:// URI তৈরি করি এবং view.startDragAndDrop() এর মাধ্যমে সিস্টেমের ড্র্যাগ অ্যান্ড ড্রপ ফ্রেমওয়ার্কে সেই URI-টি পাঠিয়ে দিই। এই সমাধানটি একটি শক্তিশালী এবং স্বজ্ঞাত ব্যবহারকারীর অভিজ্ঞতা নিশ্চিত করে এবং লেয়ার্ড UI-তে জটিল জেসচার দ্বন্দ্ব কীভাবে সমাধান করা যায় তা প্রদর্শন করে।
আধুনিক স্থাপত্য দিয়ে নির্মিত
নির্দিষ্ট এপিআই-এর বাইরেও, Cahier উচ্চ-মানের ও অভিযোজনযোগ্য অ্যাপ্লিকেশন তৈরির জন্য গুরুত্বপূর্ণ আর্কিটেকচারাল প্যাটার্ন প্রদর্শন করে।
উপস্থাপনা স্তর: জেটপ্যাক কম্পোজ এবং অভিযোজনযোগ্যতা
প্রেজেন্টেশন লেয়ারটি সম্পূর্ণরূপে জেটপ্যাক কম্পোজ দিয়ে তৈরি করা হয়েছে। যেমনটি উল্লেখ করা হয়েছে, UI অভিযোজনযোগ্যতার জন্য Cahier material3-adaptive লাইব্রেরি ব্যবহার করে। স্টেট ম্যানেজমেন্ট একটি কঠোর ইউনিডিরেকশনাল ডেটা ফ্লো (UDF) প্যাটার্ন অনুসরণ করে, যেখানে নোটের তথ্য এবং UI স্টেট ধারণকারী ডেটা কন্টেইনার হিসেবে ViewModel ইনস্ট্যান্সগুলো ব্যবহৃত হয়।
ডেটা লেয়ার: রিপোজিটরি এবং রুম
ডেটা লেয়ারের জন্য, Cahier সমস্ত ডেটা অপারেশনকে অ্যাবস্ট্রাক্ট করতে একটি NoteRepository ইন্টারফেস ব্যবহার করে। এই ডিজাইন পছন্দটি অ্যাপটিকে একটি স্থানীয় ডেটা উৎস (Room) এবং একটি সম্ভাব্য ভবিষ্যৎ রিমোট ব্যাকএন্ডের মধ্যে সহজে অদলবদল করার সুযোগ দেয়। একটি নোট সম্পাদনা করার মতো কাজের জন্য ডেটা প্রবাহটি বেশ সরল:
- Jetpack Compose UI, ViewModel-এর একটি মেথডকে ট্রিগার করে।
- ViewModel-টি NoteRepository থেকে নোটটি নিয়ে আসে, প্রয়োজনীয় লজিক পরিচালনা করে এবং আপডেট করা নোটটি রিপোজিটরিতে ফেরত পাঠায়।
- NoteRepository একটি Room ডেটাবেসে আপডেটটি সংরক্ষণ করে।
ব্যাপক ইনপুট সমর্থন
সত্যিকারের কর্মদক্ষতার কেন্দ্রবিন্দু হতে হলে, একটি অ্যাপকে অবশ্যই বিভিন্ন ধরনের ইনপুট পদ্ধতি নিখুঁতভাবে সামলাতে হবে। Cahier বড় স্ক্রিনের ইনপুট নির্দেশিকা মেনে চলার জন্য তৈরি করা হয়েছে এবং এটি নিম্নলিখিত বিষয়গুলো সমর্থন করে:
- স্টাইলাস: ইঙ্ক এপিআই (Ink API)-এর সাথে ইন্টিগ্রেশন, পাম রিজেকশন, নোটস রোলের জন্য রেজিস্ট্রেশন, টেক্সট ফিল্ডে স্টাইলাস ইনপুট, এবং ইমারসিভ মোড।
- কিবোর্ড: সর্বাধিক প্রচলিত কিবোর্ড শর্টকাট ও কম্বিনেশনের (যেমন ctrl+click, meta+click) সাপোর্ট এবং কিবোর্ড ফোকাসের জন্য সুস্পষ্ট নির্দেশনার ব্যবস্থা।
- মাউস ও ট্র্যাকপ্যাড: রাইট-ক্লিক এবং হোভার স্টেটের সাপোর্ট রয়েছে।
ভবিষ্যৎ উন্নতির জন্য প্রধান লক্ষ্য হলো উন্নত কিবোর্ড, মাউস এবং ট্র্যাকপ্যাড ইন্টারঅ্যাকশনের সুবিধা প্রদান করা।
আজই শুরু করুন।
আমরা আশা করি Cahier আপনার পরবর্তী দুর্দান্ত অ্যাপের জন্য একটি সূচনা মঞ্চ হিসেবে কাজ করবে। আমরা এটিকে একটি ব্যাপক, ওপেন সোর্স রিসোর্স হিসেবে তৈরি করেছি, যা দেখায় কীভাবে একটি অ্যাডাপ্টিভ UI, Ink ও notes role-এর মতো শক্তিশালী API এবং একটি আধুনিক, অ্যাডাপ্টিভ আর্কিটেকচারকে একত্রিত করা যায়।
ঝাঁপিয়ে পড়তে প্রস্তুত?
- কোডটি দেখুন : Cahier কোডবেসটি অন্বেষণ করতে এবং ডিজাইন নীতিগুলির প্রয়োগ দেখতে আমাদের GitHub রিপোজিটরিতে যান।
- আপনার নিজস্ব কাঠামো তৈরি করুন : আপনার নিজস্ব নোট নেওয়া, ডকুমেন্ট মার্কআপ বা সৃজনশীল অ্যাপ্লিকেশনের ভিত্তি হিসেবে Cahier ব্যবহার করুন।
- অবদান রাখুন : আমরা আপনার অবদানকে স্বাগত জানাই! অ্যান্ড্রয়েড ডেভেলপার কমিউনিটির জন্য Cahier-কে আরও উন্নত একটি রিসোর্স হিসেবে গড়ে তুলতে আমাদের সাহায্য করুন।
অফিসিয়াল ডেভেলপার গাইডগুলো দেখুন এবং আজই আপনার পরবর্তী প্রজন্মের প্রোডাক্টিভিটি ও ক্রিয়েটিভিটি অ্যাপ তৈরি করা শুরু করুন। আপনি কী তৈরি করেন তা দেখার জন্য আমরা অধীর আগ্রহে অপেক্ষা করছি!
পড়তে থাকুন

কীভাবে করবেন
আজ আমরা গুগল কর্তৃক জারি করা একটি নতুন যাচাইকৃত ইমেল ক্রেডেনশিয়াল ঘোষণা করতে পেরে আনন্দিত, যা ডেভেলপাররা এখন সরাসরি অ্যান্ড্রয়েডের ক্রেডেনশিয়াল ম্যানেজার ডিজিটাল ক্রেডেনশিয়াল এপিআই (API) থেকে সংগ্রহ করতে পারবেন।
Niharika Arora , Jean-Pierre Pralle • 3 মিনিট পঠিত৷

কীভাবে করবেন
আপনি অ্যান্ড্রয়েড স্টুডিওতে জেমিনি, জেমিনি সিএলআই, অ্যান্টিগ্র্যাভিটি, অথবা ক্লড কোড বা কোডেক্সের মতো থার্ড-পার্টি এজেন্ট ব্যবহার করুন না কেন, আমাদের লক্ষ্য হলো সর্বত্র উচ্চমানের অ্যান্ড্রয়েড ডেভেলপমেন্ট নিশ্চিত করা।
Adarsh Fernando , Esteban de la Canal • 4 মিনিট পড়া

কীভাবে করবেন
অ্যান্ড্রয়েড ব্যবহারকারীদের জন্য অতিরিক্ত ব্যাটারি খরচ একটি প্রধান উদ্বেগের বিষয়, এটা উপলব্ধি করে গুগল ডেভেলপারদের আরও শক্তি-সাশ্রয়ী অ্যাপ তৈরিতে সাহায্য করার জন্য গুরুত্বপূর্ণ পদক্ষেপ নিচ্ছে।
Alice Yuan • পড়তে ৮ মিনিট
আপ-টু-ডেট থাকুন
অ্যান্ড্রয়েড ডেভেলপমেন্টের সর্বশেষ তথ্য প্রতি সপ্তাহে আপনার ইনবক্সে পান।
কীভাবে করবেন
উপস্থাপন করা হচ্ছে Cahier: বড় স্ক্রিনে কর্মদক্ষতা ও সৃজনশীলতার জন্য একটি নতুন অ্যান্ড্রয়েড গিটহাব স্যাম্পল
১১ মিনিটের পাঠ

ইঙ্ক এপিআই এখন বিটা পর্যায়ে রয়েছে এবং আপনার অ্যাপে ইন্টিগ্রেট করার জন্য প্রস্তুত। ডেভেলপারদের মূল্যবান মতামতের ফলেই এই মাইলফলকটি অর্জন করা সম্ভব হয়েছে, যার ফলস্বরূপ এপিআই-এর পারফরম্যান্স, স্থিতিশীলতা এবং ভিজ্যুয়াল কোয়ালিটিতে ক্রমাগত উন্নতি সাধিত হয়েছে।
গুগল অ্যাপস, যেমন গুগল ডক্স , পিক্সেল স্টুডিও , গুগল ফটোস , ক্রোম পিডিএফ , ইউটিউব ইফেক্ট মেকার, এবং অ্যান্ড্রয়েডের অনন্য ফিচার যেমন সার্কেল টু সার্চ— এই সবই সর্বশেষ এপিআই ব্যবহার করে।
এই মাইলফলকটি উদযাপন উপলক্ষে, আমরা Cahier চালু করার ঘোষণা দিতে পেরে আনন্দিত। এটি একটি পূর্ণাঙ্গ নোট-নেওয়ার অ্যাপের নমুনা, যা সব আকারের অ্যান্ড্রয়েড ডিভাইস, বিশেষ করে ট্যাবলেট এবং ফোল্ডেবল ফোনের জন্য অপ্টিমাইজ করা হয়েছে।
Cahier কী?
Cahier (ফরাসি ভাষায় যার অর্থ "নোটবুক") হলো একটি নমুনা অ্যাপ, যা দেখানোর জন্য ডিজাইন করা হয়েছে যে কীভাবে এমন একটি অ্যাপ্লিকেশন তৈরি করা যায়, যা ব্যবহারকারীদের লেখা, অঙ্কন এবং ছবির সমন্বয়ে তাদের চিন্তাভাবনা লিপিবদ্ধ ও সংগঠিত করতে সক্ষম করে।
বড় স্ক্রিনে ব্যবহারকারীর কর্মক্ষমতা ও সৃজনশীলতা বাড়ানোর জন্য এই স্যাম্পলটি একটি নির্ভরযোগ্য রেফারেন্স হিসেবে কাজ করতে পারে। এটি এই ধরনের অভিজ্ঞতা তৈরির সেরা পদ্ধতিগুলো তুলে ধরে, যা ডেভেলপারদের সংশ্লিষ্ট শক্তিশালী এপিআই এবং কৌশলগুলো বুঝতে ও গ্রহণ করতে সাহায্য করে। এই পোস্টে Cahier-এর মূল বৈশিষ্ট্য, প্রধান এপিআই এবং সেইসব আর্কিটেকচারাল সিদ্ধান্তগুলো সম্পর্কে বিস্তারিত আলোচনা করা হয়েছে, যা এই স্যাম্পলটিকে আপনার নিজের অ্যাপের জন্য একটি চমৎকার রেফারেন্স হিসেবে তৈরি করেছে।
নমুনাটিতে প্রদর্শিত প্রধান বৈশিষ্ট্যগুলো হলো:
- বহুমুখী নোট তৈরি: এখানে দেখানো হয়েছে কীভাবে একটি নমনীয় কন্টেন্ট তৈরির সিস্টেম বাস্তবায়ন করতে হয়, যা একটি নোটের মধ্যেই টেক্সট, ফ্রিফর্ম ড্রয়িং এবং ছবি সংযুক্তি সহ একাধিক ফরম্যাট সমর্থন করে।
- ক্রিয়েটিভ ইঙ্কিং টুলস : ইঙ্ক এপিআই (Ink API) ব্যবহার করে একটি উচ্চ পারফরম্যান্স ও কম ল্যাটেন্সির ড্রয়িং অভিজ্ঞতা প্রদান করে। এই স্যাম্পলটিতে বিভিন্ন ব্রাশ, একটি কালার পিকার, আনডু/রিডু কার্যকারিতা এবং একটি ইরেজার টুল সমন্বিত করার একটি বাস্তব উদাহরণ দেওয়া হয়েছে।
- ড্র্যাগ অ্যান্ড ড্রপের মাধ্যমে সাবলীল কন্টেন্ট ইন্টিগ্রেশন : ড্র্যাগ অ্যান্ড ড্রপ ব্যবহার করে কীভাবে ইনকামিং এবং আউটগোয়িং উভয় কন্টেন্ট পরিচালনা করা যায় তা দেখানো হয়েছে। এর মধ্যে রয়েছে অন্য অ্যাপ থেকে ড্রপ করা ছবি গ্রহণ করা এবং নির্বিঘ্নে শেয়ার করার জন্য ব্যবহারকারীদের আপনার অ্যাপের বাইরে কন্টেন্ট ড্র্যাগ করে নিয়ে যাওয়ার সুবিধা দেওয়া।
- নোটের বিন্যাস : দ্রুত অ্যাক্সেসের জন্য নোটগুলিকে পছন্দের তালিকায় যুক্ত করুন। সবকিছু গুছিয়ে রাখতে ভিউটি ফিল্টার করুন।
- অফলাইন ফার্স্ট আর্কিটেকচার: Room ব্যবহার করে অফলাইন ফার্স্ট আর্কিটেকচারে নির্মিত, যা নিশ্চিত করে যে সমস্ত ডেটা স্থানীয়ভাবে সংরক্ষিত থাকে এবং ইন্টারনেট সংযোগ ছাড়াই অ্যাপটি সম্পূর্ণ কার্যকর থাকে।
- শক্তিশালী মাল্টি-উইন্ডো এবং মাল্টি-ইনস্ট্যান্স সাপোর্ট : এটি দেখায় কীভাবে মাল্টি-ইনস্ট্যান্স সাপোর্ট করা যায়, যার ফলে আপনার অ্যাপটি একাধিক উইন্ডোতে চালু করা যায়। এতে ব্যবহারকারীরা পাশাপাশি বিভিন্ন নোটে কাজ করতে পারেন, যা বড় স্ক্রিনে উৎপাদনশীলতা এবং সৃজনশীলতা বাড়ায়।
- সকল স্ক্রিনের জন্য অভিযোজিত UI : ফোন, ট্যাবলেট এবং ফোল্ডেবল ডিভাইসে একটি সর্বোত্তম ব্যবহারকারীর অভিজ্ঞতা প্রদানের জন্য, ইউজার ইন্টারফেসটি ListDetailPaneScaffold এবং NavigationSuiteScaffold ব্যবহার করে বিভিন্ন স্ক্রিনের আকার ও ওরিয়েন্টেশনের সাথে নির্বিঘ্নে খাপ খাইয়ে নেয়।
- গভীর সিস্টেম ইন্টিগ্রেশন : সিস্টেমব্যাপী নোটস ইন্টেন্ট-এ সাড়া দিয়ে এবং বিভিন্ন সিস্টেম এন্ট্রি পয়েন্ট থেকে দ্রুত কন্টেন্ট ক্যাপচার সক্ষম করার মাধ্যমে, কীভাবে আপনার অ্যাপকে অ্যান্ড্রয়েড ১৪ এবং তার পরবর্তী সংস্করণগুলিতে ডিফল্ট নোট-টেকিং অ্যাপ হিসেবে সেট করা যায়, তার একটি নির্দেশিকা প্রদান করে।
বড় পর্দায় উৎপাদনশীলতা এবং সৃজনশীলতার জন্য নির্মিত
প্রাথমিক উন্মোচনের জন্য, আমরা এমন কয়েকটি মূল বৈশিষ্ট্যের ওপর ঘোষণাটি কেন্দ্রীভূত করছি, যা Cahier- কে কর্মদক্ষতা এবং সৃজনশীলতা—উভয় ক্ষেত্রেই একটি গুরুত্বপূর্ণ শিক্ষণীয় উপকরণ হিসেবে গড়ে তোলে।
অভিযোজনশীলতার একটি ভিত্তি
Cahier-কে একেবারে গোড়া থেকেই অভিযোজনযোগ্য করে তৈরি করা হয়েছে। এই স্যাম্পলটি material3-adaptive লাইব্রেরির ListDetailPaneScaffold এবং NavigationSuiteScaffold অংশ ব্যবহার করে, যা অ্যাপের লেআউটকে বিভিন্ন স্ক্রিনের আকার ও ওরিয়েন্টেশনের সাথে নির্বিঘ্নে খাপ খাইয়ে নেয়। এটি একটি আধুনিক অ্যান্ড্রয়েড অ্যাপের জন্য অত্যন্ত গুরুত্বপূর্ণ একটি উপাদান, এবং কীভাবে এটি কার্যকরভাবে প্রয়োগ করতে হয় তার একটি সুস্পষ্ট উদাহরণ Cahier প্রদান করে।

ম্যাটেরিয়াল ৩ অ্যাডাপ্টিভ লাইব্রেরি দিয়ে নির্মিত Cahier অ্যাডাপ্টিভ UI
মূল এপিআই এবং ইন্টিগ্রেশনগুলি প্রদর্শন করা হচ্ছে
এই নমুনাটির মূল উদ্দেশ্য হলো এমন কিছু শক্তিশালী প্রোডাক্টিভিটি এপিআই (API) প্রদর্শন করা, যা আপনি আপনার নিজের অ্যাপ্লিকেশনগুলিতে কাজে লাগাতে পারেন, যার মধ্যে রয়েছে:
মূল এপিআইগুলির একটি বিশদ পর্যালোচনা
চলুন, প্রথম শ্রেণীর নোট নেওয়ার অভিজ্ঞতা প্রদানের জন্য Cahier যে দুটি মূল API সংহত করে, সেগুলির বিষয়ে আরও গভীরভাবে আলোচনা করা যাক।
ইঙ্ক এপিআই দিয়ে প্রাকৃতিক ইঙ্কিং অভিজ্ঞতা তৈরি করা
স্টাইলাস ইনপুট বড় স্ক্রিনের ডিভাইসগুলোকে ডিজিটাল নোটবুক এবং স্কেচবুকে রূপান্তরিত করে। আপনাকে সাবলীল এবং স্বাভাবিক ইঙ্কিং অভিজ্ঞতা তৈরিতে সাহায্য করার জন্য, আমরা এই স্যাম্পলের ভিত্তি হিসেবে ইঙ্ক এপিআই (Ink API) তৈরি করেছি। ইঙ্ক এপিআই সেরা মানের স্বল্প ল্যাটেন্সির সাথে সুন্দর ইঙ্ক স্ট্রোক তৈরি, রেন্ডার এবং পরিচালনা করা সহজ করে তোলে।
ইঙ্ক এপিআই একটি মডিউলার আর্কিটেকচার প্রদান করে, ফলে আপনি এটিকে আপনার অ্যাপের নির্দিষ্ট স্ট্যাক এবং প্রয়োজন অনুযায়ী সাজিয়ে নিতে পারেন। এপিআই মডিউলগুলোর মধ্যে রয়েছে:
- অথরিং মডিউল ( কম্পোজ - ভিউ ): ডিভাইসের পক্ষে সম্ভব সর্বনিম্ন ল্যাটেন্সিতে মসৃণ স্ট্রোক তৈরি করতে রিয়েল-টাইম ইঙ্কিং ইনপুট পরিচালনা করে।
- DrawingSurface- এ, Cahier রিয়েল-টাইম স্টাইলাস বা টাচ ইনপুট পরিচালনা করার জন্য সদ্য প্রবর্তিত InProgressStrokes কম্পোজেবলটি ব্যবহার করে। এই মডিউলটি পয়েন্টার ইভেন্ট ক্যাপচার করা এবং সর্বনিম্ন সম্ভাব্য ল্যাটেন্সিতে ওয়েট ইঙ্ক স্ট্রোক রেন্ডার করার জন্য দায়ী।
- স্ট্রোকস মডিউল: এটি ইঙ্ক ইনপুট এবং তার ভিজ্যুয়াল উপস্থাপনাকে নির্দেশ করে। একজন ব্যবহারকারী একটি লাইন আঁকা শেষ করলে, onStrokesFinished কলব্যাকটি অ্যাপকে একটি চূড়ান্ত/শুকনো স্ট্রোক অবজেক্ট প্রদান করে। এই অপরিবর্তনীয় অবজেক্টটি, যা সম্পূর্ণ ইঙ্ক স্ট্রোককে নির্দেশ করে, পরবর্তীতে DrawingCanvasViewModel- এ পরিচালিত হয়।
- রেন্ডারিং মডিউল: দক্ষতার সাথে ইঙ্ক স্ট্রোক প্রদর্শন করে, যার ফলে এগুলোকে জেটপ্যাক কম্পোজ বা অ্যান্ড্রয়েড ভিউ-এর সাথে একত্রিত করা যায়।
- বিদ্যমান এবং সদ্য শুকানো উভয় স্ট্রোক প্রদর্শন করার জন্য, Cahier সক্রিয় ড্রয়িংয়ের ক্ষেত্রে DrawingSurface- এ এবং নোটটির একটি স্থির প্রিভিউ দেখানোর ক্ষেত্রে DrawingDetailPanePreview- তে CanvasStrokeRenderer ব্যবহার করে। এই মডিউলটি দক্ষতার সাথে একটি ক্যানভাসের উপর স্ট্রোক অবজেক্টগুলো অঙ্কন করে।
- ব্রাশ মডিউল ( কম্পোজ - ভিউ ): স্ট্রোকের ভিজ্যুয়াল স্টাইল নির্ধারণের জন্য একটি ডিক্লারেটিভ উপায় প্রদান করে। সাম্প্রতিক আপডেটগুলিতে (alpha03 রিলিজের পর থেকে) একটি নতুন ড্যাশড লাইন ব্রাশ অন্তর্ভুক্ত করা হয়েছে, যা ল্যাসো সিলেকশনের মতো ফিচারের জন্য বিশেষভাবে উপযোগী। DrawingCanvasViewModel বর্তমান ব্রাশের স্টেট ধারণ করে। DrawingCanvas- এর একটি টুলবক্স ব্যবহারকারীদের বিভিন্ন ব্রাশ ফ্যামিলি (যেমন StockBrushes.pressurePen() বা StockBrushes.highlighter() ) নির্বাচন করতে এবং রং পরিবর্তন করতে দেয়। ViewModel ব্রাশ অবজেক্টটি আপডেট করে, যা পরবর্তীতে নতুন স্ট্রোকের জন্য InProgressStrokes কম্পোজেবল দ্বারা ব্যবহৃত হয়।
- জ্যামিতি মডিউল ( কম্পোজ - ভিউ ): মোছা এবং নির্বাচন করার মতো বৈশিষ্ট্যগুলির জন্য স্ট্রোক পরিবর্তন ও বিশ্লেষণ করার সুবিধা।
- টুলবক্সের মধ্যে থাকা ইরেজার টুল এবং DrawingCanvasViewModel- এর কার্যকারিতা জিওমেট্রি মডিউলের উপর নির্ভর করে। যখন ইরেজারটি সক্রিয় থাকে, তখন এটি ব্যবহারকারীর জেসচারের পথের চারপাশে একটি MutableParallelogram তৈরি করে। এরপর কোন স্ট্রোকগুলো মুছতে হবে তা নির্ধারণ করার জন্য ইরেজারটি আকৃতি এবং বিদ্যমান স্ট্রোকগুলোর বাউন্ডিং বক্সের মধ্যে ছেদবিন্দু পরীক্ষা করে, যা ইরেজারটিকে স্বজ্ঞাত এবং নির্ভুল করে তোলে।
- স্টোরেজ মডিউল: এটি ইঙ্ক ডেটার জন্য কার্যকর সিরিয়ালাইজেশন এবং ডিসিরিয়ালাইজেশন সুবিধা প্রদান করে, যার ফলে ডিস্ক এবং নেটওয়ার্কের আকার উল্লেখযোগ্যভাবে সাশ্রয় হয়। ড্রয়িং সংরক্ষণ করার জন্য, Cahier তার Room ডেটাবেসে Stroke অবজেক্টগুলো সংরক্ষণ করে। Converters- এ, নমুনাটি স্টোরেজ মডিউলের encode ফাংশন ব্যবহার করে StrokeInputBatch (কাঁচা পয়েন্ট ডেটা)-কে একটি ByteArray- তে সিরিয়ালাইজ করে। বাইট অ্যারেটি, ব্রাশের বৈশিষ্ট্যসহ, একটি JSON স্ট্রিং হিসাবে সংরক্ষিত হয়। যখন একটি নোট লোড করা হয়, তখন স্ট্রোকগুলো পুনর্গঠন করতে decode ফাংশনটি ব্যবহৃত হয়।

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

ইঙ্ক এপিআই-এর কাস্টম ব্রাশ দিয়ে তৈরি রংধনু লেজার

ইঙ্ক এপিআই-এর কাস্টম ব্রাশ দিয়ে তৈরি মিউজিক ব্রাশ
- নেটিভ জেটপ্যাক কম্পোজ ইন্টারঅপারেবিলিটি মডিউলগুলো আরও স্বাভাবিক ও কার্যকর ডেভেলপমেন্ট অভিজ্ঞতার জন্য আপনার কম্পোজ UI-এর মধ্যেই সরাসরি ইঙ্কিং ফাংশনালিটির ইন্টিগ্রেশনকে সুবিন্যস্ত করে।
কাস্টম ইমপ্লিমেন্টেশনের তুলনায় প্রোডাক্টিভিটি এবং ক্রিয়েটিভিটি অ্যাপের জন্য ইঙ্ক এপিআই বেশ কিছু সুবিধা প্রদান করে, যা এটিকে একটি আদর্শ পছন্দ করে তোলে:
- ব্যবহারের সহজতা: ইঙ্ক এপিআই গ্রাফিক্স এবং জ্যামিতির জটিলতা দূর করে, যার ফলে আপনি ক্যাহিয়ারের মূল বৈশিষ্ট্যগুলিতে মনোযোগ দিতে পারেন।
- পারফরম্যান্স: অন্তর্নির্মিত লো ল্যাটেন্সি সাপোর্ট এবং অপ্টিমাইজড রেন্ডারিং একটি মসৃণ ও প্রতিক্রিয়াশীল ইঙ্কিং অভিজ্ঞতা নিশ্চিত করে।
- নমনীয়তা: মডিউলার ডিজাইনটি আপনাকে প্রয়োজনীয় উপাদানগুলো বেছে নেওয়ার সুযোগ দেয়, যা Cahier-এর আর্কিটেকচারে Ink API-এর নির্বিঘ্ন ইন্টিগ্রেশন সম্ভব করে তোলে।
ডকস-এ মার্কআপ এবং সার্কেল টু সার্চ-এর মতো অনেক গুগল অ্যাপের পাশাপাশি ওরিয়ন নোটস এবং পিডিএফ স্ক্যানার-এর মতো পার্টনার অ্যাপগুলোতেও ইঙ্ক এপিআই ইতিমধ্যেই গ্রহণ করা হয়েছে।
“সার্কেল-টু-সার্চ (CtS)-এর জন্য ইঙ্ক এপিআই (Ink API) ছিল আমাদের প্রথম পছন্দ। তাদের বিস্তৃত ডকুমেন্টেশন ব্যবহার করে ইঙ্ক এপিআই ইন্টিগ্রেট করা অত্যন্ত সহজ ছিল, যার ফলে আমরা মাত্র এক সপ্তাহের মধ্যে আমাদের প্রথম কার্যকরী প্রোটোটাইপ তৈরি করতে সক্ষম হই। ইঙ্ক-এর কাস্টম ব্রাশ টেক্সচার এবং অ্যানিমেশন সাপোর্ট আমাদের স্ট্রোক ডিজাইনে দ্রুত পরিবর্তন আনতে সাহায্য করেছে।” - জর্ডান কোমোডা, সফটওয়্যার ইঞ্জিনিয়ার - গুগল
নোটস রোলের সাথে ডিফল্ট নোটস অ্যাপ হয়ে ওঠা
নোট নেওয়া একটি মূল সক্ষমতা যা বড় স্ক্রিনের ডিভাইসে ব্যবহারকারীর কর্মদক্ষতা বাড়ায়। নোটস রোল ফিচারের মাধ্যমে, ব্যবহারকারীরা লক স্ক্রিন থেকে অথবা অন্যান্য অ্যাপ চালু থাকা অবস্থাতেও আপনার সামঞ্জস্যপূর্ণ অ্যাপগুলো অ্যাক্সেস করতে পারেন। এই ফিচারটি সিস্টেমব্যাপী ডিফল্ট নোট-নেওয়ার অ্যাপগুলোকে শনাক্ত করে ও সেট করে এবং কন্টেন্ট ক্যাপচার করার জন্য সেগুলোকে চালু করার অনুমতি প্রদান করে।
Cahier-এ বাস্তবায়ন
নোটস রোলটি বাস্তবায়নে কয়েকটি গুরুত্বপূর্ণ ধাপ রয়েছে, যেগুলোর সবগুলোই নমুনায় দেখানো হয়েছে:
- ম্যানিফেস্ট ঘোষণা : প্রথমে, অ্যাপটিকে নোট-নেওয়ার ইন্টেন্টগুলো পরিচালনা করার সক্ষমতা ঘোষণা করতে হবে। AndroidManifest.xml- এ, Cahier android.intent.action.CREATE_NOTE অ্যাকশনের জন্য একটি
<intent-filter>অন্তর্ভুক্ত করে। এটি সিস্টেমকে সংকেত দেয় যে অ্যাপটি নোটস রোলের জন্য একটি সম্ভাব্য প্রার্থী। - রোলের অবস্থা যাচাই করা : SettingsViewModel বর্তমান অবস্থা নির্ধারণ করতে অ্যান্ড্রয়েডের RoleManager ব্যবহার করে। SettingsViewModel যাচাই করে দেখে যে ডিভাইসে নোটস রোলটি উপলব্ধ আছে কিনা ( isRoleAvailable ) এবং Cahier বর্তমানে সেই রোলটি ধারণ করে আছে কিনা ( isRoleHeld )। এই অবস্থাটি Kotlin ফ্লো ব্যবহার করে UI-তে প্রকাশ করা হয়।
- রোলের জন্য অনুরোধ : Settings.kt ফাইলে, যদি রোলটি উপলব্ধ থাকে কিন্তু ব্যবহারকারী সেটি ধারণ না করে থাকেন, তবে তাকে একটি বাটন দেখানো হয়। বাটনটি ক্লিক করা হলে, এটি ViewModel-এর
requestNotesRoleফাংশনটিকে কল করে। এই ফাংশনটি ডিফল্ট অ্যাপ সেটিংস স্ক্রিন খোলার জন্য একটি ইন্টেন্ট তৈরি করে, যেখানে ব্যবহারকারী Cahier নির্বাচন করতে পারেন। এই প্রক্রিয়াটি rememberLauncherForActivityResult API ব্যবহার করে পরিচালিত হয়, যা ইন্টেন্টটি চালু করা এবং ফলাফল গ্রহণ করার কাজটি করে। - Updating the UI : After the user returns from the settings screen, the ActivityResultLauncher callback triggers a function in the ViewModel to update the role status, ensuring the UI accurately reflects whether the app is now the default.
Learn how to integrate the notes role in your app in our create a note-taking app guide .

Cahier launched in a floating window as the default note-taking app on a Lenovo tablet
A major step forward: Lenovo enables notes role
We're thrilled to announce a major step forward for large screen Android productivity: Lenovo has enabled support for Notes Role on tablets running Android 15 and higher! With this update, you can now update your note-taking apps to allow users with compatible Lenovo devices to set them as default, granting seamless access from the lock screen and unlocking system level content capture features.
This commitment from a leading OEM demonstrates the growing importance of the notes role in delivering a truly integrated and productive user experience on Android.
Multi-instance, multi-windowing, and desktop windowing
Productivity on a large screen is all about managing information and workflows efficiently. That's why Cahier is built to fully embrace Android's advanced windowing capabilities, providing a flexible workspace that adapts to user needs. The app supports:
- Multi-windowing : The fundamental ability to run alongside another app in split-screen or free-form mode. This is essential for tasks like referencing a web page while taking notes in Cahier.
- Multi-instance : This is where true multitasking shines. Cahier allows users to open multiple, independent windows of the app simultaneously . Imagine comparing two different notes side by side or referencing a text note in one window while working on a drawing in another. Cahier demonstrates how to manage these separate instances, each with its own state, turning your app into a powerful, multifaceted tool.
- Desktop windowing : When connected to an external display, Android desktop mode transforms a tablet or foldable into a workstation. Because Cahier is built with an adaptive UI and supports multi-instance, the app performs beautifully in this environment. Users can open, resize, and position multiple Cahier windows just like on a traditional desktop, enabling complex workflows that were previously out of reach on mobile devices.

Cahier running in desktop window mode on Pixel Tablet
Here's how we implemented these features in Cahier:
To enable multi-instance, we first needed to signal to the system that the app supports being launched multiple times by adding the PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI property to MainActivity 's declaration in AndroidManifest :
<activity android:name="com.example.cahier.MainActivity" android:exported="true" android:label="@string/app_name" android:theme="@style/Theme.MyApplication" android:showWhenLocked="true" android:turnScreenOn="true" android:resizeableActivity="true" android:launchMode="singleInstancePerTask"> <property android:name="android.window.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI" android:value="true"/> ... </activity>
Next, we implemented the logic to launch a new instance of the app. In CahierHomeScreen.kt , when a user opts to open a note in a new window, we create a new Intent with specific flags that instruct the system on how to handle the new activity launch. The combination of FLAG_ACTIVITY_NEW_TASK , FLAG_ACTIVITY_MULTIPLE_TASK , and FLAG_ACTIVITY_LAUNCH_ADJACENT ensures the note opens in a new, separate window alongside the existing one.
fun openNewWindow(activity: Activity?, note: Note) {
val intent = Intent(activity, MainActivity::class.java)
intent.putExtra(AppArgs.NOTE_TYPE_KEY, note.type)
intent.putExtra(AppArgs.NOTE_ID_KEY, note.id)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK or
Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT
activity?.startActivity(intent)
} To support multi-window mode, we needed to signal to the system that the app supports resizability by setting the Manifest's <activity> or <application> element.
<activity android:name="com.example.cahier.MainActivity" android:resizeableActivity="true" ...> </activity>
The UI itself being built with the Material 3 adaptive library enables it to adapt seamlessly in multi-window scenarios like Android's split screen mode.
To enhance user experience, we added support for drag and drop. See below how we implemented this in Cahier.
Drag and drop
A truly productive or creative app doesn't function in isolation; it interacts seamlessly with the rest of the device's ecosystem. Drag and drop is a cornerstone of this interaction, especially on large screens where users are often working across multiple app windows. Cahier fully embraces this by implementing intuitive drag and drop functionality for both adding and sharing content.
- Effortless Importing : Users can drag images from other applications—like a web browser, photo gallery, or file manager—and drop them directly onto a note canvas. For this, Cahier uses the dragAndDropTarget modifier to define a drop zone, check for compatible content (like
image/*), and process the incoming URI. - Simple sharing : Content inside Cahier is just as easy to share as content from other apps. Users can long-press an image within a text note, or long-press the entire canvas of a drawing note and image composite, and drag it out to another application.
Technical deep dive: Dragging from the drawing canvas
Implementing the drag gesture on the drawing canvas presents a unique challenge. In our DrawingSurface , the composables that handle live drawing input (the Ink API's InProgressStrokes ) and the Box that detects the long-press gesture to initiate a drag are sibling composables .
By default, the Jetpack Compose pointer input system is designed so that just one sibling composable —the first one in declaration order that overlaps the touch location—receives the event. In Cahier's case, we want our drag-and-drop input handling logic to have a chance to run and potentially consume inputs before the InProgressStrokes composable uses all unconsumed input for drawing and then consumes that input. If we don't arrange things in the right order, our Box won't detect the long-press gesture to start a drag, or InProgressStrokes won't receive the input to draw.
To solve this, we created a custom pointerInputWithSiblingFallthrough modifier, and we put our Box using that modifier before InProgressStrokes in the composable code. This utility is a thin wrapper around the standard pointerInput system but with one critical change: it overrides the sharePointerInputWithSiblings() function to return true . This tells the Compose framework to allow pointer events to pass through to sibling composables, even after being consumed.
internal fun Modifier.pointerInputWithSiblingFallthrough(
pointerInputEventHandler: PointerInputEventHandler
) = this then PointerInputSiblingFallthroughElement(pointerInputEventHandler)
private class PointerInputSiblingFallthroughModifierNode(
pointerInputEventHandler: PointerInputEventHandler
) : PointerInputModifierNode, DelegatingNode() {
var pointerInputEventHandler: PointerInputEventHandler
get() = delegateNode.pointerInputEventHandler
set(value) {
delegateNode.pointerInputEventHandler = value
}
val delegateNode = delegate(
SuspendingPointerInputModifierNode(pointerInputEventHandler)
)
override fun onPointerEvent(
pointerEvent: PointerEvent,
pass: PointerEventPass,
bounds: IntSize
) {
delegateNode.onPointerEvent(pointerEvent, pass, bounds)
}
override fun onCancelPointerInput() {
delegateNode.onCancelPointerInput()
}
override fun sharePointerInputWithSiblings() = true
}
private data class PointerInputSiblingFallthroughElement(
val pointerInputEventHandler: PointerInputEventHandler
) : ModifierNodeElement<PointerInputSiblingFallthroughModifierNode>() {
override fun create() = PointerInputSiblingFallthroughModifierNode(pointerInputEventHandler)
override fun update(node: PointerInputSiblingFallthroughModifierNode) {
node.pointerInputEventHandler = pointerInputEventHandler
}
override fun InspectorInfo.inspectableProperties() {
name = "pointerInputWithSiblingFallthrough"
properties["pointerInputEventHandler"] = pointerInputEventHandler
}
} Here's how it's used in DrawingSurface :
Box(
modifier = Modifier
.fillMaxSize()
// Our custom modifier enables this gesture to coexist with the drawing input.
.pointerInputWithSiblingFallthrough {
detectDragGesturesAfterLongPress(
onDragStart = { onStartDrag() },
onDrag = { _, _ -> /* consume drag events */ },
onDragEnd = { /* No action needed */ }
)
}
)
// The Ink API's composable for live drawing sits here as a sibling.
InProgressStrokes(...) With this in place, the system correctly detects both the drawing strokes and the long-press drag gesture simultaneously. Once the drag is initiated, we create a shareable content:// URI with FileProvider and pass the URI to the system's drag and drop framework using view.startDragAndDrop() . This solution ensures a robust and intuitive user experience, showcasing how to overcome complex gesture conflicts in layered UIs.
Built with modern architecture
Beyond specific APIs, Cahier demonstrates crucial architectural patterns for building high-quality, adaptive applications.
The presentation layer: Jetpack Compose and adaptability
The presentation layer is built entirely with Jetpack Compose. As mentioned, Cahier adopts the material3-adaptive library for UI adaptability. State management follows a strict Unidirectional Data Flow (UDF) pattern, with ViewModel instances used as data containers that hold note information and UI state.
The data layer: Repositories and Room
For the data layer, Cahier uses a NoteRepository interface to abstract all data operations. This design choice cleanly allows the app to swap between a local data source (Room) and a potential future remote backend. The data flow for an action like editing a note is straightforward:
- The Jetpack Compose UI triggers a method in the ViewModel.
- The ViewModel fetches the note from NoteRepository , handles the logic, and passes the updated note back to the repository.
- NoteRepository saves the update to a Room database.
Comprehensive input support
To be a true productivity powerhouse, an app must handle a variety of input methods flawlessly. Cahier is built to be compliant with large screen input guidelines and supports:
- Stylus: Integration with the Ink API, palm rejection, registration for the notes role, stylus input in text fields, and immersive mode.
- Keyboard: Support for most common keyboard shortcuts and combinations (like ctrl+click, meta+click) and clear indication for keyboard focus.
- Mouse and trackpad: Support for right-click and hover states.
Support for advanced keyboard, mouse, and trackpad interactions is a key focus for further improvements.
আজই শুরু করুন।
We hope Cahier serves as a launchpad for your next great app. We built it to be a comprehensive, open source resource that demonstrates how to combine an adaptive UI, powerful APIs like Ink and notes role, and a modern, adaptive architecture.
Ready to dive in?
- Explore the code : Head over to our GitHub repository to explore the Cahier codebase and see the design principles in action.
- Build your own : Use Cahier as a foundation for your own note-taking, document markup, or creative application.
- Contribute : We welcome your contributions! Help us make Cahier an even better resource for the Android developer community.
Check out the official developer guides and start building your next generation productivity and creativity app today. We can't wait to see what you create!
পড়তে থাকুন

কীভাবে করবেন
আজ আমরা গুগল কর্তৃক জারি করা একটি নতুন যাচাইকৃত ইমেল ক্রেডেনশিয়াল ঘোষণা করতে পেরে আনন্দিত, যা ডেভেলপাররা এখন সরাসরি অ্যান্ড্রয়েডের ক্রেডেনশিয়াল ম্যানেজার ডিজিটাল ক্রেডেনশিয়াল এপিআই (API) থেকে সংগ্রহ করতে পারবেন।
Niharika Arora , Jean-Pierre Pralle • 3 মিনিট পঠিত৷

কীভাবে করবেন
আপনি অ্যান্ড্রয়েড স্টুডিওতে জেমিনি, জেমিনি সিএলআই, অ্যান্টিগ্র্যাভিটি, অথবা ক্লড কোড বা কোডেক্সের মতো থার্ড-পার্টি এজেন্ট ব্যবহার করুন না কেন, আমাদের লক্ষ্য হলো সর্বত্র উচ্চমানের অ্যান্ড্রয়েড ডেভেলপমেন্ট নিশ্চিত করা।
Adarsh Fernando , Esteban de la Canal • 4 মিনিট পড়া

কীভাবে করবেন
In recognition that excessive battery drain is top of mind for Android users, Google has been taking significant steps to help developers build more power-efficient apps.
Alice Yuan • 8 min read
আপ-টু-ডেট থাকুন
অ্যান্ড্রয়েড ডেভেলপমেন্টের সর্বশেষ তথ্য প্রতি সপ্তাহে আপনার ইনবক্সে পান।






