SharedPreferences: এটি কী, Android কী-ভ্যালু স্টোরেজ

লেখক: IT Sectr প্রকাশিত: 2026-03-12 পড়ার সময়: 9 মিনিট

SharedPreferences হল Android-এ একটি কী-ভ্যালু ডেটা স্টোরেজ যা সহজ সেটিংস এবং অ্যাপ কনফিগারেশন সংরক্ষণের জন্য ডিজাইন করা হয়েছে। ডেটা ডিভাইসে XML ফাইলে সংরক্ষিত হয় এবং শুধুমাত্র যে অ্যাপ এটি তৈরি করেছে তার ভিতরেই অ্যাক্সেসযোগ্য। অফিসিয়াল ডকুমেন্টেশন অনুযায়ী Android Developers, 2025, SharedPreferences প্রিমিটিভ টাইপ: String, Int, Boolean, Float, Long এবং Set<String> সংরক্ষণ সমর্থন করে। এটি SQL কুয়েরি বা সরাসরি ফাইল সিস্টেমের সাথে কাজ না করেই অল্প পরিমাণ ব্যবহারকারী সেটিংস সংরক্ষণের জন্য সবচেয়ে সহজ এবং দ্রুততম সমাধান।

মূল পয়েন্ট

  • SharedPreferences — Android কী-ভ্যালু স্টোরেজ যা XML ফাইলে সহজ অ্যাপ সেটিংস সংরক্ষণ করে।
  • পাঁচটি ডেটা টাইপ সমর্থন করে: String, Int, Boolean, Float, Long এবং Set<String>।
  • ডিস্কে সংরক্ষণের জন্য সিঙ্ক্রোনাস (get) এবং অ্যাসিঙ্ক্রোনাস (apply) রাইট অপারেশনে কাজ করে।
  • ডেটা ফাইল নাম এবং অ্যাক্সেস মোড (PRIVATE, MULTI_PROCESS) দ্বারা বিচ্ছিন্ন।
  • বড় ডেটা ভলিউমের জন্য Google SharedPreferences-এর পরিবর্তে DataStore বা Room ব্যবহারের পরামর্শ দেয়।

SharedPreferences কী?

SharedPreferences হল Android-এর একটি অন্তর্নির্মিত ব্যবস্থা যা ডিভাইসের অভ্যন্তরীণ স্টোরেজে XML ফাইলে কী-ভ্যালু জোড়া সংরক্ষণ করে। এটি API Level 1 থেকে উপলব্ধ এবং কোনো অতিরিক্ত লাইব্রেরির প্রয়োজন নেই। এর মূল উদ্দেশ্য হল ব্যবহারকারী পছন্দ, ইন্টারফেস অবস্থা, প্রথম লঞ্চ ফ্ল্যাগ এবং অন্যান্য সহজ ডেটা সংরক্ষণ করা যার জন্য কাঠামোবদ্ধ ডাটাবেসের প্রয়োজন নেই।

প্রতিটি SharedPreferences ফাইল একটি নির্দিষ্ট নাম এবং অ্যাক্সেস মোডের সাথে যুক্ত। ডিফল্টরূপে Context.MODE_PRIVATE মোড ব্যবহার করা হয়, যা ফাইলে অ্যাক্সেস শুধুমাত্র বর্তমান অ্যাপের মধ্যে সীমাবদ্ধ করে। আগে Android MODE_WORLD_READABLE এবং MODE_WORLD_WRITEABLE মোড সমর্থন করত, কিন্তু সেগুলি API Level 17 থেকে অবচিত ঘোষণা করা হয় এবং নিরাপত্তার কারণে Android 7.0 (API 24) এ সম্পূর্ণরূপে সরিয়ে ফেলা হয়।

এর সরলতা সত্ত্বেও, SharedPreferences লক্ষ লক্ষ Android অ্যাপে ব্যবহৃত হয়। Google-এর মতে, Google Play-এ প্রকাশিত 90% এর বেশি অ্যাপ সেটিংস সংরক্ষণের জন্য SharedPreferences ব্যবহার করে। তবে জটিল পরিস্থিতিতে (বড় ডেটা ভলিউম, টাইপ নিরাপত্তা, অ্যাসিঙ্ক্রোনি) Google Android Jetpack লাইব্রেরি থেকে Preferences DataStore-এর মতো আরও আধুনিক সমাধানের পরামর্শ দেয়।

