আজ, Jetpack Compose এপ্রিল ‘২৬ রিলিজ স্টেবল। এই রিলিজে মূল Compose মডিউলের ১.১১ ভার্সন (সম্পূর্ণ BOM ম্যাপিং দেখুন), শেয়ার করা এলিমেন্ট ডিবাগ টুল, ট্র্যাকপ্যাড ইভেন্ট এবং আরও অনেক কিছু রয়েছে। এছাড়াও, আমাদের কাছে কিছু পরীক্ষামূলক API আছে যেগুলি আপনি ব্যবহার করে দেখলে এবং সেই সম্পর্কে মতামত দিলে আমরা খুশি হব।
আজকের রিলিজ ব্যবহার করতে, আপনার Compose BOM ভার্সন এতে আপগ্রেড করুন:
implementation(platform("androidx.compose:compose-bom:2026.04.01"))
Compose 1.11.0-এ পরিবর্তন
পরীক্ষায় Coroutine এক্সিকিউশন
Compose কীভাবে টেস্ট টাইমিং ম্যানেজ করে সেই বিষয়ে আমরা একটি বড় আপডেট নিয়ে আসছি। Compose 1.10-এ ঘোষণা করা অপ্ট-ইন করার সময়সীমা অনুযায়ী, v2 টেস্টিং API এখন ডিফল্ট এবং v1 API-এর ব্যবহার বন্ধ করা হয়েছে। মূল পরিবর্তন হল ডিফল্ট টেস্ট ডিসপ্যাচার পরিবর্তন করা। v1 API UnconfinedTestDispatcher-এর উপর নির্ভর করে, যা অবিলম্বে coroutines এক্সিকিউট করে, v2 API StandardTestDispatcher ব্যবহার করে। এর অর্থ হল, আপনার টেস্টে কোনও কোরুটিন লঞ্চ করা হলে, সেটি এখন সারিতে থাকে এবং ভার্চুয়াল ঘড়ির সময় এগিয়ে না যাওয়া পর্যন্ত এক্সিকিউট হয় না।
এটি প্রোডাকশন কন্ডিশন আরও ভালোভাবে নকল করে, কার্যকরভাবে রেস কন্ডিশন ফ্লাশ করে এবং আপনার টেস্ট স্যুটকে উল্লেখযোগ্যভাবে আরও শক্তিশালী এবং কম ফ্লেকি করে তোলে।
আপনার টেস্ট যাতে স্ট্যান্ডার্ড কোরুটিন আচরণের সাথে সামঞ্জস্যপূর্ণ হয় এবং ভবিষ্যতে মানানসই সংক্রান্ত সমস্যা এড়াতে, আমরা আপনার টেস্ট স্যুট মাইগ্রেট করার জন্য বিশেষভাবে সাজেস্ট করি। API ম্যাপিং ও সাধারণ সমস্যার সমাধানের জন্য আমাদের বিস্তারিত মাইগ্রেশন গাইড দেখুন।
শেয়ার করা এলিমেন্ট সংক্রান্ত উন্নতি ও অ্যানিমেশন টুলিং
এছাড়াও, আমরা শেয়ার করা এলিমেন্ট ও Modifier.animatedBounds-এর জন্য কিছু সুবিধাজনক ভিজ্যুয়াল ডিবাগিং টুল যোগ করেছি। আপনি এখন ঠিক কী ঘটছে তা দেখতে পারবেন—যেমন টার্গেট বাউন্ড, অ্যানিমেশন ট্র্যাজেক্টরি এবং কতগুলি ম্যাচ পাওয়া গেছে—যার ফলে ট্রানজিশন কেন প্রত্যাশিতভাবে কাজ করছে না তা চিহ্নিত করা অনেক সহজ হয়ে যায়। নতুন টুলিং ব্যবহার করতে, আপনার SharedTransitionLayout-এর চারপাশে LookaheadAnimationVisualDebugging কম্পোজেবল যোগ করুন।
LookaheadAnimationVisualDebugging( overlayColor = Color(0x4AE91E63), isEnabled = true, multipleMatchesColor = Color.Green, isShowKeylabelEnabled = false, unmatchedElementColor = Color.Red, ) { SharedTransitionLayout { CompositionLocalProvider( LocalSharedTransitionScope provides this, ) { // your content } } }
ট্র্যাকপ্যাড ইভেন্ট
আমরা ট্র্যাকপ্যাডের জন্য Compose সাপোর্ট নতুন করে সাজিয়েছি, যেমন বিল্ট-ইন ল্যাপটপ ট্র্যাকপ্যাড, ট্যাবলেটের জন্য অ্যাটাচ করা যায় এমন ট্র্যাকপ্যাড বা এক্সটার্নাল/ভার্চুয়াল ট্র্যাকপ্যাড। বেসিক ট্র্যাকপ্যাড ইভেন্ট এখন সাধারণত PointerType.Mouse ইভেন্ট হিসেবে বিবেচনা করা হবে, যা ব্যবহারকারীর প্রত্যাশার সাথে আরও ভালভাবে ম্যাচ করার জন্য মাউস এবং ট্র্যাকপ্যাডের আচরণকে সারিবদ্ধ করে। আগে, এই ট্র্যাকপ্যাড ইভেন্টগুলি PointerType.Touch-এর নকল টাচস্ক্রিন ফিঙ্গার হিসেবে ব্যাখ্যা করা হত, যার ফলে ব্যবহারকারীর অভিজ্ঞতা বিভ্রান্তিকর হত। যেমন, ট্র্যাকপ্যাড দিয়ে ক্লিক করে টেনে আনলে, বেছে নেওয়ার পরিবর্তে স্ক্রল করা হবে। Compose-এর লেটেস্ট রিলিজে এই ইভেন্টগুলির পয়েন্টারের ধরন পরিবর্তন করার ফলে, ট্র্যাকপ্যাড দিয়ে ক্লিক ও টেনে আনার মাধ্যমে আর স্ক্রল করা যাবে না।
এছাড়াও, আমরা API 34 থেকে প্ল্যাটফর্ম দ্বারা স্বীকৃত আরও জটিল ট্র্যাকপ্যাড জেসচারের জন্য সহায়তা যোগ করেছি, যার মধ্যে দুটি আঙুল দিয়ে সোয়াইপ করা এবং পিঞ্চ করা অন্তর্ভুক্ত। ট্র্যাকপ্যাডের সাথে আরও ভালো ব্যবহারের জন্য Modifier.scrollable এবং Modifier.transformable-এর মতো কম্পোনেন্টগুলি এই জেসচারগুলি অটোমেটিক শনাক্ত করে।
এইসব পরিবর্তন বিল্ট-ইন কম্পোনেন্ট জুড়ে ট্র্যাকপ্যাডের আচরণ উন্নত করে, যার মধ্যে রয়েছে অপ্রয়োজনীয় টাচ স্লোপ সরিয়ে দেওয়া, আরও স্বজ্ঞাত ড্র্যাগ-অ্যান্ড-ড্রপ শুরুর জেসচার, টেক্সট ফিল্ডে ডবল-ক্লিক ও ট্রিপল-ক্লিক করে বেছে নেওয়া এবং টেক্সট ফিল্ডে ডেস্কটপ-স্টাইল কনটেক্সট মেনু।
ট্র্যাকপ্যাডের আচরণ পরীক্ষা করার জন্য, performTrackpadInput, সহ নতুন টেস্টিং API আছে যা ট্র্যাকপ্যাডের সাথে ব্যবহার করার সময় আপনার অ্যাপের আচরণ যাচাই করার অনুমতি দেয়। আপনার কাছে কাস্টম জেসচার ডিটেক্টর থাকলে, টাচস্ক্রিন, মাউস, ট্র্যাকপ্যাড ও স্টাইলাস সহ বিভিন্ন ইনপুট টাইপ জুড়ে আচরণ যাচাই করুন এবং মাউস স্ক্রল হুইল ও ট্র্যাকপ্যাড জেসচারের জন্য সহায়তা নিশ্চিত করুন।
কম্পোজিশন হোস্ট ডিফল্ট (কম্পোজ রানটাইম)
আমরা HostDefaultProvider, LocalHostDefaultProvider, HostDefaultKey এবং ViewTreeHostDefaultKey নিয়ে এসেছি যাতে compose-runtime-এর মাধ্যমে সরাসরি হোস্ট-লেভেল পরিষেবা প্রদান করা যায়। এর ফলে, লুকআপের জন্য লাইব্রেরিকে compose-ui-এর উপর নির্ভর করতে হয় না এবং Kotlin Multiplatform-কে আরও ভালভাবে সাপোর্ট করে। কম্পোজিশন ট্রিতে এইসব ভ্যালু লিঙ্ক করতে, লাইব্রেরি লেখক compositionLocalWithHostDefaultOf ব্যবহার করে CompositionLocal তৈরি করতে পারেন যা হোস্ট থেকে ডিফল্ট সমাধান করে।
প্রিভিউ র্যাপার
Android Studio কাস্টম প্রিভিউ হল একটি নতুন ফিচার যা আপনাকে কম্পোজ প্রিভিউয়ের কন্টেন্ট ঠিক কীভাবে দেখানো হবে তা নির্ধারণ করতে দেয়।
PreviewWrapperProvider ইন্টারফেস প্রয়োগ করে এবং নতুন @PreviewWrapper অ্যানোটেশন প্রয়োগ করে, আপনি সহজেই কাস্টম লজিক ইনজেক্ট করতে পারবেন, যেমন নির্দিষ্ট Theme প্রয়োগ করা। অ্যানোটেশনটি @Composable এবং @Preview বা @MultiPreview-এর সাথে অ্যানোটেট করা ফাংশনে প্রয়োগ করা যেতে পারে, যা একটি জেনেরিক, সহজে ব্যবহারযোগ্য সমাধান অফার করে যা প্রিভিউ ফিচার জুড়ে কাজ করে এবং বারবার কোড লেখার প্রয়োজনীয়তা উল্লেখযোগ্যভাবে কমিয়ে দেয়।
class ThemeWrapper: PreviewWrapperProvider { @Composable override fun Wrap(content: @Composable (() -> Unit)) { JetsnackTheme { content() } } } @PreviewWrapper(ThemeWrapper::class) @Preview @Composable private fun ButtonPreview() { // JetsnackTheme in effect Button(onClick = {}) { Text(text = "Demo") } }
বন্ধ ও সরিয়ে দেওয়া
- Compose 1.10 ব্লগ পোস্টে ঘোষণা করা হয়েছে যে, আমরা
Modifier.onFirstVisible()বন্ধ করে দিচ্ছি। এর নাম প্রায়ই ভুল ধারণার জন্ম দেয়, বিশেষ করে লেজি লেআউটের ক্ষেত্রে, যেখানে স্ক্রল করার সময় এটি একাধিকবার ট্রিগার হয়। আমরাModifier.onVisibilityChanged()-এ মাইগ্রেট করার সাজেশন দিই, যা আপনার নির্দিষ্ট ব্যবহারের ক্ষেত্রে প্রয়োজনীয়তা অনুসারে দৃশ্যমানতার স্ট্যাটাস আরও নির্ভুলভাবে ম্যানুয়ালি ট্র্যাক করার সুবিধা দেয়। ComposeFoundationFlags.isTextFieldDpadNavigationEnabledফ্ল্যাগটি সরিয়ে দেওয়া হয়েছে কারণTextFields-এর জন্য ডি-প্যাড নেভিগেশন এখন ডিফল্ট হিসেবে সবসময় চালু থাকে। নতুন আচরণ নিশ্চিত করে যে গেমপ্যাড বা টিভি রিমোট থেকে ডি-প্যাড ইভেন্টগুলি প্রথমে কার্সারটিকে নির্দিষ্ট দিকে নিয়ে যায়। কার্সর টেক্সটের শেষে পৌঁছালে তবেই ফোকাস অন্য এলিমেন্টে সরানো যাবে।
আসন্ন API
আসন্ন Compose 1.12.0 রিলিজে, compileSdk-কে compileSdk 37-এ আপগ্রেড করা হবে, সাথে AGP 9 এবং Compose-এর উপর নির্ভর করে এমন সব অ্যাপ ও লাইব্রেরি এই প্রয়োজনীয়তা ইনহেরিট করবে। আমরা সাজেস্ট করি যে আপনি লেটেস্ট রিলিজ করা ভার্সন ব্যবহার করুন, কারণ Compose-এর লক্ষ্য হল লেটেস্ট Android ফিচারের অ্যাক্সেস প্রদান করার জন্য নতুন compileSdks দ্রুত গ্রহণ করা। বিভিন্ন API লেভেলের জন্য AGP-এর কোন ভার্সন কাজ করে সেই সম্পর্কে আরও তথ্য পেতে এখানে ডকুমেন্টেশন চেক করতে ভুলবেন না।
Compose 1.11.0-এ, নিম্নলিখিত APIগুলি @Experimental হিসেবে চালু করা হয়েছে এবং আপনি নিজের অ্যাপে সেগুলি এক্সপ্লোর করার সময় আপনার মতামত শোনার জন্য আমরা অপেক্ষা করছি। মনে রাখবেন যে @Experimental APIs প্রাথমিক মূল্যায়ন ও মতামতের জন্য প্রদান করা হয় এবং ভবিষ্যতে রিলিজের সময় উল্লেখযোগ্য পরিবর্তন বা সরিয়ে দেওয়া হতে পারে।
স্টাইল (এক্সপেরিমেন্টাল)
আমরা স্টাইলিং-এর জন্য একটি নতুন পরীক্ষামূলক ফাউন্ডেশন API চালু করছি। স্টাইল API হল কম্পোনেন্টের ভিজ্যুয়াল এলিমেন্ট কাস্টমাইজ করার নতুন পদ্ধতি, যা সাধারণত মডিফায়ারের মাধ্যমে করা হয়। এটি সহজ স্টেট-ভিত্তিক স্টাইলিং এবং অ্যানিমেটেড ট্রানজিশন সহ স্টাইল করা যায় এমন প্রপার্টির স্ট্যান্ডার্ড সেট প্রকাশ করে আরও গভীর, সহজ কাস্টমাইজেশন আনলক করার জন্য ডিজাইন করা হয়েছে। এই নতুন API-এর মাধ্যমে, আমরা ইতিমধ্যেই আশাব্যঞ্জক পারফর্ম্যান্স সংক্রান্ত সুবিধা দেখতে পাচ্ছি। Style API স্থিতিশীল হয়ে গেলে, আমরা মেটেরিয়াল কম্পোনেন্টে স্টাইল গ্রহণ করার পরিকল্পনা করছি।
প্রেস করা স্টেট স্টাইল ব্যাকগ্রাউন্ড ওভাররাইড করার একটি প্রাথমিক উদাহরণ:
@Composable fun LoginButton(modifier: Modifier = Modifier) { Button( onClick = { // Login logic }, modifier = modifier, style = { background( Brush.linearGradient( listOf(lightPurple, lightBlue) ) ) width(75.dp) height(50.dp) textAlign(TextAlign.Center) externalPadding(16.dp) pressed { background( Brush.linearGradient( listOf(Color.Magenta, Color.Red) ) ) } } ){ Text( text = "Login", ) } }
ডকুমেন্টেশন চেক করুন এবং এখানে কোনও সমস্যা থাকলে তা জানান।
MediaQuery (এক্সপেরিমেন্টাল)
নতুন mediaQuery API, আপনার UI-কে তার পরিবেশের সাথে মানিয়ে নেওয়ার জন্য একটি ঘোষণামূলক এবং পারফর্ম্যান্ট উপায় প্রদান করে। এটি জটিল তথ্য সংগ্রহকে UiMediaScope-এর মধ্যে সহজ শর্তে অ্যাবস্ট্র্যাক্ট করে, যাতে শুধুমাত্র প্রয়োজন হলেই রিকম্পোজিশন হয়।
কীবোর্ডের ধরন ও পয়েন্টার প্রিসিশনের মতো ডিভাইস সংক্রান্ত ক্ষমতা থেকে শুরু করে উইন্ডোর সাইজ ও পোস্টারের মতো প্রাসঙ্গিক অবস্থা পর্যন্ত বিভিন্ন ধরনের এনভায়রনমেন্টাল সিগন্যালের জন্য সহায়তা প্রদান করার মাধ্যমে আপনি গভীরভাবে রেসপন্সিভ অভিজ্ঞতা তৈরি করতে পারবেন। হাই-ফ্রিকোয়েন্সি আপডেট ম্যানেজ করার জন্য derivedMediaQuery-এর সাথে পারফর্ম্যান্স যুক্ত করা হয়েছে, যেখানে স্কোপ ওভাররাইড করার ক্ষমতা হার্ডওয়্যার কনফিগারেশন জুড়ে টেস্টিং ও প্রিভিউকে নির্বিঘ্ন করে তোলে। আগে, নির্দিষ্ট কিছু ডিভাইসের প্রপার্টি অ্যাক্সেস করতে — যেমন, কোনও ডিভাইস টেবিলটপ মোডে থাকলে — আপনাকে অনেক বয়লারপ্লেট লিখতে হত:
@Composable fun isTabletopPosture( context: Context = LocalContext.current ): Boolean { val windowLayoutInfo by WindowInfoTracker .getOrCreate(context) .windowLayoutInfo(context) .collectAsStateWithLifecycle(null) return windowLayoutInfo.displayFeatures.any { displayFeature -> displayFeature is FoldingFeature && displayFeature.state == FoldingFeature.State.HALF_OPENED && displayFeature.orientation == FoldingFeature.Orientation.HORIZONTAL } } @Composable fun VideoPlayer() { if(isTabletopPosture()) { TabletopLayout() } else { FlatLayout() } }
এখন, UIMediaQuery-এর সাহায্যে, আপনি ডিভাইসের প্রপার্টি কোয়েরি করতে mediaQuery সিনট্যাক্স যোগ করতে পারবেন, যেমন কোনও ডিভাইস টেবিলটপ মোডে আছে কিনা:
@OptIn(ExperimentalMediaQueryApi::class) @Composable fun VideoPlayer() { if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) { TabletopLayout() } else { FlatLayout() } }
ডকুমেন্টেশন চেক করুন এবং এখানে কোনও সমস্যা থাকলে তা জানান।
গ্রিড (এক্সপেরিমেন্টাল)
Jetpack Compose-এ জটিল, দ্বিমাত্রিক লেআউট তৈরি করার জন্য Grid হল একটি শক্তিশালী নতুন API। Row এবং Column লিনিয়ার ডিজাইনের জন্য দারুণ হলেও, Grid আপনাকে স্ক্রলযোগ্য তালিকার ওভারহেড ছাড়াই স্ক্রিন-লেভেল আর্কিটেকচার এবং জটিল কম্পোনেন্টের জন্য প্রয়োজনীয় স্ট্রাকচারাল কন্ট্রোল প্রদান করে। Grid আপনাকে ট্র্যাক, গ্যাপ ও সেল ব্যবহার করে লেআউট নির্ধারণ করার অনুমতি দেয় এবং Dp, শতাংশ, অন্তর্নিহিত কন্টেন্ট সাইজ ও ফ্লেক্সিবল "Fr" ইউনিটের মতো পরিচিত সাইজ সংক্রান্ত বিকল্প অফার করে।
@OptIn(ExperimentalGridApi::class) @Composable fun GridExample() { Grid( config = { repeat(4) { column(0.25f) } repeat(2) { row(0.5f) } gap(16.dp) } ) { Card1(modifier = Modifier.gridItem(rowSpan = 2) Card2(modifier = Modifier.gridItem(colmnSpan = 3) Card3(modifier = Modifier.gridItem(columnSpan = 2) Card4() } }
আপনি আইটেমগুলি অটোমেটিক রাখতে পারেন বা নির্ভুলতার জন্য একাধিক সারি এবং কলাম জুড়ে স্পষ্টভাবে স্প্যান করতে পারেন। সবচেয়ে ভালো দিক হল, এটি অত্যন্ত মানানসই—টেবিলটপ মোড বা ওরিয়েন্টেশন পরিবর্তনের মতো ডিভাইসের অবস্থার সাথে মানানসই করতে আপনি নিজের গ্রিড ট্র্যাক এবং স্প্যানগুলি ডায়নামিকভাবে রিকনফিগার করতে পারেন, যা বিভিন্ন ফর্ম ফ্যাক্টর জুড়ে আপনার UI-কে দুর্দান্ত দেখায়।
ডকুমেন্টেশন চেক করুন এবং এখানে কোনও সমস্যা থাকলে তা জানান।
FlexBox (পরীক্ষামূলক)
FlexBox হল একটি লেআউট কন্টেনার যা হাই পারফর্ম্যান্স, অ্যাডাপ্টিভ UI-এর জন্য ডিজাইন করা হয়েছে। এটি উপলভ্য কন্টেনার ডাইমেনশনের উপর ভিত্তি করে আইটেমের সাইজ ও স্পেস ডিস্ট্রিবিউশন ম্যানেজ করে। এটি র্যাপিং (wrap) এবং আইটেমের মাল্টি-অ্যাক্সিস অ্যালাইনমেন্টের (justifyContent, alignItems, alignContent) মতো জটিল টাস্ক ম্যানেজ করে। এটি কন্টেনার পূরণ করার জন্য আইটেমকে বড় (grow) বা ছোট (shrink) করার অনুমতি দেয়।
@OptIn(ExperimentalFlexBoxApi::class) fun FlexBoxWrapping(){ FlexBox( config = { wrap(FlexWrap.Wrap) gap(8.dp) } ) { RedRoundedBox() BlueRoundedBox() GreenRoundedBox(modifier = Modifier.width(350.dp).flex { grow(1.0f) }) OrangeRoundedBox(modifier = Modifier.width(200.dp).flex { grow(0.7f) }) PinkRoundedBox(modifier = Modifier.width(200.dp).flex { grow(0.3f) }) } }
ডকুমেন্টেশন চেক করুন এবং এখানে কোনও সমস্যা থাকলে তা জানান।
নতুন SlotTable প্রয়োগ (এক্সপেরিমেন্টাল)
আমরা SlotTable-এর নতুন প্রয়োগ চালু করেছি, যা এই রিলিজে ডিফল্ট হিসেবে বন্ধ করা আছে। SlotTable হল ইন্টার্নাল ডেটা স্ট্রাকচার যা Compose রানটাইম আপনার কম্পোজিশন হায়ারার্কির স্টেট ট্র্যাক করতে, ইনভ্যালিডেশন/রিকম্পোজিশন ট্র্যাক করতে, মনে রাখা ভ্যালু স্টোর করতে এবং রানটাইমে কম্পোজিশনের সব মেটাডেটা ট্র্যাক করতে ব্যবহার করে। এই নতুন প্রয়োগটি পারফর্ম্যান্স উন্নত করার জন্য ডিজাইন করা হয়েছে, প্রাথমিকভাবে র্যান্ডম এডিটের ক্ষেত্রে।
নতুন SlotTable ব্যবহার করে দেখতে, ComposeRuntimeFlags.isLinkBufferComposerEnabled চালু করুন।
আজই কোডিং শুরু করুন!
Jetpack Compose-এ অনেক নতুন API আছে এবং আরও অনেক API আসছে, তাই Jetpack Compose-এ মাইগ্রেট করার এর চেয়ে ভালো সময় আর হয় না। বরাবরের মতো, আপনার মতামত এবং ফিচার সংক্রান্ত অনুরোধ (বিশেষ করে @Experimental ফিচার যা এখনও তৈরি হচ্ছে) আমাদের কাছে মূল্যবান — সেগুলি এখানে জমা দিন। কম্পোজ করার আনন্দ নিন!
-
প্রোডাক্ট সংক্রান্ত খবরআজ, Android Dev Summit-এ, আমরা অনেক টুল এবং API-এর ব্যাপক উপলভ্যতা ঘোষণা করছি যা প্রতিদিনের ঘর্ষণ দূর করতে এবং আপনাকে দুর্দান্ত Android অ্যাপ তৈরি করার জন্য আরও নমনীয়তা দেওয়ার জন্য ডিজাইন করা হয়েছে।
Matthew McCullough • ৪ মিনিট লাগবে -
প্রোডাক্ট সংক্রান্ত খবরAndroid Studio Rabbit 2 এখন স্টেবল এবং প্রোডাকশনে ব্যবহারের জন্য রেডি। এই রিলিজে আপনার ডেভেলপমেন্ট উন্নত করার জন্য গুরুত্বপূর্ণ ফিচার অন্তর্ভুক্ত করা হয়েছে, যেমন Bring Your Own Agent, নতুন XR এমুলেটর ফিচার, LeakCanary আপডেট, নতুন এজেন্ট স্কিল ম্যানেজার টুল, AI কোড রিভিউ এবং আরও অনেক কিছু।
Matthew Warner • ৩ মিনিট রিডিং -
প্রোডাক্ট সংক্রান্ত খবরযেসব অ্যাপ আসন্ন Android রিলিজকে টার্গেট করে, সেগুলি WRITE_CONTACTS অনুমতি সহ পরিচিতিতে সরাসরি লিখতে পারবে না।
Roxanna Aliabadi Walker • ৬ মিনিট রিডিং
আপনার ইনবক্সে প্রতি সপ্তাহে Android ডেভেলপমেন্ট সংক্রান্ত লেটেস্ট ইনসাইট পান।