Vous êtes sur la page 1sur 230

‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫أندرويد ببساطة‬

‫تعلم تطوير تطبيقات على نظام تشغيل أندرويد المفتوح المصدر‬


‫انتھى في )أبريل ‪(2010 /‬‬
‫نشر في )مارس ‪(2011 /‬‬

‫بواسطة‬
‫محمد بدوي‬
‫وائل علواني‬
‫‪2‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫فھرس المحتويات‬

‫الموضوع‬
‫لنتعرف على أندرويد‬
‫قاموس المصطلحات‬
‫كيف تبني تطبيق موجه لنظام تشغيل أندرويد‬
‫التعرف على البنية الداخلية لحياة التطبيق‬
‫تركيب أدوات التطوير و حزمة المطورين الموجھة الندرو يد‬
‫الخطوة األولى )‪(Java SE‬‬
‫الخطوة الثانية )‪(Android SDK‬‬
‫الخطوة الثالثة )‪(Eclipse‬‬
‫الخطوة الرابعة )‪(ADT‬‬
‫التعامل مع بيئة التطوير )‪(Eclipse‬‬
‫بناء أول تطبيق لك موجه الندرو يد بواسطة )‪(Android‬‬
‫بناء المشروع من خالل سطر األوامر‬
‫تشغيل تطبيقك على المحاكي‬
‫إعداد المحاكي‬
‫تشغيل المحاكي‬
‫التعامل مع المحاكي‬
‫التعامل مع المحاكي من خالل سطر األوامر‬
‫المحاكي و العالم الخارجي‬
‫بناء تطبيقك األول بدون كود )أھال بالعالم(‬
‫بناء مشروعك األول )قائمة المھام(‬
‫كيف تقوم بتسويق و إتاحة تطبيقك للجمھور‬
‫بناء تطبيق احترافي )‪ (Mash up‬بالتكامل مع محتوى خارجي )ريست درويد(‬

‫‪3‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫حول الكتاب‬

‫من الجيد معرفته أننا قمنا بكتابة الكتاب في نھاية العام )‪(2009‬‬
‫ميالدية و من ثم حاولنا البحث عن راعي لطباعة الكتاب أو توزيعه‬
‫و قد قامت بعض الجھات بإطالق الوعود الكثيرة ومنھا شركة‬
‫جوجل ممثلة بوكيلھا في السعودية مما جعلنا االنتظار بضعة أشھر‬
‫لنعرف رأي الراعي بالكتاب و مدى جودته لتوفيره للناس ‪ ،‬و لكن و‬
‫مع مرور الوقت لم نعد نسمع منھم ‪ ،‬و لذا تقاعسنا في نشر الكتاب‬
‫و لم نكمله و توقف العمل عليه نھائيا منذ شھر )‪ (4‬للعام )‪(2010‬‬
‫و ھا قد قمنا أخيرا بتنقيحه و على عجل إلصداره للناس و ھو و إن‬
‫كانت بعض البيانات قديمة إال أنه مازال صالحا للعمل بما فيه حتى‬
‫يومنا ھذا ‪،‬لذا في حال وجود بعض األخطاء فأرجوا أن تعذرنا فلقد‬
‫قمنا بأفضل ما يمكن للخروج بالكتاب بأفضل شكل و بأبسط ما يمكن‬
‫حيث ال يوجد أي كتب عربية حتى اآلن مھتمة في ھذا المجال و‬
‫كذلك الحال أغلب الكتب األجنبية التي طالعناھا تعاني من التعقيد ‪،‬‬
‫بل و تعتبر بأن من يقرأ الكتاب ملم بالكثير من األمور و لذا مازلنا‬
‫نجد بأن الكتاب سيكون من أفضل ما كتب حتى يومنا ھذا في ھذا‬
‫العالم‪.‬‬

‫الكتاب مجاني لألفراد و يمكن إعادة توزيعه و نشره كما ھو بدون‬


‫أي تعديل و بشكل الكتروني دون الرجوع لنا ‪ ،‬ولذا أرجوا أن ال‬
‫تنسونا من دعوة بظھر الغيب فنحن بأشد الحاجة لھا دائما‪.‬‬

‫أما في حال الطبع أو استخدامه ألغراض تجارية أو لغير األفراد‬


‫فيرجى الرجوع لنا ألخذ إذن خاص بذلك‪.‬‬

‫‪4‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫حول المؤلفين‬
‫محمد بدوي )مدون ‪،‬مبرمج ‪،‬رائد أعمال(‬

‫مطور للتطبيقات على األجھزة الذكية مثل )‪ (iPhone/iPad‬و )‪(Android‬‬


‫و )‪ (Windows Mobile‬و )‪(Blackberry‬‬

‫الموقع على االنترنت‪www.badwi.com :‬‬


‫البريد االلكتروني‪badwisoft@gmail.com :‬‬
‫الھاتف‪00966503415343 :‬‬
‫حساب على تويتر‪http://twitter.com/badwi :‬‬
‫حساب فيس بوك‪http://www.facebook.com/badwi :‬‬

‫وائل علواني )مدون ومطور تطبيقات أندرويد(‬

‫مھتم بالتقنية وتطوراتھا وخصوصا مجال األندرويد ومواضيع‬


‫تعدين البيانات ‪ ..Data Mining‬يحمل ماجستير في علوم الحاسب‬
‫‪ -‬تخصص ذكاء صنعي من جامعة الملك عبدﷲ للعلوم والتقنية‬
‫)كاوست(‪.‬‬

‫البريد االلكتروني‪wael.alalwani@gmail.com :‬‬


‫حساب على تويتر‪http://twitter.com/waelalwani :‬‬

‫‪5‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫لنتعرف بالبداية على أندرويد‬

‫أندرويد ھو نظام تشغيل مفتوح المصدر موجھة لألجھزة المحمولة‬


‫اشترته شركة جوجل من أحد الشركات في العام )‪ (2005‬ميالدية و‬
‫في العام )‪ .(2007‬تم تبنيه تحت اتحاد المصادر المفتوحة لألجھزة‬
‫المحمولة )‪ (Open Handset Alliance) (OHA‬و الذي ضم‬
‫أكثر من )‪ (48‬شركة من كبار الشركات و منھم مصنعين و شركات‬
‫تطبيقات برمجية و شركات تزود شرائح الكترونية و شركات تھتم‬
‫بالمحتوى و مزودي خدمة االتصاالت‪ .‬و في العام )‪ (2008‬قامت‬
‫شركة )‪ (HTC‬و المصنعة لألجھزة المحمولة بإصدار أول ھاتف‬
‫متنقل بنظام تشغيل )‪ (Android‬و في العام )‪ (2009‬قامت شركة‬
‫)‪ (T-Mobile‬ببيع أول خطوط ھاتف ضمن عقد سنوي مع أجھزة‬
‫)‪ (HTC‬و المتضمنة لنظام تشغيل )أندرويد( ‪.‬‬

‫نظام أندرويد يعتمد ومبني على نواة لينكس ) ‪Linux 2.6‬‬


‫‪ (kernel‬و لكنه ال يعد نظام تشغيل )‪ (GNU/Linux‬حيث أنه ال‬
‫يدعم كل من )‪ (native windowing system‬و ) ‪glibc‬‬
‫‪ (support‬و ال حتى أدوات )‪ (GNU/Linux‬و لكنه يستفيد من‬
‫النواة بقواتھا في األمان )‪ (security‬و إدارة الذاكرة ) ‪memory‬‬
‫‪ (management‬و إدارة العمليات الخلفية ) ‪process‬‬
‫‪ (management‬و كذلك الحال في إدارة الشبكة ) ‪network‬‬
‫‪ (stack‬و نموذج السواقات )‪ (driver model‬و طبقة التجريد‬
‫)‪. (abstraction layer‬‬

‫يمكن بناء التطبيقات و تطوير التطبيقات الموجھة لنظام تشغيل‬


‫)أندرويد( بواسطة كل من )‪ (Java‬و )‪ (Managed Code‬و لكن‬
‫‪6‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫ال تعبر نسخة )‪ (Java‬القياسية بل ھي مطورة لجزء من ) ‪Java5‬‬


‫‪ (SE‬و تعمل على )‪ (JDV‬اختصارا لـ ) ‪Java Dalvik‬‬
‫‪ (Virtual‬بدال من )‪ (JVM‬اختصارا لـ ) ‪Java Virtual‬‬
‫‪. (Machine‬‬

‫أندرويد و ببساطة ھو نظام تشغيل مفتوح المصدر ويدعم تعدد‬


‫التطبيقات‪ .‬أي من الممكن أن يعمل به أكثر من تطبيق في نفس‬
‫الوقت أو الخدمات في الخلفية‪ .‬و تعمل كل التطبيقات فيه بشكل‬
‫متساوي من ناحية مشاركة موارد الجھاز وان كان كل تطبيق يعمل‬
‫بشكل مستقل بطبقة منفصلة‪ .‬و تمكنك منصته من إعادة استخدام‬
‫كائناته كما و يستخدم محرك )‪ (Web Kit OSS‬كمتصف انترنت‬
‫و الذي يستخدم في متصفح )‪ . (Google chrome‬كما يدعم‬
‫مكتبة )‪ (OpenGL ES‬إلدارة الصور الثالثية و يعتمد قواعد‬
‫بيانات )‪ (SQLite‬في تخزين البيانات ‪ .‬كما و يدعم كل الصيغ‬
‫القياسية لوسائط الميديا من صور و أصوات و فيديو و الجميل فيه‬
‫أنه يتضمن عتاد متنوع من الكاميرا الرقمية و نظام التوضع‬
‫العالمي )‪ (GPS‬و البوصلة باإلضافة إلى دعم خاصية اإلحساس‬
‫بالمكان )‪. (accelerometer‬‬

‫لنتعرف أكثر على بنية أندرويد الداخلية‪. .‬‬

‫في األساس تقع نواة لينوكس )‪ (Linux Kernel‬و التي ھي‬


‫مسئولة عن‪:‬‬
‫‪• Display Driver‬‬
‫‪• Bluetooth Driver‬‬
‫‪• Camera Driver‬‬
‫‪7‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

• Flash Memory Driver


• Binder (IPC) Driver
• Keypad Driver
• USB Driver
• Wi-Fi Driver
• Audio Driver
• Power Management

: ‫ثم تليھا طبقة التشغيل و التي ھي عبارة عن‬


• Dalvik Virtual Machine
• Core Libraries

: ‫و ھذه المكتبات ھي‬


• Surface Manager
• Media Framework
• SQLite
• OpenGL ES
• Free Type
• Web Kit
• SGL
• SSL
• Libbc

8
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫ثم تلي ھذه الطبقة طبقة منصة التطبيقات و التي تستخدم من قبل كل‬
‫التطبيقات‪:‬‬
‫‪• Activity Manager‬‬
‫‪• Window Manager‬‬
‫‪• Content Provider‬‬
‫‪• View System‬‬
‫‪• Notification Manager‬‬
‫‪• Package Manager‬‬
‫‪• Telephony Manager‬‬
‫‪• Resource‬‬
‫‪• Location Manager‬‬
‫‪• Sensor Manager‬‬

‫ثم في الطبقة األخيرة تأتي التطبيقات الرئيسية المشحونة من‬


‫الشركة مثل ‪:‬‬
‫‪• Home‬‬
‫‪• Contacts‬‬
‫‪• Phone‬‬
‫‪• Browser‬‬

‫و بعض التطبيقات األخرى و التي سيكون منھا تطبيقك الخاص الذي‬


‫سوف نتعلم سوية كيف ستقوم ببنائه‪.‬‬

‫‪9‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫مصدر الصورة‪ :‬صفحة أندرويد‪-‬ويكيبيديا‬

‫‪10‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫الوحدات األساس الذي سنتعامل معه ألي تطبيق أندرويد ھو‪:‬‬

‫•‬ ‫‪Activity‬‬
‫•‬ ‫‪Intent‬‬
‫•‬ ‫‪Service‬‬
‫•‬ ‫‪Content Provider‬‬

‫قبل اإلبحار دعنا نتعرف على ھذه األسس و التي يمكن لتطبيقك أن‬
‫يستخدم أحدھا فقط أو أكثر أو كلھا مجتمعة‪:‬‬

‫النشاط أو الجلسة )‪(Activity‬‬

‫تستخدم لتوصيف شاشة وحيدة و تكون عبارة عن )‪ (Class‬و التي‬


‫يتم استدعاؤھا عن طريق الزناد )‪ (Intent‬و تكون بالعادة الجزء‬
‫الظاھر إذ يمكن أن تكون في أعلى كل التطبيقات و يمكن استدعائھا‬
‫أو جعلھا في الخلفية و إعادة استدعائه أو إغالقھا نھائيا ‪.‬‬

‫دورة حياة )‪(Activity‬‬

‫بداية )‪ (Start‬النشاط )‪ (Activity‬و التي تتعامل مع األحداث‬


‫‪• On Create‬‬
‫‪• On Start‬‬
‫‪• Om Restore Instance State‬‬
‫‪• On Resume‬‬

‫‪11‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫أما في المرحلة الثانية و ھي عندما يكون النشاط في وضع التشغيل‬


‫)‪ (Running‬فإنه يتعامل مع األحداث التالية‪:‬‬
‫‪• On Start‬‬
‫‪• On Restart‬‬
‫‪• On Resume‬‬
‫‪• On Push‬‬
‫‪• On Save Instance State‬‬

‫و بينما النشاط يعمل و االنتقال إلى نشاط أخر فإنه يكون في وضعية‬
‫اإليقاف المؤقت )‪ (Paused‬و الذي يمكن التعامل معه مع األحداث‪:‬‬
‫‪• On Save Instance State‬‬
‫‪• On Resume‬‬
‫‪• On Stop‬‬

‫أما المرحلة األخيرة و التي تعتبر نھاية النشاط و التي يتم إلغاؤه من‬
‫الذاكرة )‪ (Destroyed‬و يتم تنفيذ الحدث الوحيد‪:‬‬
‫‪• On Destroy‬‬

‫الزناد ‪ /‬الحدث )‪(Intent‬‬

‫و الذي يترجم إلى قصد أو غرض و لكن أرى أن زناد أقرب ترجمة‬
‫للفھم باللغة العربية و التي يستخدم إلتمام عمل ما ‪ ،‬مثال في‬
‫استدعاء نشاط جديد مثل شاشة أو عند استدعاء صفحة انترنت أو‬
‫البحث عن عنصر في قائمة االتصاالت و غيرھا من األمور التي‬
‫تستخدم بناء على طلب المستخدم‪.‬‬
‫‪12‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫الخدمة )‪(Service‬‬

‫تستخدم لتعمل وتبقى كذلك في الخلفية مثال و بالعادة ال تحتوي على‬


‫واجھة مستخدم فعلى سبيل المثال لو جربت و قمت بتشغيل مشغل‬
‫الموسيقى )‪ (Media Player‬فيمكنك الخروج منه و تصفح بريدك‬
‫أو كتابة مالحظاتك و في نفس الوقت مازلت تسمع الموسيقى و في‬
‫ھذه الحالة فإن الموسيقية تعمل كخدمة بالخلفية كـ )‪.(Service‬‬

‫تزويد و تبادل المحتوى )‪(Content Provider‬‬

‫يمكنك عبر ذلك مناداة أي محتوى خارجي مثال عبر تطبيق ويب أو‬
‫حتى في مبادلة المحتوى بين التطبيقات فعلى سبيل المثال يمكنك أن‬
‫تصل لقائمة عناوين االتصال في تطبيق )‪.(Contacts‬‬

‫أشكال النشاط )‪(Activity‬‬

‫يكون عبارة عن نافذة )‪ (Window‬متعددة فقد فتكون صغيرة أو‬


‫مليء الشاشة و لتوضع الكائنات عليھا فإنھا تتعامل بأربع وضعيات‬
‫مختلفة‬

‫عرض بشكل سطري )‪(Linear Layout‬‬

‫تعرض الكائنات بشكل سطري أي كل عنصر يقع بأسفل العنصر‬


‫الذي يليه‪ ،‬أو بمحاذاته بحسب الوضع المختار ) ‪vertical or‬‬
‫‪.(horizontal‬‬
‫‪13‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫بشكل نموذج ) ‪(Frame Layout‬‬

‫تعرض الكائنات بشكل متتالي ابتداء من الجھة العليا باليسار‪.‬‬

‫بشكل عالئقي )‪(Relative Layout‬‬

‫تعرض الكائنات بشكل عالئقي فيما بينھا أي مثال أن تضع زر بعد‬


‫العنصر الفالني و قبل العنصر الفالني أو لتملئ مساحة ما بين‬
‫عنصر )‪ (A‬و عنصر )‪.(B‬‬

‫بشكل جدولي )‪(Table Layout‬‬

‫تعرض الكائنات بشكل جدولي حيث يمكن وضع كل كائن داخل خلية‬
‫كما الحال في تصميم الجداول في )‪.(HTML‬‬

‫‪14‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫قاموس المصطلحات‬

‫في ھذا القسم سوف نتعرف على بعض المسميات و االختصارات و‬


‫المصطلحات التي ستمر علينا في الكتاب و لنقوم بتعريفھا ھنا لكي‬
‫نستطيع المضي قدما أثناء شرح باقي أقسام الكتاب لكي ال نحتاج‬
‫إلى تعريفھا في كل مرة نقوم بذكرھا‬

‫)‪SDK (Software Development Kit‬‬


‫الحزمة التطويرية البرمجية والتي تحوي المجموعات\كالسات‬
‫والدوال التي يمكن استخدامھا في تطوير تطبيقات األندرويد‪.‬‬
‫)‪NDA (Native Development Kit‬‬
‫حزمة التطوير بالكود األصلي‬
‫)‪ADT (Android Development Tools‬‬
‫أدوات تطوير أندرويد‬
‫)‪JDK (Java Development Kit‬‬
‫أدوات تطوير جافا‬
‫)‪JRE (Java Runtime Environment‬‬
‫بيئة تشغيل جافا‬
‫)‪JVM (Java Virtual Machine‬‬
‫آلة جافا االفتراضية‬
‫)‪AVD (Android Virtual Device‬‬
‫محاكي جھاز أندرويد‬
‫)‪AVDM (Android Virtual Device Manager‬‬
‫مدير محاكي أجھزة أندرويد‬
‫)‪APK (Android Package‬‬
‫حزمة أندرويد و ھو الملف التنفيذي النھائي للتطبيق‬
‫‪15‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫)‪DDMS (Dalvik Debug Monitor Server‬‬


‫أداة مراقبة محاكي الجھاز‬
‫)‪GPS (Global Position System‬‬
‫نظام التوضع العالمي عبر األقمار الصناعية‬
‫)‪CMD (Command Line‬‬
‫سطر األوامر‬
‫)‪ADB (Android Debug Bridge‬‬
‫جسر التواصل مع أجھزة أندرويد لمراقبة األداء و معالجة األخطاء‬

‫‪16‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫تركيب بيئة التطوير‬

‫في عملية التركيب سأحاول قدر اإلمكان عدم إغفال أي نقطة مھما‬
‫كانت صغيرة و سأقوم بتوثيقھا بالصور فكتابنا يدور حول البساطة‬
‫و ھي تبسيط كل شيء قد اإلمكان لكي ال تقف خطوة صغيرة حجر‬
‫عثرة في طريقنا لتعلم تطوير التطبيقات ‪.‬‬

‫‪17‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫الخطوة األولى )‪(Java SE‬‬

‫في البداية نحتاج إلى حزمة )‪ (Java SE‬اختصارا إلى ) ‪Java‬‬