স্টোরেজ ফরম্যাট: ডিভাইসে XML

ভৌতিকভাবে, SharedPreferences অ্যাপ ডিরেক্টরিতে XML ফাইল হিসাবে সংরক্ষিত হয়: /data/data/{package_name}/shared_prefs/{file_name}.xml। ফাইলটিতে সংরক্ষিত মানের প্রকারের উপর নির্ভর করে একটি মূল উপাদান <map> এবং শিশু উপাদান <string>, <int>, <boolean>, <float> এবং <long> থাকে। ফাইলের আকার সীমাবদ্ধ নয়, তবে বড় ডেটা ভলিউমের জন্য (100 KB এর বেশি) পড়া এবং লেখার কর্মক্ষমতা লক্ষণীয়ভাবে হ্রাস পেতে শুরু করে।

SharedPreferences ফাইলগুলি ডিফল্টরূপে এনক্রিপ্ট করা হয় না। ডেটা ডিভাইসের ফাইল সিস্টেমে প্লেইন টেক্সটে সংরক্ষিত হয়। সংবেদনশীল ডেটা (টোকেন, পাসওয়ার্ড) সংরক্ষণের জন্য AndroidX Security লাইব্রেরি থেকে EncryptedSharedPreferences ব্যবহার করার পরামর্শ দেওয়া হয়, যা AES256-GCM ব্যবহার করে স্বয়ংক্রিয়ভাবে কী এবং মান এনক্রিপ্ট করে।

Android-এ SharedPreferences কীভাবে কাজ করে

SharedPreferences পর্যায়ক্রমিক ডিস্ক সিঙ্ক্রোনাইজেশন সহ মেমরি ক্যাশিংয়ের নীতিতে কাজ করে। প্রথমবার ফাইল অ্যাক্সেস করার সময় (getSharedPreferences এর মাধ্যমে), Android XML ফাইলটি RAM-এ লোড করে এবং এটি একটি Map অবজেক্টে পার্স করে। সমস্ত পরবর্তী রিড অপারেশন ডিস্ক থেকে পুনরায় পড়া ছাড়াই মেমরি থেকে সঞ্চালিত হয়। এটি ডেটাতে উচ্চ গতির অ্যাক্সেস নিশ্চিত করে।

রাইট অপারেশন Editor ব্যবহার করে — একটি অভ্যন্তরীণ পরিবর্তন বাফার। যখন ডেভেলপার putString বা putBoolean কল করে, পরিবর্তনগুলি মেমরিতে Editor অবজেক্টে সংরক্ষিত হয়। ডিস্কে প্রকৃত লেখা ঘটে যখন commit (সিঙ্ক্রোনাস) বা apply (অ্যাসিঙ্ক্রোনাস) পদ্ধতি কল করা হয়। এই পদ্ধতিগুলি কল না করা পর্যন্ত ডেটা সংরক্ষিত হয় না, এবং অ্যাপ অপ্রত্যাশিতভাবে ক্র্যাশ হলে পরিবর্তনগুলি হারিয়ে যেতে পারে।

অ্যাক্সেস মোড এবং কনটেক্সট

SharedPreferences ইনস্ট্যান্স পাওয়ার জন্য দুটি পদ্ধতি ব্যবহার করা হয়: getPreferences এবং getSharedPreferences। প্রথমটি শুধুমাত্র Activity-এর ভিতরে উপলব্ধ এবং Activity-এর নামে একটি ফাইল তৈরি করে। দ্বিতীয়টি আরও নমনীয়, একটি ফাইল নাম এবং অ্যাক্সেস মোড গ্রহণ করে এবং যেকোনো কনটেক্সট (Application, Activity, Service) থেকে অ্যাক্সেসযোগ্য। সুপারিশ করা হয় যে getSharedPreferences একটি ফাইল নামের সাথে ব্যবহার করুন যা অ্যাপের মডিউল বা কার্যকারিতার সাথে মেলে।

kotlin
// SharedPreferences প্রাপ্তি
val prefs = context.getSharedPreferences(
    "user_settings", Context.MODE_PRIVATE
)

// ডেটা লেখা
with(prefs.edit()) {
    putString("username", "আনা")
    putInt("age", 28)
    putBoolean("isLoggedIn", true)
    apply()
}

