من خلال جعل تطبيقك أكثر أمانًا، يمكنك المساعدة في الحفاظ على ثقة المستخدمين وسلامة الأجهزة.
تعرض هذه الصفحة العديد من أفضل الممارسات التي لها تأثير إيجابي كبير على أمان تطبيقك.
فرض الاتصال الآمن
عند حماية البيانات التي يتم تبادلها بين تطبيقك والتطبيقات الأخرى، أو بين تطبيقك وموقع إلكتروني، يمكنك تحسين استقرار تطبيقك وحماية البيانات التي ترسلها وتتلقّاها.
حماية الاتصال بين التطبيقات
للتواصل بين التطبيقات بشكل أكثر أمانًا، استخدِم الأهداف الضمنية مع أداة اختيار التطبيقات والأذونات المستندة إلى التوقيع وأدوات توفير المحتوى غير المصدَّرة.
عرض أداة اختيار التطبيقات
إذا كان بإمكان هدف ضمني تشغيل تطبيقَين محتملَين على الأقل على جهاز المستخدم، يجب عرض أداة اختيار التطبيقات بشكل صريح. تتيح استراتيجية التفاعل هذه للمستخدمين نقل المعلومات الحساسة إلى تطبيق يثقون به.
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)
}
Java
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 (مستوى واجهة برمجة التطبيقات 16) أو الإصدارات الأقدم، لأنّ السمة android:exported للعنصر <provider> تكون true تلقائيًا في إصدارات Android هذه.
<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 {
...
}
Java
URL url = new URL("https://www.google.com");
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.connect();
InputStream in = urlConnection.getInputStream();
إضافة إعدادات أمان الشبكة
إذا كان تطبيقك يستخدم مراجع تصديق جديدة أو مخصّصة، يمكنك الإعلان عن إعدادات أمان شبكتك في ملف إعداد. تتيح لك هذه العملية إنشاء الإعدادات بدون تعديل أي رمز برمجي للتطبيق.
لإضافة ملف إعدادات أمان الشبكة إلى تطبيقك، اتّبِع الخطوات التالية:
- يُرجى تعريف الإعدادات في ملف البيان الخاص بتطبيقك:
-
أضِف ملف موارد XML في المسار
res/xml/network_security_config.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) التي تحدث في حال انطباق أحد الشروط التالية على حالة الاستخدام:
- أنت تتواصل مع خادم ويب لديه شهادة موقَّعة من قِبل هيئة إصدار شهادات جديدة أو مخصّصة.
- لا يثق الجهاز الذي تستخدمه بمرجع التصديق هذا.
- لا يمكنك استخدام إعدادات أمان الشبكة.
لمزيد من المعلومات حول كيفية إكمال هذه الخطوات، يمكنك الاطّلاع على المناقشة حول التعامل مع مرجع تصديق غير معروف.
معلومات ذات صلة:
استخدام عناصر WebView بعناية
يجب ألا تسمح عناصر WebView في تطبيقك للمستخدمين بالانتقال إلى مواقع إلكترونية خارج نطاق تحكّمك. استخدِم قائمة مسموح بها كلما أمكن ذلك لتقييد المحتوى الذي يتم تحميله بواسطة عناصر WebView في تطبيقك.
بالإضافة إلى ذلك، لا تفعِّل مطلقًا دعم واجهة JavaScript إلا إذا كنت تتحكّم بشكل كامل في المحتوى في عناصر WebView في تطبيقك وتثق به.
استخدام قنوات رسائل HTML
إذا كان تطبيقك يحتاج إلى استخدام واجهة JavaScript على الأجهزة التي تعمل بنظام التشغيل Android 6.0 (المستوى 23 من واجهة برمجة التطبيقات) والإصدارات الأحدث، استخدِم قنوات رسائل 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"))
Java
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"));
معلومات ذات صلة:
منح الأذونات المناسبة
اطلب فقط الحد الأدنى من الأذونات اللازمة ليعمل تطبيقك بشكل صحيح. وعندما يكون ذلك ممكنًا، تخلَّ عن الأذونات عندما لا يحتاج إليها تطبيقك.
استخدام الأهداف لتأجيل الأذونات
Whenever possible, don't add a permission to your app to complete an action that can be completed in another app. Instead, use an intent to defer the request to a different app that already has the necessary permission.
يوضّح المثال التالي كيفية استخدام نية لتوجيه المستخدمين إلى تطبيق جهات الاتصال بدلاً من طلب إذنَي 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)
}
}
Java
// 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);
}
بالإضافة إلى ذلك، إذا كان تطبيقك بحاجة إلى إجراء عمليات إدخال/إخراج مستندة إلى الملفات، مثل الوصول إلى مساحة التخزين أو اختيار ملف، لن يحتاج إلى أذونات خاصة لأنّ النظام يمكنه إكمال العمليات نيابةً عن تطبيقك. والأفضل من ذلك، بعد أن يختار المستخدم محتوى في معرّف موارد منتظم (URI) معيّن، يحصل تطبيق الاتصال على إذن بالوصول إلى المورد المحدّد.
معلومات ذات صلة:
مشاركة البيانات بأمان بين التطبيقات
اتّبِع أفضل الممارسات التالية لمشاركة محتوى تطبيقك مع تطبيقات أخرى بطريقة أكثر أمانًا:
- فرض أذونات القراءة فقط أو الكتابة فقط حسب الحاجة.
-
يمكنك منح العملاء إذن الوصول إلى البيانات لمرة واحدة باستخدام العلامتَين
FLAG_GRANT_READ_URI_PERMISSIONوFLAG_GRANT_WRITE_URI_PERMISSION. - عند مشاركة البيانات، استخدِم معرّفات الموارد المنتظمة (URI) من النوع
content://، وليس من النوعfile://. وتنفّذ مثيلات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)
}
}
Java
// 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.
لهذا السبب، لا يمكن للتطبيقات غير الموثوق بها التي تستهدف الإصدار 10 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 29) والإصدارات الأحدث استدعاء exec() على الملفات داخل الدليل الرئيسي للتطبيق، بل يمكنها فقط استدعاء الرمز الثنائي المضمّن في ملف APK الخاص بالتطبيق.
بالإضافة إلى ذلك، لا يمكن للتطبيقات التي تستهدف الإصدار 10 من نظام التشغيل 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)
}
Java
// 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"
}
}
Java
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.
}
معلومات ذات صلة:
تخزين البيانات في وحدة تخزين خارجية استنادًا إلى حالة الاستخدام
استخدِم وحدة التخزين الخارجية للملفات الكبيرة غير الحسّاسة الخاصة بتطبيقك، وكذلك الملفات التي يشاركها تطبيقك مع تطبيقات أخرى. تعتمد واجهات برمجة التطبيقات المحددة التي تستخدمها على ما إذا كان تطبيقك مصمّمًا للوصول إلى الملفات الخاصة بالتطبيق أو الوصول إلى الملفات المشتركة.
إذا كان الملف لا يحتوي على معلومات خاصة أو حساسة، ولكنه يقدّم قيمة للمستخدم في تطبيقك فقط، يمكنك تخزين الملف في دليل خاص بالتطبيق على وحدة تخزين خارجية.
إذا كان تطبيقك يحتاج إلى الوصول إلى ملف يوفّر قيمة للتطبيقات الأخرى أو تخزينه، يمكنك استخدام إحدى واجهات برمجة التطبيقات التالية، حسب حالة الاستخدام:
- ملفات الوسائط: لتخزين الصور والملفات الصوتية والفيديوهات التي تتم مشاركتها بين التطبيقات والوصول إليها، استخدِم واجهة برمجة التطبيقات 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) }
}
}
Java
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;
}
استخدام مساحة التخزين الداخلية لبيانات ذاكرة التخزين المؤقت الحسّاسة
لتوفير وصول أسرع إلى بيانات التطبيق، يمكنك تخزينها في ذاكرة التخزين المؤقت للجهاز. بالنسبة إلى ذاكرات التخزين المؤقت التي يبلغ حجمها 1 ميغابايت أو أقل، استخدِم
getCacheDir().
بالنسبة إلى ذاكرة التخزين المؤقت التي يزيد حجمها عن 1 ميغابايت، استخدِم
getExternalCacheDir().
توفّر لك كلتا الطريقتَين عنصر File الذي يحتوي على البيانات المخزّنة مؤقتًا في تطبيقك.
على الرغم من أنّ دليل ذاكرة التخزين المؤقت الداخلية (الذي يوفّره getCacheDir())
خاص بتطبيقك، فإنّ دليل ذاكرة التخزين المؤقت الخارجية ليس كذلك.
يوضّح مقتطف الرمز التالي كيفية تخزين ملف تم تنزيله مؤخرًا في تطبيقك مؤقتًا:
Kotlin
val cacheFile = File(myDownloadedFileUri).let { fileToCache ->
File(cacheDir.path, fileToCache.name)
}
Java
File cacheDir = getCacheDir();
File fileToCache = new File(myDownloadedFileUri);
String fileToCacheName = fileToCache.getName();
File cacheFile = new File(cacheDir.getPath(), fileToCacheName);
ملاحظة: إذا كنت تستخدم
getExternalCacheDir()
لوضع ذاكرة التخزين المؤقت لتطبيقك ضمن مساحة التخزين المشتركة، قد يُخرج المستخدم الوسائط
التي تحتوي على مساحة التخزين هذه أثناء تشغيل تطبيقك. يجب تضمين منطق للتعامل بسلاسة مع عدم توفّر البيانات في ذاكرة التخزين المؤقت بسبب سلوك المستخدم هذا.
تنبيه: لا يتم فرض أي إجراءات أمان على الملفات
في دليل ذاكرة التخزين المؤقت الخارجية.
وبالتالي، فإنّ أي تطبيق يستهدف الإصدار 10 من نظام التشغيل Android (المستوى 29 لواجهة برمجة التطبيقات) أو الإصدارات الأقدم ويحصل على الإذن WRITE_EXTERNAL_STORAGE يمكنه الوصول إلى محتوى ذاكرة التخزين المؤقت هذه.
معلومات ذات صلة: نظرة عامة على تخزين البيانات والملفات
استخدام SharedPreferences في الوضع الخاص
عند استخدام
getSharedPreferences()
لإنشاء عناصر SharedPreferences في تطبيقك أو الوصول إليها،
استخدِم MODE_PRIVATE. بهذه الطريقة، يمكن لتطبيقك فقط
الوصول إلى المعلومات الموجودة في ملف الإعدادات المفضلة المشتركة.
إذا أردت مشاركة البيانات بين التطبيقات، لا تستخدِم عناصر
SharedPreferences. بدلاً من ذلك، اتّبِع الخطوات لمشاركة البيانات بأمان بين التطبيقات.
معلومات ذات صلة:
تحديث الخدمات والتبعيات باستمرار
تستخدم معظم التطبيقات مكتبات خارجية ومعلومات نظام الجهاز لإكمال المهام المتخصصة. من خلال تحديث تبعيات تطبيقك، يمكنك جعل نقاط الاتصال هذه أكثر أمانًا.
التحقّق من مقدّم خدمة الأمان في "خدمات Google Play"
ملاحظة: ينطبق هذا القسم فقط على التطبيقات التي تستهدف الأجهزة التي تم تثبيت خدمات Google Play عليها.
إذا كان تطبيقك يستخدم "خدمات Google Play"، تأكَّد من تحديثها على الجهاز الذي تم تثبيت تطبيقك عليه. يجب إجراء عملية التحقّق بشكل غير متزامن خارج سلسلة واجهة المستخدم. إذا لم يكن الجهاز محدَّثًا، سيظهر خطأ في التفويض.
لتحديد ما إذا كانت "خدمات Google Play" محدَّثة على الجهاز الذي تم تثبيت تطبيقك عليه، اتّبِع الخطوات الواردة في الدليل حول تحديث موفّر الأمان للحماية من ثغرات SSL.
معلومات ذات صلة:
تحديث جميع تبعيات التطبيق
قبل نشر تطبيقك، تأكَّد من أنّ جميع المكتبات وحزم تطوير البرامج (SDK) والتبعيات الأخرى محدَّثة:
- بالنسبة إلى التبعيات التابعة للطرف الأول، مثل حزمة تطوير البرامج (SDK) لنظام التشغيل Android، استخدِم أدوات التحديث المتوفّرة في "استوديو Android"، مثل SDK Manager.
- بالنسبة إلى التبعيات التابعة لجهات خارجية، يُرجى مراجعة المواقع الإلكترونية للمكتبات التي يستخدمها تطبيقك وتثبيت أي تحديثات وتصحيحات برمجية أمنية متاحة.
معلومات ذات صلة: إضافة تبعيات الإصدار
مزيد من المعلومات
لمعرفة المزيد حول كيفية جعل تطبيقك أكثر أمانًا، يُرجى الاطّلاع على المراجع التالية:
- قائمة التحقّق من أمان الجودة الأساسية للتطبيق
- برنامج تحسين أمان التطبيقات
- قناة مطوّرو تطبيقات Android على YouTube
- ميزة "تأكيد آمن لعمليات المُستخدِم على Android": الارتقاء بأمان المعاملات إلى المستوى التالي