‫‪ (Standard Edition‬و تحديدا )‪ (JDK 6‬و التي تحتوي على‬
‫كل من )‪(JDK‬اختصارا إلى ‪ ((Java Development Kit‬و‬
‫)‪ (JRE‬اختصارا إلى )‪ (Java Runtime Environment‬و ال‬
‫يكتفي بوجود )‪ (JRE‬فقط ولذا قم بتحميل )‪ (JDK‬كاملة و التي‬
‫تحتوي على االثنين معا و التي يمكن تحميلھا من موقع االنترنت‪:‬‬

‫‪http://java.sun.com/javase/downloads/index.jsp‬‬

‫بعد فتح الصفحة ستظھر لك عدة خيارات اختر كما ھو مبين ضمن‬
‫اإلطار‪:‬‬

‫في الشاشة التالية قم بتحديد نظام التشغيل الخاص بك كما في حالتنا‬


‫ھذه ھو نظام تشغيل )‪(Windows‬‬

‫‪18‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫عند ظھور شاشة تطلب منك التسجيل قم بتجاھل ذلك عن طريق‬


‫الضغط على )‪ (Skip‬كما ھو موضح في القوس التالي‬

‫بعد ذلك سيخيرك الموقع في استخدام ) ‪Sun Download‬‬


‫‪ (Manager‬و الذي يساعدك في إكمال التحميل في حال حدث‬

‫‪19‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫انقطاع و كما يمكنك تحميل الملف مباشرة من الوصلة كما ھو‬


‫موضح في الصورة التالية‬

‫بعد ذلك ستظھر لنا شاشة تحميل الملف‬

‫اضغط على زر حفظ )‪ (Save‬و عندھا ستظھر لك الشاشة التالية و‬


‫التي تمكنك من حفظ الملف في مكان محدد على جھازك‬

‫‪20‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫قم بحفظ الملف على سطح المكتب في الوقت الحال و الحقا يمكنك‬
‫االحتفاظ بنسخة منه في مكان أمن و بعد حفظ الملف ستبدأ عملية‬
‫التحميل و التي قد تستغرق بعد الوقت بناء على سرعة االنترنت‬
‫لديك‬

‫حجم الملف تقريبا )‪ (70‬ميجا بايت ‪ ،‬ستجد أيقونته على سطح‬


‫المكتب بالشكل التالي‬

‫قم بالنقر مرتين على الملف لتشغيل برنامج اإلعداد لتظھر لك شاشة‬
‫شبيھة بھذه اضغط على قبول )‪(Accept‬‬

‫‪21‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫في الشاشة التالية سيسألك برنامج اإلعداد عن المكونات التي تود‬


‫تحميلھا ال تقم بتغيير شيء و اضغط على زر التالي )‪(Next‬‬

‫سيبدأ البرنامج بفك نفسه على الجھاز تمھيدا لعملية اإلعداد‬


‫‪22‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫بعد دقائق قليلة ستظھر لك شاشة تخيرك فيھا بتغيير المجلد الھدف‬
‫للبرنامج ال تقم بتغيير شيء و اختر زر التالي )‪(Next‬‬

‫في ھذه الخطوة يبدأ البرنامج في إعداد نفسه على الجھاز‬

‫‪23‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫بعد االنتھاء سيخبرك برنامج اإلعداد بنجاحه في عملية اإلعداد و‬


‫عند الضغط على زر إنھاء )‪ (Finish‬قد يطلب منك برنامج اإلعداد‬
‫ضرورة إعادة تشغيل الجھاز فقم بذلك و أعد تشغيل الجھاز‬

‫و بھذا نكون قد قمنا بالخطوة األولى أال و ھي دعم النظام لبريمجات‬


‫جافا‬

‫‪24‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫الخطوة الثانية )‪(Android SDK‬‬

‫تحميل حزمة مطوري التطبيقات الخاصة بأندرويد ) ‪Android‬‬


‫‪(SDK‬‬

‫اذھب إلى العنوان التالي على االنترنت‬

‫‪http://developer.android.com/sdk/index.html‬‬

‫و ھو الموقع المخصص لمطوري أندرويد من جوجل قم اآلن‬


‫بتحميل حزمة المطورين كما ھو مبين أمامك بناء على نوع نظام‬
‫التشغيل الخاص بك و في حالتنا ھذه سنختار )‪ ، (Windows‬و بعد‬
‫ذلك سيقوم بتحويلنا إلى صفحة اتفاقية االستخدام‬

‫‪25‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫انزل إلى أخر الصفحة و اختر الموافقة على اتفاقية المستخدم إن‬
‫أردت ‪ – ( : -‬و اضغط على زر تحميل )‪ (Download‬و عندھا‬
‫ستظھر لنا شاشة تحميل البرنامج كما الشكل التالي و اضغط فيھا‬
‫على زر حفظ )‪(Save‬‬

‫لتظھر لك بعد ذلك شاشة اختيار حفظ الملف كما الشكل التالي‬

‫‪26‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫قم بتحديد وجھة الحفظ و لتكن سطح المكتب ثم انقر على زر حفظ‬
‫)‪ (Save‬و عندھا ستبدأ عملية تحميل البرنامج على جھازك‬

‫حجم البرنامج تقريبا )‪ (22‬ميجابايت و بعد االنتھاء سيظھر لك ملف‬


‫مضغوط على سطح المكتب كما الشكل التالي‬

‫يمكنك فك ضغط الملف باستخدام برامج فك الضغط مثل‬


‫)‪ (WinZip‬إن كنت تملكه و في حال لم تكن تملكه فمجرد الضغط‬
‫عليه فإن نظام التشغيل )‪ (Windows‬يدعم ھذه الخاصية و سيفتح‬
‫مجلد به محتويات الملف المضغوط كما الشكل التالي‬

‫‪27‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫اآلن قم بسحب المجلد إلى سطح المكتب عن طريق السحب و‬


‫اإلفالت بزر الفأرة أو قم بالضغط بزر الفأرة األيمن عليه و اختيار‬
‫نسخ )‪ (Copy‬ثم أذھب إلى سطح المكتب و اختر من قائمة زر‬
‫الفأرة األيمن لصق )‪ (Paste‬و عندھا ستبدأ عملية فك الضغط كما‬
‫في الشاشة التالية‬

‫بعد االنتھاء من عملية فك الضغط ستجد مجلد جديد على سطح‬


‫المكتب باسم الملف )‪ (android-sdk-windows‬قم بالضغط‬
‫المضاعف على المجلد لفتحه ليظھر لك محتوياته‬

‫‪28‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫قم بتشغيل الملف التنفيذي )‪ (SDK Setup‬لتبدأ في عملية تحميل‬


‫أخر ملفات اإلعداد من موقع أندرويد و ستظھر لك الشاشة التالية‬

‫كما ترى في حالتنا ھذه تظھر الشاشة وجود عملية خطاء أثناء‬
‫عملية التحميل و ذلك لعدم تمكن برنامج اإلعداد من التخاطب عبر‬
‫بروتوكول )‪ (https‬و قد ال تظھر لك الشاشة في حال لم يكن على‬
‫‪29‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫جھازك أي إعدادات أمان مخصصة و لكن الكثيرين ممن حاولوا في‬


‫عملية التحميل واجھوا ھذه المشكلة و لذا سنقوم بشرح طريقة‬
‫حلھا و من ثم ننتقل للخطوة التي تليھا و التي في حال لم تواجھك‬
‫أي مشاكل منذ البداية من المفروض أن تظھر لك‬

‫اآلن اضغط على زر إغالق )‪ (Close‬لتظھر لك شاشة أخرى مثل‬


‫ھذه‬

‫قم بالضغط علة زر إلغاء )‪ (Cancel‬لتظھر لك الشاشة الرئيسية‬


‫لبرنامج اإلعداد كما الشكل التالي و عندھا اذھب إلى االختيار‬
‫إعدادات )‪ (Settings‬لتظھر لك شاشة شبيه بالتالية‬

‫‪30‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫اآلن قم باختيار زر الخيار )‪ (Force Https‬ليتغاضى عن العمل‬


‫ضمن بروتوكول )‪ (Https‬و في حال كنت تستخدم إعدادات‬
‫بروكسي خاصة على جھازك قم بكتابتھا في المربعات الفارغة في‬
‫األعلى ثم و من نفس الشاشة اذھب الخيار الذي يعلوه‬
‫)‪ (Available Packages‬لتظھر لك شاشة شبيھة بالتالية‬

‫و عند فرد الشجرة ستظھر لك كل األنظمة و المتوفرة حول أندرويد‬


‫و بالنسبة لحالتنا يمكنك اإلبقاء عليھا جميعا معلمة أو تقوم فقط‬
‫بتحديد )‪ (1.6‬و الذي يوف ستكون حوله أمثلتنا في ھذا الكتاب‬

‫‪31‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫قد يتساءل البعض لماذا اخترنا )‪ (1.6‬و لم نختر أحدث نظام )‪(2.1‬؟‬
‫و السبب ببساطة ھو أن قرابة )‪ (%50‬من األجھزة المتوفرة في‬
‫األسواق تعمل بنظام )‪ .(1.6‬كما أن النسخ األحدث لم تتوفر في‬
‫أسواقنا العربية بعد و األھم من ذلك فإن أندرويد يدعم بشكل تلقائي‬
‫في نظم تشغيله األحدث التطبيقات التي صممت على نظام سابق‪ .‬كما‬
‫أن أكثر التطبيقات المتوفرة في األسواق موجھة لھذا النظام و في‬
‫حال كنت مثلي و تملك جھاز على نظام )‪ (1.5‬و ھو المتوفر في‬
‫األسواق العربية فإن تطبيقك سيعمل عليه أيضا بدون أي مشاكل و‬
‫بالنھاية لك الخيار في تحميلھا جميعا أو االكتفاء بھذا حيث أن كل‬
‫عنصر من ھذه تحتاج إلى وقت طويل في عملية التحميل و يمكنك‬
‫في أي وقت العودة و تحميلھا بإتباع نفس الخطوات السابقة‪.‬‬

‫اآلن و بعد اختيار العناصر ھدف التحميل قم بالضغط على زر‬


‫)‪ (Install Selected‬و الموجود في أسفل يمين الشاشة لتظھر لك‬
‫شاشة جديدة شبيھة بالتالية و التي تحتوي اتفاقية االستخدام‬

‫‪32‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫قم بالموافقة عبر اختيار )‪ (Accept All‬للموافقة على الجميع مرة‬


‫واحدة و من ثم اضغط على زر )‪ (Install‬لتظھر لك شاشة شبيه‬
‫بالتالية‬

‫بعد االنتھاء من عملية التحميل و التي قد تأخذ بعض الوقت قم‬


‫بإغالق النافذة و بھذا نكون قد انتھينا من تحميل حزمة التطوير و‬
‫لننتقل إلى الخطوة الثالثة‪..‬‬

‫‪33‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫الخطوة الثالثة )‪(Eclipse‬‬

‫بيئة التطوير )‪ (Eclipse‬ھي بيئة تطوير متعددة االستخدام كانت‬


‫ملك شركة )‪ (IBM‬و من ثم قامت منذ بضع سنوات بتوفيرھا بشكل‬
‫مجاني و مفتوح المصدر و لذا تجد أن أشھر المبرمجين يعملون‬
‫عليھا لتطوير تطبيقاتھم إذ تدعم عدة منصات عبر تركيب اإلضافات‬
‫الخاصة بكل منصة عن طريق نفس بيئة التطوير‪.‬‬

‫في البداية قم بزيارة موقع البرنامج على الوصلة التالية‪:‬‬

‫‪http://www.Eclipsee.org/downloads‬‬

‫في الصفحة الظاھرة أمامك ستجد عدة إصدارات من التطبيق ال‬


‫تشعر باالرتباك و اذھب إلى أخر الصفحة لنقوم بتحميل النسخة‬
‫األساسية فقط و ھي كل ما نحتاج )‪(Eclipse Classic 3.5.2‬‬

‫قم بالضغط عليھا لتأخذك إلى الصفحة التالية‬

‫‪34‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫عن طريق ھذه الصفحة يمكن اختيار طريقة التحميل إما عن طريق‬
‫بروتوكول )‪ (Torrent‬أو بشكل مباشر عن طريق أحد الخوادم‬
‫التي توفر التطبيق ‪ ،‬لك الخيار في ذلك و لكني أفضل دائما استخدام‬
‫الوصالت المباشرة لعدم حاجتھا إلى أي تطبيقات أخرى كما ھو‬
‫موضح في المربع في الصورة‪.‬‬

‫بعد اختياره ستظھر لك شاشة بدء التحميل كما في الصورة التالية‬

‫قم بالضغط على زر حفظ )‪ (Save‬و من ثم في الشاشة التالية قم‬


‫بتحديد ھدف الحفظ على جھازك و ليكن سطح المكتب‬

‫‪35‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫بعد الضغط على زر الحفظ )‪ (Save‬ستظھر لك شاشة بدء التحميل‬


‫كما في الصورة التالية‬

‫قد تأخذ منك العملية بعض الوقت بناء على سرعة االنترنت لديھم و‬
‫عند انتھائھا ستجد ملف مضغوط باسم )‪Eclipsee-SDK-3.5.2-‬‬
‫‪ (win32‬على سطح المكتب كما في الصورة التالية‬

‫‪36‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫حجم البرنامج قرابة )‪ (163‬ميجابايت و في حال كنت تملك برنامج‬


‫لفك الضغط مثل )‪ (Win Zip‬فيمكنك فك البرنامج على سطح‬
‫المكتب مباشرة أو قم بالضغط المضاعف عليه ليقوم نظام التشغيل‬
‫)‪ (Windows‬بفتحه كما في الشكل التالي‪:‬‬

‫قم اآلن بسحب المجلد إلى سطح المكتب عبر خاصية السحب و‬
‫اإلفالت بالفأرة أو قم بالضغط بزر الفأرة األيمن و من ثم اختيار‬
‫خيار نسخ )‪ (Copy‬ومن ثم اذھب إلى سطح المكتب و قم بزر‬
‫الفأرة األيمن باختيار خيار )‪ (Paste‬لتبدأ عملية فك ضغط الملف‪:‬‬

‫بعد ھذه الخطوة ستجد مجلد على سطح المكتب لديك باسم‬
‫)‪ (Eclipse‬قم بالضغط المضاعف عليه ليفتح لديك محتوياته‬

‫‪37‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫وبھذا نكون قد انتھينا من عملية تنصيب بيئة التطوير إذ أنھا من‬


‫نوعية التطبيقات المحمولة و التي ال تحتاج إلى عملية إعداد على‬
‫الجھاز و تعمل مباشرة عن طريق تشغيل البرنامج التنفيذي مباشرة‬
‫بھذا نكون قد انتھينا من الخطوة الثالثة و لننتقل للخطوة التي تليھا‬

‫‪38‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫الخطوة الرابعة )‪(ADT‬‬

‫تحميل إضافة )‪ (ADT‬لدعم التطوير الموجھة لتطبيقات أندرويد‬


‫على )‪(Eclipse‬‬

‫بعد انتھاء الخطوة السابقة قم بتشغيل برنامج )‪ (Eclipse‬لتظھر لك‬


‫الشاشة التالية ألول مرة‬

‫وھذه الشاشة التي تحدد فيھا مساحة العمل الخاصة بك و التي يتم‬
‫تخزين ملفات مشاريعك فيھا و يمكنك تغيير مكانھا لحقا أو اختيار‬
‫خيار )‪ (Use this as default and do not ask again‬و‬
‫التي تحفظ اختيارك لكي ال تظھر لك في كل مرة تقوم فيھا بتشغيل‬
‫بيئة التطوير‬

‫اضغط اآلن على زر موافق )‪ (OK‬لتظھر لك الشاشة األولى من‬


‫برنامج التطوير والشبيھة بالتالية‬

‫‪39‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫في أعلى يسار الشاشة تجد لسان تبويب الترحيب )‪ (welcome‬قم‬


‫بضغط زر )‪ (X‬إلغالقه لتظھر لك شاشة بيئة التطوير كما الشكل‬
‫التالي‬

‫‪40‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫اآلن لنقوم بتحميل إضافة )‪ (ADT‬قم بالذھاب القائمة )‪ (Help‬و‬


‫منھا قم باختيار خيار )‪ (Install New Software‬كما ھو موضح‬
‫بالصورة التالية‬

‫بعد اختيارك لھذا الخيار سوف تظھر لك شاشة شبيھة بالشاشة‬


‫التالية‬

‫‪41‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫قم بالضغط علة زر )‪ (Add‬إلضافة عنوان التطبيق لتظھر لك‬


‫شاشة شبيھة بالشاشة التالية‬

‫قم بكتابة )‪ (Android‬في مربع االسم )‪ (Name‬و قم بكتابة‬


‫العنوان التالي في مربع )‪(Location‬‬

‫‪/https://dl-ssl.google.com/android/Eclipsee‬‬

‫ومن ثم اضغط على زر موافق )‪ (OK‬و بعد دقائق معدودة سيقوم‬


‫البرنامج باالتصال باالنترنت للبحث عن الملفات الخاصة بالتطبيق‬
‫لتظھر لك شاشة شبيھة بالتالية‬

‫‪42‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫في حال لم تظھر لك ھذه الشاشة قم بإزالة حرف )‪ (S‬من عنوان‬


‫الوصلة لتصبح من )‪ (https‬إلى )‪ (http‬ثم باقي الوصلة كما ھي‬
‫و عندھا بالتأكيد ستظھر لك شاشة شبيھة بالشاشة السابقة‬

‫‪43‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫قم بتعليم كل العناصر و من ثم اضغط على زر التالي )‪ (Next‬لتظھر‬


‫لك الشاشة التالية‬

‫ثم اضغط على زر التالي لتظھر شاشة اتفاقية المستخدم كما الصورة‬
‫التالية‬

‫‪44‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫قم بالموافقة على اتفاقية المستخدم عبر اختيار خيار )‪ (I accept‬و‬


‫من ثم اختر زر إنھاء )‪ (Finish‬لتظھر لك شاشة بدء التحميل كما‬
‫الصورة التالية‬

‫و بعد انتھائه من التحميل عبر االنترنت ستظھر لك شاشة تحذير‬


‫بأن ھناك المزيد من التطبيقات التي تود التنصيب على جھازك قم‬
‫بالضغط على زر موافق‬

‫ثم بعد االنتھاء من عملية التنصيب ستظھر لك شاشة أخرى تخبرك‬


‫بأنك بحاجة إلى إعادة تشغيل تطبيق بيئة التطوير )‪(Eclipse‬‬
‫لتصبح اإلعدادات الجديدة نافذة فاضغط على زر موافق‬

‫‪45‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫ستقوم بيئة التطوير باإلغالق بشكل ألي و من ثم ستعاود التشغيل‬


‫مرة أخرى و بھذا تصبح بيئة التطوير لديك إمكانية البرمجة‬
‫الموجھة الندرويد‪.‬‬

‫بھذا نكون قد انتھينا من الخطوة الرابعة و لننتقل للخطوة الخامسة‬


‫و األخيرة و بعدھا نبدأ في البرمجة‪.‬‬

‫من القائمة ‪ window‬قم باختيار خيار )‪ (Preferences‬كما ھو‬


‫موضح بالصورة التالية‪:‬‬

‫‪46‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫لتظھر لك شاشة شبيھة بالتالية‪:‬‬

‫‪47‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫من أعلى الشاشة في الجھة اليسرى قم باختيار )‪ (Android‬و قد‬


‫تظھر لك شاشة خطاء و في حال ظھورھا اضغط على موافق‬
‫وتجاھلھا لتصبح لك الشاشة بالشكل التالي‪:‬‬

‫اآلن من زر استعراض )‪ (Browse‬قم بالبحث عن مكان ملفات‬


‫حزمة التطوير و التي قمنا سابقا في تحميلھا على جھازنا و التي‬
‫كانت على سطح المكتب و نختار المجلد الرئيسي كما الصورة‬
‫التالية‪:‬‬

‫‪48‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫ثم نضغط على زر موافق )‪ (OK‬لتصبح الشاشة لدينا كما في‬


‫الشكل التالي‪:‬‬

‫‪49‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫اآلن قم بالضغط على زر )‪ (Apply‬و الموجود في أسفل يمين‬


‫الشاشة لتطبيق اإلعدادات الجديدة لتظھر لك شاشة شبيھة بالشاشة‬
‫التالية‪:‬‬

‫و التي تقوم بعرض المنصات التي قمنا بتحميلھا سابقا أثناء عملية‬
‫تنصيب حزمة التطوير ‪.‬‬

‫قم بالضغط على زر موافق إلغالق النافذة و اآلن انتھينا من عملية‬


‫إعداد بيئة التطوير و كل توابعھا بشكل كامل و لننتقل للخطوة التالية‬
‫للتعرف أكثر على بيئة التطوير و كيفية التعامل معھا‪.‬‬
‫‪50‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫برنامجك األول‬

‫لربما و قبل اإلبحار في البرمجة دعنا نمتع أعيننا بالتطبيق األول و‬


‫نشاھد مدى سھولة العمل حيث أننا سنقوم ببناء تطبيقان األول و‬
‫الذي تعارف عليه لدى كل لغات البرمجة باسم )‪(Hell World‬‬
‫)أھال بالعالم( و الذي يعني لحظة والدة التطبيق األولى و التي خرج‬
‫بھا إلى العالم و يبدأھم التحية‪.‬‬

‫إال أني أرى أن )أندرويد ببساطة( أسھل و لذا سنبني تطبيق أندرويد‬
‫ببساطة و بكل بساطة و بدون سطر برمجي واحد و بعد أن نقوم‬
‫ببناء التطبيق و التعرف على خطوات بدء مشروع جديد سنقوم‬
‫بإعداد محاكي جھاز أندرويد لتستطيع تشغيل برنامجك عليه‪.‬‬
‫إن كنت قد قمت بإغالق بيئة التطوير )‪ (Eclipse‬فقم بإعادة‬
‫تشغيلھا اآلن لتظھر لنا الشاشة الرئيسية‬

‫‪51‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫من القائمة العليا ملف )‪ (File‬قم باختيار )‪ (New‬ثم ) ‪New‬‬


‫‪ (Project‬أي مشروع جديد كما ھو موضح بالصورة التالية‬

‫عن الضغط على زر مشروع جديد ستظھر لك شاشة توصيف‬


‫المشروع و ھي شبيھة بالشكل التالي‬

‫‪52‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫اختر منھا مشروع أندرويد كما الصورة التالية‬

‫ثم اضغط على زر التالية )‪ (Next‬لتظھر لك الشاشة التالية‬

‫‪53‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫حيث سنقوم فيھا بكتابة اسم المشروع و اسم التطبيق و اسم‬


‫الحزمة و النشاط و تحديد المنصة الھدف و التي في حالتنا ھذه ھي‬
‫الوحيدة )‪ (1.6‬اآلن قم بمليء الفراغات بالمعلومات التالية لتصبح‬
‫لديك شاشة شبيھة بھذه ‪:‬‬

‫‪Project Nam: AndroidVerySimple‬‬


‫‪Build Target: 1.6‬‬
‫‪Application Name:VerySimple‬‬
‫‪Package name:com.book.VerySimple‬‬
‫‪Create Activity:Activity_VerySimple‬‬
‫‪54‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫ثم اضغط على زر إنھاء )‪ (Finish‬ليتم فتح مشروع جديد بالشكل‬


‫التالي‬

‫اآلن دعنا نتعرف على ماذا قام المعالج ببنائه لنا و ذلك بسرد أبناء‬
‫العنصر لتكون بالشكل التالي‬

‫اآلن قم فتح العنصر )‪ (Res‬ليظھر تحته )‪ (Layout‬ومن ثم قم‬


‫بالنقر مرتين على الملف )‪ (main.xml‬لتظھر لك شاشة تطبيقك‬
‫‪55‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫األولى و نرى أن أندرويد يجبرنا أن نرحب بالعالم بوضع ) ‪Hello‬‬


‫‪ (World‬و ھذا ما سيظھر على الشاشة عند تشغيل البرنامج‬

‫اآلن ال داعي لتعرف أكثر من ذلك و لنقم بتشغيل تطبيقنا األول و‬


‫لكن في البداية علينا إعداد تطبيق المحاكي و لذا فلننتقل للخطوة‬
‫التالية‬

‫‪56‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫بناء مشروع جديد عن طريق سطر األوامر‬

‫في حال لم تكن تملك )‪ (Eclipse‬أو واجھت مشكلة أثناء عملية‬


‫بناء معالج مشروع جديد فيمكنك دائما بناء المشروع عن طريق‬
‫سطر األوامر‬

‫في البداية علينا تعريف مسار سطر األوامر في النظام ليتعرف عليھا‬
‫عند طلبھا في أي مسار و ذلك عن طريق الذھاب إلى جھاز‬
‫الكمبيوتر من على سطح المكتب أو من القائمة إبداء و بالضغط على‬
‫أيقونة جھاز الكمبيوتر بزر الفأرة األيمن و من ثم الذھاب إلى‬
‫خصائص )‪ (Properties‬ومن ثم الذھاب إلى لسان تبويب خيارات‬
‫متقدمة )‪ (Advanced‬لتظھر لنا بالشكر التالي‬

‫‪57‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫ثم اضغط على زر )‪ (Environment Variables‬وعندھا‬


‫ستظھر لنا شاشة المسارات كما الشكل التالي‬

‫‪58‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫في القسم العلوي و تحت بند )‪ (User Environment‬اختر زر‬


‫جديد )‪ (New‬لتعريف مسار جديد لتظھر شاشة جديدة بالشكل‬
‫التالي‬

‫سنقوم بملء الشاشة بالمعلومات التالية‬

‫في مربع االسم )‪ (Name‬نكتب كلمة )‪ (Path‬و في مربع القيمة‬


‫)‪ (Variable Value‬نضع مسار مجلد األدوات الموجود داخل‬
‫مجلد حزمة التطوير و الذي قمنا بفك ضغطه سابقا على سطح‬
‫المكتب و لتكن بالشكل التالي‬
‫‪C:\Documents and Settings\UserName\Desktop\android-sdk-windows\tools‬‬

‫حيث أن )‪ (UserName‬ھو اسم المستخدم الحالي للنظام أو في‬


‫حال قمت بفك ضغط الملف في أي مكان أخر فاذھب إليه و انسخ‬
‫عنوان المسار كامال مع مجلد )‪ (tools‬و ضعه في القيمة‬

‫‪59‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫ثم اضغط موافق )‪ (OK‬ليتم إضافة المسار الجديد ليكون بالشكل‬


‫التالي‬

‫‪60‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫ثم بعد ذلك اضغط على زر موافق )‪ (OK‬ثم مرة أخرى للشاشة‬
‫الرئيسية اضغط موافق )‪(OK‬‬

‫اآلن لتجرب استخدام األوامر من سطر األوامر قم بالذھاب إلى‬


‫تشغيل من قائمة ابدأ )‪ (Start >> Run‬و اكتب األمر )‪(CMD‬‬
‫ثم اضغط على موافق كما في الشكل التالي‬

‫‪61‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫عندما تضغط على زر موافق )‪ (OK‬ستظھر لك شاشة سوداء و‬


‫ھي شاشة سطر األوامر و الشبيھة بالشكل التالي‬

‫في البداية لنتعرف على المنصات المتواجدة في جھازنا و ترقيمھا‬


‫في الجھاز و ذلك عبر كتابة األمر التالي‬

‫‪android list target‬‬

‫ثم اضغط زر اإلدخال )‪(Enter‬‬

‫ستجد قائمة المنصات لديك كما في الشكل التالي‬

‫‪62‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫وفي حالتنا ھذه ال يتوفر لدينا سوى منصة واحدة رقمھا )‪ (1‬و التي‬
‫سنستخدمھا لبناء المشروع الخاص بنا عبر سطر األوامر‬
‫االن لنجرب بناء مشروع جديد عن طريق سطر األوامر فلذا علينا‬
‫كتابة األمر التالي‬
‫‪android create project -n AndroidVerySimple -p c:\1\ -k‬‬
‫‪com.book.VerySimple -a Activity_VerySimple -t 1‬‬

‫مالحظة )سطر األوامر السابق يكتب على سطر واحد و لكن النص‬
‫ھنا تم تقسيمه على سطرين لدواعي الكتاب(‬

‫حيث أن‪:‬‬

‫)‪ (AndroidVerySimple‬اسم المشروع )‪(Project Name‬‬


‫و نستخدم البارمتر التالي لتعريفھا )‪(-n‬‬

‫‪63‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫)‪ (com.book.VerySimple‬اسم الحزمة ) ‪Package‬‬


‫‪(Name‬و نستخدم البارمتر التالي لتعريفھا )‪(-k‬‬

‫)‪ (Activity_VerySimple‬اسم النشاط )‪ (Activity Name‬و‬


‫نستخدم البارمتر التالي لتعريفھا )‪(-a‬‬

‫)\‪ (c:\1‬ھو مسار المشروع الذي سوف يتم تخزينه على جھاز‬
‫)‪(Path‬و نستخدم البارمتر التالي لتعريفھا )‪(-p‬‬

‫)‪ (1‬المنصة التي نستھدفھا و التي استعرضنا رقمھا في الخطوة‬


‫السابقة )‪ (Target‬و نستخدم البارمتر التالي لتعريفھا )‪(-t‬‬

‫بعد االنتھاء من كتابة سطر األمر كما ھو بالكامل و الضغط على زر‬
‫اإلدخال )‪ (Enter‬ستظھر لنا الشاشة التالية‬

‫يمكنك اآلن تصفح ملفات المشروع داخل المجلد الذي قمنا بتحديده‬
‫سابقا )‪ (c:\1‬و الذي يمكنك أيضا اختيار نفس مساحة المشاريع‬
‫‪64‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫التي يستخدمھا )‪ (Eclipse‬في بناء المشاريع و التي تكون بالعادة‬


‫على المسار التالي‬

‫‪C:\Documents and Settings\UserName\workspace‬‬

‫لتستعرض الملفات التي قام المعالج عبر سطر األوامر بإنشائھا‬


‫فلتذھب للمسار لتجد ملفات المشروع بالشكل التالي‬

‫‪65‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫إعداد محاكي )‪(Android‬‬

‫من الشاشة الرئيسية لبيئة التطوير اذھب إلى القائمة )‪(Window‬‬


‫و من ثم اختر العنصر ) ‪Android SDK and AVD‬‬
‫‪ (Manager‬كما ھو موضح بالشاشة التالية‬

‫لتظھر لك الشاشة التالية‬

‫‪66‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫في حال واجھتك مشكلة ولم تفتح ھذه الشاشة فال تقلق فيمكنك‬
‫دائما تشغيلھا بشكل يدوي عبر الذھاب إلى المجلد الذي قمنا به بفرد‬
‫حزمة التطوير و الذي يتواجد على سطح المكتب باسم )‪android-‬‬
‫‪ (sdk-windows‬و قم بتشغيل البرنامج )‪ (SDK Setup‬و في‬
‫حال لم يعمل معك أيضا فال تقلق فھناك طريقة أخرى يمكن فيھا أن‬
‫نبني المحاكي عن طريق سطر األوامر و التي سنتحدث عنھا في‬
‫أخر ھذا الجزء‪.‬‬

‫لنفترض بأن كل ما لديك يعمل بشكل سليم و ظھرت الشاشة السابقة‬


‫فلتذھب إلى الخيار )‪ (Virtual Devices‬و من ثم اضغط على زر‬
‫)‪ (New‬في أعلم يمين الشاشة لتظھر لك شاشة إعداد جھاز‬
‫افتراضي جديد‪.‬‬

‫‪67‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫في الشاشة السابقة سنقوم بتعريف بيانات الجھاز االفتراضي و ذلك‬


‫بتحديد اسم خاص بنا و من ثم اختيار إصدارة نظام التشغيل مما قمنا‬
‫بتحميلھا سابقا أثناء عملية إعداد حزمة التطوير وفي حالتنا ھذه لن‬
‫يتواجد لدينا سوى اإلصدارة )‪ (1.6‬و من ثم نعرف الملحقات التي‬
‫يدعمھا الجھاز و منھا كرت ذاكرة داخلي )‪ (SD‬و بعض الملحقات‬
‫اإلضافية و التي سنتعرف على كيفية التعامل معھا الحقا‪.‬‬

‫اآلن قم بكتابة اسم المحاكي )‪ (VM_Android1.6‬و اختر‬


‫إصدارة نظام التشغيل )‪ (1.6‬و من ثم قم بتحديد حجم كرت الذاكرة بـ‬
‫)‪ (500‬ميجا و التي سنحتاجھا الحقا لكي نقوم بتحميل التطبيقات و‬
‫الملفات عليھا من سوق التطبيقات و التعرف على التطبيقات‬
‫الموجودة و نوعيتھا لنستطيع بناء تطبيقات مشابھة و بعد ذلك‬

‫‪68‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫سنقوم بإضافة العتاد عن طريق القسم )‪ (Hardware‬و اختيار زر‬


‫)‪ (New‬فتظھر لنا الشاشة التالية‬

‫بما أننا اخترنا حجم كرت الذاكرة فعلينا دعم خاصية كرت الذاكرة و‬
‫لذا سنضيف )‪ (SD Card Support‬و من ثم سنضغط على زر‬
‫)‪ (OK‬و نكرر نفس العملية بالضغط على زر )‪ (New‬إلضافة عتاد‬
‫جديد و لنختر كل من‬
‫‪GPS Support‬‬
‫‪Accelerometer‬‬
‫لتظھر لنا الشاشة النھائية بالشكل التالي‬

‫‪69‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫بعد ذلك قم بالضغط على زر )‪ (Create AVD‬و انتظر قليال ليتم‬


‫بناء المحاكي و بعدھا ستظھر لنا رسالة مفادھا بأنه تم بناء لمحاكي‬
‫بنجاح كما في الشكل التالي‬

‫و بعد الضغط على زر موافق )‪ (OK‬سيظھر الجھاز ضمن قائمة‬


‫األجھزة كما في الشكل التالي‬

‫‪70‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫االن لتشغيل الجھاز ما عليك سوى تحديده و من ثم الضغط على زر‬


‫)‪ (Start‬و عندھا ستظھر لنا شاشة بالشكل التالي تجاھلھا للوقت‬
‫الحالي و اضغط )‪(Launch‬‬

‫االن سيبدأ المحاكي بالعمل ليظھر لنا بالشكل التالي‬

‫‪71‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫بعد أن شغلنا المحاكي و الذي يحاج بعض الوقت إلقالع نظام‬


‫التشغيل الداخلي إذا أردت أن تتجول في الجھاز فلك ذلك و لكن بعد‬
‫ذلك فلنعود إلى بيئة التطوير لنقوم بتشغيل برنامجنا األول و ذلك‬
‫عبر الذھاب إلى اسم المشروع في رأس الشجرة و الضغط بزر‬
‫الفأرة األيمن و من ثم اختيار )‪ (Run As‬ومن ثم من القائمة‬
‫الفرعية اختر )‪(Android Application‬‬

‫‪72‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫و ستجد أن التطبيق الخاص بك سيظھر في المحاكي و ھي عبارة‬


‫عن شاشة فقط تحتوي على سطر وحيد )‪(HelloWorld‬‬

‫‪73‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫في حال واجھت مشكلة عند محاولة تشغيل تطبيقك و ذلك بسبب أنه‬
‫أحيانا معالج إعداد المشروع ال يقوم ببناء كامل المراجع في ملفات‬
‫المشروع المتنوعة وستظھر لك رسالة خطأ شبيھة بالتالية‬

‫فلذلك إما عليك أن تغلق المشروع و تعيد فتحه أو تقوم بالذھاب إلى‬
‫القائمة )‪ (Project‬ومن ثم اختيار خيار )‪ (Clean‬كما في الصورة‬
‫التالية‬

‫‪74‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫و بعد ذلك ستظھر لك شاشة كما في الشكل التالي اضغط على زر‬
‫موافق )‪(OK‬‬

‫ستالحظ أنه كانت ھناك عالمة )‪ (X‬صغيرة حمراء كانت على اسم‬
‫المشروع في أعلى الشجرة و بعد ھذه العملية ستختفي ھذه العالمة‬
‫و عليك اآلن أن تكرر الخطوة السابقة لتشغيل تطبيقك على المحاكي‪.‬‬

‫‪75‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫التعامل مع الجھاز االفتراضي عن طريق سطر األوامر‬

‫كما ذكرنا سابقا كيف يمكن إنشاء مشروع جديد عن طريق سطر‬
‫األوامر دعنا نتعلم كيفية التعامل مع المحاكي عن طريق سطر‬
‫األوامر و لكن من المفروض أنك قمت بإضافة ) ‪Environment‬‬
‫‪ (Variables‬كما تعلمنا ذلك عندما شرحنا كيف تبدأ مشروع جديد‬
‫و في حال قمت بذلك سابقا فال حاجة لتكرار األمر و عليك الذھاب‬
‫مباشرة لتشغيل سطر األوامر‬

‫قم بالذھاب إلى تشغيل من قائمة ابدأ )‪ (Start >> Run‬و اكتب‬
‫األمر )‪ (CMD‬ثم اضغط على موافق كما في الشكل التالي‬

‫عندما تضغط على زر موافق )‪ (OK‬ستظھر لك شاشة سوداء و‬


‫ھي شاشة سطر األوامر و الشبيھة بالشكل التالي‬

‫‪76‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫اآلن قم بتجربة كتابة األمر التالي الكتشاف ملف المساعدة و‬


‫البارامتر المختلفة التي يمكن استخدامھا إلنشاء جھاز‬

‫‪Android –h‬‬

‫و من ثم اضغط على زر اإلدخال )‪(enter‬‬

‫)‪ (android -h‬حيث أن المتغير )‪ (h‬الذي قمنا بتمريره لألمر‬


‫)‪ (android‬يطلب منه عرض ملف المساعدة و الذي يشرح كل‬
‫المتغيرات الممكنة و ستظھر لنا قائمة كبيرة يمكن اإلطالع عليھا و‬
‫ھي شبيھة بھذه الشاشة‬

‫‪77‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫مثال في حال أردنا إضافة جھاز افتراضي جديد جرب السطر التالي‬
‫أوال لمعرفة المنصات و أرقامھا لديك‬

‫‪android list target‬‬

‫ثم اضغط زر اإلدخال )‪(Enter‬‬

‫ستجد قائمة المنصات لديك كما في الشكل التالي‬

‫‪78‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫وفي حالتنا ھذه ال يتوفر لدينا سوى منصة واحدة رقمھا )‪ (1‬و الذي‬
‫سنستخدمه لبناء المحاكي الخاص بنا عبر سطر األوامر لكتابة‬
‫السطر التالي ثم الضغط على زر االدخال )‪(Enter‬‬

‫‪android create avd -n VM_Android1.6 -t 1‬‬

‫حيث أن )‪ (VM_Android1.6‬ھو اسم المحاكي و ) ‪create‬‬


‫‪ (avd -n‬يعني إنشاء جھاز افتراضي جديد و البارمتر )‪ (-t‬يحدد‬
‫الواجھة المستخدمة و في حالتنا ھي )‪ (1‬ليظھر لنا المعالج بعد ذلك‬
‫ليسألنا بعض األسئلة عن العتاد الذي نود إضافته و الذي سنجيب‬
‫عليه بـ )‪ (yes‬أو )‪ (No‬فقط أو بالضغط على زر اإلدخال )‪(Enter‬‬
‫ألخذ القيمة االفتراضية التي تكون ضمن القوسين مثال ]‪[yes‬‬

‫‪79‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫مالحظة‪ :‬إن كنت قد قمت ببناء الجھاز المحاكي‬


‫)‪ (VM_Android1.6‬عبر المعالج الرسومي سابقا و جربت‬
‫القيام بنفس الشيء عبر سطر األوامر فستأتيك رسالة بأن االسم قد‬
‫تم حجزه الحقا و تحتاج إلى تغيير اسمه مثال ليكون‬
‫)‪(VM_Android1.6_1‬‬

‫بعد االنتھاء من إنشاء المحاكي و لتشغيله قم بكتابة األمر التالي‬

‫‪emulator -avd VM_Android1.6_1‬‬


‫‪80‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫ليظھر لديك المحاكي‬

‫مالحظة‪ :‬في حال قمت بإغالق نافذة سطر األوامر فأنك ستقوم‬
‫بإغالق المحاكي تباعا الن األمر مازال تحت التشغيل حتى ينتھي و‬
‫لذا في حال قمت بتشغيل المحاكي عن طريق سطر األوامر فانك‬
‫ستحتاج لإلبقاء على شاشة سطر األوامر تعمل في الخلفية أو قم‬
‫بالذھاب إلى حزمة التطوير و تشغيل )‪ (SDK Setup‬لتجد بأن‬
‫المحاكي الجديد الذي قمنا بإنشائه ضمن سطر األوامر موجود‬
‫باإلضافة للسابق ضمن قائمة األجھزة االفتراضية‪.‬‬

‫‪81‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

‫إضافة اللغة العربية إلى المحاكي )يتوجب عليك الحصول على‬


DroidSans-Bold.ttf, :‫ملفات الخطوط‬
(DroidSansFallback.ttf, DroidSans.ttf

adb remount
adb shell rm /system/fonts/*

adb push c:\fontss\DroidSans-Bold.ttf


/system/fonts/
adb push c:\fontss\DroidSansFallback.ttf
/system/fonts/
adb push c:\fontss\DroidSans.ttf /system/fonts/

‫في حال ظھور رسالة خطأ تفيد بعدم وجود مساحة كافية و يمكنك‬
:‫ مثال‬،‫حذف بعض التطبيقات‬
adb shell rm /system/app/AlarmClock.apk

‫تنصيب برنامج من سطر األوامر‬

adb install c:\Vending.apk

82
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫المحاكي و العالم الخارجي‬

‫لنتعرف اآلن على أداة جديدة موجودة ضمن بيئة التطوير تتيح لنا‬
‫التخاطب مع المحاكي و الوصول إلى ملفاته و خصائصه و التعامل‬
‫معه و كأنه جھاز حقيقي لكي نستطيع تجربة كل خصائص الجھاز و‬
‫ھذا بالتأكيد ال يغني عن تجربة تطبيقك النھائي على جھاز حقيقي‬
‫لتعرف كيفية عمله‬

‫أداة )‪(DDMS‬‬

‫أفترض حاليا أنك قد قمت بتشغيل بيئة التطوير )‪ (Eclipse‬و علينا‬


‫تشغيل أداة )‪ (DDMS‬و ذلك من أعلى يمين الشاشة قم بالضغط‬
‫على زر اإلضافة )‪ (+‬لتظھر لنا قائمة كما الشكل التالي‬

‫قم باختيار )‪ (DDMS‬لتصبح ضمن محتويات الشاشة و يمكن‬


‫الوصول لھا مباشرة و لتظھر لنا الشاشة التالية‬

‫‪83‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫االن ستالحظ بأن )‪ (DDMS‬أصبحت في األعلى و التي يمكن‬


‫التحويل ما بينھا و ما بين بيئة التطوير )‪ (Java‬لسھولة الوصول و‬
‫التنقل‬

‫الخطوة التالية تقتضي بأن نقوم بتشغيل المحاكي بأي من الطرق‬


‫السابقة التي قمنا بشرحھا ليتعرف عليھا )‪ (DDMS‬و يمكننا من‬
‫التواصل معھا لتظھر لنا شاشة شبيھة بالشكل التالي بعد تشغيل‬
‫المحاكي‬

‫‪84‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫كما ترى فإنه يمكنك الوصول لملفات الجھاز بالكامل و كذلك الحال‬
‫لكرت الذاكرة الداخلي من الجھة اليمنى العلوية )‪(File Explorer‬‬
‫و معرفة العمليات التي تعمل في الخلفية )‪ (Threads‬أو )‪(Heap‬‬
‫أو )‪(Allocation Tracker‬‬

‫يمكنك من قائمة )‪ (File Explorer‬اختيار المجلد مثال و ليكن‬


‫كرت الذاكرة )‪ (sd card‬و من ثم من أعلى القائمة اختيار زر‬
‫ھاتف الجوال لسحب ملف من جھاز الكمبيوتر إلى المحاكي أو‬
‫اختيار زر الحفظ لنسخ ملف من المحاكي إلى جھاز الكمبيوتر‪.‬‬
‫تنويه‪ :‬قم بالتعرف على ھيكلية ملفات النظام و قم بنسخ الملفات‬
‫على جھازك و اعرف كيفية بنيتھا لتعرف الحقا كيف يتعامل النظام‬
‫معھا أو حال في أردت تغيرھا مثال )تغيير ملفات الرنين( أو صورة‬
‫الخلفية‪.‬‬

‫في الجھة اليسرى ستجد قائمة باألجھزة )‪ (Devices‬التي تعمل‬


‫حاليا حتى لو قمت بشبك جھاز فعلي و قمت بتعريف ) ‪USB‬‬
‫‪85‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫‪ (Driver‬و الموجود ضمن حزمة التطوير )‪ (SDK‬فإنك ستجد‬


‫الجھاز بھذه القائمة و يمكن الوصول لملفاته الداخلية و التعامل معه‬
‫كما لو أنه محاكي‪.‬‬

‫تحت قائمة األجھزة توجد قائمة التحكم بالمحاكي ) ‪Emulator‬‬


‫‪ (Control‬و التي تمكنك من التخاطب مع الجھاز كما لو أنه فعلي‬
‫فعلى سبيل المثال تستطيع كتابة رقم ھاتف و االتصال فيظھر على‬
‫شاشة المحاكي بأن ھناك اتصال وارد من الرقم الذي كتبته و كذلك‬
‫الحال في حال أردت إرسال رسالة نصية )‪ (SMS‬أو أردت أن‬
‫ترسل مكان عبر التوضع العالمي )‪ (GPS‬عبر تمرير خطي الطول‬
‫و العرض )‪ (Longitude‬و )‪ (latitude‬في حال كان تطبيق‬
‫يعتمد مثال على جھاز )‪. (GPS‬‬

‫‪86‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫تدريب‬

‫ما رأيك اآلن لو تقوم بالعمل على المحاكي قليال و تحميل بعض‬
‫التطبيقات المجانية من سوق البرامج لتتعرف أكثر على ھذه البرامج‬

‫من شاشة جھاز المحاكي قم بالذھاب إلى متصفح االنترنت‬


‫)‪ (Browser‬كما في الشكل التالي‬

‫‪87‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫قد تظھر لك الشاشة بھذا الشكل و ذلك بسبب أن المحاكي يقوم‬


‫بالتعرف على إعدادات الجھاز لديك و يرسلھا للموقع و الذي يأتي‬
‫بالواجھة العربية و بما أن المحاكي ال يحتوي على الخطوط العربية‬
‫حتى اآلن و لذا قم باختيار )‪ (Google.com in English‬للتحول‬
‫إلى الواجھة االنجليزي‬

‫تنويه‪ :‬المحاكي يقوم بالحصول على االنترنت مباشرة من جھازك‬


‫فلذا ال بد من أن يكون جھاز الكمبيوتر لديك متصل باالنترنت‬

‫‪88‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫و قم بكتابة العنوان التالي للذھاب إلى أحد مواقع سوق البرامج‬


‫العامة )‪(slideme.org‬‬

‫‪89‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫اآلن اذھب إلى الموقع في القائمة‬

‫وقم بالضغط على الزر األحمر )‪ (SAM v2.42‬ليبدأ في تحميل‬


‫البرنامج على جھازك‬

‫‪90‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫بعد انتھاء تحميل البرنامج بعمل تنصيب له و ذلك بالضغط على‬


‫صورة البرنامج‬

‫بعد ذلك ستبدأ عملية تحميل التطبيق على جھازك‬

‫‪91‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫بعد االنتھاء من عملية التحميل عليك أن تقوم بالضغط على زر‬


‫)‪ (Done‬النتھاء عملية التحميل‬

‫في حال لم تتمكن من عملية التحميل فعليك أن تقوم بعمل تعديل‬


‫بسيط في إعدادات النظام للسماح بالتطبيقات الغير موقعه بالتحميل‬
‫على جھازك و بجميع األحوال أنت بحاجة لتفعيل ھذا الخيار‬
‫لتستطيع من تحميل أغلب التطبيقات الموجودة في سوق ) ‪Slide‬‬
‫‪ (Me‬الحقا على جھازك و للقيام بذلك قم بالضغط على زر‬
‫)‪ (Menu‬و آنت على الشاشة الرئيسية لتظھر لك الشاشة التالية‬

‫‪92‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫عند الضغط على زر )‪ (Settings‬ستظھر لك شاشة بخيارات‬


‫اإلعدادات كالتالي‬

‫‪93‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫قم بالضغط على خيار )‪ (Applications‬للوصول إلى القائمة‬


‫الفرعية الخاصة بھا كھذه‬

‫قم بتمكين الخيار االول )‪ (Unknown sources‬إن لم يكن كذلك‬


‫ليصبح كما الشاشة التالية و كذلك الحال تحتاج لتطبيق ذلك في‬
‫جھازك الفعلي إن أردت التجربة عليه و بعد ذلك اضغط أيضا على‬
‫الخيار)‪ (Development‬لتظھر لك شاشة شبيھة بالتالية‬

‫‪94‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫قم بعبرھا بتمكين الثالث خيارات في حال لم تكن كذلك و ھي‬


‫الخاصة بتمكين التعامل مع )‪ (DDMS‬و تسھيل عملية متابعة‬
‫األخطاء و البرمجة على األجھزة و كذلك الحال تحتاج إلى عمل‬
‫نفس الخطوات على جھازك الفعلي في حال أردت التجربة عليه‬
‫االن عبر سھم الرجوع قم بالضغط عليه عدة مرات للعودة إلى‬
‫الشاشة الرئيسية و حفظ اإلعدادات التي قمنا بھا‬

‫االن من قائمة البرامج قم بتشغيل برنامج )‪ (Slide Me‬لتظھر‬


‫الشاشة التالية و التي تحتوي على تصنيفات فرعية ألنواع‬
‫التطبيقات الموجودة و عند تشغيل البرنامج ألول مرة ستظھر لك‬
‫شاشة اتفاقية االستخدام قم بالموافقة عليھا لتظھر لك شاشة‬
‫البرنامج‬

‫قم باستكشاف أنواع التطبيقات في كل قسم و حمل منھا ما تشاء‬


‫فمنھا ما ھو مجاني و منھا ما ھو مدفوع و في حال أردت تجربة‬
‫التطبيقات المدفوعة فأنت تحتاج للتسجيل في موقع‬
‫‪95‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫)‪ (slideme.org‬و تخزين بيانات بطاقاتك االئتمانية و تأكيد‬


‫ملكيتك لھا عبر عملية تتم أثناء التسجيل مما يتيح لك الشراء‬
‫مباشرة من التطبيق و تقييد المبالغ مباشرة من الموقع على حساب‬
‫بطاقتك االئتمانية دون الحاجة لمعرفة الطرف الثالث لبيانات بطاقة‬
‫االئتمانية أو إلدخال بياناتك مرة أخرى في أي مكان‬

‫فلنجرب اآلن تحميل تطبيق من القائمة )‪ (Utilities‬و ھو تطبيق‬


‫قائمة المشترٮات )‪ (OI Shopping List‬للتعرف عليه و من ثم‬
‫في األجزاء القادمة لنقوم ببناء تطبيق مشابه بقائمة المھام‬

‫من القائمة )‪ (Utilities‬ابحث عن البرنامج ) ‪OI Shopping‬‬


‫‪(List‬‬

‫اضغط عليه لتظھر لك شاشة بمعلومات البرنامج و التي يمكنك أن‬


‫تتعرف فيھا أكثر عن معلومات التطبيق باإلضافة إلى صور عن‬
‫‪96‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫واجھة البرنامج و سعره و ما إلى ذلك من أمور مع العلم أن ھذا‬


‫البرنامج مجاني بل و يمكن تحميل الشفرة المصدرية الخاصة به من‬
‫موقع المبرمج و الذي سندل عليه الحقا في جزء المصادر‬

‫قم بالنقر على زر )‪ (Terms & Download‬لتظھر لك شاشة‬


‫اتفاقية االستخدام‬

‫‪97‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫بعد ذلك قم بالنقر على زر )‪ (Install‬لتبدأ عملية التحميل و التي‬


‫ستكون في قائمة اإلنذارات العلوية )‪ (Notifications‬إذ يقوم فيھا‬
‫بعملية تحميل البرنامج على جھازك في الخلفية و يمكنك الوصول‬
‫لھا عبر تمرير القائمة العلوية و التي تظھر فيھا معلومات البطارية‬
‫و الساعة‬

‫بعد انتھاء البرنامج من التحميل اضغط عليه لتبدأ عملية التنصيب‬


‫على جھازك‬

‫‪98‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫تقوم بالضغط على زر )‪ (Install‬لتظھر لك شاشة انتھاء التحميل‬


‫بعد لحظات‬

‫قم بالضغط على زر )‪ (Open‬لتشغيل البرنامج‬

‫مالحظة الملفات التي تقوم بتحميلھا يتم وھي من نوع )‪ (apk‬و يتم‬
‫االحتفاظ بھا في مجلد )‪ (Download‬في ذاكرة الجھاز الخارجية‬
‫)‪ (SD Card‬و لتستطيع تنصيبھا على جھاز أخر دون الحاجة‬
‫إلعادة الخطوات أو وجودة ‪ Slide Me‬أنت بحاجة لوجود تطبيق‬
‫أسمة )‪ (Apps Installer‬و الذي يقوم بالبحث عن الملفات من‬
‫نوع )‪ (apk‬على جھازك و تمكينك من تنصيبھا مباشرة و يمكنك‬
‫الحصول على ھذا التطبيق من موقع )‪(Slide Me‬‬

‫‪99‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫قم باستكشاف البرنامج و التعرف على كيفية التعامل مع تطبيق‬


‫فعلي على أندرويد لتستطيع التعرف على كيفية القيام ببناء واجھات‬
‫تطبيق مشابھة بنفسك‪.‬‬

‫تنويه ‪:‬يمكنك و عبر أداة )‪ (DDMS‬أن تقوم بأخذ صور عن شاشة‬


‫المحاكي و ذلك من القائمة )‪ (Devices‬ثم الذھاب إلى زر األدوات‬
‫)شكل صورة( )‪ (Screen Capture‬و يمكنك أن تقوم بأخذ‬
‫صورة من المحاكي و حفظھا على جھازك كما قمت أنا بذلك عند‬
‫شرح ھذا التدريب‬
‫دلع المحاكي‬
‫مارأيك لو تقوم بتغيير شكل المحاكي لديك ليصبح بشكل الجھاز‬
‫ما عليك سوى الذھاب إلى المجلد‬

‫‪android-sdk-windows\platforms\android-1.6\skins\HVGA‬‬

‫و من ثم التالعب بالصور الموجودة في حال أردت مثال تغيير صورة‬


‫الجھاز لتصبح كالتالي‬

‫‪100‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫بناء مشروعك الثاني )قائمة المھام(‬

‫الخطوات األولى في ھذا الكتاب كانت تركز على تعريفك على بيئة‬
‫التطوير و كيفية تھيئتھا و تعليمك أساسيات التعامل معھا و لم نقم‬
‫بكتابة أي سطر كود حتى اآلن و لذا فعلينا البدء في التشمير عن‬
‫ساعدينا و كتابة أول برنامج فعلي يحتوي على بعض الكود و الذي‬
‫سنشرح بداخله المزيد عن بيئة التطوير و كيفية التعامل معھا‪.‬‬

‫اختياري وقع على برنامج قائمة المھام باألساس ألنه ال يأتي ضمنيا‬
‫مع نظام التشغيل كما أنه بسيط في فھم وظيفته و بنفس الوقت فھو‬
‫يستخدم الكثير من الخصائص التي سنتعلم منھا أساسيات البرمجة‬
‫الموجھة الندرويد و منھا التعامل مع أكثر من شاشة )نشاط( و حفظ‬
‫المھام و بناء قائمة أوامر و غيرھا من المميزات التي تكسبنا المزيد‬
‫من المھارة‪.‬‬

‫قم اآلن بتشغيل بيئة التطوير )‪ (Eclipse‬و ابدأ في إعداد مشروع‬


‫جديد و لنسيمه )‪ (Task List‬ليكون في الشكل التالي‪:‬‬

‫‪101‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫بعد أن تظھر لنا شاشة ملفات المشروع كما في الشكل التالي‬

‫‪102‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫لربما تالحظ وجود عالمة )‪ (X‬باللون األحمر على رأس الشجرة و‬


‫التي تدل على وجود خطاء في المشروع و لتصحيحھا قم باستخدام‬
‫)‪ (Project >> Clean‬كما ذكرنا سابقا عندما قمنا ببناء أول‬
‫مشروع و ذلك لتنظيف المشروع من أي أخطاء بسبب المعالج‪.‬‬

‫لنستعرض الكود البرمجي و الذي قام المعالج بإنشائه ألول شاشة‬


‫)نشاط( لنا بشكل افتراضي و لنذھب إلى مجلد )‪ (src‬و من تحته‬
‫نذھب إلى الحزمة )‪ (com.android.TaskList‬ومن ثم من‬
‫تحتھا نقوم بالنقر المضاعف على الملف )‪(Activity_TaskList‬‬
‫ليظھر لنا الكود األساسي و الذي قام النظام بإضافته و المسئول عن‬
‫تشغيل الشاشة الرئيسية و التي تحتوي فقط و بشكل افتراضي على‬
‫مربع عنوان يحتوي أسم المشروع‬

‫‪103‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫كما يمكنك استعراض الشاشة )شكل النشاط( الذي قامت بيئة‬


‫التطوير ببنائه بشكل افتراضي و ذلك تحت مجلد المصادر )‪ (res‬ثم‬
‫اختيار )‪ (layout‬و من تحتھا بالنقر المضاعف على الملف‬
‫)‪ (main.xml‬ليظھر لدينا شكل الشاشة كما الصورة التالية‬

‫‪104‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫من أعلى لسان التبويب )‪ (main.xml‬قم بتغيير شكل الشاشة‬


‫لتصبح بشكل طولي بدال من شكل عرضي للتحكم أكثر في شكل‬
‫الشاشة االفتراضية عندما تعمل على الجھاز ‪ ،‬قم بتغيير الخاصية‬
‫)‪ (Config‬من القيمة )‪ (Landscape‬إلى القيمة )‪(Portrait‬‬
‫لتتغير شكل الشاشة قليال و تصبح بالشكل التالي‬

‫‪105‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫من القائمة اليسرى بجانب الشاشة ھناك مربعين باسم )‪(Layout‬‬


‫و )‪ (Views‬و التي يمكنك أن تقوم بسحب عناصرھا مباشرة و‬
‫وضعھا على الشاشة و لكننا سنذھب إلى الملف المصدري لنتعرف‬
‫أكثر على ھيكلية الكود و نقوم بعمله بشكل يدوي لنحترف العمل‬
‫عليه‪.‬‬

‫تحت الشاشة في الناحية اليسرى ستجد لسان تبويب )‪(main.xml‬‬


‫و )‪ (layout‬قم بالتغيير إلى )‪ (main.xml‬لتظھر لك الشاشة‬
‫التالية‪:‬‬

‫‪106‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

‫لنتعرف على األكواد المكتوبة‬

1 <?xml version="1.0" encoding="utf-8"?>


2<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/andr
oid"
3 android:orientation="vertical"
4 android:layout_width="fill_parent"
5 android:layout_height="fill_parent"
6 >
7 <TextView
8 android:layout_width="fill_parent"
9 android:layout_height="wrap_content"
10 android:text="@string/hello"
11 />
12 </LinearLayout>
107
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫لقد قمت ھنا بترقيم األسطر لسھولة الرجوع لھا كما و يمكنك أنت‬
‫أيضا أن تقوم بإظھار أرقام األسطر من داخل بيئة التطوير‬
‫)‪ (Eclipse‬و ذلك بالضغط بزر الفأرة األيمن على أقصى اليسار من‬
‫سطر الكود في المنطقة الفارغة و من ثم من القائمة المنسدلة قم‬
‫بتحديد خيار )‪(Show Line Numbers‬‬

‫لتظھر لنا الشاشة كما في الشكل التالي و التي تحتوي أرقام أسطر‬
‫الكود البرمجي لنستطيع اإلشارة إليھا الحقا‬

‫‪108‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

‫االن و بالعودة إلى الكود و شرحه‬

1 <?xml version="1.0" encoding="utf-8"?>

‫( الدولي‬UTF-8) ‫( المعياري و ترميز‬XML) ‫فتح ترويسة ملف‬


‫لدعم كل اللغات‬

2<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/andr
oid"
3 android:orientation="vertical"
4 android:layout_width="fill_parent"
5 android:layout_height="fill_parent">

109
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫األسطر من )‪ (2‬و حتى )‪ (6‬ھي عبارة عن سطر واحد و لكنه موزع‬


‫إلى عدة أسطر لسھولة القراءة و يمكنك تغيير ذلك أو اإلبقاء على‬
‫ذلك‬

‫المھم في ھذا السطر ھو اختيار طريقة العرض‬


‫)‪ (LinearLayout‬و التي كما ذكرنا في أول الكتاب أحدى طرق‬
‫العرض من أًل )‪ (4‬طرق عرض مختلفة و التي تقضي برصف‬
‫العناصر بشكل متتالي من األعلى إلى األسفل تباعا‬

‫ما بداخل الوسم )‪ (LinearLayout‬ھناك مجموعة من الخصائص‬


‫التي تحدد طريقة العرض و لعل من أھمھا الخاصية‬
‫)‪ (orientation‬و التي توصف طريق الرصف المتتالي بشكل‬
‫عامودي أو أفقي و ھي و بشكل افتراضي تقوم بالرصف بشكل‬
‫عامودي و يمكن تغيرھا لتصبح بشكل أفقي إال بالخاصية‬
‫)‪ (horizontal‬و كذلك الحال الخاصيتين )‪ (layout_width‬و‬
‫)‪ (layout_height‬و التي تحدد مكان توضع كل عنصر و التي‬
‫تأخذ القيمة )‪ (fill_parent‬أي تعبئة المساحة األب و في ھذه‬
‫الحالة في حال كان الشكل عاموديا كما ھو افتراضي فإن كل عنصر‬
‫سيقوم بتعبئة اسكر من أقصى يسار الشاشة إلى أقصى يمين‬
‫الشاشة أما في حال كان العرض أفقيا فأنه سيتم التعبئة من األعلى‬
‫إلى األسفل‬
‫‪7 <TextView‬‬
‫"‪8 android:layout_width="fill_parent‬‬
‫"‪9 android:layout_height="wrap_content‬‬
‫>‪10 android:text="@string/hello"/‬‬

‫‪110‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫من السطر )‪ (7‬و حتى السطر )‪ (11‬ھو سطر واحد لتوصيف كائن‬
‫نصي و التي تم توزيعه على عدة سطور لنفس االسباب السابقة‬

‫ھناك بعض الخصائص المشتركة في أغلب العناصر و قد تتغير‬


‫بعضھا بناء على وظيفة العنصر و لكن في حالتنا ھذه سنقوم بشرح‬
‫الخصائص االفتراضية و ھي )‪ (layout_width‬و التي تأخذ‬
‫القيمة الخاصة بتعبئة األب )‪ (fill_parent‬و الخاصية‬
‫)‪ (layout_height‬و التي تأخذ القيمة )‪ (wrap_content‬و‬
‫التي تعني أنه يمكن لھذا العنصر التمدد عاموديا و النزول ألكثر من‬
‫سطر في حال استدعى ذلك بناء على طول النص الداخلي ‪ ،‬أما‬
‫بالنسبة للخاصية )‪ (text‬و التي تأخذ قيمتھا من ملف المصادر‬
‫الخارجي و ھي القيمة التي ستعرض داخل النص و ال يمكن تغييرھا‬
‫مباشرة من ھنا إذ أن )‪ (@string/hello‬ھي عنوان القيمة في‬
‫ملف المصادر و ليست القيمة نفسھا و التي سنتعرف عليھا بعد‬
‫شرح ھذا الكود مباشرة‬

‫>‪12 </LinearLayout‬‬

‫السطر )‪ (12‬ينھي الوسم )‪ (LinearLayout‬و الذي ينھي بذلك‬


‫الكود الخاص بنا‬

‫كما ذكرنا سابقا بأن مربع النص )‪ (TextView‬لديه بعض‬


‫الخصائص و منھا االسم و التي يأخذ قيمتھا من ملف المصادر و‬
‫الذي يمكن الوصول له من ملفات المشروع تحت المجلد )‪ (res‬و‬
‫من ثم مجلد )‪ (Value‬و بعدھا قم بالنقر على اسم الملف )( لتظھر‬
‫الشاشة التالية‬

‫‪111‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫االن يمكننا تعديل قيمة التي بداخل النص من ھنا و ذلك بالضغط‬
‫على اسم المرجع و ليكن مثال )‪ (hell‬ومن ثم عندما تفتح النافذة قم‬
‫بتعديل القيمة من )‪(!Hello World, Activity_TaskList‬‬
‫إلى )‪ (Task List‬لتصبح بالشكل التالي‬

‫‪112‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫االن يمكنك أيضا تغيير المرجع )‪ (app_name‬و تغيير القيمة فيه‬


‫من )‪ (Task List‬إلى )‪ (My 1st Application‬والتي ستغير‬
‫عنوان التطبيق في أعلى النافذة و التي ستظھر عندما نقوم بتشغيل‬
‫البرنامج في المرة القادمة‬

‫بعد ذلك سنضيف مرجع أخر عبارة عن لون خلفية النص لنتعرف‬
‫على كيفية تغيير القيم و استخدامھا‬

‫قم بالضغط على زر )‪ (add‬الموجود بجانب قائمة المراجع لتظھر‬


‫الشاشة التالية‬

‫‪113‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫قم باختيار المرجع )‪ (color‬من ثم اضغط على زر )‪ (OK‬ليظھر‬


‫لدينا عنصر مرجع جديد في القائمة مع تركنا لتعبئة ھذا العنصر‬
‫بالقيم حيث قمنا بتعريف كل من‬
‫‪Name : TextViewBackColor‬‬
‫‪Value: #FF0000‬‬
‫كما في الشاشة التالية‬

‫‪114‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫حيث أن القيمة )‪ (#FF0000‬تستخدم معادلة ألوان )‪ (RGB‬و‬


‫المستخدمة في كود األلوان في )‪ (HTML‬مثال و التي تكون فيھا‬
‫عبارة أن أول خانتين )‪ (FF‬ھي للقيمة )‪ (R‬و التي تعني )‪ (Red‬و‬
‫من ثم الخانتين الالحقتين )‪ (00‬خاصة بالقيمة )‪ (G‬و التي تعني‬
‫)‪ (Green‬و من ثم الخانتين األخيرتين )‪ (00‬خاصة بالقيمة )‪(B‬‬
‫أي )‪ (Blue‬و بذلك يمكن خلط األلوان الرئيسية الثالثة لتكوين لون‬
‫جديد و في حالتنا ھذه قم بوضع قيمة للون األحمر و صفر للونين‬
‫األخضر و األزرق و ذلك للحصول على اللون األحمر فقط‬

‫تحتاج اآلن إلغالق لسان تبويب )‪ (string.xml‬و ذلك لكي يقوم‬


‫بحفظ القيم في المشروع و يمكن استخدامھا في المشروع نفسه‬

‫االن بالعودة إلى الكود الموجود في )‪ (main.xml‬تحت المجلد‬


‫)‪ (layout‬و قمنا بالتعديل على الكود الخاص بمربع النص ليصبح‬
‫بالشكل التالي‬
‫‪<TextView‬‬
‫"‪android:layout_width="fill_parent‬‬
‫"‪android:layout_height="wrap_content‬‬
‫"‪android:text="@string/hello‬‬
‫"‪android:background="@color/TextViewBackColor‬‬ ‫>‪/‬‬

‫حيث أننا قمنا بإضافة الخاصية )‪ (background‬و أسندنا لھا‬


‫المصادر‬ ‫ملف‬ ‫في‬ ‫عرفناھا‬ ‫التي‬ ‫اللون‬ ‫قيمة‬
‫)‪ (TextViewBackColor‬اآلن بعد ھذه التعديالت البسيطة قم‬
‫بتشغيل برنامجك لترى أثر التعديالت التي قمنا بھا‬
‫قد يطلب منك البرنامج حفظ المشروع برسالة فقم بالضغط على زر‬
‫موافق‬
‫‪115‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫و لترى بعدھا تطبيقنا و ھو يعمل على جھاز المحاكي ليكون بالشكل‬


‫التالي‬

‫حيث أن عنوان التطبيق أصبح )‪ (My 1st Application‬و القيمة‬


‫النصية في أول سطر أصبحت )‪ (Task List‬و كذلك ستالحظ بأن‬
‫مربع النص أصبح بخلفية حمراء اللون‬

‫تنويه‪ :‬كما رأينا كيفية إسناد القيم من ملف )‪ (String‬و التي تتيح‬
‫لنا تغيير ھذه القيم الحقا مثال في حال أتحنا للمستخدم تغيير واجھة‬
‫التطبيق حيث تقوم بالداللة على ملف )‪ (String‬أخر بداللة اللغة‬

‫‪116‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫المحلية مثال و كذلك الحال يمكننا تمرير النص مباشرة دون الحاجة‬
‫للداللة إلى المرجع بالتعويض مباشرة كما الكود الحالي‬

‫‪<TextView‬‬
‫"‪android:layout_width="fill_parent‬‬
‫"‪android:layout_height="wrap_content‬‬
‫"‪android:text="Task List‬‬
‫>‪android:background="@color/TextViewBackColor" /‬‬

‫نحن اآلن بحاجة إلى خطوة إضافية و ھي إعطاء عنصر صندوق‬


‫النص )‪ (TextView‬اسم وحيد و ذلك لكي نستطيع التعامل معه‬
‫عن طريق الكود الخاص بنا و ليكن مثال )‪ (MainTextView‬و‬
‫لنقوم بذلك ھناك طريقتين إما عن طريق الكود مباشرة أو عن طريق‬
‫استخدام صندوق الخصائص و الذي سنتعرف عليه ھذه المرة ليقوم‬
‫ھو بالعمل بدال عنا‬

‫قم بالعودة إلى الشاشة تحت مجلد )‪ (res >> layout‬ليظھر شكل‬
‫الشاشة الخاصة بالواجھة و في أسفلھا ستجد لسان تبويب‬
‫)‪ (Properties‬و لتقم بالبحث عن الخاصية )‪ (id‬و لتقم بإسناد‬
‫القيمة )‪ (MainTextView‬إليھا ليكون بالشكل التالي‬

‫‪117‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫عند انتھائك من ھذه النقطة ستقوم بيئة التطوير بإضافة سطر إلى‬
‫النظام لتعريف ھذا الكائن و ھو ضمن خصائص مربع النص داخل‬
‫الملف )‪ (main.xml‬ليكون بالشكل التالي‬
‫‪<TextView‬‬
‫"‪android:layout_width="fill_parent‬‬
‫"‪android:layout_height="wrap_content‬‬
‫"‪android:text="Task List‬‬
‫"‪android:background="@color/TextViewBackColor‬‬
‫>‪android:id="@+id/MainTextView"/‬‬

‫أو في حال أردت أن تقوم بتعريفه مباشرة من الكود فعليك أن تقوم‬


‫بكتابته بالشكل التالي‬

‫"‪android:id="@+id/MainTextView‬‬

‫‪118‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫و التي تقوم بإخبار بيئة التطوير بأننا نقوم بتعريف عنصر جديد‬
‫باسم )‪ (MainTextView‬و عندھا سنتمكن من التعامل معه دون‬
‫الحاجة لتعريفه في مكان أخر إال أن محدودية ذلك تقع أنه ال يمكنك‬
‫التعامل مع ھذا العنصر ضمن الكائنات التي قبله مثله فإنھا لن‬
‫تعرف انه موجود مثال في حال استخدمنا طريقة العرض‬
‫)‪ (Relative‬و أردنا أن تتخاطب ھذه الكائنات مع بعضھا البعض و‬
‫تحتاج إلى التعامل معھا عن طريق الكائنات أالحقة‬

‫حيث أن )‪ (@+id/‬و التي وضعناھا قبل االسم تخبر النظام بأن‬


‫ھناك كائن جديد تم تعريفه ھنا و الحقا يمكن التعامل معه مباشرة‬
‫عبر المرجع مثال‬

‫‪@id/MainTextView‬‬

‫بدون وجود إشارة الموجب )‪ (+‬إذ أننا اآلن نتعامل معه و ليس‬
‫تعريفه كما سترى الحقا‬

‫اضافة شاشة جديدة للمشروع )نشاط جديد(‬

‫اآلن لنقوم بإنشاء شاشة جديدة و ھي التي سوف نصل إليھا عن‬
‫طريق قائمة من الشاشة الرئيسية و وظيفة ھذه الشاشة ھي تمكيننا‬
‫من كتابة بيانات المھمة و التي تحتوي على مربعي نص أحدھما‬
‫يحتوي على عنوان المھمة )‪ (Title‬و الثاني يحتوي على تفاصيل‬
‫المھمة )‪(Details‬‬

‫‪119‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

‫( على‬Menu) ‫بعد أن انتھينا من بناء الشاشة فلنقم ببناء قائمة‬


‫الشاشة الرئيسية لتمكننا من استدعاء الشاشة الثانية‬

(Menu) ‫بناء قائمة‬

‫( و قم بإضافة‬Activity_TaskList) ‫عد اآلن إلى الشاشة األولى‬


‫( حتى نستطيع التعامل معھا في داخل‬Menu) ‫سطر استدعاء الدالة‬
(View) ‫الكود الخاص بنا و كذلك الحال للدالة الرئيسية‬

import android.view.Menu;
import android.view.View;

‫كما نحتاج إلى إضافة دالة التعامل مع مربعات النص‬

import android.widget.TextView;

‫ليصبح الكود لدينا بھذا الشكل‬

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.Menu;
import android.widget.TextView;

public class Activity_TaskList extends Activity {


/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {

120
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫;)‪super.onCreate(savedInstanceState‬‬
‫;)‪setContentView(R.layout.main‬‬
‫}‬
‫}‬
‫اآلن سنضيف بعض الكود إلنشاء )قائمة جديدة(‬

‫صناديق الحوار )‪(activities,alertdialog,toast‬‬

‫يوجد في أندرويد ثالث أنواع من صناديق الحوار و التي تختلف‬


‫باالختالف الوظيفة ما رأيك اآلن لو أضفنا رسالة صغيرة تظھر‬
‫لفترة عند افتتاح البرنامج تظھر فيھا رسالة ترحيب مثال‬
‫)‪ (Welcome‬و يمكنك أن تقوم الحقا بتضمينھا معلومات مفيدة‬
‫مثال عدد المھام أو مثال عدد المھام الواجب أدائھا اليوم في حال‬
‫طورت البرنامج و إضافة خاصية تحديد وقت إلنھاء كل مھمة مثال‬
‫االن الستدعاء دالة صناديق الحوار قم بإضافة الشطر التالي في‬
‫أعلى الكود‬

‫في البداية أنت بحاجة إلى إضافة مرجع‬

‫;‪import android.widget.Toast‬‬
‫و من ثم قم بإضافة الكود التالي إلى المشروع ليصبح‬
‫{ )‪public void onCreate(Bundle savedInstanceState‬‬
‫;)‪super.onCreate(savedInstanceState‬‬
‫;)‪setContentView(R.layout.main‬‬

‫)(‪Toast.makeText(Activity_TaskList.this,"Welcome",0).show‬‬
‫;‬
‫‪121‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫;‪TextView[] tvs‬‬
‫;]‪tvs = new TextView[10‬‬
‫)‪for (int i=0; i<10; ++i‬‬
‫{‬
‫;)‪tvs[i] = new TextView(this‬‬
‫;)"‪tvs[i].setText("hi‬‬
‫}‬
‫}‬
‫اآلن عند تشغيل التطبيق ستظھر مربع حوار للترحيب‬

‫سنضيف إلى الكود قائمة تظھر عند الضغط على زر)‪ (Menu‬و‬
‫التي سنضع بھا زر وحيد يحتوي كلمة حفظ )‪ (Save‬و يظھر‬
‫الصورة االفتراضية الخاصة بالحفظ من النظام‬

‫‪@Override‬‬
‫{ )‪public boolean onCreateOptionsMenu(Menu menu‬‬
‫;)‪super.onCreateOptionsMenu(menu‬‬
‫;)"‪MenuItem item1 = menu.add(0, 1, 0, "Save‬‬
‫;) ‪item1.setIcon(android.R.drawable.ic_menu_save‬‬
‫;‪return true‬‬
‫}‬
‫اآلن عند الضغط على ھذا العنصر سنقوم بطباعة قيمة النص داخل‬
‫الكونسول )سجل العمل(‬

‫في البداية تحتاج إلى إضافة مرجع إلى‬

‫;‪import android.util.Log‬‬

‫‪122‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

‫و من ثم إضافة الكود التالي‬


@Override
public boolean onOptionsItemSelected(MenuItem item) {
TextView MainTextView =
(TextView)findViewById(R.id.MainTextView);
switch (item.getItemId())
{
case 1 :

Log.v("Task:",MainTextView.getText().toString());
return true;
}
return false;
}

‫و بھذا نكون قد أنھينا المدخل إلى ھذا المشروع‬

123
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫نشر التطبيق على سوق أندرويد‬

‫لنشر التطبيق على سوق أندرويد تحتاج أوال إلى تسجيل حساب‬
‫خاص بك للبيع و الذي يتطلب دفع مبلغ )‪ (50‬دوالر أمريكي و لمرة‬
‫واحدة‬

‫ثم أنت بحاجة إلى إنشاء مفتاح خاص لكل تطبيق ليكون بمثابة‬
‫بصمة أو توقيع رقمي لھذا التطبيق ‪ ،‬و في حال إنشاء ھذا الملف‬
‫تحتاج إلى حفظه في مكان أمن ‪ ،‬حيث عند قيامك برفع التطبيق على‬
‫سوق أندرويد بھذا التوقيع فلن تستطيع أن تقوم برفع أي تحديثات‬
‫جديدة إال بنفس التوقيع الذي قمت به بأول مرة‬

‫تسجيل مفتاح خاص لتطبيقك‬

‫ابحث في جھازك عن أداة )‪ (keytool‬و الموجودة داخل مجلد‬


‫)‪ (JDK‬و ليكن على المسار التالي مثال‬

‫‪C:\Program Files\Java\jdk1.6.0_18\bin\keytool.exe‬‬

‫من سطر األوامر في جھازك قم بكتابة األمر التالي‬

‫‪keytool -list -alias alias_name -keystore my-‬‬


‫‪release-key.keystore‬‬

‫حيث أنك ستستبدل بعض العوامل بأخرى و ليكن مثال‬

‫‪124‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

keytool -genkey -v -keystore badwi.keystore -alias


badwi -keyalg RSA -keysize 2048 -validity 10000

‫( و عندھا ستظھر لك بعض المدخالت‬badwi) ‫الحظ اسم التطبيق‬


‫التي تحتاج إلى تعريفھا و ذلك من أجل التشفير الخاص إلنشاء ملف‬
‫التعريف الخاص‬

‫( و الذي يكون عادة في‬badwi.keystore) ‫اآلن ابحث عن الملف‬


:‫المسار‬

Windows Vista or 7:
C:\Users\<user>\.android\badwi.keystore

Windows XP:
C:\Documents and Settings\<user>\.android\badwi.keystore

125
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫تصدير التطبيق مع المفتاح‬

‫بعد ھذه الخطوة تحتاج لربط ھذا الملف مع الملف المنتج و ذلك عن‬
‫طريق بيئة التطوير ‪،‬اذھب إلى اسم المشروع و اضغط بزر الفأرة‬
‫األيمن‬

‫ليظھر لك مربع معالج تصدير الملف و الذي يحوي اسم المشروع‬

‫اختر التالي‬
‫‪126‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫في ھذه الشاشة تحتاج إلى تحديد مكان ملف المفتاح الذي انشئناھا‬
‫سابقا و كذلك كلمة السر الذي استخدمتھا أثناء بناء المفتاح‬

‫اكتب كلمة السر الذي اخترتھا أثناء تعريف معرف المفتاح أثناء‬
‫اإلنشاء‬

‫‪127‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫في ھذه الشاشة ستحدد أين سوف تقوم بتصدير الملف النھائي و‬
‫الذي سوف تقوم برفعه على سوق أندرويد‬

‫رفع التطبيق على سوق أندرويد‬

‫اذھب إلى العنوان التالي‬


‫‪http://market.android.com/publish/Home‬‬

‫ستجد الصفحة الرئيسية التي تستعرض قائمة التطبيقات الحالية‬

‫اضغط على زر )‪(Upload Application‬‬


‫‪128‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫لتظھر لك شاشة إضافة تطبيق جديد ‪ ،‬ما عليك سوى رفع التطبيق‬
‫النھائي الذي قمنا بتصديره و الصور الخاصة بالتطبيق و األيقونات‬
‫و المعلومات الخاصة بك‬

‫الشاشة الخاصة باإلضافة في الصفحة التالية‪ ،‬و في الصفحة التي‬


‫تليھا توجد صورة للشاشة بعد رفع البيانات‬

‫‪129‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫‪130‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫‪131‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫‪132‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫تطبيق ‪RestDroid-mini‬‬

‫‪133‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫تطبيق‪RestDroid-mini‬‬
‫يتناول ھذا الفصل شرح الكود البرمجي الخاص بتطبيق ‪ RestDroid‬والذي‬
‫طرحناه كأول مشروع من مشاريع مجتمع مطوري أندرويد العرب بالتعاون مع‬
‫موقع أردرويد المتخصص بكل ماله عالقة بنظام األندرويد وھواتفه‪ .‬التطبيق تم‬
‫طرحه في سوق تطبيقات األندرويد “أندرويد ماركت وسوق ساليد مي” وكنا قد‬
‫كتبنا عنه وعن المميزات التي يملكھا‪ .‬وكما ذكرنا من قبل‪ ،‬التطبيق سيكون‬
‫مفتوح المصدر بشكل كامل ليتمكن المھتمون العرب ببرمجة األندرويد من‬
‫دراسة وفھم الشفرة المصدرية واالنطالق نحو مجال تطبيقات األندرويد‪ .‬ولكن‬
‫سنقوم في ھذا الكتاب بتقديم شرح كامل لنسخة مصغرة من تطبيق ‪RestDroid‬‬
‫األصلي سميناھا ب‪RestDroid-mini.‬‬

‫النسخة الكاملة من التطبيق تحتوي على الخصائص التالية‪:‬‬

‫تطبيق ‪ RestDroid‬يستخدم الواجھة البرمجية التطويرية ‪ API‬الخاصة بموقع‬


‫قيم ليبني عليھا المزايا التالية‪:‬‬
‫‪-‬اختيار الدولة والمدينة والبحث عن المطاعم فيھا‪.‬‬
‫‪-‬اختيار الدولة والمدينة وعرض أفضل ‪ ٥٠‬مطعما فيھا‪.‬‬
‫‪-‬اختيار الدولة والمدينة والبحث عن مطاعم باستخدام مواصفات معينة )مطعم‬
‫ايطالي‪ ،‬صيني‪ ،‬نباتي‪ ،‬أسماك‪…). ،‬‬
‫‪-‬عرض المطاعم التي تناسب معلومات البحث وبجانبھا التقييمات الخاصة بھا‪.‬‬
‫‪-‬عرض المطاعم على خرائط غوغل‪.‬‬
‫‪-‬إمكانية استعراض معلومات الفروع )وقد ال يظھر بعضھا على الخريطة وذلك‬
‫بسبب عدم تحديد مواقعھا في األصل في موقع قيم من قبل المستخدمين‪).‬‬
‫‪-‬إمكانية استعراض تعليقات المستخدمين على المطاعم‪.‬‬

‫التطبيق يستخدم التقنيات التالية‪:‬‬


‫‪-‬االتصال باالنترنت واستخدام ال‪API.‬‬
‫‪-‬خرائط غوغل‪.‬‬

‫لالستزادة‪:‬‬
‫‪134‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫مقطع تعريفي على اليوتيوب‪:‬‬


‫‪http://www.youtube.com/watch?v=BEDuS6gq4JA‬‬

‫بالنسبة للنسخة المصغرة والتي سنشرحھا ھنا‪ ،‬سيكتفي التطبيق بعرض زر واحد‬
‫بالضغط عليه يتم جلب أفضل ‪ ٥٠‬مطعما في مدينة الرياض‪-‬المملكة العربية‬
‫السعودية ويعرض تقييمھا‪ .‬بالضغط على أي مطعم‪ ،‬سيتم عرض موقعه على‬
‫خريطة غوغل‪.‬‬

‫واجھات التطبيق‪:‬‬
‫الخطوة التي تسبق البرمجة‪ ،‬ھي تحديد شكل وعدد الواجھات المطلوب إظھارھا‬
‫في التطبيق‪ .‬نحتاج في تطبيقنا الى ثالثة واجھات وھي‪:‬‬

‫واجھة البداية‪:‬‬
‫وفيھا يظھر شعار التطبيق وزر مكتوب عليه “جلب أفضل ‪ ٥٠‬مطعما في‬
‫الرياض‪”.‬‬

‫واجھة المطاعم‪:‬‬
‫وفيھا تظھر أسماء المطاعم وتقييماتھا‪ .‬الشكل المرغوب ھو أن يظھر تقييم كل‬
‫مطعم )العالمة الموزونة( على شكل ‪ ٥‬نجوم ‪ +‬العالمة الموزونة رقما ‪ +‬عدد‬
‫األصوات رقما )العالمة الموزونة ھي المعيار األنسب لمقارنة المطاعم بحسب‬
‫موقع قيم(‪.‬‬

‫واجھة الخريطة‪:‬‬
‫وھي الواجھة التي يظھر فيھا اسم المطعم ومكانه على خريطة غوغل بحيث يتم‬
‫تمثيل مكان المطعم بنقطة خضراء‪.‬‬

‫بعد تصميم الواجھات‪ ،‬نأتي اآلن الى تصميم المجموعات ‪ Classes‬والدوال‬


‫‪Methods‬الخاصة بالتطبيق‪ .‬سنقوم جاھدين بإتباع أفضل السبل في تصميم‬
‫المجموعات بشكل يسھل على القارىء فھمھا وفھم وظيفتھا )نفترض في شرحنا‬
‫إلمام القارىء بلغة الجافا ‪-‬مستوى مبتدئ متقدم‪ -‬وتمكنه من فھم األكواد التي‬
‫عرضناھا في الصفحات السابقة من ھذا الكتاب(‬
‫‪135‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫بداية كما نعرف فإن كل واجھة يقترن بھا مجموعة خاصة بھا إضافة إلى ملف‬
‫‪XML‬يحتوي على العناصر المرئية المطلوب إظھارھا )الشعار ‪ +‬زر في‬
‫الواجھة األولى مثال( وھذا يعني أننا بحاجة إلى ‪ ٣‬مجموعات جافا و‪ ٣‬ملفات‬
‫‪XML‬بالشكل التالي‪:‬‬

‫طبعا الواجھة األولى ھي ‪ intro‬والثانية ھي ‪ Best50‬والثالثة ھي‬


‫‪ViewOnMapActivity.‬‬

‫باإلضافة الى الثالث مجموعات أعاله‪ ،‬يوجد لدينا عدد من المجموعات المساعدة‬
‫وھي على النحو التالي‪:‬‬
‫‪RestDroidApplication.java‬‬
‫وھي المجموعة األم التي تعتبر باقي المجموعات أطفاال لھا “كونھا تقوم بوراثة‬
‫مجموعة ‪ Application‬والتي تندرج تحتھا حكما األنشطة ‪Activities‬‬
‫والمجموعات ‪ Classes‬الموجودة في التطبيق”‪ .‬الھدف من تواجدھا ھو وضع‬

‫‪136‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫الدوال المشتركة بين المجموعات فيھا بحيث ال يتكرر الكود البرمجي للدوال في‬
‫أكثر من مجموعة‪ .‬باإلضافة الى استخدامھا كمستودع للمتغيرات العامة والتي‬
‫يمكن ألي مجموعة الدخول اليھا( ‪ Global Variables‬ھذه المتغيرات سيتم‬
‫توظيفھا كوسيلة لتمرير القيم التي تطلبھا مجموعة\واجھة من المجموعة التي‬
‫قبلھا(‪ .‬بمعنى آخر أننا لسنا بحاجة الى اللجوء لھذا النوع من المجموعات في كل‬
‫تطبيق نبرمجه‪ ،‬ولكن في حالة وجود عدد من الدوال المشتركة بين المجموعات‬
‫فإنه يفضل وضعھا في مكان واحد ليسھل فيما بعد التعديل على ھذه الدوال‪.‬‬

‫‪RatedItem.java‬‬
‫وھي مجموعة بسيطة لكائن ‪ Object‬يمثل المطعم‪ .‬ھذا المطعم لديه الخصائص‬
‫التالية‪ :‬رقم مميز ‪ +‬اسم ‪ +‬عدد األصوات ‪ +‬العالمة الموزونة‪.‬‬

‫‪RatedRestaurantListItem.java‬‬
‫ويقترن بھا‬
‫‪rest_list_item.xml‬‬
‫ودور ھذه المجموعة وملف االكس ام ال ھو تكوين قالب العرض الخاص بكل‬
‫مطعم‪ .‬كما نعرف فإن ما يتم وضعه في ملف االكس ام ال يظھر في الواجھة عند‬
‫تشغيلھا‪ ،‬فإذا وضعنا به ‪ ٣‬أزرار وصورة‪ ،‬ستظھر كما ھي‪ .‬السؤال ھو ماذا لو‬
‫كنا نريد أن تتغير الواجھة وتتشكل بشكل تفاعلي يتناسب في حالتنا مع عدد‬
‫المطاعم )في ھذا التطبيق لدينا رقم ثابت وھو ‪ ٥٠‬مطعما‪ ،‬ولكن في التطبيق‬
‫األشمل‪ ،‬قد ال تملك احدى المدن أكثر من ‪ ٣٠‬مطعما( أضف الى أننا ال نريد‬
‫تكرار عناصر الواجھة ‪ ٥٠‬مرة؟‬
‫الحل ھو بتشكيل الواجھة الخاصة بعنصر واحد )أي مطعم واحد( والتحكم‬
‫برمجيا بعدد مرات التكرار ومحتوى كل عنصر )وھنا تأتي الحاجة لمجموعة‬
‫‪RatedItem.java‬والتي سنستقي منھا معلومات كل عنصر(‪.‬‬

‫‪137‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫الشكل ‪١‬‬

‫‪AddressOverlay.java‬‬
‫ھذه المجموعة يتم استخدامھا كطبقة تظھر فوق الخريطة بحيث يمكننا رسم نقطة‬
‫خضراء في المكان المقابل لموقع المطعم‪.‬‬

‫إذ يصبح لدينا الشكل النھائي للمجموعات كما ھو في الشكل ‪.٢‬‬

‫‪138‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫الشكل ‪٢‬‬
‫نالحظ من الشكل أعاله ما يلي‪:‬‬
‫‪-‬مجموعة ‪ RestDroidApplication.java‬أصبحت مجموعة عامة تستطيع‬
‫باقي المجموعات التواصل معھا كون األولى ورثت خصائص مجموعة‬
‫‪Application‬وھي المجموعة التي تمثل جسد تطبيق األندرويد )أي أن التطبيق‬
‫‪Application‬مكون من مجموعة نشاط ‪ Activity‬واحدة أو أكثر(‪.‬‬

‫‪-‬المجموعات الثالث التي تستمد خصائصھا من ‪ Activity‬يجمعھا أنھا تستطيع‬


‫رؤية دوال ومتغيرات الجسد الذي يحتويھا‪ ،‬أي المجموعة السابقة‪.‬‬

‫‪-‬المجموعات الباقية ھي كما ذكرنا مساعد )‪ (Auxiliary‬وبعضھا يستفيد من‬


‫خصائص مجموعات أعلى ويعيد صياغتھا وتعريفھا )كمجموعتي‬
‫‪RatedRestaurantListItem.java‬و )‪ AddressOverlay.java‬وھو ما‬
‫سيتم توضيحه الحقا‪.‬‬

‫‪-‬مجموعة ‪ RatedRestaurantListItem.java‬ترتبط بملف‬


‫‪rest_list_item.xml‬بشكل مغاير نوعا ما الرتباط باقي المجموعات بملفات‬
‫االكس ام ال خاصتھا وھذا سيبرز جليا في الشرح القادم )لذلك تم وصل‬
‫المجموعة وملفھا بخط رمادي وليس أسود(‪.‬‬

‫إنشاء التطبيق‪:‬‬
‫نقوم بتشغيل االكليبس والتوجه إلى قائمة‪File>new>project‬‬
‫نقوم بفتح مجلد ‪ Android‬ونختار منه‪Android Project‬‬

‫‪139‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫ثم نقوم بمليء البيانات بشكل مشابه لما في الصور التالية‪:‬‬

‫‪140‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫‪141‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫حتى نتمكن من استخدام األحرف العربية داخل المشروع‪ ،‬يتوجب علينا تعريف‬
‫الترميز ليكون ‪ UTF-8‬في المشروع‪ .‬اضغط بالزر األيمن على اسم المشروع‬
‫ومن ثم‪Properties:‬‬

‫‪142‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫نقوم اآلن بإنشاء مجموعة ‪ Class‬بمسمى‪intro:‬‬

‫ونمأل البيانات الخاصة بھا‪:‬‬

‫‪143‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫(الحظ اسم المجموعة التي تعلو المجموعة المنشأة) ‪android.app.Activity‬‬

‫قبل الشروع في كتابة الكود البرمجي الخاص بھذه المجموعة )والتي ستقترن‬
‫بالواجھة اإلبتدائية التي ستظھر للمستخدم(‪ ،‬يفضل أن نقوم بإنشاء الواجھة‬
‫المرئية‪ .‬لعمل ذلك‪ ،‬نقوم باستخدام ملف ‪ main.xml‬الذي تم إنشاؤه تلقائيا عند‬
‫إنشاء المشروع‪.‬‬

‫‪144‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫الواجھة التي نريد تصميمھا بسيطة جدا‪ ،‬وستكون على الشكل التالي‪:‬‬
‫خلفية بيضاء‪ ،‬صورة تظھر في المنتصف‪ ،‬زر‪.‬‬

‫بالنسبة للخلفية البيضاء‪ ،‬سنترك ملف ‪ main.xml‬قليال ونقوم بإنشاء ملف نسميه‬
‫مثال ‪ colors.xml‬ونضعه تحت مجلد( ‪ values‬يتم اإلنشاء بالضغط بالزر‬
‫األيمن على مجلد ‪ values‬ومن ثم‪ new>file>colors.xml .‬تسمية ملفات‬
‫االكس ام ال يجب أن تتم باستخدام حروف صغيرة ‪ lower case‬وعليھا أن‬
‫تخلو من الرموز‪).‬‬
‫محتوى الملف‪:‬‬

‫>?"‪<?xml version="1.0" encoding="utf-8‬‬


‫>‪<resources‬‬
‫>‪<color name="background">#FFFFFFFF</color‬‬
‫>‪</resources‬‬
‫‪145‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫ھذا النوع من الملفات له دور مھم في عملية التطوير‪ ،‬فباستخدام أسماء‬


‫المتغيرات الموجودة بداخله في الكود البرمجي‪ ،‬يمكنك فيما بعد مجرد تعديل قيم‬
‫المتغيرات في ھذا الملف ليتم استخدام القيمة الجديدة في البرنامج ككل‪ .‬وھذا‬
‫األمر ينطبق على ملف ‪ strings.xml‬في نفس المجلد وفيه يتم تعريف متغيرات‬
‫نصية يتم اإلشارة إليھا باالسم في الكود‪ ،‬وعندما يراد تغيير قيم ھذه النصوص‪،‬‬
‫فبدال من البحث عن كل متغير في الكود البرمجي‪ ،‬نلجأ إلى ھذا الملف تحديدا‬
‫ونغير القيم الموجودة بداخله‪ ،‬ولكنني لألسف ال أتبع ھذه الطريقة حيث أقوم‬
‫بكتابة النصوص داخل الكود‪ ،‬فمعذرة‪.‬‬

‫نعود اآلن إلى ملف الـ‪ ، main.xml‬ونضيف التالي‪:‬‬

‫ھذا السطر يجب أن يكون متواجدا وھو يعرف النسخة المستخدمة ونوع ‪<!--‬‬
‫>‪ --‬الترميز‬
‫>?"‪<?xml version="1.0" encoding="utf-8‬‬

‫‪<LinearLayout‬‬
‫"‪xmlns:android="http://schemas.android.com/apk/res/android‬‬
‫"‪android:layout_width="fill_parent‬‬
‫"‪android:layout_height="fill_parent‬‬
‫>"‪android:background="@color/background‬‬

‫‪<RelativeLayout‬‬
‫"‪xmlns:android="http://schemas.android.com/apk/res/android‬‬
‫"‪android:layout_width="fill_parent‬‬
‫>"‪android:layout_height="fill_parent‬‬

‫>‪ --‬يستخدم لتعريف الصورة وتحديد مصدرھا‪<!--‬‬

‫‪<ImageView‬‬
‫‪146‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

android:id="@+id/ImageView01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/andbooklogo"
android:adjustViewBounds="true"
android:layout_centerHorizontal="true"
>
</ImageView>

<!--‫ يستخدم لتعريف الزر‬-->

<Button android:id="@+id/search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/ImageView01"
android:paddingLeft="20px"
android:paddingRight="20px"
android:layout_centerInParent="true"
android:layout_marginTop="20px"
/>

</RelativeLayout>
</LinearLayout>

.‫ قمنا بإضافة مصدر الصورة التي نريد استخدامھا‬ImageView ‫نالحظ أننا في‬
‫ نقوم بالضغط عليھا وسحبھا إلى مجلد‬،‫إلضافة الصورة إلى المشروع‬
‫ بحسب الموجود )يمكنكم استخدام‬res/drawable ‫أو‬res/drawable-hdpi
).‫صورة لديكم أو تلك الموجودة في ملفات التطبيق على الموقع‬

‫ ؟ للتعرف‬RelativeLayout‫ و‬LinearLayout ‫السؤال القادم ھو ماذا عن‬


.‫ أدعوكم لقراءة الملحق “أ” من ھذا الكتاب‬،‫عليھا‬
147
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫لم أقم بشرح ‪ RelativeLayout‬كونه يتشابه مع األوعية الباقية في المبدأ ولكنه‬


‫يختلف عنھم في أن ترتيب العناصر )األزرار والصور وغيرھا( يكون بنسبة‬
‫أماكنھا بين بعضھا‪ .‬بمعنى اذا رغبت بوضع زر أسفل الصورة مع محاذاته الى‬
‫اليمين‪ ،‬فھذا الوعاء سيعطيك ھذه اإلمكانية حيث ستعرف الزر بأنه سيقع أسفل‬
‫الصورة مع محاذاته إلى اليمين‪ .‬وھذا تفسير ‪ android:layout_below‬في‬
‫تعريف الزر‪ ،‬والقيمة المعطاة ھي رقم معرف الصورة‪.‬‬

‫انتھينا من عمل الواجھة المرئية‪ ،‬ويمكننا استعراضھا بالضغط على زر‬


‫‪Layout‬كما في الشكل‪:‬‬

‫واآلن نعود لملف المجموعة ‪ intro .‬الكود سيكون التالي‪) :‬سأقوم بالشرح على‬
‫الكود)‬

‫;‪package android.prog.easily‬‬
‫‪148‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class intro extends Activity


{
‫تعريف متغير من نوع زر‬//
private Button getbest50;

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);

‫ من أجل الواجھة المرئية‬main ‫نستخدم ملف‬ //


setContentView(R.layout.main);
setUpViews();
}

private void setUpViews()


{
getbest50 = (Button)findViewById(R.id.search);
");‫ مطعم‬٥٠ ‫أفضل‬ getbest50.setText("

‫تعريف ماذا سيتم في حال الضغط على الزر‬//


getbest50.setOnClickListener(new
View.OnClickListener()
{
public void onClick(View v)
149
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫{‬
‫;)(‪top50Handler‬‬
‫}‬
‫;)}‬

‫}‬

‫)(‪protected void top50Handler‬‬


‫{‬

‫}‬
‫}‬

‫ما يتوجب علينا عمله في حال الضغط على الزر ھو التالي‪:‬‬


‫االتصال باالنترنت وجلب أفضل ‪ ٥٠‬مطعما في مدينة الرياض‪ ،‬ومن ثم االنتقال‬
‫إلى واجھة تعرض المطاعم وتقييماتھا ‪.‬‬

‫سنتوقف ھنا قليال ونترك ملف( ‪ intro.java‬والذي يمكنك بالمناسبة تشغيله على‬
‫المحاكي ورؤية شكله الحالي‪ ،‬ولن يحصل شيئا إذا ضغطنا على الزر( ونقوم‬
‫بتعريف المجموعة ‪ RatedItem.java‬بالشكل التالي‪:‬‬

‫;‪package android.prog.easily‬‬

‫;‪import java.io.Serializable‬‬

‫‪public class RatedItem implements Serializable‬‬


‫{‬
‫= ‪private static final long serialVersionUID‬‬
‫;‪5500258407135652423L‬‬

‫‪150‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

private String name;


private int id;
private int voteCount;
private double wScore;

public RatedItem(String name, int id, int voteCount,


double wScore)
{
this.name = name;
this.id = id;
this.voteCount = voteCount;
this.wScore = wScore;
}

public String getName()


{
return name;
}

public void setName(String name)


{
this.name = name;
}

public int getId()


{
return id;
}

public void setId(int id)


{
151
1 ‫أندرويد ببساطة اإلصدار بيتا‬

this.id = id;
}

public int getVoteCount()


{
return voteCount;
}

public void setVoteCount(int voteCount)


{
this.voteCount = voteCount;
}

public double getwScore()


{
return wScore;
}

public void setwScore(int wScore)


{
this.wScore = wScore;
}

‫ والذي كما قلنا‬RestDroidApplication.java ‫واآلن سنقوم بإنشاء ملف‬


Activities ‫سيحتوي على دوال ومتغيرات يمكن لجميع الواجھات واألنشطة‬
). ‫استخدامھا )أي ال داعي لنسخ الدوال نفسھا في كل األنشطة عدة مرات‬

152
1 ‫أندرويد ببساطة اإلصدار بيتا‬

:‫المجموعة تحتوي ما يلي‬

package android.prog.easily;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Application;

public class RestDroidApplication extends Application


{

//‫ يتوجب الحصول عليه من موقع قيم‬Qaym API Key


private String key = "xxxxxxxxxxxxxxxxxxxx";
private int[] countryAndCityIds;
private JSONObject[] ratedRestaurants;
private ArrayList<RatedItem> globalAdapterData;
private RatedItem itemOnMap;
private String branchesDetailsText;

public String getBranchesDetailsText()


153
1 ‫أندرويد ببساطة اإلصدار بيتا‬

{
return branchesDetailsText;
}

public void setBranchesDetailsText(String


branchesDetailsText)
{
this.branchesDetailsText = branchesDetailsText;
}

public RatedItem getItemOnMap()


{
return itemOnMap;
}

public void setItemOnMap(RatedItem itemOnMap)


{
this.itemOnMap = itemOnMap;
}

@Override
public void onCreate()
{
super.onCreate();
}

@Override
public void onTerminate()
{
super.onTerminate();
}
154
1 ‫أندرويد ببساطة اإلصدار بيتا‬

‫ للحصول من معلومات الموقع المعطى‬HTTP ‫دالة تقوم بعمل طلب‬//


REST‫عبر بروتوكول‬
public String queryRESTurl(String url)
{
HttpClient httpclient = new DefaultHttpClient();

HttpGet httpget = new HttpGet(url);

HttpResponse response;

try
{
response = httpclient.execute(httpget);

HttpEntity entity = response.getEntity();

if (entity != null)
{
InputStream instream = entity.getContent();
String result1 =
convertStreamToString(instream);

instream.close();

return result1;
}

catch (IOException e)
155
1 ‫أندرويد ببساطة اإلصدار بيتا‬

return null;

}
‫ يمكن‬String ‫دالة تقوم بتحويل المعلومات المستلمة إلى صيغة‬//
‫التعامل معھا‬
public String convertStreamToString(InputStream is)
throws IOException
{

if (is != null)
{
StringBuilder sb = new StringBuilder();
String line;

try
{
BufferedReader reader = new BufferedReader(new
while ((line = reader.readLine()) != null)
{
sb.append(line).append("\n");
}
}

finally
{
is.close();
}
156
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫;)(‪return sb.toString‬‬
‫}‬

‫‪else‬‬
‫{‬
‫;"" ‪return‬‬
‫}‬
‫}‬
‫*‪/‬‬
‫المعلومات المستلمة من قيم تتبع الترميز ‪ JSON‬ولكن المكتبة البرمجية‬
‫الموجودة بالجافا والتي تحمل نفس اسم الترميز تتعامل مع الترميز بشكل مختلف‬
‫نوعا ما لذلك اضطررت لعمل بعض التغييرات على القيم المستلمة ألتمكن من‬
‫استخالصھا وتعبئتھا في مصفوفة من عناصر ‪ JSON‬التي يسھل التعامل معھا‬
‫ألنھا تعمل على نمط مفتاح وقيمة ‪ Key/value ..‬يمكنكم تتبع السياق البرمجي‬
‫للكود لمعرفة الطريقة التي اتبعتھا )وھي بسيطة(‪ ..‬كما يلزمكم مراجعة صفحة‬
‫توثيق "قيم" ورؤية‬
‫الصيغة التي يتم فيھا إرسال البيانات ومقارنتھا بالصيغة التي تقبلھا الجافا‬
‫لعناصر الـ‪JSON‬‬
‫‪*/‬‬
‫)‪public JSONObject[] retrieveJSONs(String urlString‬‬
‫{‬
‫;)‪String result = queryRESTurl(urlString‬‬
‫;‪JSONObject[] jarr = null‬‬

‫)‪if (result != null‬‬


‫{‬
‫‪try‬‬
‫{‬
‫‪result = result.substring(1, result.length()-‬‬
‫;)‪1‬‬
‫‪157‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

int counter = 0;
boolean firstSeen = false;
boolean secondSeen = false;

‫ لمعرفة عدد العناصر المستلمة‬for ‫حلقة من نوع‬ //


‫ المطلوبة‬JSON ‫وبالتالي تحديد عدد عناصر‬

for (int i = 0; i < result.length(); i++)


{
if (result.charAt(i) == '{' && firstSeen ==
{
firstSeen = true;
counter++;
}

else if (result.charAt(i) == '{' && firstSeen


true) ==
{
secondSeen = true;
}

if (result.charAt(i) == '}' && secondSeen


true) ==
{
secondSeen = false;
}

else if (result.charAt(i) == '}' &&


false) secondSeen ==
{
firstSeen = false;
158
1 ‫أندرويد ببساطة اإلصدار بيتا‬

jarr = new JSONObject [counter];

int ind1 = 0;
int ind2 = 0;

boolean firstSeenS = false;


boolean secondSeenS = false;

JSON‫ حلقة إلنشاء عناصر‬//


for (int i = 0; i < result.length(); i++)
{
firstSeenS = false;
secondSeenS = false;

if (result.charAt(i) == '{' && firstSeenS


false) ==
{
firstSeenS = true;
ind1 = i;
for (int j = i+1; j < result.length();
j++)
{
if (result.charAt(j) == '{' &&
{
secondSeenS = true;
}

159
1 ‫أندرويد ببساطة اإلصدار بيتا‬

if (result.charAt(j) == '}' &&


{
secondSeenS = false;
}

else if (result.charAt(j) == '}'


&&
secondSeenS == false)
{
String mid =

jarr[ind2] = new
ind2++;
i = j;
break;
}
}
}
}
}
catch (JSONException e)
{

}
}

return jarr;
}

‫ وتقوم بإضافة المفتاح له‬API ‫ دالة تقوم بعمل النص الكامل لطلب ال‬//
public String getUrlStringCommand(String command)
160
1 ‫أندرويد ببساطة اإلصدار بيتا‬

{
String service_url = "http://api.qaym.com/0.1/";
String url = "";
url = service_url + command + "/key=" + key;

return url;
}

public void setCountryAndCityIds(int[]


countryAndCityIds)
{
this.countryAndCityIds = countryAndCityIds;
}

public int[] getCountryAndCityIds()


{
return countryAndCityIds;
}

public JSONObject[] getRatedRestaurants()


{
return ratedRestaurants;
}

public void setRatedRestaurants(JSONObject[]


ratedRestaurants)
{
this.ratedRestaurants = ratedRestaurants;
}

public ArrayList<RatedItem> getGlobalAdapterData()


161
1 ‫أندرويد ببساطة اإلصدار بيتا‬

{
return globalAdapterData;
}

public void
setGlobalAdapterData(ArrayList<RatedItem>
globalAdapter)
{
this.globalAdapterData = globalAdapter;
}

public RatedItem getGlobalAdapterDataItem(int


position)
{
return globalAdapterData.get(position);
}
}

:‫ نقوم بإضافة الكود التالي‬، intro.java‫بالعودة لملف‬

protected void top50Handler()


{
try
{
‫ مطعما‬٥٠ ‫ الخاص بجلب أفضل‬API ‫عمل نص ال‬//
"٥٧ ‫من مدينة الرياض "الكود الخاص بھا‬
String attrcommand = "cities/" + "57" +
"/items/top";
162
1 ‫أندرويد ببساطة اإلصدار بيتا‬

‫بمجرد استخدام دالة يسبقھا‬//


‫اعرفوا أننا نقوم باستخدام دالة من ملف‬accessApplicationMethods()
RestDroidApplication.java

String attributesCommand =

accessApplicationMethods().getUrlStringCommand(attrcom
mand);

JSONObject[] topCities =

accessApplicationMethods().retrieveJSONs(attributesComma
nd);

‫مصفوفة سنقوم بتعبئتھا بعناصر من نوع‬//


‫وتزويد كل عنصر بمعلوماته الخاصة باالستعانة بكائنات\عناصر‬ReatedItem
‫التي قمنا بتكوينھا في السطر السابق‬JSON
ArrayList<RatedItem> sRest = new
ArrayList<RatedItem>();

if (topCities != null)
{
for (int ff = 0; ff < topCities.length;
ff++)
{
‫الحظوا كيفية الحصول على قيمة من‬//
‫" وقس على ذلك‬item_id" ‫ عبر مفتاح‬JSON ‫عنصر‬
int id =
Integer.parseInt(topCities[ff].getString("item_id"));

163
1 ‫أندرويد ببساطة اإلصدار بيتا‬

String name =
topCities[ff].getString("item_name");

int voteConutt =
Integer.parseInt(topCities[ff].getString("total_number_of_vot
es"));

double weScore =
Double.parseDouble(topCities[ff].getString("weighted_score
"));

‫تعديل العالمة الموزونة لتكون على‬//


١٠ ‫ بدال من‬٥ ‫مقياس‬
double weScoreR = weScore *
100;
weScoreR =
Math.round(weScoreR);
weScoreR = weScoreR / 10 / 2;

RatedItem singleRest = new


id, RatedItem(name,
voteConutt, weScoreR);
sRest.add(singleRest);
}
}
else
{
RatedItem singleRest = new
0, 0, 0); RatedItem("Empty List",
sRest.add(singleRest);
}
164
1 ‫أندرويد ببساطة اإلصدار بيتا‬

accessApplicationMethods().setGlobalAdapterData(sRest);
// *** goToBest50Act();
}
catch (JSONException e)
{

}
}

‫دالة يتم تعريفھا في أي نشاط يستخدم دوال المجموعة‬//


‫ونتمكن بھا من دخول الدوال الموجودة بھا‬RestDroidApplication.java
protected RestDroidApplication
accessApplicationMethods()
{
return (RestDroidApplication)getApplication();
}

‫ وبقي لدينا االنتقال للواجھة‬.‫ مطعما‬٥٠ ‫اإلضافة السابقة تمكننا من جلب أفضل‬
: ‫ وھذا ما يقوم به السطر الذي رمزت له بـ‬،‫التي تعرض المطاعم‬
// ***
:‫ ونعرفھا بالشكل التالي‬goToBest50Act ‫والذي يستدعي الدالة‬

protected void goToBest50Act()


{
Intent goToBest = new Intent(this, Best50.class);
startActivity(goToBest);
}
165
1 ‫أندرويد ببساطة اإلصدار بيتا‬

:‫ بالشكل التالي‬intro.java ‫ليصبح ملف‬

package android.prog.easily;

import java.util.ArrayList;

import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class intro extends Activity


{
‫تعريف متغير من نوع زر‬//
private Button getbest50;

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
‫ من أجل الواجھة المرئية‬main ‫نستخدم ملف‬ //
setContentView(R.layout.main);
setUpViews();
}

private void setUpViews()


166
1 ‫أندرويد ببساطة اإلصدار بيتا‬

{
getbest50 = (Button)findViewById(R.id.search);
setText("

‫تعريف ماذا سيتم في حال الضغط على الزر‬//


getbest50.setOnClickListener(new
View.OnClickListener()
{
public void onClick(View v)
{
top50Handler();
}
});

protected void goToBest50Act()


{
Intent goToBest = new Intent(this, Best50.class);
startActivity(goToBest);
}

protected void top50Handler()


{
try
{
‫ مطعما‬٥٠ ‫ الخاص بجلب أفضل‬API ‫عمل نص ال‬//
"٥٧ ‫من مدينة الرياض "الكود الخاص بھا‬
String attrcommand = "cities/" + "57" +
"/items/top";

167
1 ‫أندرويد ببساطة اإلصدار بيتا‬

‫بمجرد استخدام دالة يسبقھا‬//


‫اعرفوا أننا نقوم باستخدام دالة من ملف‬accessApplicationMethods()
RestDroidApplication.java
String attributesCommand =
accessApplicationMethods().getUrlStringCommand(attrcom
mand);

JSONObject[] topCities =
accessApplicationMethods().retrieveJSONs(attributesComma
nd);

‫مصفوفة سنقوم بتعبئتھا بعناصر من نوع‬//


‫وتزويد كل عنصر بمعلوماته الخاصة باالستعانة بكائنات\عناصر‬ReatedItem
‫التي قمنا بتكوينھا في السطر السابق‬JSON
ArrayList<RatedItem> sRest = new
ArrayList<RatedItem>();

if (topCities != null)
{
for (int ff = 0; ff < topCities.length;
ff++)
{
‫الحظوا كيفية الحصول على قيمة من‬//
‫" وقس على ذلك‬item_id" ‫ عبر مفتاح‬JSON ‫عنصر‬
int id =
Integer.parseInt(topCities[ff].getString("item_id"));

String name =
topCities[ff].getString("item_name");

int voteConutt =
168
1 ‫أندرويد ببساطة اإلصدار بيتا‬

Integer.parseInt(topCities[ff].getString("total_number_of_vot
es"));

double weScore =
Double.parseDouble(topCities[ff].getString("weighted_score
"));

‫تعديل العالمة الموزونة لتكون على‬//


١٠ ‫ بدال من‬٥ ‫مقياس‬
double weScoreR = weScore *
100;
weScoreR =
Math.round(weScoreR);
weScoreR = weScoreR / 10 / 2;

RatedItem singleRest = new


id, RatedItem(name,
voteConutt, weScoreR);
sRest.add(singleRest);
}
}
else
{
RatedItem singleRest = new
0, 0, 0); RatedItem("Empty List",
sRest.add(singleRest);
}

‫الحظوا أننا نقوم بتمرير قائمة المطاعم إلى متغير‬//


‫ لنتمكن من التعامل معه وقراءة‬RestDroidApplication.java ‫موجود في‬
‫ أخرى‬Activities ‫محتواه في مجموعات وأنشطة‬
169
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫;)‪accessApplicationMethods().setGlobalAdapterData(sRest‬‬
‫;)(‪goToBest50Act‬‬
‫}‬
‫)‪catch (JSONException e‬‬
‫{‬

‫}‬
‫}‬

‫‪//‬دالة يتم تعريفھا في أي نشاط يستخدم دوال المجموعة‬


‫‪RestDroidApplication.java‬لنتمكن من دخول الدوال والمتغيرات‬
‫الموجودة بھا كما ھو في األعلى‬
‫‪protected RestDroidApplication‬‬
‫)(‪accessApplicationMethods‬‬
‫{‬
‫;)(‪return (RestDroidApplication)getApplication‬‬
‫}‬

‫}‬

‫نالحظ من الكود في األعلى أننا قمنا بتمرير بعض البيانات إلى متغيرات موجودة‬
‫في مجموعة‬
‫‪RestDroidApplications‬‬
‫والسبب كما قلنا ھو لتمكين المجموعات واألنشطة األخرى من دخول ھذه‬
‫المتغيرات‪ .‬ھناك طريقة أخرى ال أقوم بھا في ھذا الشرح على أنني أستخدمھا‬
‫حاليا بشكل أساسي ويمكن للقارئ إتباعھا إذا وجدھا أفضل وھي إنشاء كائن من‬
‫مجموعة( ‪ Intent‬والتي تعرف بأنھا مجموعة خاصة بـ فعل ‪ action‬نود عمله(‬
‫وبرمجته بحيث يقوم بتمرير بيانات معينة من النشاط الحالي إلى آخر‪.‬‬

‫‪170‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫بالطبع ستظھر لنا رسالة خطأ كوننا لم ننشئ ملف المجموعة التي سننتقل إليھا‬
‫والتي سنسميھا ‪ Best50.java.‬ولكن قبل إنشائھا‪ ،‬يتوجب علينا إنشاء المجموعة‬
‫المساعدة لھا وھي‪:‬‬

‫‪RatedRestaurantListItem.java‬‬
‫ويقترن بھا ‪ rest_list_item.xml‬وكما ذكرنا من قبل فإن ھذه المجموعة تقوم‬
‫بتشكيل الواجھة الخاصة بكل عنصر )مطعم( ‪-‬الشكل ‪ -١‬وبما أنھا مرتبطة‬
‫ومتعلقة بالواجھات‪ ،‬فستقوم ھذه المجموعة بوراثة قالب\مجموعة‬
‫‪RelativeLayout‬للتعديل عليه بالشكل الذي نريده‪ .‬ھذا األمر يعني أننا لن نقوم‬
‫بوضع وسم ‪ RelativeLayout‬في ملف الـ ‪ xml‬المقترن‪ ،‬وإنما اسم مجموعتنا‬
‫الجديدة ‪-‬سأوضح ذلك بعد قليل‪-.‬‬

‫ننشئ مجموعة ‪ RatedRestaurantListItem.java‬ويكون محتواھا‪:‬‬

‫;‪package android.prog.easily‬‬

‫;‪import android.content.Context‬‬
‫;‪import android.util.AttributeSet‬‬
‫;‪import android.widget.RelativeLayout‬‬

‫‪public class RatedRestaurantListItem extends RelativeLayout‬‬


‫{‬

‫‪public RatedRestaurantListItem(Context context,‬‬


‫)‪AttributeSet attr‬‬
‫{‬
‫;)‪super(context, attr‬‬
‫}‬
‫}‬

‫واآلن ندعھا قليال ونقوم بإنشاء ملف الـ ‪ rest_list_item.xml‬داخل المجلد ‪:‬‬
‫‪171‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

‫ باليمين ومن ثم‬layout ‫أنشئ ملف جديد بالضغط على مجلد‬res>layout (


):‫المحتوى الخاص بھذا الملف ھو ما يلي )والحظ)ـي( وسم القالب‬new>file).

<?xml version="1.0" encoding="utf-8"?>


<android.prog.easily.RatedRestaurantListItem

xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<!--‫ عنصر يمكن المستخدم من الضغط على الواجھة وعمل شيء في المقابل‬--
>
<CheckedTextView
android:layout_width="wrap_content"
android:id="@+id/ctext"
android:layout_height="wrap_content"
android:textSize="30sp"
>
</CheckedTextView>

<!-- ‫ واستخدمنا ستايل معرف مسبقا في األندرويد‬،‫عنصر لعرض التقييم عليه‬


‫ نجوم‬٥ ‫ وھو سطر من النجوم وحددناھا لتكون‬-->
<RatingBar
android:id="@+id/rate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/ctext"
android:numStars="5"
style="?android:attr/ratingBarStyleIndicator"
/>

172
1 ‫أندرويد ببساطة اإلصدار بيتا‬

<!--‫ واجھات نصية لعرض العالمات التي حصل عليھا المطعم‬-->


<TextView
android:id="@+id/ratedlabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/ctext"
android:textSize="20sp"
android:layout_toRightOf="@id/rate"
android:paddingLeft="30px"
/>

<TextView
android:id="@+id/scorelabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/rate"
android:textSize="20sp"
android:paddingTop="10px"
android:paddingRight="10px"
/>

</android.prog.easily.RatedRestaurantListItem>

‫ ونقوم باستخدام‬RatedRestaurantListItem.java ‫واآلن نعود لملف‬


‫عناصر الواجھة التي عرفناھا منذ لحظات ونربطھا بالقيم التي نريدھا عرضه‬
:‫ الكود يصبح‬.(‫)وھي معلومات المطعم‬

173
1 ‫أندرويد ببساطة اإلصدار بيتا‬

package android.prog.easily;

import android.prog.easily.R;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.CheckedTextView;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class RatedRestaurantListItem extends RelativeLayout


{
private CheckedTextView ratedButton;
private RatedItem ratedItem1;
private TextView texty;
private TextView texty2;

public RatedRestaurantListItem(Context context,


AttributeSet attr)
{
super(context, attr);
}

‫دالة يتم استدعاؤھا تلقائيا بعد قراءة العناصر التي عرفناھا في ملف ال‬//
‫وعندھا يمكننا التعامل مع ھذه العناصر‬xml
@Override
protected void onFinishInflate()
{
super.onFinishInflate();
ratedButton =
(CheckedTextView)findViewById(R.id.ctext);

174
1 ‫أندرويد ببساطة اإلصدار بيتا‬

texty =
(TextView)findViewById(R.id.ratedlabel);
texty2 =
(TextView)findViewById(R.id.scorelabel);
}

‫دالة تقوم بتعيين معلومات وقيم العنصر الذي تم تمريره لھا داخل‬//
‫عناصر الواجھة‬
public void setRatedItem(RatedItem ratedItem1)
{
this.ratedItem1 = ratedItem1;
ratedButton.setText(ratedItem1.getName());
: ‫عدد األصوات‬texty.setText("
"+ratedItem1.getVoteCount());
: "+ratedItem1.getwScore() ‫العالمة‬texty2.setText("
+ "/5");
}

public RatedItem getRatedItem()


{
return ratedItem1;
}
}

: ‫ سننشئ الواجھة الخاصة بھا أوال وھي‬،‫ وكما تعودنا‬، Best50.java‫بالنسبة لـ‬
rated_rest_list.xml
:‫وستكون بالشكل التالي‬

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout
175
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫"‪xmlns:android="http://schemas.android.com/apk/res/android‬‬
‫"‪android:orientation="vertical‬‬
‫"‪android:layout_width="fill_parent‬‬
‫>"‪android:layout_height="fill_parent‬‬

‫"‪<TextView android:id="@+id/RRselect‬‬
‫"‪android:layout_width="fill_parent‬‬
‫>‪android:layout_height="wrap_content"/‬‬

‫‪<ListView‬‬
‫"‪android:layout_width="fill_parent‬‬
‫"‪android:layout_height="wrap_content‬‬
‫"‪android:id="@id/android:list‬‬
‫>‪android:layout_below="@id/RRselect"/‬‬

‫>‪</RelativeLayout‬‬

‫اآلن جاء دور المجموعة ‪ Best50.java.‬ھذه المجموعة ستقوم بعرض بيانات‬


‫أفضل ‪ ٥٠‬مطعما في الرياض‪ .‬وبما أنھا ستكون على شكل قائمة‪ ،‬فمن األفضل‬
‫استخدام مجموعة جزئية\خاصة من مجموعة ‪ Activity‬التي استخدمناھا في‬
‫‪intro.java.‬ھذه المجموعة ھي ‪ ListActivity‬وأھم ما يميزھا أن القائمة‬
‫‪List‬التي تتبناھا تتطلب استخدام أحد المفاھيم المعروفة لدى مھندسي البرمجيات‬
‫وھو مفھوم الوسيط ‪ Adapter‬أحد أنواع أنماط التصميم ‪Design Patterns .‬‬
‫مھمة الوسيط ھو التعامل مع البيانات )المطاعم( وإنشاء الواجھات الخاصة بھا‪،‬‬
‫ومن ثم تمريرھا لقائمة الواجھة الرئيسية التي ستحتضن ھذه المعلومات )أي‬
‫الواجھة المقترنة بمجموعة ‪ Best50).‬أحد األھداف ھو تقليل تداخل مجموعة‬
‫‪Best50‬وواجھتھا مع البيانات نفسھا‪ ،‬فلو أردنا تغيير البيانات أو إضافة‬
‫خصائص جديدة عليھا‪ ،‬سنقوم حينھا بالتعديل على الوسيط فقط‪ ،‬ولن نضطر إلى‬
‫تغيير كود مجموعة ‪ Best50.java.‬تخيل لو أن ھذه البيانات تستخدمھا ‪١٠‬‬
‫مجموعات‪ ،‬وبشكل وطلبات مختلفة‪ ،‬ھل سيكون حينھا من األسھل التعديل على‬
‫الوسيط فقط )والذي تتخاطب معه المجموعات العشر كلھا( أم تعديل المجموعات‬
‫‪176‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

!‫كلھا في حال عدم استخدام الوسيط‬

‫ ولكن‬inner class ‫الكود الخاص بالوسيط سيكون على شكل مجموعة داخلية‬
.‫يمكنكم عمله في مجموعة منفصلة‬

:‫كود ھذه المجموعة على الشكل التالي‬

package android.prog.easily;

import java.util.ArrayList;

import android.app.Activity;
import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.RatingBar;
import android.widget.TextView;

public class Best50 extends ListActivity


{
private TextView selectAttr;
private RatedRestaurantListAdapter adapter;

@Override
public void onCreate(Bundle savedInstanceState)
{
177
1 ‫أندرويد ببساطة اإلصدار بيتا‬

super.onCreate(savedInstanceState);
setContentView(R.layout.rated_rest_list);
setUpViews();
}

‫دالة تقوم بالفعل المناسب في حال تم الضغط على أحد القيم المعروضة‬//
‫على الشاشة‬
@Override
protected void onListItemClick(ListView l, View v, int
position, long id)
{
super.onListItemClick(l, v, position, id);

RatedItem ite =
accessApplicationMethods().getGlobalAdapterDataItem(posi
tion);

accessApplicationMethods().setItemOnMap(ite);

goToViewOnMapActivity();

private void goToViewOnMapActivity()


{
Intent goToMapActivity = new Intent(this,

startActivity(goToMapActivity);
}

private void setUpViews()


178
1 ‫أندرويد ببساطة اإلصدار بيتا‬

{
selectAttr =
(TextView)findViewById(R.id.RRselect);
");‫اضغط على أحد المطاعم‬selectAttr.setText("

‫إنشاء وسيط جديد واستخدامه ليكون على اتصال مع القائمة‬//


‫التي أنشأھا ھذا النشاط‬
adapter = new RatedRestaurantListAdapter

setListAdapter(adapter);
}

‫ الذي‬Adapter ‫ تعرف الوسيط‬InnerClass ‫مجموعة داخلية‬//


.‫سيتعامل مع بيانات المطاعم ويقوم بإنشاء واجھة خاصة بكل واحد منھا‬
‫سنستعين بمجموعة مخصصة لعمل وسيط يتعامل مع قوائم وھذه‬//
ArrayAdapter‫المجموعة ھي‬
class RatedRestaurantListAdapter extends
ArrayAdapter<RatedItem>
{
Activity context;
private ArrayList<RatedItem> myRatedItems;
RatedRestaurantListAdapter(Activity context,
{
super(context, R.layout.rest_list_item,
items);
this.context=context;
this.myRatedItems = items;
}
‫كما في الشكل‬- ‫دالة تقوم بإنشاء الواجھة الخاصة بعرض كل عنصر‬//

public View getView(int position, View
179
1 ‫أندرويد ببساطة اإلصدار بيتا‬

parent) convertView, ViewGroup


{

RatedRestaurantListItem row =
(RatedRestaurantListItem)convertView;
if (null == row)
{
‫ حيث‬،‫ تتعلق بأداء التطبيق وسرعته‬LayoutInflator ‫مھمة ھذه المجموعة‬//
‫أنھا تقتطع جزء من البيانات وتنشئ واجھاتھا‬
‫ أي‬،‫بشكل يتناسب مع مساحة عرض الشاشة‬//
‫أنھا ال تمأل ذاكرة الجھاز بعمل واجھة لكل البيانات وإنما تقوم بعملھا بشكل‬
‫تفاعلي‬
‫أي كلما قام المستخدم بتمرير إصبعه ألسفل‬//
‫ يتم إنشاء الواجھات‬،‫لرؤية المزيد من البيانات‬
LayoutInflater
inflater=context.getLayoutInflater();

row =
(RatedRestaurantListItem)inflater.inflate(R.layout.rest_list_it
em, null);
}

row.setRatedItem(myRatedItems.get(position));

RatingBar rateBar =
(RatingBar)row.findViewById(R.id.rate);
rateBar.setStepSize((float) 0.1);

rateBar.setRating((float)myRatedItems.get(position).getwSco
180
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫;))(‪re‬‬

‫;‪return row‬‬
‫}‬

‫)‪public RatedItem getItem(int position‬‬


‫{‬
‫;)‪return myRatedItems.get(position‬‬
‫}‬

‫)(‪public void reload‬‬


‫{‬
‫‪//‬دالة مھمة إلعالم القائمة التي تحتضن الوسيط بأن‬
‫بعض المعلومات تغيرت ويتوجب عليھا إذا تحديث نفسھا‬
‫;)(‪notifyDataSetChanged‬‬
‫}‬

‫}‬

‫‪protected RestDroidApplication‬‬
‫)(‪accessApplicationMethods‬‬
‫{‬
‫;)(‪return (RestDroidApplication)getApplication‬‬
‫}‬

‫}‬

‫إذا كما ھو واضح‪ ،‬فإن ‪ OnListItemClick‬ھي دالة مھمتھا القيام بعمل معين‬
‫عند الضغط على أي عنصر في القائمة‪ .‬العمل الذي نريد منھا القيام به ھو أوال‬
‫جلب معلومات المطعم الذي تم الضغط عليه )يتم ذلك عبر معرفة رقم عنصر‬
‫القائمة الذي تم الضغط عليه ‪ position‬وھو يكافئ رقم المطعم كما ھو موجود‬
‫‪181‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

‫ لذلك نقوم بجلب المطعم المختار ونضعه‬.‫في المتغير الذي يحمل بيانات المطاعم‬
‫في متغير آخر لتستخدمه الخريطة( وثانيا االنتقال إلى واجھة أخرى تحوي‬
.‫الخريطة ومكان المطعم عليھا‬

‫ والتي تقوم بعرض فروع‬ViewOnMapActivity.java ‫جاء دور مجموعة‬


(‫ الواجھة المرئية‬xml (‫ سننشئ بداية ملف الـ‬.‫المطعم المختار على الخريطة‬
: view_map.xml :‫المقترن بھا وھو‬

<?xml version="1.0" encoding="utf-8"?>


<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="@+id/restaurantNameMap"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
/>

<com.google.android.maps.MapView
android:id="@+id/map"
android:layout_width="fill_parent"
android:layout_height="wrap_content"

android:layout_below="@id/restaurantNameMap"
android:clickable="true"

android:apiKey="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
182
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫>‪xx" /‬‬

‫>‪</RelativeLayout‬‬

‫تالحظون وجود ‪ android:apikey‬وھو رقم يجب عليكم الحصول عليه عن‬


‫طريق موقع غوغل‪ .‬يتم توليد الرقم باستخدام الوثيقة االلكترونية التي يتم بھا‬
‫توقيع التطبيقات )تطبيقات أندرويد يتم توقيعھا بوثيقة الكترونية تأتي بشكل‬
‫افتراضي مع الـ ‪ SDK-‬وھذه الوثيقة ھي لدواعي التجربة ‪debugging‬‬
‫ويتوجب عليكم إنشاء وثيقة جديدة خاصة بكم في حال رغبتم بنشر التطبيق على‬
‫الماركت(‪ .‬نقوم باستخراج بصمة الوثيقة االلكترونية عبر األمر )في الوحدة‬
‫الطرفية ‪ cmd‬أو‪trminal shell):‬‬

‫\ ‪$ keytool -list -alias androiddebugkey‬‬


‫\ ‪-keystore xxx‬‬
‫‪-storepass android -keypass android‬‬

‫نستبدل الـ ‪ xxx‬بأحد ما يلي بحسب نظام التشغيل‪:‬‬


‫‪Windows Vista: C:\Users\<user>\.android\debug.keystore‬‬
‫‪Windows XP: C:\Documents‬‬ ‫‪and‬‬
‫‪Settings\<user>\.android\debug.keystore‬‬
‫‪OS X and Linux: ~/.android/debug.keystore‬‬

‫النتيجة ستكون شبيھة بما يلي‪:‬‬


‫‪Certificate fingerprint (MD5):‬‬
‫‪94:1E:43:49:87:73:BB:E6:A6:88:D7:20:F1:8E:B5:98‬‬

‫نقوم بنسخ ھذا الرقم والتوجه إلى الموقع‪:‬‬


‫‪http://code.google.com/android/maps-api-signup.html‬‬
‫‪183‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

‫ الذي نقوم‬API ‫ وعندھا سيتم تزويدنا برقم الـ‬.‫وإكمال الخطوات المطلوبة‬


xxxxxxxxxx.‫بوضعه في األعلى بدال من الـ‬

:‫ زوروا ھذه الصفحة‬،‫لمزيد من المعلومات‬


http://code.google.com/android/add-ons/google-
apis/mapkey.html

‫ سنقوم بكتابة‬، ViewOnMapActivity.java ‫واآلن قبل كتابة محتوى ملف‬


: AddressOverlay.java:‫كود المجموعة المساعدة‬

package android.prog.easily;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.location.Address;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;

public class AddressOverlay extends Overlay


{
private static final int CONTAINER_RADIUS
private static final int
= 1; CONTAINER_SHADOW_OFFSET

184
1 ‫أندرويد ببساطة اإلصدار بيتا‬

private Address address;


private GeoPoint geopoint;
Bitmap bb;

public AddressOverlay(Address address)


{
super();
assert(null != address);
‫استخالص معلومات العنوان الذي يتم تمريره‬//
this.setAddress(address);
Double convertedLongitude =
address.getLongitude() * 1E6;
Double convertedLatitude = address.getLatitude()
* 1E6;

setGeopoint(new GeoPoint(
convertedLatitude.intValue(),
convertedLongitude.intValue()));
}

‫دالة تقوم برسم نقطة خضراء فوق الخريطة عند العنوان المحدد‬//
@Override
public void draw(Canvas canvas, MapView mapView,
boolean shadow)
{
super.draw(canvas, mapView, shadow);
Point locationPoint = new Point();
Projection projection = mapView.getProjection();
projection.toPixels(getGeopoint(), locationPoint);
Paint containerPaint = new Paint();
containerPaint.setAntiAlias(true);
185
1 ‫أندرويد ببساطة اإلصدار بيتا‬

int containerX = locationPoint.x;


int containerY = locationPoint.y;
if (shadow)
{
containerX +=
CONTAINER_SHADOW_OFFSET;
containerY +=
CONTAINER_SHADOW_OFFSET;
containerPaint.setARGB(90, 0, 0, 0);

canvas.drawCircle(containerX, containerY,
CONTAINER_RADIUS, containerPaint);
}

else
{
containerPaint.setColor(Color.GREEN);
canvas.drawCircle(containerX, containerY,
CONTAINER_RADIUS, containerPaint);
}
}

public void setAddress(Address address)


{
this.address = address;
}

public Address getAddress()


{
return address;
}
186
1 ‫أندرويد ببساطة اإلصدار بيتا‬

public void setGeopoint(GeoPoint geopoint)


{
this.geopoint = geopoint;
}

public GeoPoint getGeopoint()


{
return geopoint;
}
}

‫األخيرة‬ ‫المجموعة‬ ‫كود‬ ‫بكتابة‬ ‫سنقوم‬ ،‫وأخيرا‬ ‫واآلن‬


ViewOnMapActivity.java:

package android.prog.easily;

import java.io.IOException;
import java.util.List;

import org.json.JSONException;
import org.json.JSONObject;

import android.graphics.Bitmap;
import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.widget.TextView;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
187
1 ‫أندرويد ببساطة اإلصدار بيتا‬

import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;

public class ViewOnMapActivity extends MapActivity


{
public static final String ADDRESS_RESULT =
"address";

private MapView mapView;


private Address address;
private TextView restName;
private JSONObject[] restaurantsLocObjects;
private String[] restaurantsBranchesNames;
private double [][] longLat;
private int maxLat = 0;
private int minLat = 0;
private int maxLon = 0;
private int minLon = 0;
Bitmap bmp;

@Override
protected void onCreate(Bundle bundle)
{
super.onCreate(bundle);
setContentView(R.layout.view_map);
setUpViews();

bringRestLocations();

188
1 ‫أندرويد ببساطة اإلصدار بيتا‬

mapCurrentAddress();
}

‫دالة لجلب موقع المطعم المختار وفروعه‬//


private void bringRestLocations()
{
try
{
‫ المطعم الذي تم اختياره في‬ID ‫جلب رقم معرف‬//
‫ وتم تخزينه في متغير في مجموعة‬Best50.java ‫المجموعة السابقة‬
RestDroidApplication
int restNum =
accessApplicationMethods().getItemOnMap().getId();

‫ متضمنا رقم المطعم الذي‬API ‫تشكيل نص أمر الـ‬//


‫نريد معلوماته‬
String command = "items/" + restNum +
"/locations";

String restaurantsCommand =
accessApplicationMethods().getUrlStringCommand(comman
d);

restaurantsLocObjects =
accessApplicationMethods().retrieveJSONs(restaurantsCom
mand);

restaurantsBranchesNames = new
String[restaurantsLocObjects.length];

longLat = new double[restaurantsLocObjects.length][2];


189
1 ‫أندرويد ببساطة اإلصدار بيتا‬

for (int i = 0; i <


restaurantsBranchesNames.length; i++)
{
restaurantsBranchesNames[i] = (i+1)
" + ‫البلد‬+ "\n" +" :
restaurantsLocObjects[i].getString("country") + "\n"
: " ‫المدينة‬+ "
+
restaurantsLocObjects[i].getString("city") + "\n"
: "‫رقم الفرع‬+ "
+
restaurantsLocObjects[i].getString("location_id") + "\n"
: "‫العنوان‬+ "
+
restaurantsLocObjects[i].getString("address") + "\n"
: "‫رقم التلفون‬+ "
+
restaurantsLocObjects[i].getString("phone") + "\n"
: "‫اسم الفرع‬+ "
+
restaurantsLocObjects[i].getString("title") + "\n";

longLat[i][0] =
Double.parseDouble(restaurantsLocObjects[i].getString("latit
ude"));
longLat[i][1] =
Double.parseDouble(restaurantsLocObjects[i].getString("lon
gitude"));
}

190
1 ‫أندرويد ببساطة اإلصدار بيتا‬

catch (JSONException e)
{

‫دالة تقوم بوضع فروع المطعم على الخريطة‬//


protected void mapCurrentAddress()
{
Geocoder g = new Geocoder(this);
List<Address> addresses;

boolean firstTime = true;

for (int i = 0; i <


restaurantsBranchesNames.length; i++)
{
try
{
addresses =
g.getFromLocation(longLat[i][0], longLat[i][1], 1);
if (addresses.size() > 0)
{
address = addresses.get(0);
List<Overlay> mapOverlays =
mapView.getOverlays();
AddressOverlay addressOverlay
= new AddressOverlay(address);
191
1 ‫أندرويد ببساطة اإلصدار بيتا‬

mapOverlays.add(addressOverlay);

‫ھذه الجملة الشرطية واألسطر األربعة‬//


‫ المراد عمله بحيث نرى‬zoom ‫التي تليھا الھدف منھا ھو تحديد نسبة الزوم‬
‫النقاط كلھا عند عرض الخريطة‬
‫أي لو كان لدينا فرعين األول في‬//
‫ فالزوم سيكون بعيدا بحيث تظھر النقطتان الخضر‬،‫الرياض والثاني في الدمام‬
‫على الخريطة معا‬
if (firstTime)
{
minLat =
addressOverlay.getGeopoint().getLatitudeE6();
maxLat =
addressOverlay.getGeopoint().getLatitudeE6();
minLon =
addressOverlay.getGeopoint().getLongitudeE6();
maxLon =
addressOverlay.getGeopoint().getLongitudeE6();
firstTime = false;
}

minLat = (minLat >


addressOverlay.getGeopoint().getLatitudeE6()) ?
addressOverlay.getGeopoint().getLatitudeE6() : minLat;
maxLat = (maxLat <
addressOverlay.getGeopoint().getLatitudeE6()) ?
addressOverlay.getGeopoint().getLatitudeE6() : maxLat;

minLon = (minLon >


addressOverlay.getGeopoint().getLongitudeE6()) ?
192
1 ‫أندرويد ببساطة اإلصدار بيتا‬

addressOverlay.getGeopoint().getLongitudeE6() : minLon;
maxLon = (maxLon <
addressOverlay.getGeopoint().getLongitudeE6()) ?
addressOverlay.getGeopoint().getLongitudeE6() : maxLon;

mapView.invalidate();
}
else
{

}
}

catch (IOException e)
{

}
}

final MapController mapController =


mapView.getController();
GeoPoint center = new GeoPoint((maxLat +
minLat)/2,(maxLon + minLon)/2);

mapController.animateTo(center, new Runnable()


{
public void run()
{
mapController.zoomToSpan(maxLat -
minLat,maxLon - minLon);
}
193
1 ‫أندرويد ببساطة اإلصدار بيتا‬

});

private void setUpViews()


{
restName =
(TextView)findViewById(R.id.restaurantNameMap);

restName.setText(accessApplicationMethods().getItemOnMa
p().getName());
mapView = (MapView)findViewById(R.id.map);

Zoomin/out ‫تفعيل أزرار التكبير و التصغير‬//


mapView.setBuiltInZoomControls(true);
}

@Override
protected boolean isLocationDisplayed()
{
return true;
}

@Override
protected boolean isRouteDisplayed()
{
return false;
}

protected RestDroidApplication
194
1 ‫أندرويد ببساطة اإلصدار بيتا‬

accessApplicationMethods()
{
return (RestDroidApplication)getApplication();
}
}

:‫واآلن نلقي نظرة على ملفات المشروع‬

195
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫ھل نسينا شيئا؟! الجواب نعم‪ ..‬نسينا تعديل ملف الـ ‪AndroidManifest.xml‬‬
‫‪196‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

‫ ھذا الملف مسئول عن‬.‫وھو الملف الذي أسميه بالمايسترو أو خارطة الطريق‬
‫إعالم نظام التشغيل بكيفية تشغيل التطبيق وأي واجھة ونشاط يشغلھا في البداية‬
.‫وغير ذلك‬

:‫نقوم بتعديله بالشكل التالي‬

<?xml version="1.0" encoding="utf-8"?>


<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="android.prog.easily"
android:versionCode="1"
android:versionName="1.0">

<!-- ‫معلومات عن التطبيق تتضمن اسمه ومصدر صورة األيقونة الخاصة‬


‫ به‬-->
<application android:name=".RestDroidApplication"
android:icon="@drawable/icon"
android:label="@string/app_name">

<!-- ‫" بكتابة اسم المجموعة خاصتھا بدون‬٣ ‫نقوم بتعريف كل واجھة "وعددھا‬
.java -->
<activity android:name=".intro"
android:label="@string/app_name">

<!-- ‫ھذا الجزء يعني أن ھذه الواجھة ھي الواجھة األولى التي نريد إطالقھا‬
‫ عن تشغيل التطبيق‬-->
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
197
1 ‫أندرويد ببساطة اإلصدار بيتا‬

</intent-filter>

</activity>

<activity android:name=".Best50"
android:label="Best 50 rest">
</activity>

<activity android:name=".ViewOnMapActivity"
android:label="view on Map">
</activity>

<!-- ‫ نخبر نظام التشغيل أنه يتوجب عليه استدعاء مكتبة الخرائط‬-->
<uses-library android:name="com.google.android.maps"
/>

</application>

<!-- ‫ األذونات والتصاريح التي يمكننا بھا استخدام االنترنت‬-->


<uses-permission
android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCAT
ION" />

<!-- ‫ لدي‬٧ ‫ورقمھا‬- ‫ وأعلى من األندرويد‬٢٫١ ‫ھذا التطبيق يستخدم نسخة‬


‫ ستجدون رقما‬،‫ ويمكن معرفته عند إنشاء المشروع‬،‫وھذا الرقم قد يختلف لديكم‬
‫بجانب النسخة‬- -->
<uses-sdk android:minSdkVersion="7" />
198
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫>‪</manifest‬‬

‫صور من التطبيق‪:‬‬

‫‪199‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫‪200‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫‪201‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫‪202‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫متفرقات‪:‬‬
‫‪-‬التأكد من وجود أجھزة فعلية أو افتراضية )محاكي( ليتم التواصل معھا عبر‬
‫الوحدة الطرفية‪:‬‬

‫‪$ cd /Developer/android-sdk-mac_86/tools/‬‬
‫‪$ ./adb devices‬‬

‫النتيجة‪:‬‬

‫‪List of devices attached‬‬


‫‪emulator-5554 device‬‬

‫‪-‬مساحة الذاكرة الداخلية للجھاز االفتراضي قد تكون غير كافية للتطبيق أو‬
‫لملفات نرغب برفعھا إليه )كملفات الخطوط العربية(‪ ،‬لذلك يمكننا إطالق محاكي‬
‫بمساحة نقوم بتخصيصھا عبر األمر‪:‬‬

‫‪$ cd /Developer/android-sdk-mac_86/tools/‬‬
‫‪$ ./emulator -avd GPSenables -partition-size 500‬‬

‫اسم المحاكي يتم تحديده بعد ‪ -avd‬أي أن المحاكي الذي أريد تشغيله‬
‫‪ ،GPSenables‬لذلك قم \ قومي بتغيير ھذا االسم وضع المحاكي الذي ترغب‬
‫بإطالقه‪.‬‬

‫ستنطلق نسخة من المحاكي وتجد أن الوحدة الطرفية أصبحت ال تقبل مدخالت‪،‬‬


‫لذلك دع ھذه النافذة وافتح نافذة وحدة طرفية أخرى‪.‬‬

‫‪-‬للقيام برفع خطوط عربية إلى المحاكي )الخطوط موجودة في الموقع الذي‬
‫وضعنا عليه ملفات البرنامج( وبما أننا سنقوم بالكتابة على ملفات النظام‪ ،‬علينا‬
‫أوال كتابة األمر‪:‬‬

‫‪203‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

$ ./adb remount

‫النتيجة‬

remount succeeded

):‫ومن ثم )مع تغيير المسار‬

$ ./adb push /Users/wa2el/Desktop/fontss/DroidSans-Bold.ttf


/system/fonts/

$ ./adb push /Users/wa2el/Desktop/fontss/DroidSans.ttf


/system/fonts/

$ ./adb push
/Users/wa2el/Desktop/fontss/DroidSansFallback.ttf
/system/fonts/

‫ قد تظھر لك أحيانا خطوط صفراء تحت الكود‬،‫أثناء لصق الكود المنسوخ‬-


‫ الحل ھو إعادة اللصق أعلى الكود الذي تحته‬xml) ‫)تحصل كثيرا في ملفات الـ‬
.‫خطوط صفراء ومن ثم إزالة األخير‬

204
1 ‫أندرويد ببساطة اإلصدار بيتا‬

”:‫الملحق “أ‬
:‫وظيفة و كيفية إنشاء ما يلي‬
<LinearLayout>‫وعاء‬- ١
<TableLayout>‫وعاء‬- ٢
<ScrollView>‫وعاء‬- ٣

<LinearLayout>‫وعاء‬- ١
:‫لدينا عادة الخصائص\العناصر التالية‬

<LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

>

‫ يتم عبرھا تحديد طريقة رصف األزرار‬Orientation ‫بالنسبة لخاصية التوجه‬


‫ يعني وضع العناصر‬Vertical ‫ الوضع الرأسي‬.‫ في الصفحة‬Widgets ‫وال‬
.‫ فيعني صفھا بشكل أفقي‬Horizontal ‫ أما‬،‫بشكل عمودي‬

205
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫خاصية ‪ layout_width‬مسئولة عن تحديد عرض الوعاء‪ ،‬ونحن في ھذه الحالة‬


‫نريد من الوعاء مأل الشاشة واحتالل جميع المساحات‪ ،‬لذلك نختار‬
‫‪fill_parent.‬‬

‫خاصية ‪ layout_height‬يتم عبرھا تحديد ارتفاع الوعاء‪ ،‬وأيضا نريده مأل‬


‫المساحات كاملة‪.‬‬

‫نقوم اآلن بإنشاء زر لنرى كيفية التحكم بطريقة ظھوره في واجھة التطبيق‪.‬‬

‫‪<Button‬‬

‫"‪android:text="@+id/Button01‬‬

‫"‪android:id="@+id/Button01‬‬

‫"‪android:layout_width="wrap_content‬‬

‫>"‪android:layout_height="wrap_content‬‬

‫>‪</Button‬‬
‫بالنسبة للخاصية األولى‪android:text ،‬فھي المسئولة عن تحديد النص المراد‬
‫ظھوره على الزر ‪. android:id‬تقوم بإعطاء رقم خاص للعنصر يميزه عن‬
‫غيره‪ .‬بالنسبة للخاصيتين األخيرتين فقد تم شرحھما في األعلى‪ ،‬ولكني سأتعرض‬
‫للقيم التي من الممكن إعطاءھا لھما‪ .‬ھناك ‪ ٣‬احتماالت‪ .‬األول ‪fill_parent‬‬
‫الذي يقوم بمليء المساحة الخالية بالزر بحسب الخاصية التي أعطي لھا‬

‫‪206‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫‪(layout_width‬أو ‪ layout_height).‬الثاني ھو ‪ wrap_content‬والذي‬


‫يقوم بضغط حجم الزر بحسب محتواه النصي‪ .‬االحتمال الثالث ھو أن يتم تحديد‬
‫االرتفاع والعرض بمقياس البيكسل‪.‬‬

‫مثال للحالة األولى والثانية )سيمأل الزر المساحات المجاورة له بالعرض‪ ،‬ولكن‬
‫ارتفاعه سيكون مضغوطا‪):‬‬

‫‪<Button‬‬

‫"‪android:text="Ardroid‬‬

‫"‪android:id="@+id/Button01‬‬

‫"‪android:layout_width="fill_parent‬‬

‫>"‪android:layout_height="wrap_content‬‬

‫>‪</Button‬‬

‫‪207‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫(قم بتجربة االحتماالت األخرى‪ ،‬ويمكنك االستعانة بتبويب ‪ Layout‬الستعراض‬


‫نتيجة التصميم بدال من تشغيل التطبيق في كل مرة‪ ..‬كما يمكنك استخدام ھذه‬
‫الواجھة لتصميم صفحة النشاط في التطبيق دون كتابة كود ال ‪ XML‬في كل‬
‫مرة)‬

‫مثال للحالة الثالثة‪:‬‬

‫‪<Button‬‬

‫"‪android:text="Ardroid‬‬

‫"‪android:id="@+id/Button01‬‬

‫"‪android:layout_width="300px‬‬
‫‪208‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

android:layout_height="100px">

</Button>

‫ كيف نقوم‬.‫ ولكننا نريد وضعه اآلن بجانب الزر األول‬،‫ثان‬


ٍ ‫سنقوم بإضافة زر‬
‫ وھي‬LinearLayout ‫بذلك؟ ال ننس الخاصية األولى الخاصة بوعاء‬
:‫ بشكل أفقي‬Widgets ‫نقوم بتعديلھا ليتم عرض ال‬Orientation.

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="horizontal"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

>
):‫والزر الثاني )قم بتسميته بنفس اسم الزر السابق‬
209
1 ‫أندرويد ببساطة اإلصدار بيتا‬

<Button

android:text="Ardroid"

android:id="@+id/Button02"

android:layout_width="wrap_content"

android:layout_height="wrap_content">

</Button>

‫ والتي‬android:layout_weight ‫سنقوم اآلن بالتعرف على خاصية الوزن‬


‫تقوم بإعطاء أولوية نقوم بتحديدھا ألحد الزرين ليحتل أعالھما أولوية كمية أكبر‬
:‫ فمثال‬.‫من المساحات الفارغة‬

<Button

android:text="Ardroid"

android:id="@+id/Button01"

210
1 ‫أندرويد ببساطة اإلصدار بيتا‬

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_weight="1"

>

</Button>

<Button

android:text="Ardroid"

android:id="@+id/Button02"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_weight="2"

>

</Button>

211
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫ھناك عدد من الخصائص األخرى والتي يتم عبرھا التحكم بطريقة وضع ال‬
‫‪Widgets‬فلدينا مثال ‪ android:layout_agravity‬وھي مناسبة أكثر في حالة‬
‫التعامل مع ال ‪Widgets‬عند رصفھم رأسيا ونقوم عبرھا بالتحكم بخاصية‬
‫المحاذاة ‪ alignment‬التي سيكون عليھا الزر مثال‪ .‬وفي حال أردنا التحكم‬
‫بالمحاذاة في طريقة الرصف األفقية‪ ،‬فمن األفضل استخدام‬
‫‪android:layout_marginLeft‬وتحديد عدد النقاط ‪ Pixels‬التي تفصل بين‬
‫الزر واآلخر‪.‬‬

‫مثال على ‪ android:layout_marginLeft‬في حالة الرصف األفقية‬


‫‪android:orientation=”horizontal” :‬‬

‫‪<Button‬‬

‫"‪android:text="Ardroid‬‬

‫"‪android:id="@+id/Button02‬‬

‫"‪android:layout_width="wrap_content‬‬

‫"‪android:layout_height="wrap_content‬‬
‫‪212‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

android:layout_marginLeft="180px"

>

</Button>

‫الرأسي‬ ‫بالوضع‬ android:layout_gravity ‫على‬ ‫ومثال‬


android:orientation=”vertical”:

<Button

android:text="Ardroid"

android:id="@+id/Button02"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="right"

>

213
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫>‪</Button‬‬

‫طبعا نالحظ القائمة المنسدلة والتي تحوي عددا من القيم التي يمكنكم تجربتھا‬
‫ورؤية تأثيرھا‪.‬‬

‫و‬ ‫قوموا بتجربة خصائص أخرى كال ‪android:gravity‬‬


‫‪android:paddingLeft‬وغيرھا والحظوا تأثيراتھا‪.‬‬

‫في نھاية ھذا القسم‪ ،‬تجدر اإلشارة إلى أنه يمكننا تغيير خاصية توجه\وضع‬
‫الوعاء ‪ Orientation‬أثناء عمل التطبيق‪ .‬فمثال يمكننا برمجة التطبيق بأن يقوم‬
‫بتغيير التوجه ليصبح بالوضع األفقي عند ضغط زر‪ .‬تتم ھذه العملية باستدعاء‬
‫دالة‬
‫;)‪x.setOrientation(LinearLayout.HORIZONTAL‬‬
‫‪214‬‬
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫حيث ‪ x‬ھي اسم ال ‪ ، Widget‬زر مثال‪.‬‬

‫‪- ٢‬وعاء>‪<TableLayout‬‬
‫يأخذ ھذا الوعاء شكل الجدول‪ .‬لذا‪ ،‬فإننا نستخدم وسم <‪ >TableRow‬كلما‬
‫أردنا إنشاء صف جديد‪ .‬يتميز ھذا الوعاء بعدد من الخصائص‪:‬‬
‫أ ‪- android:layout_span :‬وھي خاصية تحدد المدى الذي نود أن يحتله‬
‫العنصر‪ ،‬وتأخذ قيمة عددية‪ .‬القيمة العددية تحدد بشكل غير مباشر عدد األعمدة‬
‫‪Columns‬داخل الصف‪.‬‬
‫ب ‪- android:layout_column :‬وھي خاصية تحدد رقم العمود الذي‬
‫سيتوضع عنده العنصر ‪ Widget.‬وترقيم األعمدة يبدأ من الصفر‪ ،‬بمعنى أن أول‬
‫عمود رقمه صفر‪ ،‬وھكذا‪.‬‬
‫ج ‪- android:stretchColumns :‬وھي خاصية محصورة بالوعاء نفسه )أي‬
‫ال يمكن تطبيقھا على العناصر ) ‪ Widgets‬وھي تعمل على شد العمود ليغطي‬
‫المساحة الفارغة‪ ،‬وتأخذ قيمة عددية تحدد رقم العمود‪.‬‬
‫د ‪- android:shrinkColumns :‬وھي عكس الخاصية السابقة‪.‬‬
‫مثال توضيحي‪:‬‬
‫للحصول على التصميم التالي‪:‬‬

‫‪215‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

:‫نستعمل الكود‬

<?xml version="1.0" encoding="utf-8"?>

<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"
216
1 ‫أندرويد ببساطة اإلصدار بيتا‬

android:stretchColumns="2"

>

<TableRow>

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Hello!"

android:layout_column="2"

android:layout_gravity="center"

/>

</TableRow>

<TableRow>

<SeekBar

android:id="@+id/SeekBar01"

217
1 ‫أندرويد ببساطة اإلصدار بيتا‬

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_span="2"

android:layout_column="1">

</SeekBar>

</TableRow>

<TableRow>

<Button

android:text="Ardroid"

android:id="@+id/Button01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_column="2"

>

218
1 ‫أندرويد ببساطة اإلصدار بيتا‬

</Button>

<CheckBox

android:text="checkBox"

android:id="@+id/CheckBox01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_column="0"

>

</CheckBox>

</TableRow>

<TableRow>

<RadioButton

android:text="Radio Button"

android:id="@+id/RadioButton01"

219
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫"‪android:layout_width="wrap_content‬‬

‫"‪android:layout_height="wrap_content‬‬

‫>‬

‫>‪</RadioButton‬‬

‫>‪</TableRow‬‬

‫>‪</TableLayout‬‬

‫‪- ٣‬وعاء>‪<ScrollView‬‬
‫نستعمل ھذا الوعاء في حالة كان المحتوى الذي نود عرضه في الصفحة كبيرا‬
‫بحيث أنه ال يمكن وضعه في صفحة واحدة‪ .‬طريقة عمله سھلة وھي تضمين‬
‫التصميم الذي نرغبه بداخله‪ .‬فمثال‪ ،‬يمكننا وضع الكود الذي كتبناه في األعلى‬
‫بداخله )بعد إضافة عدد من العناصر ‪ Widgets‬حتى يتطلب عرض المحتوى‬
‫أكثر من صفحة‪).‬‬

‫>?"‪<?xml version="1.0" encoding="utf-8‬‬

‫‪<ScrollView‬‬

‫"‪xmlns:android="http://schemas.android.com/apk/res/android‬‬

‫"‪android:layout_width="fill_parent‬‬
‫‪220‬‬
1 ‫أندرويد ببساطة اإلصدار بيتا‬

android:layout_height="wrap_content">

<TableLayout
xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:stretchColumns="2"

>

<TableRow>

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Hello!"

android:layout_column="2"

221
1 ‫أندرويد ببساطة اإلصدار بيتا‬

android:layout_gravity="center"

/>

</TableRow>

<TableRow>

<SeekBar

android:id="@+id/SeekBar01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_span="2"

android:layout_column="1">

</SeekBar>

</TableRow>

<TableRow>

<Button

222
1 ‫أندرويد ببساطة اإلصدار بيتا‬

android:text="Ardroid"

android:id="@+id/Button01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_column="2"

>

</Button>

<CheckBox

android:text="checkBox"

android:id="@+id/CheckBox01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_column="0"

>

223
1 ‫أندرويد ببساطة اإلصدار بيتا‬

</CheckBox>

</TableRow>

<TableRow>

<RadioButton

android:text="Radio Button"

android:id="@+id/RadioButton01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

>

</RadioButton>

</TableRow>

<TableRow>

<RadioButton

android:text="Radio Button"

224
1 ‫أندرويد ببساطة اإلصدار بيتا‬

android:id="@+id/RadioButton01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

>

</RadioButton>

</TableRow>

<TableRow>

<RadioButton

android:text="Radio Button"

android:id="@+id/RadioButton01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

>

</RadioButton>

225
1 ‫أندرويد ببساطة اإلصدار بيتا‬

</TableRow>

<TableRow>

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Hello!"

android:layout_column="2"

android:layout_gravity="center"

/>

</TableRow>

<TableRow>

<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

226
1 ‫أندرويد ببساطة اإلصدار بيتا‬

android:text="Hello!"

android:layout_column="2"

android:layout_gravity="center"

/>

</TableRow>

<TableRow>

<SeekBar

android:id="@+id/SeekBar01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_span="2"

android:layout_column="1">

</SeekBar>

</TableRow>

227
1 ‫أندرويد ببساطة اإلصدار بيتا‬

<TableRow>

<SeekBar

android:id="@+id/SeekBar01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_span="2"

android:layout_column="1">

</SeekBar>

</TableRow>

<TableRow>

<SeekBar

android:id="@+id/SeekBar01"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

228
1 ‫أندرويد ببساطة اإلصدار بيتا‬

android:layout_span="2"

android:layout_column="1">

</SeekBar>

</TableRow>

</TableLayout>

</ScrollView>

229
‫أندرويد ببساطة اإلصدار بيتا ‪1‬‬

‫انتھى بحمد ﷲ‬

‫أرجوا أن يتقبل ﷲ ھذا العمل كما أتمنى أن يكون الكتاب قد أفادكم و‬


‫أرجوا منكم دعوة بظھر الغيب‬

‫محمد بدوي ‪ ،‬وائل علواني‬

‫دمتم بود‪،،،‬‬

‫‪230‬‬

Vous aimerez peut-être aussi