Faragiri
العربية

كل اللغات

تعلم برمجة التطبيقاتالبرمجة

رسم الناشر والمراجعة والانعكاس والحفظ عند الإيقاف: أربعة أشياء تقرر مصير أول تطبيق، وواحد منها فقط مكتوب في الدروس.

7الأقسام
6دقائق القراءة
2العمق

القرار

تكتب مرة أو تكتب مرتين، والجهاز هو الذي يقرر لا الذوق

صفان يذهبان في اتجاه وصفان في الاتجاه الآخر، والصف الأول وحده يقلب الحساب لمن يكتب بالعربية.

قاعدة كود واحدةالمتجران من مشروع واحد، بقرابة نصف الكلفة
قاعدتان أصليتانيكتب مرتين، بلغة كل منصة وأدواتها
قوائم ونماذج ونصوص، وانعكاسها للعربيةتكتب مرة، والانعكاس يضبط في مكان واحدالشاشة نفسها مرتين، والانعكاس يضبط مرتين
ثمن المتجر الثانيهدف بناء آخرفريق ثان، أو نصف سنة أخرى
ميزة أطلقتها المنصة الخريف الماضيتصل بعد أن يكتب أحدهم الجسرتصل يوم تطلقها المنصة
الموقع في الخلفية والودجات ونظام الدفع في المتجرممكن، والصعب فيه الجسرالطريق الموثق، وبأمثلة المنصة نفسها

الصفوف غير موزونة، والصفان الأخيران يحملان القرار وحدهما في العمل. التطبيق الذي لا يحتاج واحدا منهما لا سبب لكتابته مرتين.

فيصل يدرس في الرياض وأنهى تطبيقا صغيرا يحسب أقساط ورشة والده. التطبيق يعمل على محاكي أندرويد وعلى هاتفه. توقف المشروع أسبوعين، ولم يكن التوقف في سطر كود.

حساب الناشر في متجر Google Play يكلف 25 دولارا مرة واحدة، وحساب أبل 99 دولارا في السنة. والبطاقة الوحيدة التي يملكها فيصل بطاقة مدى، وهي شبكة خصم محلية، وما لم تكن مزدوجة العلامة يرفضها نموذج التسجيل. لا رسالة تشرح ذلك. النموذج يقول إن البطاقة غير صالحة، فيعيد المحاولة ببطاقة أخرى ثم يستنتج أن في التطبيق عيبا.

البوابة التي تسبق الكود بطاقة لا محرر

هذه البوابة ليست في أي درس، لأن كاتب الدرس مر بها مرة واحدة قبل سنوات ونسيها. وهي أول ما يواجه القارئ هنا، وثمنها يختلف باختلاف البلد لا باختلاف المهارة.

في الخليج البطاقة الدولية عادية، والعقبة الوحيدة هي مدى غير المزدوجة، وحلها بطاقة ائتمان من البنك نفسه أو بطاقة مسبقة الدفع بعلامة دولية. وفي مصر والشام والمغرب العربي العقبة أثقل: سقف العملة الأجنبية على البطاقة يجعل اشتراكا سنويا بالدولار قرارا يؤجل، فيبدأ أكثر الناس من أندرويد لأن رسمه يدفع مرة واحدة ولا يتكرر. وفي سوريا والسودان واليمن وليبيا ترفض بعض المتاجر التسجيل عند اختيار البلد نفسه، والمخرج الوحيد المشروع نشر خارج المتاجر أو عبر شريك في بلد آخر، وهذا حال يقال كما هو.

ويضاف إلى الرسم شرط ثان لا يقل ثقلا: Xcode لا يعمل إلا على جهاز أبل، فبناء نسخة iOS يفترض حاسوبا لا يملكه أكثر من يقرأ هذا. أندرويد لا يفترض شيئا: أدواته تعمل على أنظمة التشغيل الثلاثة. هذا وحده يقرر بأي منصة يبدأ القارئ العربي، قبل أي حجة تقنية.

الهاتف يوقف تطبيقك ولا يخبره

على حاسوب المطور يبقى البرنامج مفتوحا حتى يغلق. على الهاتف الأمر مختلف. التطبيق يوقف في الخلفية، وعليه أن يعيد بناء نفسه مما حفظه. المستخدم ينتقل إلى مكالمة، ثم إلى رسالة، ثم يعود بعد ساعة فيجد التطبيق قد بدأ من أول شاشة، وقد ضاع ما كتبه في النموذج.

