رقم الإصدار في صفحة About كان مكتوباً بشكل يدوي (hard-coded) ولا يتحدث تلقائياً عند تغيير رقم الإصدار في build.gradle.
val appVersion = "1.0.0" // Hard-coded for now, can be replaced with BuildConfig.VERSION_NAME when available- ❌ يجب تحديث الرقم يدوياً في كل إصدار
- ❌ احتمالية النسيان وعرض رقم خاطئ
- ❌ عدم التزامن مع
build.gradle - ❌ صعوبة الصيانة
val context = LocalContext.current
val uriHandler = LocalUriHandler.current
// Get version info from BuildConfig (automatically updated from build.gradle)
val appVersion = try {
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
packageInfo.versionName ?: BuildConfig.VERSION_NAME
} catch (e: Exception) {
BuildConfig.VERSION_NAME // Fallback to BuildConfig
}val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
packageInfo.versionName- يقرأ رقم الإصدار من
AndroidManifest.xmlالمدمج في APK - هذا هو الرقم الفعلي الذي يراه المستخدمون في متجر التطبيقات
- الأكثر دقة لأنه يعكس الـ APK المثبت فعلياً
BuildConfig.VERSION_NAME- يتم توليده تلقائياً من
build.gradleأثناء البناء - يُستخدم كـ fallback إذا فشل قراءة PackageInfo
- مضمون الوجود دائماً
try {
// محاولة قراءة من PackageManager
} catch (e: Exception) {
// استخدام BuildConfig كـ fallback
}عند تغيير رقم الإصدار في build.gradle:
versionCode 3
versionName "1.0.2"سيظهر تلقائياً في صفحة About بدون أي تعديل على الكود!
- يقرأ من APK المثبت فعلياً
- لا يمكن أن يكون غير متزامن
- يعكس الحقيقة دائماً
- إذا فشل PackageManager → يستخدم BuildConfig
- إذا فشل BuildConfig → يستخدم قيمة افتراضية
- لن يتعطل التطبيق أبداً
- لا حاجة لتذكر تحديث الرقم
- مكان واحد للتحديث (
build.gradle) - أقل احتمالية للأخطاء البشرية
import androidx.compose.ui.platform.LocalContext
import com.dxbmark.nfcmanager.BuildConfig// قبل
val appVersion = "1.0.0"
// بعد
val context = LocalContext.current
val appVersion = try {
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
packageInfo.versionName ?: BuildConfig.VERSION_NAME
} catch (e: Exception) {
BuildConfig.VERSION_NAME
}✅ فتح صفحة About
✅ التحقق من عرض رقم الإصدار الصحيح
✅ مطابقة الرقم مع build.gradle
✅ تحديث versionName في build.gradle
✅ بناء APK جديد
✅ تثبيت APK
✅ فتح صفحة About
✅ التحقق من عرض الرقم الجديد
✅ محاكاة فشل PackageManager
✅ التحقق من استخدام BuildConfig
✅ عدم تعطل التطبيق
defaultConfig {
applicationId 'com.dxbmark.nfcmanager'
versionCode 3
versionName "1.0.2"
// ...
}سيظهر تلقائياً:
NFC Manager
Version 1.0.2
versionCode 4
versionName "1.0.3"سيظهر تلقائياً:
NFC Manager
Version 1.0.3
لا حاجة لتعديل أي كود! 🎉
BuildConfig هو class يتم توليده تلقائياً من Gradle ويحتوي على:
object BuildConfig {
const val VERSION_NAME = "1.0.2"
const val VERSION_CODE = 3
const val APPLICATION_ID = "com.dxbmark.nfcmanager"
const val BUILD_TYPE = "release"
const val DEBUG = false
// ...
}PackageInfo يحتوي على معلومات عن الـ APK المثبت:
data class PackageInfo {
val packageName: String
val versionName: String?
val versionCode: Int
val applicationInfo: ApplicationInfo
// ...
}// ✅ صحيح - يقرأ من APK المثبت
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
val version = packageInfo.versionName
// ❌ خطأ - قد لا يعكس APK المثبت في بعض الحالات
val version = BuildConfig.VERSION_NAME// ✅ صحيح - معالجة الأخطاء
val version = try {
packageInfo.versionName ?: BuildConfig.VERSION_NAME
} catch (e: Exception) {
BuildConfig.VERSION_NAME
}
// ❌ خطأ - قد يتعطل التطبيق
val version = packageInfo.versionName// ✅ صحيح - قيمة احتياطية
packageInfo.versionName ?: BuildConfig.VERSION_NAME
// ❌ خطأ - قد يكون null
packageInfo.versionName- ✅ Android 11+ (API 30+) - مدعوم بالكامل
- ✅ Android 12+ (API 31+) - مدعوم بالكامل
- ✅ Android 13+ (API 33+) - مدعوم بالكامل
- ✅ Android 14+ (API 34+) - مدعوم بالكامل
- ✅ Debug - يعمل
- ✅ Release - يعمل
- ✅ Signed APK - يعمل
- ✅ App Bundle (AAB) - يعمل
❌ رقم يدوي: "1.0.0"
❌ يجب التحديث يدوياً
❌ احتمالية النسيان
❌ عدم التزامن
✅ رقم تلقائي من build.gradle
✅ تحديث تلقائي
✅ لا احتمالية للنسيان
✅ دائماً متزامن
✅ معالجة أخطاء قوية
رقم الإصدار الآن يتحدث تلقائياً دائماً! 🚀
- يتم توليده تلقائياً أثناء البناء
- يتطلب
buildFeatures { buildConfig true }فيbuild.gradle - موجود في جميع build types
- يقرأ من APK المثبت
- الأكثر دقة
- قد يفشل في حالات نادرة (لذلك نستخدم try-catch)
- عند إصدار نسخة جديدة:
- تحديث
versionCodeوversionNameفيbuild.gradle - بناء APK
- انتهى! رقم الإصدار سيظهر تلقائياً
- تحديث
val buildNumber = try {
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
packageInfo.longVersionCode
} else {
@Suppress("DEPRECATION")
packageInfo.versionCode.toLong()
}
} catch (e: Exception) {
BuildConfig.VERSION_CODE.toLong()
}
// عرض: "Version 1.0.2 (Build 3)"val buildType = if (BuildConfig.DEBUG) "Debug" else "Release"
// عرض: "Version 1.0.2 (Release)"val buildDate = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
.format(Date(BuildConfig.BUILD_TIME))
// عرض: "Version 1.0.2 (Built on 2025-10-17)"تم حل مشكلة رقم الإصدار اليدوي:
- ✅ قراءة تلقائية من
build.gradle - ✅ تحديث تلقائي عند كل إصدار
- ✅ معالجة أخطاء قوية
- ✅ سهولة الصيانة
لن ننسى تحديث رقم الإصدار بعد الآن! 🎉