بلبيل

Page 1


‫أندرويد ببساطة اإلصدار بيتا ‪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 : ‫و ھذه المكتبات ھي‬ • • • • • • • • •

8

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


‫أندرويد ببساطة اإلصدار بيتا ‪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) == '}' && secondSeen == false) { 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, voteConutt, weScoreR); sRest.add(singleRest); } } else { RatedItem singleRest = new 0, 0, 0); sRest.add(singleRest); } 164

RatedItem(name,

RatedItem("Empty List",


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, voteConutt, weScoreR); sRest.add(singleRest); } } else { RatedItem singleRest = new 0, 0, 0); sRest.add(singleRest); }

RatedItem(name,

RatedItem("Empty List",

‫الحظوا أننا نقوم بتمرير قائمة المطاعم إلى متغير‬// ‫ لنتمكن من التعامل معه وقراءة‬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/googleapis/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‬‬


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.