// ডেটা পড়া
val username = prefs.getString("username", "")
val age = prefs.getInt("age", 0)
val isLoggedIn = prefs.getBoolean("isLoggedIn", false)

MODE_MULTI_PROCESS (অবচিত) ব্যবহার করার সময় SharedPreferences প্রক্রিয়াগুলির মধ্যে সিঙ্ক্রোনাইজ হয়। তবে এই সিঙ্ক্রোনাইজেশন পারমাণবিকতা নিশ্চিত করে না, এবং Google মাল্টি-প্রসেস পরিস্থিতিতে SharedPreferences এড়ানোর পরামর্শ দেয়। এই ধরনের ক্ষেত্রে ContentProvider, আন্তঃপ্রক্রিয়া অ্যাক্সেস সহ Room বা DataStore ব্যবহার করা ভাল।

SharedPreferences-এর প্রধান পদ্ধতিগুলি

SharedPreferences কী দ্বারা ডেটা পড়ার জন্য পদ্ধতির একটি সেট এবং লেখার জন্য Editor ইন্টারফেস প্রদান করে। প্রতিটি রিড পদ্ধতি দুটি প্যারামিটার নেয়: একটি কী এবং একটি ডিফল্ট মান যা কী না পাওয়া গেলে ফেরত দেওয়া হয়। ডিফল্ট মান রিটার্ন টাইপও নির্ধারণ করে: getString String ফেরত দেয়, getInt Int ফেরত দেয়, ইত্যাদি।

রিড পদ্ধতিরাইট পদ্ধতিডেটার প্রকার
getStringputStringString
getIntputIntInt
getBooleanputBooleanBoolean
getFloatputFloatFloat
getLongputLongLong
getStringSetputStringSetSet<String>

Editor এবং apply বনাম commit

Editor হল SharedPreferences-এর একটি অভ্যন্তরীণ অবজেক্ট যা একটি বাফারে পরিবর্তন সংগ্রহ করে। সমস্ত পরিবর্তন করার পরে, ডেভেলপার commit() (সিঙ্ক্রোনাস রাইট) বা apply() (অ্যাসিঙ্ক্রোনাস রাইট) কল করে। পার্থক্যটি গুরুত্বপূর্ণ: commit ডিস্কে সম্পূর্ণ লেখা না হওয়া পর্যন্ত বর্তমান থ্রেড ব্লক করে এবং একটি boolean (সফল/ব্যর্থ) ফেরত দেয়, যখন apply ব্যাকগ্রাউন্ড থ্রেডে লেখা সম্পাদন করে এবং অবিলম্বে নিয়ন্ত্রণ ফেরত দেয় কিন্তু ফলাফল ফেরত দেয় না।

সব ক্ষেত্রে যেখানে লেখার ফলাফল জানার প্রয়োজন নেই, commit-এর পরিবর্তে apply ব্যবহার করার পরামর্শ দেওয়া হয়। apply দ্রুততর এবং UI থ্রেড ব্লক করে না। commit শুধুমাত্র তখন ব্যবহার করা উচিত যখন এটি জানা গুরুত্বপূর্ণ যে ডেটা সফলভাবে সংরক্ষিত হয়েছে কিনা, বা মাল্টি-প্রসেস মোডে কাজ করার সময়। পৃথক কী মুছতে remove পদ্ধতি ব্যবহার করা হয়, সম্পূর্ণ পরিষ্কারের জন্য — clear। সমস্ত মুছে ফেলার অপারেশনও Editor-এর মাধ্যমে সম্পাদিত হয়।

kotlin
// একাধিক পরিবর্তন - একটি apply
prefs.edit {
    putString("theme", "dark")
    putBoolean("notifications", false)
    remove("old_key")
}

// মান পরিবর্তন শ্রোতা
prefs.registerOnSharedPreferenceChangeListener { prefs, key ->
    Log.d("TAG", "কী পরিবর্তিত হয়েছে: $key")
}

