আপনার অ্যাপ আরও সুরক্ষিত করার মাধ্যমে, আপনি ব্যবহারকারীর বিশ্বাস ও ডিভাইসের অখণ্ডতা বজায় রাখতে সাহায্য করেন।
এই পৃষ্ঠায় এমন কিছু পেশাদার পদ্ধতি উল্লেখ করা হয়েছে যা আপনার অ্যাপের সুরক্ষার উপর উল্লেখযোগ্য ও ইতিবাচক প্রভাব ফেলে।
নিরাপদ যোগাযোগ এনফোর্স করুন
আপনার অ্যাপ ও অন্যান্য অ্যাপের মধ্যে অথবা আপনার অ্যাপ ও ওয়েবসাইটের মধ্যে আদান-প্রদান করা ডেটা সুরক্ষিত রাখলে, আপনার অ্যাপের স্টেবিলিটি উন্নত হয় এবং আপনার পাঠানো ও পাওয়া ডেটা সুরক্ষিত থাকে।
অ্যাপের মধ্যে কমিউনিকেশন সুরক্ষিত করা
অ্যাপের মধ্যে আরও নিরাপদে যোগাযোগ করতে, অ্যাপ চুজারের সাথে ইমপ্লিসিট ইনটেন্ট, স্বাক্ষর-ভিত্তিক অনুমতি এবং এক্সপোর্ট না করা কন্টেন্ট প্রোভাইডার ব্যবহার করুন।
অ্যাপ বেছে নেওয়ার বিকল্প দেখান
কোনও ইমপ্লিসিট ইনটেন্ট যদি ব্যবহারকারীর ডিভাইসে অন্তত দুটি সম্ভাব্য অ্যাপ চালু করতে পারে, তাহলে এক্সপ্লিসিটভাবে একটি অ্যাপ বেছে নেওয়ার বিকল্প দেখান। এই ইন্টার্যাকশন স্ট্র্যাটেজি ব্যবহারকারীদের তাদের বিশ্বস্ত অ্যাপে সংবেদনশীল তথ্য ট্রান্সফার করতে দেয়।
Kotlin
val intent = Intent(Intent.ACTION_SEND)
val possibleActivitiesList: List<ResolveInfo> =
packageManager.queryIntentActivities(intent, PackageManager.MATCH_ALL)
// Verify that an activity in at least two apps on the user's device
// can handle the intent. Otherwise, start the intent only if an app
// on the user's device can handle the intent.
if (possibleActivitiesList.size > 1) {
// Create intent to show chooser.
// Title is something similar to "Share this photo with."
<b>val chooser = resources.getString(R.string.chooser_title).let { title ->
Intent.createChooser(intent, title)
}
startActivity(chooser)</b>
} else if (intent.resolveActivity(packageManager) != null) {
startActivity(intent)
}
জাভা
Intent intent = new Intent(Intent.ACTION_SEND);
List<ResolveInfo> possibleActivitiesList = getPackageManager()
.queryIntentActivities(intent, PackageManager.MATCH_ALL);
// Verify that an activity in at least two apps on the user's device
// can handle the intent. Otherwise, start the intent only if an app
// on the user's device can handle the intent.
if (possibleActivitiesList.size() > 1) {
// Create intent to show chooser.
// Title is something similar to "Share this photo with."
<b>String title = getResources().getString(R.string.chooser_title);
Intent chooser = Intent.createChooser(intent, title);
startActivity(chooser);</b>
} else if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
সম্পর্কিত তথ্য:
স্বাক্ষর-ভিত্তিক অনুমতি প্রয়োগ করুন
আপনার নিয়ন্ত্রণ বা মালিকানাধীন দুটি অ্যাপের মধ্যে ডেটা শেয়ার করার সময়, স্বাক্ষর-ভিত্তিক অনুমতি ব্যবহার করুন। এইসব অনুমতির জন্য ব্যবহারকারীর কনফার্মেশনের প্রয়োজন হয় না, পরিবর্তে এটি চেক করে যে ডেটা অ্যাক্সেস করা অ্যাপ একই সাইনিং কী ব্যবহার করে সাইন-ইন করছে কিনা। তাই, এইসব অনুমতি আরও স্ট্রিমলাইন করা, নিরাপদ ব্যবহারকারীর অভিজ্ঞতা প্রদান করে।
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp"> <permission android:name="my_custom_permission_name" android:protectionLevel="signature" />
সম্পর্কিত তথ্য:
আপনার অ্যাপের কন্টেন্ট প্রোভাইডারদের অ্যাক্সেস করার অনুমতি দেবেন না
আপনার অ্যাপ থেকে অন্য কোনও অ্যাপে ডেটা পাঠানোর ইচ্ছা না থাকলে, অন্যান্য ডেভেলপারের অ্যাপকে আপনার অ্যাপের ContentProvider
অবজেক্ট অ্যাক্সেস করার অনুমতি দেবেন না। আপনার অ্যাপ Android 4.1.1 (API লেভেল ১৬) বা তার আগের ভার্সনে চলা ডিভাইসে ইনস্টল করা গেলে, এই
সেটিং বিশেষভাবে গুরুত্বপূর্ণ, কারণ Android-এর এইসব ভার্সনে
<provider>
এলিমেন্টের
android:exported
অ্যাট্রিবিউট ডিফল্ট হিসেবে true থাকে।
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp"> <application ... > <provider android:name="androidx.core.content.FileProvider" android:authorities="com.example.myapp.fileprovider" ... android:exported="false"> <!-- Place child elements of <provider> here. --> </provider> ... </application> </manifest>
সংবেদনশীল তথ্য দেখানোর আগে ক্রেডেনশিয়াল চাওয়া
ব্যবহারকারী যাতে আপনার অ্যাপে সংবেদনশীল তথ্য বা প্রিমিয়াম কন্টেন্ট অ্যাক্সেস করতে পারেন, তার জন্য ক্রেডেনশিয়াল সংক্রান্ত অনুরোধ করার সময়, পিন/পাসওয়ার্ড/প্যাটার্ন অথবা বায়োমেট্রিক ক্রেডেনশিয়াল, যেমন ফেস রেকগনিশন বা ফিঙ্গারপ্রিন্ট রেকগনিশন সংক্রান্ত অনুরোধ করুন।
বায়োমেট্রিক ক্রেডেনশিয়ালের জন্য কীভাবে অনুরোধ করবেন সেই সম্পর্কে আরও জানতে, বায়োমেট্রিক যাচাইকরণ সম্পর্কিত গাইড দেখুন।
নেটওয়ার্ক সুরক্ষা সংক্রান্ত ব্যবস্থা প্রয়োগ করা
নিম্নলিখিত বিভাগগুলি বর্ণনা করে যে আপনি কীভাবে আপনার অ্যাপের নেটওয়ার্ক নিরাপত্তা উন্নত করতে পারেন।
TLS ট্রাফিক ব্যবহার করুন
আপনার অ্যাপ যদি এমন কোনও ওয়েব সার্ভারের সাথে যোগাযোগ করে যার সার্টিফিকেট কোনও সুপরিচিত, বিশ্বস্ত সার্টিফিকেট অথরিটি (CA) ইস্যু করেছে, তাহলে নিম্নলিখিত HTTPS অনুরোধের মতো অনুরোধ ব্যবহার করুন:
Kotlin
val url = URL("https://www.google.com")
val urlConnection = url.openConnection() as HttpsURLConnection
urlConnection.connect()
urlConnection.inputStream.use {
...
}
জাভা
URL url = new URL("https://www.google.com");
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.connect();
InputStream in = urlConnection.getInputStream();
নেটওয়ার্ক সুরক্ষা কনফিগারেশন যোগ করা
আপনার অ্যাপ নতুন বা কাস্টম CA ব্যবহার করলে, আপনি কনফিগারেশন ফাইলে আপনার নেটওয়ার্কের নিরাপত্তা সেটিংস ঘোষণা করতে পারবেন। এই প্রসেস আপনাকে কোনও অ্যাপ কোড পরিবর্তন না করেই কনফিগারেশন তৈরি করতে দেয়।
আপনার অ্যাপে নেটওয়ার্ক সুরক্ষা কনফিগারেশন ফাইল যোগ করতে, এই ধাপগুলি অনুসরণ করুন:
- আপনার অ্যাপের ম্যানিফেস্টে কনফিগারেশন ঘোষণা করুন:
-
res/xml/network_security_config.xml-এ অবস্থিত একটি XML রিসোর্স ফাইল যোগ করুন।ক্লিয়ার-টেক্সট বন্ধ করে দিয়ে নির্দিষ্ট ডোমেনে সব ট্রাফিককে HTTPS ব্যবহার করতে বাধ্য করুন:
<network-security-config> <domain-config cleartextTrafficPermitted="false"> <domain includeSubdomains="true">secure.example.com</domain> ... </domain-config> </network-security-config>
ডেভেলপমেন্ট প্রসেস চলাকালীন, ব্যবহারকারীর ইনস্টল করা সার্টিফিকেট স্পষ্টভাবে অনুমোদন করতে আপনি
<debug-overrides>এলিমেন্ট ব্যবহার করতে পারবেন। এই এলিমেন্টটি অ্যাপের রিলিজ কনফিগারেশনকে প্রভাবিত না করেই ডিবাগিং এবং টেস্টিংয়ের সময় আপনার অ্যাপের নিরাপত্তা-গুরুত্বপূর্ণ বিকল্পগুলিকে ওভাররাইড করে। আপনার অ্যাপের নেটওয়ার্ক সুরক্ষা কনফিগারেশন XML ফাইলে কীভাবে এই এলিমেন্টটি সংজ্ঞায়িত করবেন তা নিম্নলিখিত স্নিপেট থেকে জানতে পারবেন:<network-security-config> <debug-overrides> <trust-anchors> <certificates src="user" /> </trust-anchors> </debug-overrides> </network-security-config>
<manifest ... > <application android:networkSecurityConfig="@xml/network_security_config" ... > <!-- Place child elements of <application> element here. --> </application> </manifest>
সম্পর্কিত তথ্য: নেটওয়ার্ক সুরক্ষা কনফিগারেশন
আপনার নিজস্ব ট্রাস্ট ম্যানেজার তৈরি করুন
আপনার TLS চেকার যেন সব সার্টিফিকেট গ্রহণ না করে। আপনার ব্যবহারের ক্ষেত্রে নিম্নলিখিত শর্তগুলির মধ্যে একটি প্রযোজ্য হলে, আপনাকে একটি ট্রাস্ট ম্যানেজার সেট-আপ করতে হতে পারে এবং TLS সংক্রান্ত সমস্ত সতর্কতা ম্যানেজ করতে হতে পারে:
- আপনি এমন একটি ওয়েব সার্ভারের সাথে যোগাযোগ করছেন যার সার্টিফিকেট নতুন বা কাস্টম CA দ্বারা স্বাক্ষরিত।
- আপনি যে ডিভাইস ব্যবহার করছেন সেটি এই CA-কে বিশ্বাস করে না।
- আপনি নেটওয়ার্ক সুরক্ষা কনফিগারেশন ব্যবহার করতে পারবেন না।
এইসব ধাপ কীভাবে সম্পূর্ণ করবেন সেই সম্পর্কে আরও জানতে, অজানা সার্টিফিকেট অথরিটি ম্যানেজ করা সংক্রান্ত আলোচনা দেখুন।
সম্পর্কিত তথ্য:
WebView অবজেক্ট সাবধানে ব্যবহার করুন
WebView
আপনার অ্যাপের অবজেক্ট ব্যবহারকারীদের এমন সাইটে নেভিগেট করতে দেবে না যা আপনার
নিয়ন্ত্রণের বাইরে। সম্ভব হলে, আপনার অ্যাপের WebView অবজেক্টের মাধ্যমে লোড করা কন্টেন্ট সীমাবদ্ধ করতে
একটি অনুমোদিত তালিকা ব্যবহার করুন।
এছাড়াও, আপনার অ্যাপের WebView অবজেক্টে থাকা কন্টেন্ট সম্পূর্ণভাবে নিয়ন্ত্রণ ও বিশ্বাস না করলে, কখনও
জাভাস্ক্রিপ্ট ইন্টারফেস
সহায়তা চালু করবেন না।
HTML মেসেজ চ্যানেল ব্যবহার করা
আপনার অ্যাপকে যদি Android 6.0 (API লেভেল 23) এবং তার পরবর্তী যেকোনও ভার্সনে চলা ডিভাইসে JavaScript ইন্টারফেস সাপোর্ট ব্যবহার করতে হয়, তাহলে ওয়েবসাইট এবং আপনার অ্যাপের মধ্যে যোগাযোগ করার পরিবর্তে HTML মেসেজ চ্যানেল ব্যবহার করুন, যেমনটি নিম্নলিখিত কোড স্নিপেটে দেখানো হয়েছে:
Kotlin
val myWebView: WebView = findViewById(R.id.webview)
// channel[0] and channel[1] represent the two ports.
// They are already entangled with each other and have been started.
val channel: Array<out WebMessagePort> = myWebView.createWebMessageChannel()
// Create handler for channel[0] to receive messages.
channel[0].setWebMessageCallback(object : WebMessagePort.WebMessageCallback() {
override fun onMessage(port: WebMessagePort, message: WebMessage) {
Log.d(TAG, "On port $port, received this message: $message")
}
})
// Send a message from channel[1] to channel[0].
channel[1].postMessage(WebMessage("My secure message"))
জাভা
WebView myWebView = (WebView) findViewById(R.id.webview);
// channel[0] and channel[1] represent the two ports.
// They are already entangled with each other and have been started.
WebMessagePort[] channel = myWebView.createWebMessageChannel();
// Create handler for channel[0] to receive messages.
channel[0].setWebMessageCallback(new WebMessagePort.WebMessageCallback() {
@Override
public void onMessage(WebMessagePort port, WebMessage message) {
Log.d(TAG, "On port " + port + ", received this message: " + message);
}
});
// Send a message from channel[1] to channel[0].
channel[1].postMessage(new WebMessage("My secure message"));
সম্পর্কিত তথ্য:
সঠিক অনুমতি দিন
আপনার অ্যাপ যাতে সঠিকভাবে কাজ করতে পারে তার জন্য প্রয়োজনীয় অনুমতির ন্যূনতম সংখ্যা অনুরোধ করুন। সম্ভব হলে, আপনার অ্যাপের আর প্রয়োজন না থাকলে অনুমতি প্রত্যাহার করুন।
অনুমতি স্থগিত রাখতে ইনটেন্ট ব্যবহার করা
যখনই সম্ভব, অন্য অ্যাপে সম্পূর্ণ করা যেতে পারে এমন কোনও অ্যাকশন সম্পূর্ণ করার জন্য আপনার অ্যাপে অনুমতি যোগ করবেন না। এর পরিবর্তে, প্রয়োজনীয় অনুমতি আগে থেকেই আছে এমন একটি ভিন্ন অ্যাপে অনুরোধটি স্থগিত করার জন্য একটি ইনটেন্ট ব্যবহার করুন।
নিম্নলিখিত উদাহরণে দেখানো হয়েছে যে কীভাবে ইনটেন্ট ব্যবহার করে ব্যবহারকারীকে
READ_CONTACTS এবং
WRITE_CONTACTS অনুমতির অনুরোধ করার পরিবর্তে পরিচিতি অ্যাপে ডাইরেক্ট করা যায়:
Kotlin
// Delegates the responsibility of creating the contact to a contacts app,
// which has already been granted the appropriate WRITE_CONTACTS permission.
Intent(Intent.ACTION_INSERT).apply {
type = ContactsContract.Contacts.CONTENT_TYPE
}.also { intent ->
// Make sure that the user has a contacts app installed on their device.
intent.resolveActivity(packageManager)?.run {
startActivity(intent)
}
}
জাভা
// Delegates the responsibility of creating the contact to a contacts app,
// which has already been granted the appropriate WRITE_CONTACTS permission.
Intent insertContactIntent = new Intent(Intent.ACTION_INSERT);
insertContactIntent.setType(ContactsContract.Contacts.CONTENT_TYPE);
// Make sure that the user has a contacts app installed on their device.
if (insertContactIntent.resolveActivity(getPackageManager()) != null) {
startActivity(insertContactIntent);
}
এছাড়াও, আপনার অ্যাপকে ফাইল-ভিত্তিক I/O—যেমন স্টোরেজ অ্যাক্সেস করা বা ফাইল বেছে নেওয়ার মতো কাজ করতে হলে—এটির জন্য বিশেষ অনুমতির প্রয়োজন হয় না কারণ সিস্টেম আপনার অ্যাপের হয়ে অপারেশন সম্পূর্ণ করতে পারে। আরও ভাল হয়, ব্যবহারকারী কোনও নির্দিষ্ট URI-তে কন্টেন্ট বেছে নেওয়ার পরে, কলিং অ্যাপ বেছে নেওয়া রিসোর্সের জন্য অনুমতি পেয়ে যায়।
সম্পর্কিত তথ্য:
বিভিন্ন অ্যাপ জুড়ে নিরাপদে ডেটা শেয়ার করুন
আরও সুরক্ষিতভাবে অন্যান্য অ্যাপের সাথে আপনার অ্যাপের কন্টেন্ট শেয়ার করতে, এইসব পেশাদার পদ্ধতি অনুসরণ করুন:
- প্রয়োজন অনুযায়ী শুধু-পড়ার বা শুধু-লেখার অনুমতি প্রয়োগ করুন।
-
FLAG_GRANT_READ_URI_PERMISSIONএবংFLAG_GRANT_WRITE_URI_PERMISSIONফ্ল্যাগ ব্যবহার করে ক্লায়েন্টকে ডেটার এককালীন অ্যাক্সেস দিন। - ডেটা শেয়ার করার সময়,
content://URI ব্যবহার করুন,file://URI নয়।FileProvider-এর ইনস্ট্যান্স আপনার জন্য এটি করে।
নিম্নলিখিত কোড স্নিপেট দেখায় যে কীভাবে URI অনুমতি গ্র্যান্ট ফ্ল্যাগ এবং কন্টেন্ট প্রোভাইডার অনুমতি ব্যবহার করে আলাদা PDF ভিউয়ার অ্যাপে কোনও অ্যাপের PDF ফাইল দেখানো যায়:
Kotlin
// Create an Intent to launch a PDF viewer for a file owned by this app.
Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse("<b>content:</b>//com.example/personal-info.pdf")
// This flag gives the started app read access to the file.
<b>addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)</b>
}.also { intent ->
// Make sure that the user has a PDF viewer app installed on their device.
intent.resolveActivity(packageManager)?.run {
startActivity(intent)
}
}
জাভা
// Create an Intent to launch a PDF viewer for a file owned by this app.
Intent viewPdfIntent = new Intent(Intent.ACTION_VIEW);
viewPdfIntent.setData(Uri.parse("<b>content://</b>com.example/personal-info.pdf"));
// This flag gives the started app read access to the file.
<b>viewPdfIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);</b>
// Make sure that the user has a PDF viewer app installed on their device.
if (viewPdfIntent.resolveActivity(getPackageManager()) != null) {
startActivity(viewPdfIntent);
}
মনে রাখবেন: রাইটেবল অ্যাপ হোম ডিরেক্টরি থেকে ফাইল এক্সিকিউট করা হল
W^X লঙ্ঘন।
এই কারণে, Android 10 (API লেভেল ২৯) এবং তার চেয়ে উন্নত ভার্সনকে টার্গেট করা, ভরসাযোগ্য নয় এমন অ্যাপ,
অ্যাপের হোম ডিরেক্টরির মধ্যে থাকা ফাইলের উপর exec() প্রয়োগ করতে পারে না, শুধুমাত্র
অ্যাপের APK ফাইলের মধ্যে এম্বেড করা বাইনারি কোডের উপর তা প্রয়োগ করতে পারে।
এছাড়াও, Android ১০ ও তার পরবর্তী ভার্সনকে টার্গেট করা অ্যাপ, মেমরিতে, dlopen()-এর মাধ্যমে খোলা ফাইল থেকে এক্সিকিউটেবল কোড
পরিবর্তন করতে পারে না। এর মধ্যে টেক্সট রিলোকেশন সহ যেকোনও শেয়ার করা অবজেক্ট (.so) ফাইল
অন্তর্ভুক্ত।
সম্পর্কিত তথ্য:
android:grantUriPermissions
নিরাপদে ডেটা স্টোর করা
আপনার অ্যাপের ব্যবহারকারীর সংবেদনশীল তথ্য অ্যাক্সেস করার প্রয়োজন হতে পারে, তবে ব্যবহারকারীরা আপনার অ্যাপকে তাদের ডেটা অ্যাক্সেস করার অনুমতি তখনই দেন যখন তারা বিশ্বাস করেন যে আপনি তাদের ডেটা সঠিকভাবে সুরক্ষিত রাখবেন।
ইন্টার্নাল স্টোরেজে ব্যক্তিগত ডেটা স্টোর করুন
ব্যবহারকারীর সব ব্যক্তিগত ডেটা ডিভাইসের ইন্টার্নাল স্টোরেজে সেভ করুন, যা প্রতিটি অ্যাপের জন্য স্যান্ডবক্স করা থাকে। এইসব ফাইল দেখার জন্য আপনার অ্যাপকে অনুমতি চাইতে হয় না এবং অন্যান্য অ্যাপ এইসব ফাইল অ্যাক্সেস করতে পারে না। অতিরিক্ত নিরাপত্তা ব্যবস্থা হিসেবে, ব্যবহারকারী কোনও অ্যাপ আনইনস্টল করলে, ইন্টার্নাল স্টোরেজে অ্যাপের সেভ করা সব ফাইল ডিভাইস মুছে দেয়।
নিম্নলিখিত কোড স্নিপেট ইন্টার্নাল স্টোরেজে ডেটা লেখার একটি উপায় দেখায়:
Kotlin
// Creates a file with this name, or replaces an existing file
// that has the same name. Note that the file name cannot contain
// path separators.
val FILE_NAME = "sensitive_info.txt"
val fileContents = "This is some top-secret information!"
File(filesDir, FILE_NAME).bufferedWriter().use { writer ->
writer.write(fileContents)
}
জাভা
// Creates a file with this name, or replaces an existing file
// that has the same name. Note that the file name cannot contain
// path separators.
final String FILE_NAME = "sensitive_info.txt";
String fileContents = "This is some top-secret information!";
try (BufferedWriter writer =
new BufferedWriter(new FileWriter(new File(getFilesDir(), FILE_NAME)))) {
writer.write(fileContents);
} catch (IOException e) {
// Handle exception.
}
নিম্নলিখিত কোড স্নিপেট বিপরীত অপারেশন দেখায়, ইন্টার্নাল স্টোরেজ থেকে ডেটা রিড করে:
Kotlin
val FILE_NAME = "sensitive_info.txt"
val contents = File(filesDir, FILE_NAME).bufferedReader().useLines { lines ->
lines.fold("") { working, line ->
"$working\n$line"
}
}
জাভা
final String FILE_NAME = "sensitive_info.txt";
StringBuffer stringBuffer = new StringBuffer();
try (BufferedReader reader =
new BufferedReader(new FileReader(new File(getFilesDir(), FILE_NAME)))) {
String line = reader.readLine();
while (line != null) {
stringBuffer.append(line).append('\n');
line = reader.readLine();
}
} catch (IOException e) {
// Handle exception.
}
সম্পর্কিত তথ্য:
ব্যবহারের উপর ভিত্তি করে এক্সটার্নাল স্টোরেজে ডেটা স্টোর করুন
আপনার অ্যাপের জন্য নির্দিষ্ট বড়, সংবেদনশীল নয় এমন ফাইল এবং আপনার অ্যাপ অন্যান্য অ্যাপের সাথে শেয়ার করে এমন ফাইলের জন্য এক্সটার্নাল স্টোরেজ ব্যবহার করুন। আপনি কোন নির্দিষ্ট API ব্যবহার করবেন তা নির্ভর করে আপনার অ্যাপটি অ্যাপ-নির্দিষ্ট ফাইল অ্যাক্সেস করার জন্য ডিজাইন করা হয়েছে নাকি শেয়ার করা ফাইল অ্যাক্সেস করার জন্য ডিজাইন করা হয়েছে তার উপর।
কোনও ফাইলে ব্যক্তিগত বা সংবেদনশীল তথ্য না থাকলে, কিন্তু শুধুমাত্র আপনার অ্যাপে ব্যবহারকারীর জন্য ভ্যালু প্রদান করলে, ফাইলটি এক্সটার্নাল স্টোরেজে অ্যাপ-নির্দিষ্ট ডিরেক্টরিতে স্টোর করুন।
আপনার অ্যাপকে যদি এমন কোনও ফাইল অ্যাক্সেস বা স্টোর করতে হয় যা অন্য অ্যাপের জন্য গুরুত্বপূর্ণ, তাহলে আপনার ব্যবহারের উপর নির্ভর করে নিম্নলিখিত API-এর মধ্যে কোনও একটি ব্যবহার করুন:
- মিডিয়া ফাইল: অ্যাপের মধ্যে শেয়ার করা ছবি, অডিও ফাইল ও ভিডিও স্টোর ও অ্যাক্সেস করতে, Media Store API ব্যবহার করুন।
- অন্যান্য ফাইল: ডাউনলোড করা ফাইল সহ অন্যান্য ধরনের শেয়ার করা ফাইল স্টোর ও অ্যাক্সেস করতে, Storage Access Framework ব্যবহার করুন।
স্টোরেজ ভলিউমের উপলভ্যতা চেক করা
আপনার অ্যাপ যদি কোনও এক্সটার্নাল স্টোরেজ ডিভাইসের সাথে ইন্টার্যাক্ট করে, তাহলে মনে রাখবেন যে আপনার অ্যাপ সেটি অ্যাক্সেস করার চেষ্টা করার সময় ব্যবহারকারী স্টোরেজ ডিভাইসটি সরিয়ে ফেলতে পারেন। স্টোরেজ ডিভাইস উপলভ্য আছে কিনা তা যাচাই করার জন্য লজিক অন্তর্ভুক্ত করুন।
ডেটার বৈধতা চেক করা
আপনার অ্যাপ এক্সটার্নাল স্টোরেজ থেকে ডেটা ব্যবহার করলে, ডেটার কন্টেন্ট খারাপ বা পরিবর্তন করা হয়নি তা নিশ্চিত করুন। যেসব ফাইল আর স্টেবল ফর্ম্যাটে নেই, সেগুলি ম্যানেজ করার জন্য লজিক অন্তর্ভুক্ত করুন।
নিম্নলিখিত কোড স্নিপেটে হ্যাশ যাচাইকারীর উদাহরণ অন্তর্ভুক্ত আছে:
Kotlin
val hash = calculateHash(stream)
// Store "expectedHash" in a secure location.
if (hash == <var>expectedHash</var>) {
// Work with the content.
}
// Calculating the hash code can take quite a bit of time, so it shouldn't
// be done on the main thread.
suspend fun calculateHash(stream: InputStream): String {
return withContext(Dispatchers.IO) {
val digest = MessageDigest.getInstance("SHA-512")
val digestStream = DigestInputStream(stream, digest)
while (digestStream.read() != -1) {
// The DigestInputStream does the work; nothing for us to do.
}
digest.digest().joinToString(":") { "%02x".format(it) }
}
}
জাভা
Executor threadPoolExecutor = Executors.newFixedThreadPool(4);
private interface HashCallback {
void onHashCalculated(@Nullable String hash);
}
boolean hashRunning = calculateHash(inputStream, threadPoolExecutor, hash -> {
if (Objects.equals(hash, <var>expectedHash</var>)) {
// Work with the content.
}
});
if (!hashRunning) {
// There was an error setting up the hash function.
}
private boolean calculateHash(@NonNull InputStream stream,
@NonNull Executor executor,
@NonNull HashCallback hashCallback) {
final MessageDigest digest;
try {
digest = MessageDigest.getInstance("SHA-512");
} catch (NoSuchAlgorithmException nsa) {
return false;
}
// Calculating the hash code can take quite a bit of time, so it shouldn't
// be done on the main thread.
executor.execute(() -> {
String hash;
try (DigestInputStream digestStream =
new DigestInputStream(stream, digest)) {
while (digestStream.read() != -1) {
// The DigestInputStream does the work; nothing for us to do.
}
StringBuilder builder = new StringBuilder();
for (byte aByte : digest.digest()) {
builder.append(String.format("%02x", aByte)).append(':');
}
hash = builder.substring(0, builder.length() - 1);
} catch (IOException e) {
hash = null;
}
final String calculatedHash = hash;
runOnUiThread(() -> hashCallback.onHashCalculated(calculatedHash));
});
return true;
}
সংবেদনশীল ক্যাশে ডেটার জন্য ইন্টার্নাল স্টোরেজ ব্যবহার করুন
অ্যাপ ডেটায় আরও দ্রুত অ্যাক্সেস দিতে, ডিভাইসের ক্যাশেতে
এটি স্টোর করুন। ১ এমবি বা তার চেয়ে ছোট ক্যাশের জন্য, getCacheDir() ব্যবহার করুন।
১ এমবির চেয়ে বড় ক্যাশের জন্য, getExternalCacheDir() ব্যবহার করুন।
দুটি পদ্ধতিই আপনাকে
File অবজেক্ট প্রদান করে যাতে
আপনার অ্যাপের ক্যাশে করা ডেটা থাকে।
ইন্টার্নাল ক্যাশে ডিরেক্টরি (getCacheDir()-এর মাধ্যমে প্রদান করা)
আপনার অ্যাপের জন্য ব্যক্তিগত হলেও, এক্সটার্নাল ক্যাশে ডিরেক্টরি তা নয়।
আপনার অ্যাপ সম্প্রতি ডাউনলোড করেছে এমন ফাইল কীভাবে ক্যাশে করবেন তা নিম্নলিখিত কোড স্নিপেট থেকে জানতে পারবেন:
Kotlin
val cacheFile = File(myDownloadedFileUri).let { fileToCache ->
File(cacheDir.path, fileToCache.name)
}
জাভা
File cacheDir = getCacheDir();
File fileToCache = new File(myDownloadedFileUri);
String fileToCacheName = fileToCache.getName();
File cacheFile = new File(cacheDir.getPath(), fileToCacheName);
মনে রাখবেন: আপনি যদি শেয়ার করা স্টোরেজের মধ্যে অ্যাপের ক্যাশে রাখার জন্য
getExternalCacheDir() ব্যবহার করেন, তাহলে আপনার অ্যাপ চলাকালীন ব্যবহারকারী এই স্টোরেজ
সহ মিডিয়া ইজেক্ট করতে পারেন। ব্যবহারকারীর এই আচরণের কারণে
ক্যাশে মিস হওয়ার ঘটনাটি সুন্দরভাবে ম্যানেজ করার জন্য লজিক অন্তর্ভুক্ত করুন।
সতর্কতা: এক্সটার্নাল ক্যাশে ডিরেক্টরি-তে
থাকা ফাইলের ক্ষেত্রে কোনও নিরাপত্তা এনফোর্স করা হয় না।
তাই, Android 10 (API লেভেল ২৯) বা তার আগের ভার্সনকে টার্গেট করে এবং
WRITE_EXTERNAL_STORAGE অনুমতি আছে এমন যেকোনও অ্যাপ
এই ক্যাশের কন্টেন্ট অ্যাক্সেস করতে পারে।
সম্পর্কিত তথ্য: ডেটা ও ফাইল স্টোরেজ ওভারভিউ
ব্যক্তিগত মোডে SharedPreferences ব্যবহার করুন
আপনার অ্যাপের SharedPreferences অবজেক্ট
তৈরি বা অ্যাক্সেস করতে
getSharedPreferences() ব্যবহার করার সময়,
MODE_PRIVATE ব্যবহার করুন। এইভাবে, শুধুমাত্র আপনার অ্যাপই
শেয়ার করা প্রেফারেন্স ফাইলের মধ্যে থাকা তথ্য অ্যাক্সেস করতে পারবে।
আপনি যদি বিভিন্ন অ্যাপ জুড়ে ডেটা শেয়ার করতে চান, তাহলে
SharedPreferences
অবজেক্ট ব্যবহার করবেন না। পরিবর্তে, বিভিন্ন অ্যাপ জুড়ে নিরাপদে ডেটা শেয়ার
করতে ধাপগুলি অনুসরণ করুন।
সম্পর্কিত তথ্য:
পরিষেবা ও ডিপেন্ডেন্সি আপ-টু-ডেট রাখুন
বেশিরভাগ অ্যাপ বিশেষ কাজ সম্পূর্ণ করতে এক্সটার্নাল লাইব্রেরি ও ডিভাইস সিস্টেমের তথ্য ব্যবহার করে। আপনার অ্যাপের ডিপেন্ডেন্সি আপ-টু-ডেট রাখার মাধ্যমে, আপনি যোগাযোগের এই পয়েন্টগুলি আরও সুরক্ষিত করেন।
Google Play পরিষেবার নিরাপত্তা প্রদানকারী চেক করুন
মনে রাখবেন: এই বিভাগটি শুধুমাত্র সেইসব অ্যাপের ক্ষেত্রে প্রযোজ্য যেগুলি এমন ডিভাইসকে টার্গেট করে যেখানে Google Play পরিষেবা ইনস্টল করা আছে।
আপনার অ্যাপ Google Play পরিষেবা ব্যবহার করলে, যে ডিভাইসে আপনার অ্যাপ ইনস্টল করা আছে সেখানে এটি আপডেট করা আছে কিনা তা নিশ্চিত করুন। UI থ্রেড থেকে, অ্যাসিঙ্ক্রোনাসভাবে চেক করুন। ডিভাইস আপ-টু-ডেট না থাকলে, অনুমোদন সংক্রান্ত সমস্যা ট্রিগার করুন।
আপনার অ্যাপ ইনস্টল করা ডিভাইসে Google Play পরিষেবা আপ-টু-ডেট আছে কিনা তা নির্ধারণ করতে, SSL এক্সপ্লয়েট থেকে সুরক্ষিত রাখতে আপনার নিরাপত্তা প্রদানকারী আপডেট করা সংক্রান্ত গাইডের ধাপগুলি অনুসরণ করুন।
সম্পর্কিত তথ্য:
সব অ্যাপ ডিপেন্ডেন্সি আপডেট করুন
আপনার অ্যাপ ডিপ্লয় করার আগে, সব লাইব্রেরি, SDK ও অন্যান্য ডিপেন্ডেন্সি আপ-টু-ডেট আছে কিনা তা দেখে নিন:
- Android SDK-এর মতো ফার্স্ট-পার্টি ডিপেন্ডেন্সির জন্য, Android Studio-তে থাকা আপডেট করার টুল ব্যবহার করুন, যেমন SDK Manager।
- থার্ড-পার্টি নির্ভরতার জন্য, আপনার অ্যাপ ব্যবহার করে এমন লাইব্রেরির ওয়েবসাইট চেক করুন এবং উপলভ্য যেকোনও আপডেট ও নিরাপত্তা প্যাচ ইনস্টল করুন।
সম্পর্কিত তথ্য: বিল্ড ডিপেন্ডেন্সি যোগ করুন
আরও তথ্য
আপনার অ্যাপ কীভাবে আরও সুরক্ষিত করবেন সেই সম্পর্কে আরও জানতে, নিম্নলিখিত রিসোর্স দেখুন:
- মূল অ্যাপের কোয়ালিটি নিরাপত্তা চেকলিস্ট
- অ্যাপ সুরক্ষা ইমপ্রুভমেন্ট প্রোগ্রাম
- YouTube-এ Android Developers চ্যানেল
- Android প্রোটেক্টেড কনফার্মেশন: ট্রানজ্যাকশন সংক্রান্ত সুরক্ষাকে পরবর্তী লেভেলে নিয়ে যাওয়া