وهذا العطل لا يظهر لصاحب التطبيق. جهازه موصول بالكهرباء والمحرر، والنظام لا يقتل تطبيقا يجري تنقيحه. فيصل شغل تطبيقه ثلاثة أسابيع على مكتبه ولم ير المشكلة مرة واحدة، وظهرت عند أول مستخدم في اليوم الأول.

والقاعدة العملية أن كل ما يكتبه المستخدم يحفظ عند كتابته لا عند إنهائه، وأن الشاشة تبنى من الحالة المحفوظة لا من الذاكرة. وهذا يفحص بأمر واحد على أندرويد بدل انتظار الصدفة:

  • adb shell am kill com.example.aqsat

يقتل الأمر التطبيق بالطريقة نفسها التي يقتله بها النظام، ثم يفتح من قائمة المهام. ما يعود سليما هو ما حفظ، وما عاد فارغا هو العطل.

44 و48: مقاس اللمس ليس رأيا في التصميم

44 نقطة على iOS و48 بكسلا مستقلا عن الكثافة على أندرويد، وهذان رقمان منشوران في دليلي المنصتين لا اجتهاد من مصمم. الزر الأصغر منهما يعمل عند من صنعه ويخطئ عند من إبهامه أكبر أو يده مشغولة أو يمشي.

والوحدتان ليستا بكسلات الشاشة. النقطة والبكسل المستقل عن الكثافة وحدتان منطقيتان يضربهما النظام في معامل الشاشة، فيبقى الزر بالحجم نفسه على شاشة عادية وعلى شاشة عالية الكثافة. من قاس بالبكسل الفعلي حصل على زر يصغر كلما تحسنت الشاشة.

ويقع هنا خطأ عربي محدد: الأزرار التي فيها نص عربي قصير مثل «حفظ» و«تم» تبدو صغيرة، فيصغر المصمم إطارها ليناسب النص. مساحة اللمس ليست مساحة النص، وتوسع تحته دون أن تظهر.

من البناء إلى من فتحه مرة ثانية

البناء ليس النهاية، هو أول خمس بوابات. الرفض يعيدك إلى آخر طابور المراجعة، وهذه هي البوابة التي يجهل ثمنها أكثر الناس: المراجعة نفسها أيام، والرفض لا يعيدك يوما واحدا بل يعيدك إلى أول الطابور من جديد.

وأسباب الرفض المتكررة ليست في الكود. إذن يطلب على شاشة الفتح بلا سبب ظاهر، أو سياسة خصوصية بلا رابط يعمل، أو وصف في المتجر يعد بشيء لا يفعله التطبيق. وواحد منها يخص هذا السوق: تطبيق يبيع خدمة داخل التطبيق بطريقة دفع محلية بدل نظام الدفع في المتجر يرفض، وهذه مسألة تقرأ قبل الكتابة لا بعدها، وموضعها الربح من التطبيق.

ثم تأتي بوابتان لا يفتحهما كود: أن يعثر أحد على التطبيق في المتجر، وأن ينزله. صفحة المتجر نتيجة بحث قبل أن تكون تطبيقا، وعنوانها ولقطاتها بالعربية تقرران نصف ذلك، وهما آخر ما يكتبه أكثر الناس وأول ما يقرؤه الزائر.

وشكل السلسلة يقرأ على إصدار أول واحد لتطبيق صغير، منسوبا إلى مئة: من 100 يبنى على الجهاز، يجتاز المراجعة 71، ويعثر عليه في المتجر 34، وينزل 19، ويفتح مرة ثانية 6. هذه أعداد إصدار واحد لا أرقام قطاع، والدعوى فيها ليست العدد بل الموضع: أربع من البوابات الخمس تعبر بعد أن ينتهي الكود، وأكبر هبوط واحد يقع في آخرها، وهو الذي كان الإيقاف في الخلفية يأكله.

إصدار واحد

البناء أول خمس بوابات، وهو وحده المصنوع من كود

عرض كل شريط عدده هو، فالهبوط نفسه هو المعطى لا زينة حوله.

  1. يبنى على الجهازالبوابة التي تنتهي عندها الدروس، وأرخص الخمس100
  2. يجتاز المراجعةرفض مرة بسبب إذن طلب على شاشة الفتح، وكلفة ذلك أربعة أيام71
  3. يعثر عليه في المتجرصفحة المتجر نتيجة بحث قبل أن تكون تطبيقا، وعنوانها بالعربية34
  4. ينزلحيث يتوقف أكثر القياس، وحيث لم يقع شيء بعد19
  5. يفتح مرة ثانيةأول رقم صادق، وهو الذي كان الإيقاف في الخلفية يأكله6