Android 12 (API 31) থেকে শুরু করে, SharedPreferences-কে Lifecycle-এর মাধ্যমে স্বয়ংক্রিয় আনসাবস্ক্রিপশন সহ registerOnSharedPreferenceChangeListener সমর্থনের সাথে উন্নত করা হয়েছে। এটি ভুলে যাওয়া listener-এর সাথে সম্পর্কিত মেমরি লিক এড়াতে সহায়তা করে। পুরানো সংস্করণগুলিতে, ডেভেলপারকে কম্পোনেন্টের onDestroy বা onStop-এ ম্যানুয়ালি unregisterOnSharedPreferenceChangeListener কল করতে হয়।

SharedPreferences বনাম স্টোরেজ বিকল্প

এর ব্যাপক ব্যবহার সত্ত্বেও, SharedPreferences Android-এ সমস্ত ডেটা স্টোরেজ পরিস্থিতির জন্য একটি সার্বজনীন সমাধান নয়। ডেটা ভলিউম, টাইপ নিরাপত্তা প্রয়োজনীয়তা এবং কর্মক্ষমতার উপর নির্ভর করে, Google Android Jetpack এবং স্ট্যান্ডার্ড Android লাইব্রেরিতে অন্তর্ভুক্ত বিভিন্ন বিকল্পের পরামর্শ দেয়।

সমাধানকখন ব্যবহার করবেনত্রুটিগুলি
SharedPreferencesছোট সেটিংস (100 কী পর্যন্ত)কোনো টাইপ নিরাপত্তা নেই, সিঙ্ক্রোনাস পড়া
DataStoreকরুটিন সহ মাঝারি জটিলতার সেটিংসAPI 14 এর নিচে কোনো পশ্চাদগত সামঞ্জস্য নেই
Roomকাঠামোবদ্ধ ডেটা এবং তালিকা3-5 সেটিংসের জন্য অতিরিক্ত
EncryptedSharedPreferencesসংবেদনশীল ডেটা এবং টোকেনAndroidX Security-এর উপর নির্ভরশীলতা

DataStore — আধুনিক বিকল্প

DataStore হল Android Jetpack লাইব্রেরি যা Google SharedPreferences-এর প্রতিস্থাপন হিসেবে উপস্থাপন করেছে। এটি দুটি রূপ প্রদান করে: Preferences DataStore (কী-ভ্যালু, SharedPreferences-এর মতো) এবং Proto DataStore (Protocol Buffers-এর মাধ্যমে টাইপকৃত স্টোরেজ)। DataStore অ্যাসিঙ্ক্রোনাস অপারেশনের জন্য করুটিন এবং Flow ব্যবহার করে, টাইপ নিরাপত্তা নিশ্চিত করে এবং স্বয়ংক্রিয়ভাবে সংস্করণ মাইগ্রেশন পরিচালনা করে। Google সব নতুন প্রকল্পের জন্য DataStore সুপারিশ করে।

DataStore-এর প্রধান সুবিধা হল API স্তরে অ্যাসিঙ্ক্রোনি। সমস্ত রিড অপারেশন Flow ফেরত দেয় এবং রাইট অপারেশনগুলি suspend ফাংশন। এটি UI থ্রেড ব্লকিং সম্পূর্ণরূপে দূর করে যা SharedPreferences-এর সিঙ্ক্রোনাস পড়ার সময় ঘটতে পারে। অতিরিক্তভাবে, DataStore ডেটা সঙ্গতি নিশ্চিত করে: লেখা একটি লেনদেনে সম্পাদিত হয় এবং ব্যর্থ হলে সমস্ত পরিবর্তন পূর্বাবস্থায় ফিরিয়ে আনা হয়।

অ্যাপ্লিকেশনে SharedPreferences ব্যবহারের উদাহরণ

একটি ব্যবহারিক উদাহরণ দেখা যাক: Android অ্যাপে থিম সেটিংস (হালকা/গাঢ়/সিস্টেম)। ব্যবহারকারী একটি থিম নির্বাচন করে এবং পছন্দটি SharedPreferences-এ সংরক্ষিত হয়। পরবর্তী অ্যাপ লঞ্চে, থিম সংরক্ষিত সেটিংস থেকে পুনরুদ্ধার করা হয়। প্রতিক্রিয়াশীল UI আপডেটের জন্য, SharedPreferences.OnSharedPreferenceChangeListener-এর মাধ্যমে পরিবর্তন পর্যবেক্ষণ ব্যবহার করা হয়।

ব্যবহারকারী সেটিংস সংরক্ষণ

