أندرويد ببساطة اإلصدار بيتا 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 myrelease-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