Professional Documents
Culture Documents
Learn Android Easily PDF
Learn Android Easily PDF
أندرويد ببساطة
بواسطة
محمد بدوي
وائل علواني
2
أندرويد ببساطة اإلصدار بيتا 1
فھرس المحتويات
الموضوع
لنتعرف على أندرويد
قاموس المصطلحات
كيف تبني تطبيق موجه لنظام تشغيل أندرويد
التعرف على البنية الداخلية لحياة التطبيق
تركيب أدوات التطوير و حزمة المطورين الموجھة الندرو يد
الخطوة األولى )(Java SE
الخطوة الثانية )(Android SDK
الخطوة الثالثة )(Eclipse
الخطوة الرابعة )(ADT
التعامل مع بيئة التطوير )(Eclipse
بناء أول تطبيق لك موجه الندرو يد بواسطة )(Android
بناء المشروع من خالل سطر األوامر
تشغيل تطبيقك على المحاكي
إعداد المحاكي
تشغيل المحاكي
التعامل مع المحاكي
التعامل مع المحاكي من خالل سطر األوامر
المحاكي و العالم الخارجي
بناء تطبيقك األول بدون كود )أھال بالعالم(
بناء مشروعك األول )قائمة المھام(
كيف تقوم بتسويق و إتاحة تطبيقك للجمھور
بناء تطبيق احترافي ) (Mash upبالتكامل مع محتوى خارجي )ريست درويد(
3
أندرويد ببساطة اإلصدار بيتا 1
حول الكتاب
من الجيد معرفته أننا قمنا بكتابة الكتاب في نھاية العام )(2009
ميالدية و من ثم حاولنا البحث عن راعي لطباعة الكتاب أو توزيعه
و قد قامت بعض الجھات بإطالق الوعود الكثيرة ومنھا شركة
جوجل ممثلة بوكيلھا في السعودية مما جعلنا االنتظار بضعة أشھر
لنعرف رأي الراعي بالكتاب و مدى جودته لتوفيره للناس ،و لكن و
مع مرور الوقت لم نعد نسمع منھم ،و لذا تقاعسنا في نشر الكتاب
و لم نكمله و توقف العمل عليه نھائيا منذ شھر ) (4للعام )(2010
و ھا قد قمنا أخيرا بتنقيحه و على عجل إلصداره للناس و ھو و إن
كانت بعض البيانات قديمة إال أنه مازال صالحا للعمل بما فيه حتى
يومنا ھذا ،لذا في حال وجود بعض األخطاء فأرجوا أن تعذرنا فلقد
قمنا بأفضل ما يمكن للخروج بالكتاب بأفضل شكل و بأبسط ما يمكن
حيث ال يوجد أي كتب عربية حتى اآلن مھتمة في ھذا المجال و
كذلك الحال أغلب الكتب األجنبية التي طالعناھا تعاني من التعقيد ،
بل و تعتبر بأن من يقرأ الكتاب ملم بالكثير من األمور و لذا مازلنا
نجد بأن الكتاب سيكون من أفضل ما كتب حتى يومنا ھذا في ھذا
العالم.
4
أندرويد ببساطة اإلصدار بيتا 1
حول المؤلفين
محمد بدوي )مدون ،مبرمج ،رائد أعمال(
5
أندرويد ببساطة اإلصدار بيتا 1
8
أندرويد ببساطة اإلصدار بيتا 1
ثم تلي ھذه الطبقة طبقة منصة التطبيقات و التي تستخدم من قبل كل
التطبيقات:
• Activity Manager
• Window Manager
• Content Provider
• View System
• Notification Manager
• Package Manager
• Telephony Manager
• Resource
• Location Manager
• Sensor Manager
9
أندرويد ببساطة اإلصدار بيتا 1
10
أندرويد ببساطة اإلصدار بيتا 1
• Activity
• Intent
• Service
• Content Provider
قبل اإلبحار دعنا نتعرف على ھذه األسس و التي يمكن لتطبيقك أن
يستخدم أحدھا فقط أو أكثر أو كلھا مجتمعة:
11
أندرويد ببساطة اإلصدار بيتا 1
و بينما النشاط يعمل و االنتقال إلى نشاط أخر فإنه يكون في وضعية
اإليقاف المؤقت ) (Pausedو الذي يمكن التعامل معه مع األحداث:
• On Save Instance State
• On Resume
• On Stop
أما المرحلة األخيرة و التي تعتبر نھاية النشاط و التي يتم إلغاؤه من
الذاكرة ) (Destroyedو يتم تنفيذ الحدث الوحيد:
• On Destroy
و الذي يترجم إلى قصد أو غرض و لكن أرى أن زناد أقرب ترجمة
للفھم باللغة العربية و التي يستخدم إلتمام عمل ما ،مثال في
استدعاء نشاط جديد مثل شاشة أو عند استدعاء صفحة انترنت أو
البحث عن عنصر في قائمة االتصاالت و غيرھا من األمور التي
تستخدم بناء على طلب المستخدم.
12
أندرويد ببساطة اإلصدار بيتا 1
الخدمة )(Service
يمكنك عبر ذلك مناداة أي محتوى خارجي مثال عبر تطبيق ويب أو
حتى في مبادلة المحتوى بين التطبيقات فعلى سبيل المثال يمكنك أن
تصل لقائمة عناوين االتصال في تطبيق ).(Contacts
تعرض الكائنات بشكل جدولي حيث يمكن وضع كل كائن داخل خلية
كما الحال في تصميم الجداول في ).(HTML
14
أندرويد ببساطة اإلصدار بيتا 1
قاموس المصطلحات
16
أندرويد ببساطة اإلصدار بيتا 1
في عملية التركيب سأحاول قدر اإلمكان عدم إغفال أي نقطة مھما
كانت صغيرة و سأقوم بتوثيقھا بالصور فكتابنا يدور حول البساطة
و ھي تبسيط كل شيء قد اإلمكان لكي ال تقف خطوة صغيرة حجر
عثرة في طريقنا لتعلم تطوير التطبيقات .
17
أندرويد ببساطة اإلصدار بيتا 1
http://java.sun.com/javase/downloads/index.jsp
بعد فتح الصفحة ستظھر لك عدة خيارات اختر كما ھو مبين ضمن
اإلطار:
18
أندرويد ببساطة اإلصدار بيتا 1
19
أندرويد ببساطة اإلصدار بيتا 1
20
أندرويد ببساطة اإلصدار بيتا 1
قم بحفظ الملف على سطح المكتب في الوقت الحال و الحقا يمكنك
االحتفاظ بنسخة منه في مكان أمن و بعد حفظ الملف ستبدأ عملية
التحميل و التي قد تستغرق بعد الوقت بناء على سرعة االنترنت
لديك
قم بالنقر مرتين على الملف لتشغيل برنامج اإلعداد لتظھر لك شاشة
شبيھة بھذه اضغط على قبول )(Accept
21
أندرويد ببساطة اإلصدار بيتا 1
بعد دقائق قليلة ستظھر لك شاشة تخيرك فيھا بتغيير المجلد الھدف
للبرنامج ال تقم بتغيير شيء و اختر زر التالي )(Next
23
أندرويد ببساطة اإلصدار بيتا 1
24
أندرويد ببساطة اإلصدار بيتا 1
http://developer.android.com/sdk/index.html
25
أندرويد ببساطة اإلصدار بيتا 1
انزل إلى أخر الصفحة و اختر الموافقة على اتفاقية المستخدم إن
أردت – ( : -و اضغط على زر تحميل ) (Downloadو عندھا
ستظھر لنا شاشة تحميل البرنامج كما الشكل التالي و اضغط فيھا
على زر حفظ )(Save
لتظھر لك بعد ذلك شاشة اختيار حفظ الملف كما الشكل التالي
26
أندرويد ببساطة اإلصدار بيتا 1
قم بتحديد وجھة الحفظ و لتكن سطح المكتب ثم انقر على زر حفظ
) (Saveو عندھا ستبدأ عملية تحميل البرنامج على جھازك
27
أندرويد ببساطة اإلصدار بيتا 1
28
أندرويد ببساطة اإلصدار بيتا 1
كما ترى في حالتنا ھذه تظھر الشاشة وجود عملية خطاء أثناء
عملية التحميل و ذلك لعدم تمكن برنامج اإلعداد من التخاطب عبر
بروتوكول ) (httpsو قد ال تظھر لك الشاشة في حال لم يكن على
29
أندرويد ببساطة اإلصدار بيتا 1
30
أندرويد ببساطة اإلصدار بيتا 1
31
أندرويد ببساطة اإلصدار بيتا 1
قد يتساءل البعض لماذا اخترنا ) (1.6و لم نختر أحدث نظام )(2.1؟
و السبب ببساطة ھو أن قرابة ) (%50من األجھزة المتوفرة في
األسواق تعمل بنظام ) .(1.6كما أن النسخ األحدث لم تتوفر في
أسواقنا العربية بعد و األھم من ذلك فإن أندرويد يدعم بشكل تلقائي
في نظم تشغيله األحدث التطبيقات التي صممت على نظام سابق .كما
أن أكثر التطبيقات المتوفرة في األسواق موجھة لھذا النظام و في
حال كنت مثلي و تملك جھاز على نظام ) (1.5و ھو المتوفر في
األسواق العربية فإن تطبيقك سيعمل عليه أيضا بدون أي مشاكل و
بالنھاية لك الخيار في تحميلھا جميعا أو االكتفاء بھذا حيث أن كل
عنصر من ھذه تحتاج إلى وقت طويل في عملية التحميل و يمكنك
في أي وقت العودة و تحميلھا بإتباع نفس الخطوات السابقة.
32
أندرويد ببساطة اإلصدار بيتا 1
33
أندرويد ببساطة اإلصدار بيتا 1
http://www.Eclipsee.org/downloads
34
أندرويد ببساطة اإلصدار بيتا 1
عن طريق ھذه الصفحة يمكن اختيار طريقة التحميل إما عن طريق
بروتوكول ) (Torrentأو بشكل مباشر عن طريق أحد الخوادم
التي توفر التطبيق ،لك الخيار في ذلك و لكني أفضل دائما استخدام
الوصالت المباشرة لعدم حاجتھا إلى أي تطبيقات أخرى كما ھو
موضح في المربع في الصورة.
35
أندرويد ببساطة اإلصدار بيتا 1
قد تأخذ منك العملية بعض الوقت بناء على سرعة االنترنت لديھم و
عند انتھائھا ستجد ملف مضغوط باسم )Eclipsee-SDK-3.5.2-
(win32على سطح المكتب كما في الصورة التالية
36
أندرويد ببساطة اإلصدار بيتا 1
قم اآلن بسحب المجلد إلى سطح المكتب عبر خاصية السحب و
اإلفالت بالفأرة أو قم بالضغط بزر الفأرة األيمن و من ثم اختيار
خيار نسخ ) (Copyومن ثم اذھب إلى سطح المكتب و قم بزر
الفأرة األيمن باختيار خيار ) (Pasteلتبدأ عملية فك ضغط الملف:
بعد ھذه الخطوة ستجد مجلد على سطح المكتب لديك باسم
) (Eclipseقم بالضغط المضاعف عليه ليفتح لديك محتوياته
37
أندرويد ببساطة اإلصدار بيتا 1
38
أندرويد ببساطة اإلصدار بيتا 1
وھذه الشاشة التي تحدد فيھا مساحة العمل الخاصة بك و التي يتم
تخزين ملفات مشاريعك فيھا و يمكنك تغيير مكانھا لحقا أو اختيار
خيار ) (Use this as default and do not ask againو
التي تحفظ اختيارك لكي ال تظھر لك في كل مرة تقوم فيھا بتشغيل
بيئة التطوير
39
أندرويد ببساطة اإلصدار بيتا 1
40
أندرويد ببساطة اإلصدار بيتا 1
41
أندرويد ببساطة اإلصدار بيتا 1
/https://dl-ssl.google.com/android/Eclipsee
42
أندرويد ببساطة اإلصدار بيتا 1
43
أندرويد ببساطة اإلصدار بيتا 1
ثم اضغط على زر التالي لتظھر شاشة اتفاقية المستخدم كما الصورة
التالية
44
أندرويد ببساطة اإلصدار بيتا 1
45
أندرويد ببساطة اإلصدار بيتا 1
46
أندرويد ببساطة اإلصدار بيتا 1
47
أندرويد ببساطة اإلصدار بيتا 1
48
أندرويد ببساطة اإلصدار بيتا 1
49
أندرويد ببساطة اإلصدار بيتا 1
و التي تقوم بعرض المنصات التي قمنا بتحميلھا سابقا أثناء عملية
تنصيب حزمة التطوير .
برنامجك األول
إال أني أرى أن )أندرويد ببساطة( أسھل و لذا سنبني تطبيق أندرويد
ببساطة و بكل بساطة و بدون سطر برمجي واحد و بعد أن نقوم
ببناء التطبيق و التعرف على خطوات بدء مشروع جديد سنقوم
بإعداد محاكي جھاز أندرويد لتستطيع تشغيل برنامجك عليه.
إن كنت قد قمت بإغالق بيئة التطوير ) (Eclipseفقم بإعادة
تشغيلھا اآلن لتظھر لنا الشاشة الرئيسية
51
أندرويد ببساطة اإلصدار بيتا 1
52
أندرويد ببساطة اإلصدار بيتا 1
53
أندرويد ببساطة اإلصدار بيتا 1
اآلن دعنا نتعرف على ماذا قام المعالج ببنائه لنا و ذلك بسرد أبناء
العنصر لتكون بالشكل التالي
56
أندرويد ببساطة اإلصدار بيتا 1
في البداية علينا تعريف مسار سطر األوامر في النظام ليتعرف عليھا
عند طلبھا في أي مسار و ذلك عن طريق الذھاب إلى جھاز
الكمبيوتر من على سطح المكتب أو من القائمة إبداء و بالضغط على
أيقونة جھاز الكمبيوتر بزر الفأرة األيمن و من ثم الذھاب إلى
خصائص ) (Propertiesومن ثم الذھاب إلى لسان تبويب خيارات
متقدمة ) (Advancedلتظھر لنا بالشكر التالي
57
أندرويد ببساطة اإلصدار بيتا 1
58
أندرويد ببساطة اإلصدار بيتا 1
59
أندرويد ببساطة اإلصدار بيتا 1
60
أندرويد ببساطة اإلصدار بيتا 1
ثم بعد ذلك اضغط على زر موافق ) (OKثم مرة أخرى للشاشة
الرئيسية اضغط موافق )(OK
61
أندرويد ببساطة اإلصدار بيتا 1
62
أندرويد ببساطة اإلصدار بيتا 1
وفي حالتنا ھذه ال يتوفر لدينا سوى منصة واحدة رقمھا ) (1و التي
سنستخدمھا لبناء المشروع الخاص بنا عبر سطر األوامر
االن لنجرب بناء مشروع جديد عن طريق سطر األوامر فلذا علينا
كتابة األمر التالي
android create project -n AndroidVerySimple -p c:\1\ -k
com.book.VerySimple -a Activity_VerySimple -t 1
مالحظة )سطر األوامر السابق يكتب على سطر واحد و لكن النص
ھنا تم تقسيمه على سطرين لدواعي الكتاب(
حيث أن:
63
أندرويد ببساطة اإلصدار بيتا 1
)\ (c:\1ھو مسار المشروع الذي سوف يتم تخزينه على جھاز
)(Pathو نستخدم البارمتر التالي لتعريفھا )(-p
بعد االنتھاء من كتابة سطر األمر كما ھو بالكامل و الضغط على زر
اإلدخال ) (Enterستظھر لنا الشاشة التالية
يمكنك اآلن تصفح ملفات المشروع داخل المجلد الذي قمنا بتحديده
سابقا ) (c:\1و الذي يمكنك أيضا اختيار نفس مساحة المشاريع
64
أندرويد ببساطة اإلصدار بيتا 1
65
أندرويد ببساطة اإلصدار بيتا 1
66
أندرويد ببساطة اإلصدار بيتا 1
في حال واجھتك مشكلة ولم تفتح ھذه الشاشة فال تقلق فيمكنك
دائما تشغيلھا بشكل يدوي عبر الذھاب إلى المجلد الذي قمنا به بفرد
حزمة التطوير و الذي يتواجد على سطح المكتب باسم )android-
(sdk-windowsو قم بتشغيل البرنامج ) (SDK Setupو في
حال لم يعمل معك أيضا فال تقلق فھناك طريقة أخرى يمكن فيھا أن
نبني المحاكي عن طريق سطر األوامر و التي سنتحدث عنھا في
أخر ھذا الجزء.
67
أندرويد ببساطة اإلصدار بيتا 1
68
أندرويد ببساطة اإلصدار بيتا 1
بما أننا اخترنا حجم كرت الذاكرة فعلينا دعم خاصية كرت الذاكرة و
لذا سنضيف ) (SD Card Supportو من ثم سنضغط على زر
) (OKو نكرر نفس العملية بالضغط على زر ) (Newإلضافة عتاد
جديد و لنختر كل من
GPS Support
Accelerometer
لتظھر لنا الشاشة النھائية بالشكل التالي
69
أندرويد ببساطة اإلصدار بيتا 1
70
أندرويد ببساطة اإلصدار بيتا 1
71
أندرويد ببساطة اإلصدار بيتا 1
72
أندرويد ببساطة اإلصدار بيتا 1
73
أندرويد ببساطة اإلصدار بيتا 1
في حال واجھت مشكلة عند محاولة تشغيل تطبيقك و ذلك بسبب أنه
أحيانا معالج إعداد المشروع ال يقوم ببناء كامل المراجع في ملفات
المشروع المتنوعة وستظھر لك رسالة خطأ شبيھة بالتالية
فلذلك إما عليك أن تغلق المشروع و تعيد فتحه أو تقوم بالذھاب إلى
القائمة ) (Projectومن ثم اختيار خيار ) (Cleanكما في الصورة
التالية
74
أندرويد ببساطة اإلصدار بيتا 1
و بعد ذلك ستظھر لك شاشة كما في الشكل التالي اضغط على زر
موافق )(OK
ستالحظ أنه كانت ھناك عالمة ) (Xصغيرة حمراء كانت على اسم
المشروع في أعلى الشجرة و بعد ھذه العملية ستختفي ھذه العالمة
و عليك اآلن أن تكرر الخطوة السابقة لتشغيل تطبيقك على المحاكي.
75
أندرويد ببساطة اإلصدار بيتا 1
كما ذكرنا سابقا كيف يمكن إنشاء مشروع جديد عن طريق سطر
األوامر دعنا نتعلم كيفية التعامل مع المحاكي عن طريق سطر
األوامر و لكن من المفروض أنك قمت بإضافة ) Environment
(Variablesكما تعلمنا ذلك عندما شرحنا كيف تبدأ مشروع جديد
و في حال قمت بذلك سابقا فال حاجة لتكرار األمر و عليك الذھاب
مباشرة لتشغيل سطر األوامر
قم بالذھاب إلى تشغيل من قائمة ابدأ ) (Start >> Runو اكتب
األمر ) (CMDثم اضغط على موافق كما في الشكل التالي
76
أندرويد ببساطة اإلصدار بيتا 1
Android –h
77
أندرويد ببساطة اإلصدار بيتا 1
مثال في حال أردنا إضافة جھاز افتراضي جديد جرب السطر التالي
أوال لمعرفة المنصات و أرقامھا لديك
78
أندرويد ببساطة اإلصدار بيتا 1
وفي حالتنا ھذه ال يتوفر لدينا سوى منصة واحدة رقمھا ) (1و الذي
سنستخدمه لبناء المحاكي الخاص بنا عبر سطر األوامر لكتابة
السطر التالي ثم الضغط على زر االدخال )(Enter
79
أندرويد ببساطة اإلصدار بيتا 1
مالحظة :في حال قمت بإغالق نافذة سطر األوامر فأنك ستقوم
بإغالق المحاكي تباعا الن األمر مازال تحت التشغيل حتى ينتھي و
لذا في حال قمت بتشغيل المحاكي عن طريق سطر األوامر فانك
ستحتاج لإلبقاء على شاشة سطر األوامر تعمل في الخلفية أو قم
بالذھاب إلى حزمة التطوير و تشغيل ) (SDK Setupلتجد بأن
المحاكي الجديد الذي قمنا بإنشائه ضمن سطر األوامر موجود
باإلضافة للسابق ضمن قائمة األجھزة االفتراضية.
81
1 أندرويد ببساطة اإلصدار بيتا
adb remount
adb shell rm /system/fonts/*
في حال ظھور رسالة خطأ تفيد بعدم وجود مساحة كافية و يمكنك
: مثال،حذف بعض التطبيقات
adb shell rm /system/app/AlarmClock.apk
82
أندرويد ببساطة اإلصدار بيتا 1
لنتعرف اآلن على أداة جديدة موجودة ضمن بيئة التطوير تتيح لنا
التخاطب مع المحاكي و الوصول إلى ملفاته و خصائصه و التعامل
معه و كأنه جھاز حقيقي لكي نستطيع تجربة كل خصائص الجھاز و
ھذا بالتأكيد ال يغني عن تجربة تطبيقك النھائي على جھاز حقيقي
لتعرف كيفية عمله
أداة )(DDMS
83
أندرويد ببساطة اإلصدار بيتا 1
84
أندرويد ببساطة اإلصدار بيتا 1
كما ترى فإنه يمكنك الوصول لملفات الجھاز بالكامل و كذلك الحال
لكرت الذاكرة الداخلي من الجھة اليمنى العلوية )(File Explorer
و معرفة العمليات التي تعمل في الخلفية ) (Threadsأو )(Heap
أو )(Allocation Tracker
86
أندرويد ببساطة اإلصدار بيتا 1
تدريب
ما رأيك اآلن لو تقوم بالعمل على المحاكي قليال و تحميل بعض
التطبيقات المجانية من سوق البرامج لتتعرف أكثر على ھذه البرامج
87
أندرويد ببساطة اإلصدار بيتا 1
88
أندرويد ببساطة اإلصدار بيتا 1
89
أندرويد ببساطة اإلصدار بيتا 1
90
أندرويد ببساطة اإلصدار بيتا 1
91
أندرويد ببساطة اإلصدار بيتا 1
92
أندرويد ببساطة اإلصدار بيتا 1
93
أندرويد ببساطة اإلصدار بيتا 1
94
أندرويد ببساطة اإلصدار بيتا 1
97
أندرويد ببساطة اإلصدار بيتا 1
98
أندرويد ببساطة اإلصدار بيتا 1
مالحظة الملفات التي تقوم بتحميلھا يتم وھي من نوع ) (apkو يتم
االحتفاظ بھا في مجلد ) (Downloadفي ذاكرة الجھاز الخارجية
) (SD Cardو لتستطيع تنصيبھا على جھاز أخر دون الحاجة
إلعادة الخطوات أو وجودة Slide Meأنت بحاجة لوجود تطبيق
أسمة ) (Apps Installerو الذي يقوم بالبحث عن الملفات من
نوع ) (apkعلى جھازك و تمكينك من تنصيبھا مباشرة و يمكنك
الحصول على ھذا التطبيق من موقع )(Slide Me
99
أندرويد ببساطة اإلصدار بيتا 1
android-sdk-windows\platforms\android-1.6\skins\HVGA
100
أندرويد ببساطة اإلصدار بيتا 1
الخطوات األولى في ھذا الكتاب كانت تركز على تعريفك على بيئة
التطوير و كيفية تھيئتھا و تعليمك أساسيات التعامل معھا و لم نقم
بكتابة أي سطر كود حتى اآلن و لذا فعلينا البدء في التشمير عن
ساعدينا و كتابة أول برنامج فعلي يحتوي على بعض الكود و الذي
سنشرح بداخله المزيد عن بيئة التطوير و كيفية التعامل معھا.
اختياري وقع على برنامج قائمة المھام باألساس ألنه ال يأتي ضمنيا
مع نظام التشغيل كما أنه بسيط في فھم وظيفته و بنفس الوقت فھو
يستخدم الكثير من الخصائص التي سنتعلم منھا أساسيات البرمجة
الموجھة الندرويد و منھا التعامل مع أكثر من شاشة )نشاط( و حفظ
المھام و بناء قائمة أوامر و غيرھا من المميزات التي تكسبنا المزيد
من المھارة.
101
أندرويد ببساطة اإلصدار بيتا 1
102
أندرويد ببساطة اإلصدار بيتا 1
103
أندرويد ببساطة اإلصدار بيتا 1
104
أندرويد ببساطة اإلصدار بيتا 1
105
أندرويد ببساطة اإلصدار بيتا 1
106
1 أندرويد ببساطة اإلصدار بيتا
لقد قمت ھنا بترقيم األسطر لسھولة الرجوع لھا كما و يمكنك أنت
أيضا أن تقوم بإظھار أرقام األسطر من داخل بيئة التطوير
) (Eclipseو ذلك بالضغط بزر الفأرة األيمن على أقصى اليسار من
سطر الكود في المنطقة الفارغة و من ثم من القائمة المنسدلة قم
بتحديد خيار )(Show Line Numbers
لتظھر لنا الشاشة كما في الشكل التالي و التي تحتوي أرقام أسطر
الكود البرمجي لنستطيع اإلشارة إليھا الحقا
108
1 أندرويد ببساطة اإلصدار بيتا
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
110
أندرويد ببساطة اإلصدار بيتا 1
من السطر ) (7و حتى السطر ) (11ھو سطر واحد لتوصيف كائن
نصي و التي تم توزيعه على عدة سطور لنفس االسباب السابقة
>12 </LinearLayout
111
أندرويد ببساطة اإلصدار بيتا 1
االن يمكننا تعديل قيمة التي بداخل النص من ھنا و ذلك بالضغط
على اسم المرجع و ليكن مثال ) (hellومن ثم عندما تفتح النافذة قم
بتعديل القيمة من )(!Hello World, Activity_TaskList
إلى ) (Task Listلتصبح بالشكل التالي
112
أندرويد ببساطة اإلصدار بيتا 1
بعد ذلك سنضيف مرجع أخر عبارة عن لون خلفية النص لنتعرف
على كيفية تغيير القيم و استخدامھا
113
أندرويد ببساطة اإلصدار بيتا 1
114
أندرويد ببساطة اإلصدار بيتا 1
تنويه :كما رأينا كيفية إسناد القيم من ملف ) (Stringو التي تتيح
لنا تغيير ھذه القيم الحقا مثال في حال أتحنا للمستخدم تغيير واجھة
التطبيق حيث تقوم بالداللة على ملف ) (Stringأخر بداللة اللغة
116
أندرويد ببساطة اإلصدار بيتا 1
المحلية مثال و كذلك الحال يمكننا تمرير النص مباشرة دون الحاجة
للداللة إلى المرجع بالتعويض مباشرة كما الكود الحالي
<TextView
"android:layout_width="fill_parent
"android:layout_height="wrap_content
"android:text="Task List
>android:background="@color/TextViewBackColor" /
قم بالعودة إلى الشاشة تحت مجلد ) (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/MainTextView
بدون وجود إشارة الموجب ) (+إذ أننا اآلن نتعامل معه و ليس
تعريفه كما سترى الحقا
اآلن لنقوم بإنشاء شاشة جديدة و ھي التي سوف نصل إليھا عن
طريق قائمة من الشاشة الرئيسية و وظيفة ھذه الشاشة ھي تمكيننا
من كتابة بيانات المھمة و التي تحتوي على مربعي نص أحدھما
يحتوي على عنوان المھمة ) (Titleو الثاني يحتوي على تفاصيل
المھمة )(Details
119
1 أندرويد ببساطة اإلصدار بيتا
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;
120
أندرويد ببساطة اإلصدار بيتا 1
;)super.onCreate(savedInstanceState
;)setContentView(R.layout.main
}
}
اآلن سنضيف بعض الكود إلنشاء )قائمة جديدة(
;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 أندرويد ببساطة اإلصدار بيتا
Log.v("Task:",MainTextView.getText().toString());
return true;
}
return false;
}
123
أندرويد ببساطة اإلصدار بيتا 1
لنشر التطبيق على سوق أندرويد تحتاج أوال إلى تسجيل حساب
خاص بك للبيع و الذي يتطلب دفع مبلغ ) (50دوالر أمريكي و لمرة
واحدة
ثم أنت بحاجة إلى إنشاء مفتاح خاص لكل تطبيق ليكون بمثابة
بصمة أو توقيع رقمي لھذا التطبيق ،و في حال إنشاء ھذا الملف
تحتاج إلى حفظه في مكان أمن ،حيث عند قيامك برفع التطبيق على
سوق أندرويد بھذا التوقيع فلن تستطيع أن تقوم برفع أي تحديثات
جديدة إال بنفس التوقيع الذي قمت به بأول مرة
C:\Program Files\Java\jdk1.6.0_18\bin\keytool.exe
124
1 أندرويد ببساطة اإلصدار بيتا
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
في ھذه الشاشة ستحدد أين سوف تقوم بتصدير الملف النھائي و
الذي سوف تقوم برفعه على سوق أندرويد
لتظھر لك شاشة إضافة تطبيق جديد ،ما عليك سوى رفع التطبيق
النھائي الذي قمنا بتصديره و الصور الخاصة بالتطبيق و األيقونات
و المعلومات الخاصة بك
129
أندرويد ببساطة اإلصدار بيتا 1
130
أندرويد ببساطة اإلصدار بيتا 1
131
أندرويد ببساطة اإلصدار بيتا 1
132
أندرويد ببساطة اإلصدار بيتا 1
تطبيق RestDroid-mini
133
أندرويد ببساطة اإلصدار بيتا 1
تطبيقRestDroid-mini
يتناول ھذا الفصل شرح الكود البرمجي الخاص بتطبيق RestDroidوالذي
طرحناه كأول مشروع من مشاريع مجتمع مطوري أندرويد العرب بالتعاون مع
موقع أردرويد المتخصص بكل ماله عالقة بنظام األندرويد وھواتفه .التطبيق تم
طرحه في سوق تطبيقات األندرويد “أندرويد ماركت وسوق ساليد مي” وكنا قد
كتبنا عنه وعن المميزات التي يملكھا .وكما ذكرنا من قبل ،التطبيق سيكون
مفتوح المصدر بشكل كامل ليتمكن المھتمون العرب ببرمجة األندرويد من
دراسة وفھم الشفرة المصدرية واالنطالق نحو مجال تطبيقات األندرويد .ولكن
سنقوم في ھذا الكتاب بتقديم شرح كامل لنسخة مصغرة من تطبيق RestDroid
األصلي سميناھا بRestDroid-mini.
لالستزادة:
134
أندرويد ببساطة اإلصدار بيتا 1
بالنسبة للنسخة المصغرة والتي سنشرحھا ھنا ،سيكتفي التطبيق بعرض زر واحد
بالضغط عليه يتم جلب أفضل ٥٠مطعما في مدينة الرياض-المملكة العربية
السعودية ويعرض تقييمھا .بالضغط على أي مطعم ،سيتم عرض موقعه على
خريطة غوغل.
واجھات التطبيق:
الخطوة التي تسبق البرمجة ،ھي تحديد شكل وعدد الواجھات المطلوب إظھارھا
في التطبيق .نحتاج في تطبيقنا الى ثالثة واجھات وھي:
واجھة البداية:
وفيھا يظھر شعار التطبيق وزر مكتوب عليه “جلب أفضل ٥٠مطعما في
الرياض”.
واجھة المطاعم:
وفيھا تظھر أسماء المطاعم وتقييماتھا .الشكل المرغوب ھو أن يظھر تقييم كل
مطعم )العالمة الموزونة( على شكل ٥نجوم +العالمة الموزونة رقما +عدد
األصوات رقما )العالمة الموزونة ھي المعيار األنسب لمقارنة المطاعم بحسب
موقع قيم(.
واجھة الخريطة:
وھي الواجھة التي يظھر فيھا اسم المطعم ومكانه على خريطة غوغل بحيث يتم
تمثيل مكان المطعم بنقطة خضراء.
بداية كما نعرف فإن كل واجھة يقترن بھا مجموعة خاصة بھا إضافة إلى ملف
XMLيحتوي على العناصر المرئية المطلوب إظھارھا )الشعار +زر في
الواجھة األولى مثال( وھذا يعني أننا بحاجة إلى ٣مجموعات جافا و ٣ملفات
XMLبالشكل التالي:
باإلضافة الى الثالث مجموعات أعاله ،يوجد لدينا عدد من المجموعات المساعدة
وھي على النحو التالي:
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واحدة أو أكثر(.
إنشاء التطبيق:
نقوم بتشغيل االكليبس والتوجه إلى قائمةFile>new>project
نقوم بفتح مجلد Androidونختار منهAndroid Project
139
أندرويد ببساطة اإلصدار بيتا 1
140
أندرويد ببساطة اإلصدار بيتا 1
141
أندرويد ببساطة اإلصدار بيتا 1
حتى نتمكن من استخدام األحرف العربية داخل المشروع ،يتوجب علينا تعريف
الترميز ليكون UTF-8في المشروع .اضغط بالزر األيمن على اسم المشروع
ومن ثمProperties:
142
أندرويد ببساطة اإلصدار بيتا 1
143
أندرويد ببساطة اإلصدار بيتا 1
قبل الشروع في كتابة الكود البرمجي الخاص بھذه المجموعة )والتي ستقترن
بالواجھة اإلبتدائية التي ستظھر للمستخدم( ،يفضل أن نقوم بإنشاء الواجھة
المرئية .لعمل ذلك ،نقوم باستخدام ملف main.xmlالذي تم إنشاؤه تلقائيا عند
إنشاء المشروع.
144
أندرويد ببساطة اإلصدار بيتا 1
الواجھة التي نريد تصميمھا بسيطة جدا ،وستكون على الشكل التالي:
خلفية بيضاء ،صورة تظھر في المنتصف ،زر.
بالنسبة للخلفية البيضاء ،سنترك ملف main.xmlقليال ونقوم بإنشاء ملف نسميه
مثال colors.xmlونضعه تحت مجلد( valuesيتم اإلنشاء بالضغط بالزر
األيمن على مجلد valuesومن ثم new>file>colors.xml .تسمية ملفات
االكس ام ال يجب أن تتم باستخدام حروف صغيرة lower caseوعليھا أن
تخلو من الرموز).
محتوى الملف:
ھذا السطر يجب أن يكون متواجدا وھو يعرف النسخة المستخدمة ونوع <!--
> --الترميز
>?"<?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
).صورة لديكم أو تلك الموجودة في ملفات التطبيق على الموقع
واآلن نعود لملف المجموعة intro .الكود سيكون التالي) :سأقوم بالشرح على
الكود)
;package android.prog.easily
148
1 أندرويد ببساطة اإلصدار بيتا
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
{
;)(top50Handler
}
;)}
}
}
}
سنتوقف ھنا قليال ونترك ملف( intro.javaوالذي يمكنك بالمناسبة تشغيله على
المحاكي ورؤية شكله الحالي ،ولن يحصل شيئا إذا ضغطنا على الزر( ونقوم
بتعريف المجموعة RatedItem.javaبالشكل التالي:
;package android.prog.easily
;import java.io.Serializable
150
1 أندرويد ببساطة اإلصدار بيتا
this.id = id;
}
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;
{
return branchesDetailsText;
}
@Override
public void onCreate()
{
super.onCreate();
}
@Override
public void onTerminate()
{
super.onTerminate();
}
154
1 أندرويد ببساطة اإلصدار بيتا
HttpResponse response;
try
{
response = httpclient.execute(httpget);
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
int counter = 0;
boolean firstSeen = false;
boolean secondSeen = false;
int ind1 = 0;
int ind2 = 0;
159
1 أندرويد ببساطة اإلصدار بيتا
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;
}
{
return globalAdapterData;
}
public void
setGlobalAdapterData(ArrayList<RatedItem>
globalAdapter)
{
this.globalAdapterData = globalAdapter;
}
String attributesCommand =
accessApplicationMethods().getUrlStringCommand(attrcom
mand);
JSONObject[] topCities =
accessApplicationMethods().retrieveJSONs(attributesComma
nd);
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
"));
accessApplicationMethods().setGlobalAdapterData(sRest);
// *** goToBest50Act();
}
catch (JSONException e)
{
}
}
وبقي لدينا االنتقال للواجھة. مطعما٥٠ اإلضافة السابقة تمكننا من جلب أفضل
: وھذا ما يقوم به السطر الذي رمزت له بـ،التي تعرض المطاعم
// ***
: ونعرفھا بالشكل التاليgoToBest50Act والذي يستدعي الدالة
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;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
من أجل الواجھة المرئيةmain نستخدم ملف //
setContentView(R.layout.main);
setUpViews();
}
{
getbest50 = (Button)findViewById(R.id.search);
setText("
167
1 أندرويد ببساطة اإلصدار بيتا
JSONObject[] topCities =
accessApplicationMethods().retrieveJSONs(attributesComma
nd);
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
"));
;)accessApplicationMethods().setGlobalAdapterData(sRest
;)(goToBest50Act
}
)catch (JSONException e
{
}
}
}
نالحظ من الكود في األعلى أننا قمنا بتمرير بعض البيانات إلى متغيرات موجودة
في مجموعة
RestDroidApplications
والسبب كما قلنا ھو لتمكين المجموعات واألنشطة األخرى من دخول ھذه
المتغيرات .ھناك طريقة أخرى ال أقوم بھا في ھذا الشرح على أنني أستخدمھا
حاليا بشكل أساسي ويمكن للقارئ إتباعھا إذا وجدھا أفضل وھي إنشاء كائن من
مجموعة( Intentوالتي تعرف بأنھا مجموعة خاصة بـ فعل actionنود عمله(
وبرمجته بحيث يقوم بتمرير بيانات معينة من النشاط الحالي إلى آخر.
170
أندرويد ببساطة اإلصدار بيتا 1
بالطبع ستظھر لنا رسالة خطأ كوننا لم ننشئ ملف المجموعة التي سننتقل إليھا
والتي سنسميھا Best50.java.ولكن قبل إنشائھا ،يتوجب علينا إنشاء المجموعة
المساعدة لھا وھي:
RatedRestaurantListItem.java
ويقترن بھا rest_list_item.xmlوكما ذكرنا من قبل فإن ھذه المجموعة تقوم
بتشكيل الواجھة الخاصة بكل عنصر )مطعم( -الشكل -١وبما أنھا مرتبطة
ومتعلقة بالواجھات ،فستقوم ھذه المجموعة بوراثة قالب\مجموعة
RelativeLayoutللتعديل عليه بالشكل الذي نريده .ھذا األمر يعني أننا لن نقوم
بوضع وسم RelativeLayoutفي ملف الـ xmlالمقترن ،وإنما اسم مجموعتنا
الجديدة -سأوضح ذلك بعد قليل-.
;package android.prog.easily
;import android.content.Context
;import android.util.AttributeSet
;import android.widget.RelativeLayout
واآلن ندعھا قليال ونقوم بإنشاء ملف الـ rest_list_item.xmlداخل المجلد :
171
1 أندرويد ببساطة اإلصدار بيتا
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>
172
1 أندرويد ببساطة اإلصدار بيتا
<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>
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;
دالة يتم استدعاؤھا تلقائيا بعد قراءة العناصر التي عرفناھا في ملف ال//
وعندھا يمكننا التعامل مع ھذه العناصر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");
}
: سننشئ الواجھة الخاصة بھا أوال وھي، وكما تعودنا، Best50.javaبالنسبة لـ
rated_rest_list.xml
:وستكون بالشكل التالي
<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
ولكن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;
@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();
startActivity(goToMapActivity);
}
{
selectAttr =
(TextView)findViewById(R.id.RRselect);
");اضغط على أحد المطاعمselectAttr.setText("
setListAdapter(adapter);
}
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
}
}
protected RestDroidApplication
)(accessApplicationMethods
{
;)(return (RestDroidApplication)getApplication
}
}
إذا كما ھو واضح ،فإن OnListItemClickھي دالة مھمتھا القيام بعمل معين
عند الضغط على أي عنصر في القائمة .العمل الذي نريد منھا القيام به ھو أوال
جلب معلومات المطعم الذي تم الضغط عليه )يتم ذلك عبر معرفة رقم عنصر
القائمة الذي تم الضغط عليه positionوھو يكافئ رقم المطعم كما ھو موجود
181
1 أندرويد ببساطة اإلصدار بيتا
لذلك نقوم بجلب المطعم المختار ونضعه.في المتغير الذي يحمل بيانات المطاعم
في متغير آخر لتستخدمه الخريطة( وثانيا االنتقال إلى واجھة أخرى تحوي
.الخريطة ومكان المطعم عليھا
<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
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;
184
1 أندرويد ببساطة اإلصدار بيتا
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 أندرويد ببساطة اإلصدار بيتا
canvas.drawCircle(containerX, containerY,
CONTAINER_RADIUS, containerPaint);
}
else
{
containerPaint.setColor(Color.GREEN);
canvas.drawCircle(containerX, containerY,
CONTAINER_RADIUS, containerPaint);
}
}
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;
@Override
protected void onCreate(Bundle bundle)
{
super.onCreate(bundle);
setContentView(R.layout.view_map);
setUpViews();
bringRestLocations();
188
1 أندرويد ببساطة اإلصدار بيتا
mapCurrentAddress();
}
String restaurantsCommand =
accessApplicationMethods().getUrlStringCommand(comman
d);
restaurantsLocObjects =
accessApplicationMethods().retrieveJSONs(restaurantsCom
mand);
restaurantsBranchesNames = new
String[restaurantsLocObjects.length];
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)
{
mapOverlays.add(addressOverlay);
addressOverlay.getGeopoint().getLongitudeE6() : minLon;
maxLon = (maxLon <
addressOverlay.getGeopoint().getLongitudeE6()) ?
addressOverlay.getGeopoint().getLongitudeE6() : maxLon;
mapView.invalidate();
}
else
{
}
}
catch (IOException e)
{
}
}
});
restName.setText(accessApplicationMethods().getItemOnMa
p().getName());
mapView = (MapView)findViewById(R.id.map);
@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 أندرويد ببساطة اإلصدار بيتا
ھذا الملف مسئول عن.وھو الملف الذي أسميه بالمايسترو أو خارطة الطريق
إعالم نظام التشغيل بكيفية تشغيل التطبيق وأي واجھة ونشاط يشغلھا في البداية
.وغير ذلك
<!-- " بكتابة اسم المجموعة خاصتھا بدون٣ نقوم بتعريف كل واجھة "وعددھا
.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>
></manifest
صور من التطبيق:
199
أندرويد ببساطة اإلصدار بيتا 1
200
أندرويد ببساطة اإلصدار بيتا 1
201
أندرويد ببساطة اإلصدار بيتا 1
202
أندرويد ببساطة اإلصدار بيتا 1
متفرقات:
-التأكد من وجود أجھزة فعلية أو افتراضية )محاكي( ليتم التواصل معھا عبر
الوحدة الطرفية:
$ cd /Developer/android-sdk-mac_86/tools/
$ ./adb devices
النتيجة:
-مساحة الذاكرة الداخلية للجھاز االفتراضي قد تكون غير كافية للتطبيق أو
لملفات نرغب برفعھا إليه )كملفات الخطوط العربية( ،لذلك يمكننا إطالق محاكي
بمساحة نقوم بتخصيصھا عبر األمر:
$ 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/DroidSansFallback.ttf
/system/fonts/
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"
>
205
أندرويد ببساطة اإلصدار بيتا 1
نقوم اآلن بإنشاء زر لنرى كيفية التحكم بطريقة ظھوره في واجھة التطبيق.
<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
مثال للحالة األولى والثانية )سيمأل الزر المساحات المجاورة له بالعرض ،ولكن
ارتفاعه سيكون مضغوطا):
<Button
"android:text="Ardroid
"android:id="@+id/Button01
"android:layout_width="fill_parent
>"android:layout_height="wrap_content
></Button
207
أندرويد ببساطة اإلصدار بيتا 1
<Button
"android:text="Ardroid
"android:id="@+id/Button01
"android:layout_width="300px
208
1 أندرويد ببساطة اإلصدار بيتا
android:layout_height="100px">
</Button>
<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>
<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التي تفصل بين
الزر واآلخر.
<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>
<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
طبعا نالحظ القائمة المنسدلة والتي تحوي عددا من القيم التي يمكنكم تجربتھا
ورؤية تأثيرھا.
في نھاية ھذا القسم ،تجدر اإلشارة إلى أنه يمكننا تغيير خاصية توجه\وضع
الوعاء Orientationأثناء عمل التطبيق .فمثال يمكننا برمجة التطبيق بأن يقوم
بتغيير التوجه ليصبح بالوضع األفقي عند ضغط زر .تتم ھذه العملية باستدعاء
دالة
;)x.setOrientation(LinearLayout.HORIZONTAL
214
أندرويد ببساطة اإلصدار بيتا 1
- ٢وعاء><TableLayout
يأخذ ھذا الوعاء شكل الجدول .لذا ،فإننا نستخدم وسم < >TableRowكلما
أردنا إنشاء صف جديد .يتميز ھذا الوعاء بعدد من الخصائص:
أ - android:layout_span :وھي خاصية تحدد المدى الذي نود أن يحتله
العنصر ،وتأخذ قيمة عددية .القيمة العددية تحدد بشكل غير مباشر عدد األعمدة
Columnsداخل الصف.
ب - android:layout_column :وھي خاصية تحدد رقم العمود الذي
سيتوضع عنده العنصر Widget.وترقيم األعمدة يبدأ من الصفر ،بمعنى أن أول
عمود رقمه صفر ،وھكذا.
ج - android:stretchColumns :وھي خاصية محصورة بالوعاء نفسه )أي
ال يمكن تطبيقھا على العناصر ) Widgetsوھي تعمل على شد العمود ليغطي
المساحة الفارغة ،وتأخذ قيمة عددية تحدد رقم العمود.
د - android:shrinkColumns :وھي عكس الخاصية السابقة.
مثال توضيحي:
للحصول على التصميم التالي:
215
1 أندرويد ببساطة اإلصدار بيتا
:نستعمل الكود
<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حتى يتطلب عرض المحتوى
أكثر من صفحة).
<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