স্টোরেজ একটা জিনিস যেটি আমরা সবাই জানি, কিন্তু সবসময় আমরা সেটিকে স্বাভাবিক मानি। زیاد দিন হলো না, স্টোরেজ ক্যাপাসিটির প্রতিটি লাফ ইনক্রিমেন্টাল ছিল এবং অসম্ভব মনে হতো। আজকাল, আমরা আমাদের ডিভাইসগুলোর কতটুকু স্টোরেজ আছে সেটি বিবেচনা করার সময় দ্বিতীয়বার চিন্তা করি না (এবং পার্থক্যগুলোর পার্থক্য নিয়ে কেয়ার করি না)।
বड़ा পয়েন্ট হল মেমরিতে কী সংরক্ষিত হচ্ছে তার বিবর্তনকে দেখতে। স্মার্টফোনের আগে, আমরা কখনো কখনো এক বা দুটি ফটো, কিছু গেম এবং ढের সারি টেক্সট মেসেজ সেভ করতাম। কিন্তু এখন, যেকোনো স্ট্যান্ডার্ড ফোনে অ্যাপ্লিকেশন, ডকুমেন্ট, ফটো, ভিডিও, মিউজিক ফাইল, এবং আরও অনেক কিছুর মিশ্রণ থাকে। চলুন জানি কীভাবে আমরা আমাদের অ্যাপ্লিকেশনের জন্য একটি ডিভাইসের স্টোরেজ স্পেস ব্যবহার করতে পারি।
এই নিবন্ধে আমরা কভার করব:
- Android ফোনের বিভিন্ন ধরনের স্টোরেজ
- স্টোরেজ প্রকারগুলোর মধ্যে পার্থক্য
- আপনার অ্যাপ্লিকেশনে স্টোরেজ কীভাবে ব্যবহার করবেন
প্রতিটি অ্যাপ্লিকেশনের দুটি ভিন্ন ধরনের স্টোরেজে অ্যাক্সেস থাকে: আন্তরিক এবং বাহ্যিক। এই দুটি স্টোরেজ টাইপের মধ্যে বড় পার্থক্য রয়েছে, এবং সেগুলো জানা আপনার পরের অ্যাপ্লিকেশন ডিজাইন করার সময় সাহায্য করবে।
শুরু করার আগে, স্টোরেজ এবং ক্যাশ সম্পর্কে একটা কথা বলতে হবে। স্টোরেজ সেগুলোর জন্য যেগুলো আপনি পরমাণবিকভাবে সংরক্ষণ করতে চান, আর ক্যাশ হল অস্থায়ীভাবে জিনিসগুলো সংরক্ষণ করার জন্য।
আন্তরিক স্টোরেজ
অপারেটিং সিস্টেমে প্রতিটি অ্যাপ্লিকেশন রান হলে, এর নিজস্ব আন্তরিক স্টোরেজ থাকে। এই স্টোরেজ প্রাইভেট এবং শুধু অ্যাপ্লিকেশনের ব্যবহার জন্য। অর্থাৎ, অন্যান্য অ্যাপ্লিকেশন এটি অ্যাক্সেস করতে পারে না, ব্যবহারকারিতাও পারে না। আন্তরিক স্টোরেজ ব্যবহার করার সময় মনে রাখার আরেকটি বিষয় হল এর উপলব্ধতা। বাহ্যিক স্টোরেজের বিপরীতে, আন্তরিক স্টোরেজ আপনার অ্যাপ্লিকেশনের জন্য সবসময় উপলব্ধ থাকে।
এই স্টোরেজ ব্যবহার করার কিছু ড্রব্যাকও আছে। যদি ব্যবহারকারী অ্যাপ্লিকেশনটি আনইনস্টল করে, তবে আপনার অ্যাপের আন্তরিক স্টোরেজে সংরক্ষিত সকল ডেটা সরিয়ে ফেলা হয়। কল্পনা করুন আপনি আপনার ফোনে একটি গেম ইনস্টল করেছেন এবং পথে कहीं যেন আপনি সেটি মুছে ফেলতে সিদ্ধান্ত নেন। আপনি চাইবেন আপনার গেম প্রগ্রেস সেভড থাকে, যদি কখনো আবার আপনি গেমটি ইনস্টল করেন।
তাহলে, আমরা আন্তরিক স্টোরেজে ফাইল কীভাবে সেভ করব?
public void saveFileInternalStorage() { String FILENAME = "hello_world_file"; String inputToFile = "Hello From Internal Storage!"; try { FileOutputStream fileOutputStream = openFileOutput(FILENAME, Context.MODE_PRIVATE); fileOutputStream.write(inputToFile.getBytes()); fileOutputStream.close(); Toast.makeText(getApplicationContext(), "File " + FILENAME + " has been saved successfully", Toast.LENGTH_SHORT).show(); } catch (FileNotFoundException e) { e.printStackTrace(); Toast.makeText(getApplicationContext(), "File " + FILENAME + " has not been saved successfully due to an exception " + e.getLocalizedMessage(), Toast.LENGTH_SHORT).show(); } catch (IOException e) { e.printStackTrace(); Toast.makeText(getApplicationContext(), "File " + FILENAME + " has not been saved successfully due to an exception " + e.getLocalizedMessage(), Toast.LENGTH_SHORT).show(); } }
কোড উদাহরণে আপনি দেখতে পাচ্ছেন, আমরা hello_world_file নামক একটি ফাইল সেভ করছি যাতে টেক্সট থাকে, “Hello From Internal Storage!”। আমি দুটি ক্যাচ ক্লজ তৈরি করেছি শুধু এটি প্রদর্শন করার জন্য যে এই কাজ করার সময় কী কী এক্সেপশন হতে পারে, কিন্তু আপনি সাধারণ Exception অবজেক্ট দিয়ে একটিক্যাচ ক্লজে ছোটিয়ে ফেলতে পারেন।
লক্ষ্য করুন যে openFileOutput মেথডটি ফাইলটি খোলবে যদি সেটি ইতিমধ্যে বিদ্যমান থাকে, কিন্তু যদি না থাকে, তবে সেটি তৈরি করবে। এই মেথডের দ্বিতীয় প্যারামিটার হল ফাইল মোড। এই প্যারামিটার ফাইল স্কোপ এবং এটিতে অ্যাক্সেস ডেজিগনেট করে। ডিফল্ট মান MODE_PRIVATE, যা ফাইলটিকে শুধু আপনার অ্যাপ্লিকেশনের জন্য অ্যাক্সেসযোগ্য করে।
এই প্যারামিটারের অন্যান্য দুটি মান হল MODE_WORLD_READABLE এবং MODE_WORLD_WRITEABLE, কিন্তু API 17 থেকে সেগুলো ডিপ্রিকেটেড। অন্যান্য অ্যাপ্লিকেশনের সাথে প্রাইভেট ফাইল শেয়ারিং একাধিক লজিক ব্যবহার করে যা আপনি এখানে আরও পড়তে পারেন। শেষে, ফাইলে লেখার সময়, আমরা আমাদের স্ট্রিংকে বাইটে কনভার্ট করি এবং ফাইলটি ক্লোজ করতে ভুলি না।
বাহ্যিক স্টোরেজ
নামটি ইঙ্গিত দেয় তার বিপরীতে, এটি সেই স্টোরেজ যা এই ফ্যাক্ট দ্বারা ডিফাইন করা হয় যে এটি সবসময় অ্যাক্সেসযোগ্য নয়। এর মানে এটি একটি এক্সটার্নাল SD কার্ড (সেকেন্ডারি এক্সটার্নাল স্টোরেজ) হতে পারে, কিন্তু এটি ডিভাইসে পাওয়া স্টোরেজও হতে পারে (প্রাইমারি এক্সটার্নাল স্টোরেজ)।
ফ্যাক্টটি হোমে আনার জন্য, বাহ্যিক স্টোরেজ হল সেই স্টোরেজ যা আপনি আপনার ডিভাইস কম্পিউটারের সাথে USB কেবল দিয়ে কানেক্ট করলে অ্যাক্সেস করতে পারেন। আপনি অনুমান করতে পারেন, এই ধরনের স্টোরেজে সংরক্ষিত যেকোনো জিনিস আপনার ডিভাইসের অন্যান্য অ্যাপ্লিকেশনগুলোর জন্য অ্যাক্সেসযোগ্য, কিন্তু অ্যাপ্লিকেশন আনইনস্টল করলে সেটি থাকবে।
বাহ্যিক স্টোরেজে ফাইল সেভ করার প্রদর্শন করার আগে, আমাদের দুটি কাজ করতে হবে:
- নিশ্চিত করুন যে ফাইল সেভ করার জন্য সেখানে পর্যাপ্ত স্পেস আছে
- রানটাইমে পারমিশন চাইুন
पर্যাপ্ত স্টোরেজ স্পেস আছে কিনা নিশ্চিত করতে নিচের কোড লাইনগুলো দরকার:
//Check if you can read/write to external storage public boolean isExternalStorageWritable() { String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) { return true; } return false; }
বাহ্যিক স্টোরেজে অ্যাক্সেস পেতে, আমাদের AndroidManifest.xml-এ নিচের পারমিশন যোগ করতে হবে:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
আরো, যেহেতু API 23, ডেঞ্জারাস পারমিশনগুলো ইনস্টল টাইমে অথরাইজড হয় না, বরং রানটাইমে। বাহ্যিক স্টোরেজে লেখা একটিকে ক্যাটাগরাইজ করা হয়েছে, তাই আমাদের লজিক যোগ করতে হবে যাতে ব্যবহারকারী 決定 করতে পারে অ্যাপ্লিকেশনকে পারমিশন দেবে কিনা।
public void saveFileExternalStorage(View view) { if (isExternalStorageWritable()) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { writeFileToExternalStorage(); } else{ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0); } } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { switch (requestCode) { case 0: { writeFileToExternalStorage(); break; } } }
আমাদের writeFileToExternalStorage নিচের মতো:
public void writeFileToExternalStorage() { String root = Environment.getExternalStorageDirectory().toString(); File myDir = new File(root + "/saved_files"); if (!myDir.exists()) { myDir.mkdirs(); } try { File file = new File(myDir, "myfile.txt"); FileOutputStream out = new FileOutputStream(file); out.write(inputToFile.getBytes()); out.close(); Toast.makeText(getApplicationContext(), "File myfile.txt" + " has been saved successfully to external storage", Toast.LENGTH_SHORT).show(); } catch (Exception e) { e.printStackTrace(); } }
আপনি এখানে উপস্থাপিত সকল কোডের উদাহরণ দেখতে চাইলে, এই GitHub রিপোজিটরিতে যেতে পারেন।
জেনে রাখা ভালো
উপরোক্ত ছিল আপনার অ্যাপ্লিকেশনের জন্য বিভিন্ন ধরনের স্টোরেজের সাথে কীভাবে কাজ করবেন তার দুটি সিম্পল উদাহরণ। যেহেতু আমরা একটি রিসোর্সের সাথে ডील করছি যা সিস্টেম ম্যানেজ করে, আমাদের তার সাথে জড়িত আচরণগুলো সম্পর্কেও সচেতন হওয়া উচিত।
ডিফল্টভাবে, আপনার অ্যাপ্লিকেশন ইন্টার্নাল স্টোরেজে ইনস্টল হবে (internalOnly ব্যাখ্যা দেখুন), কিন্তু API লেভেল 8 থেকে, আপনি আপনার ম্যানিফেস্টে একটি অ্যাট্রিবিউট, installLocation, যোগ করতে পারেন যা আপনার অ্যাপ্লিকেশনকে এক্সটার্নাল স্টোরেজে ইনস্টল হতে দেয়। এটি করার একটি কারণ হল যদি আপনার অ্যাপ্লিকেশন খুব বড় হয়, এবং আপনি পছন্দ করেন ব্যবহারকারী ডিভাইসের বাহ্যিক স্টোরেজে ইনস্টল করুন কারণ সেখানে বেশি স্পেস আছে।
এই অ্যাট্রিবিউটের তিনটি মান রয়েছে:
- auto - মানে আপনার কোনো নির্দিষ্ট পছন্দ নেই অ্যাপ্লিকেশন কোথায় ইনস্টল হবে। অ্যাপ্লিকেশন ইন্টারনাল স্টোরেজে ইনস্টল হওয়ার চেষ্টা করবে, কিন্তু যদি সেটি ফুল থাকে, তবে এক্সটার্নাল স্টোরেজে ইনস্টল করবে
- internalOnly - অ্যাপ্লিকেশন শুধু ইন্টারনাল স্টোরেজে ইনস্টল হবে, এবং যদি সেখানে পর্যাপ্ত স্পেস না থাকে, তবে ইনস্টল হবে না
- preferExternal - মানে আপনি চান আপনার অ্যাপ্লিকেশন এক্সটার্নাল স্টোরেজে ইনস্টল হয়, কিন্তু যদি সেখানে পর্যাপ্ত রুম না থাকে, তবে ইন্টারনালি ইনস্টল হবে
auto এবং preferExternal উভয় অপশনের জন্য, ব্যবহারকারীর অপশন থাকে অ্যাপ্লিকেশন এক্সটার্নাল স্টোরেজ থেকে ইন্টারনালে, এবং বিপরীতমুখী সরানো।
মনে রাখবেন যে একবার ব্যবহারকারী তাদের ডিভাইস কম্পিউটারের সাথে কানেক্ট করলে এবং ডেটা শেয়ার করার জন্য এনেবল করলে বা একটি SD কার্ড আনমাউন্ট করলে, এক্সটার্নাল স্টোরেজ থেকে চলমান সকল অ্যাপ্লিকেশন নষ্ট হয়ে যায়। আপনার অ্যাপ্লিকেশন যদি নিচের ফিচারগুলো ব্যবহার করে, তবে আপনাকে এক্সটার্নাল স্টোরেজে ইনস্টল করা উচিত নয়:
বিভিন্ন সার্ভিস (বিশেষ করে অ্যালার্ম সার্ভিস), ইনপुट মেথড ইঞ্জিন, লাইভ ওয়ালপেপার, অ্যাপ্লিকেশন উইজেট, অ্যাকাউন্ট ম্যানেজার, সিঙ্ক অ্যাডাপ্টার, ডিভাইস অ্যাডমিনিস্ট্রেটর এবং বুট কমপ্লিটেড জন্য লিসেনিং ব্রডকাস্ট রিসিভার।