আসুন একটি ThemePreferences ক্লাস তৈরি করি যা থিমের জন্য SharedPreferences-এর সাথে সমস্ত কাজ এনক্যাপসুলেট করে। ক্লাসটি getTheme (পড়া), setTheme (লেখা) এবং observeTheme (পর্যবেক্ষণ) পদ্ধতি প্রদান করে। সেটিংস ফাইলের নাম হবে "app_preferences" MODE_PRIVATE মোড সহ। সুবিধার জন্য, কীগুলি কনস্ট্যান্ট হিসাবে কম্প্যানিয়ন অবজেক্টে রাখা হয়েছে।

kotlin
class ThemePreferences(context: Context) {
    companion object {
        private const val PREF_NAME = "app_preferences"
        private const val KEY_THEME = "theme_mode"
        const val THEME_LIGHT = "light"
        const val THEME_DARK = "dark"
        const val THEME_SYSTEM = "system"
    }

    private val prefs = context
        .getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)

    fun getTheme(): String =
        prefs.getString(KEY_THEME, THEME_SYSTEM) ?: THEME_SYSTEM

    fun setTheme(theme: String) {
        prefs.edit { putString(KEY_THEME, theme) }
    }

    fun observeTheme(callback: (String) -> Unit) {
        prefs.registerOnSharedPreferenceChangeListener { _, key ->
            if (key == KEY_THEME) {
                callback.invoke(getTheme())
            }
        }
    }
}

Activity বা Fragment-এ, ThemePreferences ইনস্ট্যান্স পাওয়া অ্যাপ কনটেক্সটের মাধ্যমে করা হয়। ইনিশিয়ালাইজেশনে, বর্তমান থিম সেট করতে getTheme কল করা হয়। যখন ব্যবহারকারী একটি নতুন থিম নির্বাচন করে, setTheme কল করা হয়, এবং observeTheme-এর মাধ্যমে Activity পুনরায় চালু না করেই ইন্টারফেস আপডেট হয়। মেমরি লিক প্রতিরোধ করতে onDestroy-এ listener থেকে আনসাবস্ক্রাইব করা গুরুত্বপূর্ণ, বিশেষ করে যদি কনফিগারেশন পরিবর্তনে Activity পুনরায় তৈরি হয়।

ন্যূনতম লক্ষ্য সংস্করণ Android 12+ সহ অ্যাপগুলির জন্য, LifecycleObserver-এর সাথে registerOnSharedPreferenceChangeListener ব্যবহার করার পরামর্শ দেওয়া হয়। এটি কম্পোনেন্টের জীবনচক্র পরিবর্তনে স্বয়ংক্রিয়ভাবে সাবস্ক্রিপশন এবং আনসাবস্ক্রিপশন পরিচালনা করে। পুরানো সংস্করণগুলির জন্য, সাবস্ক্রিপশন এবং আনসাবস্ক্রিপশন ম্যানুয়ালি পরিচালনা করতে হয়, যা SharedPreferences ব্যবহার করে প্রোডাকশন অ্যাপে ত্রুটির একটি সাধারণ উৎস।

প্রায়শই জিজ্ঞাসিত প্রশ্ন

SharedPreferences-এ কি অবজেক্ট সংরক্ষণ করা যায়?

SharedPreferences সরাসরি শুধুমাত্র প্রিমিটিভ টাইপ এবং Set<String> সমর্থন করে। অবজেক্ট সংরক্ষণ করতে, আপনাকে সেগুলিকে Gson বা Moshi-এর মাধ্যমে JSON স্ট্রিং-এ সিরিয়ালাইজ করতে হবে, putString-এর মাধ্যমে সংরক্ষণ করতে হবে এবং পড়ার সময় ডিসিরিয়ালাইজ করতে হবে। অনেক ফিল্ড সহ জটিল অবজেক্টের জন্য, JSON সিরিয়ালাইজেশন সহ SharedPreferences-এর পরিবর্তে Room ব্যবহার করার পরামর্শ দেওয়া হয়।

SharedPreferences কি থ্রেড-সেফ?