الأعداد إصدار أول لتطبيق صغير منسوبة إلى مئة، لا رقم قطاع. وتبدأ من البناء، فتترك خارجها بوابة تسبقه وليست من الكود: حساب الناشر وبطاقته.

العربية في التطبيق سطر في البيان، وأربعة أشياء لا تنعكس

android:supportsRtl سطر في ملف البيان، ولا تنعكس الواجهة بدونه. يكتب على عنصر التطبيق في AndroidManifest.xml، والمشاريع القديمة تولد بدونه:

  • <application android:supportsRtl="true" ... >

وبعده تكتب التخطيطات بحواف منطقية: layout_marginStart بدل layout_marginLeft، وpaddingEnd بدل paddingRight. وعلى iOS الاسمان leading وtrailing، ونظام التخطيط يقلبهما وحده.

ثم يبدأ الجزء الذي يخطئ فيه من ضبط السطر الأول وظن أنه انتهى. الانعكاس ليس شاملا للشاشة كلها. الأرقام والساعة وأزرار التشغيل لا تنعكس مع الواجهة: الرقم 1250 يبقى 1250 ولا يقلب، وشريط تقدم الصوت يمشي من اليسار إلى اليمين لأنه يمثل زمنا لا نصا، وزر التشغيل يبقى متجها إلى اليمين. والذي ينعكس هو سهم الرجوع، وسهم الانتقال إلى الشاشة التالية، وترتيب العناصر في الصف.

والقاعدة التي تفصل بينهما جملة واحدة: ينعكس ما يعني اتجاه القراءة، ولا ينعكس ما يعني اتجاه الزمن أو مقدارا. وأسرع فحص لهذا تبديل لغة الجهاز نفسه إلى العربية ثم فتح كل شاشة، لا قراءة ملف التخطيط.

ثلاث أدوات، وواحدة منها تفترض جهازا بعينه

Android Studio هو الأداة الرسمية لأندرويد سنة 2026، وحل محل Eclipse مع إضافة أندرويد، وهو ما تعرضه الدروس الأقدم من 2015 تقريبا. مجاني، ويعمل على أنظمة التشغيل الثلاثة، وينزل من أي بلد عربي.

Xcode هو الطريق الوحيد إلى iOS ولا بديل له، وهو مجاني، لكن الجهاز الذي يشغله ليس مجانيا وحساب الناشر الذي ينشر منه ليس مجانيا. هذه الجملة هي كل الفرق بين المنصتين بالنسبة لقارئ هذه الصفحة.

وFlutter وReact Native إطاران مفتوحان ومجانيان، وحلا محل شحن موقع داخل قشرة تطبيق، وهي حيلة يشعر بها المستخدم بلا استثناء. وكلاهما يعالج انعكاس الواجهة في مكان واحد بدل مكانين، وتلك ميزة تخص هذا السوق أكثر مما تخص غيره.

الخمسة تحت هذه الصفحة، والسؤال الذي يليها

أندرويد هي المنصة التي يبدأ منها أكثر قراء هذه الصفحة، لسبب الرسم والجهاز لا لسبب تقني. وiOS تدخل حين يكون المستخدم المستهدف في الخليج، حيث الإنفاق داخل التطبيقات أعلى، فيصير حساب أبل السنوي بندا يحسب لا عقبة تتجنب. والمنصات المتعددة هي الجواب حين تكون الشاشات قوائم ونماذج ونصوصا، وهي أكثر التطبيقات.

والتصميم للهاتف يقرأ قبل الكود لا بعده، لأن قرار مساحة اللمس وترتيب الشاشات يكتب مرة واحدة، وتغييره بعد بناء عشر شاشات أغلى من كتابته. ومن يريد أن يرى الشيء نفسه على سطح آخر يجده تحت تطوير الويب، ومن يريد أن يعرف ما الذي يبني التطبيق ويوقعه ويرفعه بلا يد فموضعه نشر المشاريع. ومن يبني تطبيقا ليبيع به مهارته لا ليبيع التطبيق نفسه يجد ذلك تحت العمل الحر.

ويبقى السؤال الذي يصل بعد أول إصدار. تطبيق فيصل يحسب الأقساط ويحفظها على الهاتف وحده، فإذا ضاع الهاتف ضاعت السنة كلها، وإذا أراد والده أن يرى الأرقام من جهاز آخر فلا سبيل. أين تسكن البيانات حين يكون لها أكثر من جهاز واحد، وما الذي يقرر شكلها قبل أن تملأ؟ جوابه في قواعد البيانات.

بجانب هذه العقدة

فوق هذه العقدة