হ্যাঁ, SharedPreferences থ্রেড-সেফ। সমস্ত রিড এবং রাইট অপারেশন SharedPreferences অবজেক্ট এবং এর Editor স্তরে সিঙ্ক্রোনাইজ করা হয়। তবে মাল্টি-প্রসেস মোড ব্যবহার করার সময় সিঙ্ক্রোনাইজেশন নিশ্চিত নয়। একটি অ্যাপের ভিতরে একাধিক থ্রেড থেকে সমবর্তী অ্যাক্সেসের জন্য, SharedPreferences অতিরিক্ত লক ছাড়াই নিরাপদ।

SharedPreferences-এর সমস্ত ডেটা কীভাবে সাফ করবেন?

SharedPreferences থেকে সমস্ত ডেটা সম্পূর্ণরূপে সাফ করতে, Editor-এ clear() পদ্ধতি কল করুন এবং apply-এর মাধ্যমে পরিবর্তন প্রয়োগ করুন। যদি আপনাকে XML ফাইলটি নিজেই মুছতে হয়, কনটেক্সটে deleteSharedPreferences(name) ব্যবহার করুন। সেটিংস → অ্যাপস → ডেটা সাফ করুন-এর মাধ্যমে অ্যাপ ডেটা সাফ করাও সমস্ত SharedPreferences ফাইল মুছে ফেলে।

SharedPreferences বা DataStore: কী বেছে নেবেন?

নতুন প্রকল্পের জন্য, Google SharedPreferences-এর বিকল্প হিসাবে DataStore সুপারিশ করে। DataStore করুটিন সহ অ্যাসিঙ্ক্রোনাস অপারেশন, টাইপ নিরাপত্তা (Proto DataStore) এবং স্বয়ংক্রিয় মাইগ্রেশন প্রদান করে। SharedPreferences শুধুমাত্র API 14-এর নিচে ন্যূনতম সংস্করণ সহ প্রকল্পের জন্য বা যখন অতিরিক্ত নির্ভরতা ছাড়া দ্রুত একীকরণ প্রয়োজন তখন বেছে নেওয়া উচিত।

SharedPreferences-এ ডেটা কীভাবে এনক্রিপ্ট করবেন?

ডেটা এনক্রিপশনের জন্য, AndroidX Security লাইব্রেরি থেকে EncryptedSharedPreferences ব্যবহার করুন। এটি AES-256 GCM ব্যবহার করে স্বয়ংক্রিয়ভাবে কী এবং মান এনক্রিপ্ট করে। সেটআপ প্রক্রিয়াটি ন্যূনতম: getSharedPreferences-কে Android Keystore থেকে মাস্টার কী নির্দিষ্ট করে EncryptedSharedPreferences.create দিয়ে প্রতিস্থাপিত করা হয়।

সারসংক্ষেপ

  • SharedPreferences — Android-এর অন্তর্নির্মিত কী-ভ্যালু স্টোরেজ যা XML ফরম্যাটে সহজ অ্যাপ সেটিংস সংরক্ষণ করে।
  • ছয়টি ডেটা প্রকার সমর্থন করে: String, Int, Boolean, Float, Long এবং Set<String> ডিফল্ট মান নির্দিষ্ট করার সাথে।
  • রিড অপারেশন মেমরি (ক্যাশ) থেকে সঞ্চালিত হয়, রাইটিং — সিঙ্ক্রোনাস commit বা অ্যাসিঙ্ক্রোনাস apply সহ Editor-এর মাধ্যমে।
  • ডেটা ফাইল নাম এবং MODE_PRIVATE মোড দ্বারা বিচ্ছিন্ন, শুধুমাত্র তৈরি করা অ্যাপের ভিতরে অ্যাক্সেসযোগ্য।
  • সংবেদনশীল ডেটা সংরক্ষণের জন্য, AES-256 এনক্রিপশন সহ EncryptedSharedPreferences ব্যবহার করুন।
  • নতুন প্রকল্পের জন্য, Google করুটিন এবং Flow সহ DataStore-কে আধুনিক অ্যাসিঙ্ক্রোনাস বিকল্প হিসাবে সুপারিশ করে।
  • SharedPreferences অতিরিক্ত নির্ভরতা ছাড়াই 5-50টি সহজ সেটিংস দ্রুত সংরক্ষণের জন্য সেরা পছন্দ হিসাবে রয়ে গেছে।

আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব

IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।

প্রকল্প নিয়ে আলোচনা করুন

আরও পড়ুন