سلسلة تعلم برمجة تطبيقات الأندرويد .. الدرس الرابع

مرحبا بكم من جديد..

تساءل عدد من القراء إن كان يلزمهم الالمام بلغة الجافا حتى يتمكنوا من اتمام هذه السلسلة واستيعابها. الجواب نعم! وهناك عدد من الكتب التي تشرح لغة الجافا البرمجية بشكل مبسط وسهل الفهم ولعل أهمها برأيي هو كتاب Thinking in Java. وطبعا يوجد عدد من المواقع\المنتديات العربية التي تقدم دروسا في الجافا لمختلف المستويات.

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

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

حسنا، بعد المقدمة الطويلة، سنتعرف اليوم على:

١- كيفية التأكد من صحة المدخلات باستخدام Regular Expressions وكيفية إظهار رسالة خطأ.

٢- استخدام زر القائمة Menu وكيفية اضافة خيارات له.

٣- كيفية عمل تطبيق متعدد الأنشطة.

لنبدأ..

١- كيفية التأكد من صحة المدخلات باستخدام Regular Expressions وكيفية إظهار رسالة خطأ.

سنقوم باستدعاء المكتبة

import java.util.regex.*;

وسنقوم في داخل المجموعة المجهولة الخاصة بزر الاتصال بعمل باستدعاء دالة validatePhoneNumber (سنقوم بكتابة محتواها بعد قليل) لتتحقق من البيانات التي قام بإدخالها المستخدم. والآن، عند استدعاء الدالة الخاصة بالزر (عند ضغط الزر) سنستخدم جملة if على الشكل التالي:

callButton.setOnClickListener(new Button.OnClickListener() {

public void onClick(View v)

{

if(validatePhoneNumber(phoneNumber.getText().toString()))

{

Intent callIntent = new Intent(Intent.ACTION_CALL,Uri.parse("tel:" + phoneNumber.getText()));

callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

startActivity(callIntent);

}

else

{

showDialog(1);

}

}

بالنسبة لما ورد في جملة else، سنقوم بتجاهله حاليا.

علينا الآن كتابة محتوى الدالة validatePhoneNumber على الشكل التالي: (وهي ستكون كدالة تابعة للمجموعة المجهولة Anonymous Class):

private boolean validatePhoneNumber(String number) {

Pattern phoneNumber1 = Pattern.compile("(\\d{2}-)?\\d{7}");

Matcher matcher = phoneNumber1.matcher(number);

return matcher.matches();

}

عند استدعاء هذه الدالة، نستدعي بداية الدالة Pattern.compile التي تقوم بإنشاء رقم بناء على الصيغة التي عرفناها (وهناك قواعد عديدة لصيغ التحقق وقمت باختيار

(\\d{2}-)?\\d{7}

والتي تعني أن المستخدم يمكنه ادخال رقمين في البداية ووضع – بعدهم ومن ثم اكمال الرقم بسبعة أعداد. كما يحق له عدم ادخال الرقمين الأولين وعدم ادخال – ولكنه يجب أن يدخل سبعة أعداد. فمثلا الرقم 01-1234567 هو رقم صحيح، والرقم 1234567صحيح ولكن 1-1234567 والرقم 123456 هو غير صحيح.).

تقوم الدالة

matcher(number);

بمقارنة الرقم المدخل من قبل المستخدم بالرقم المنشأ الذي يتبع الصيغة التي عرّفناها. تقوم الدالة

validatePhoneNumber(...);

بإعادة صح أم خطأ True or Flase .

المجموعة المجهولة الخاصة بالزر تصبح على النحو التالي:

callButton.setOnClickListener(new Button.OnClickListener() {

public void onClick(View v)

{

if(validatePhoneNumber(phoneNumber.getText().toString()))

{

Intent callIntent = new Intent(Intent.ACTION_CALL,Uri.parse("tel:" + phoneNumber.getText()));

callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

startActivity(callIntent);

}

else

{

showDialog(1);

}

}

private boolean validatePhoneNumber(String number) {

Pattern phoneNumber1 = Pattern.compile("(\\d{2}-)?\\d{7}");

Matcher matcher = phoneNumber1.matcher(number);

return matcher.matches();

}

});

نتحول الآن الى كيفية إظهار رسالة خطأ والتي استدعيناها في جملة ال Else في الدالة السابقة عبر استدعاء

showDialog(1);

وهي دالة موجودة في مجموعة Activity التي يتبع لها تطبيقنا ككل. تقوم دالة أخرى موجودة في ال Activity أيضا وتسمى

onCreateDialog(int id)

باستقبال الطلب الذي أطلقته الدالة السابقة

showDialog(1)

بداية، نقوم باستدعاء المكتبات والمجموعات التالية:

import android.app.Dialog;

import android.app.AlertDialog;

import android.content.DialogInterface;

ونقوم الآن بكتابة محتوى الدالة

onCreateDialog(int id)

بالشكل التالي:

protected Dialog onCreateDialog(int id) {

if (id == 1){

return new AlertDialog.Builder(AndroidPhoneDialer.this)

.setTitle("Error")

.setMessage("please enter a valid number")

.setPositiveButton("OK", new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int whichButton) {

/* User clicked OK so do some stuff */

}

})

.create();

}

else

{

}

}

لا صعوبة تذكر في هذه الدالة، ولاحظوا كيفية تحديد النص المراد عرضه. لاحظوا أيضا إمكانية عمل شيء معين في حال ضغط المستخدم زر ال OK في رسالة الخطأ. ولاحظوا أيضا أننا مررنا رقم ١ في showDialog ويمكننا طبعا تمرير أرقام مختلفة لعرض رسائل مختلفة بحسب الحالة، وهذا يتم عبر If .

اذا يصبح الملف المصدري ArdroidCaller.java  كاملا:

package android_programmers_guide.AndroidPhoneDialer;

import android.app.Activity;

import android.os.Bundle;

import android.content.Intent;

import android.net.Uri;

import android.widget.Button;

import android.widget.EditText;

import android.view.View;

import java.util.regex.*;

import android.app.Dialog;

import android.app.AlertDialog;

import android.content.DialogInterface;

public class ArdroidCaller extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

final EditText phoneNumber = (EditText) this.findViewById(R.id.phoneNumber);

final Button callButton = (Button) this.findViewById(R.id.callButton);

callButton.setOnClickListener(new Button.OnClickListener() {

public void onClick(View v)

{

if(validatePhoneNumber(phoneNumber.getText().toString()))

{

Intent callIntent = new Intent(Intent.ACTION_CALL,Uri.parse("tel:" + phoneNumber.getText()));

callIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

startActivity(callIntent);

}

else

{

showDialog(1);

}

}

private boolean validatePhoneNumber(String number) {

Pattern phoneNumber1 = Pattern.compile("(\\d{2}-)?\\d{7}");

Matcher matcher = phoneNumber1.matcher(number);

return matcher.matches();

}

});

}

protected Dialog onCreateDialog(int id) {

return new AlertDialog.Builder(AndroidPhoneDialer.this)

.setTitle("Error")

.setMessage("please enter a valid number")

.setPositiveButton("OK", new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int whichButton) {

}

})

.create();

}

}

٢- استخدام زر القائمة Menu وكيفية اضافة خيارات له.

ما سنقوم بعمله بكل بساطة هو انشاء المشروع التالي:

والذي سيقوم باستخدام زر القائمة لعرض محتوياتها، ولكل خيار، سنقوم بعمل نشاط Activity معين. اذا سنبدأ بكيفية توظيف زر القائمة.

نقوم بداية باستدعاء المكتبات التالية:

import android.view.Menu;

import android.view.MenuItem;

ومن ثم نقوم بإعادة كتابة Override الدالة الموجودة في مجموعة Activity والمسماة onCreateOptionsMenu على النحو التالي:

@Override

public boolean onCreateOptionsMenu(Menu menu)

{

super.onCreateOptionsMenu(menu);

menu.add(0, 0, 0, "Act1");

menu.add(0, 1, 0, "Act2");

return true;

}

الدالة menu.add لها عدة أشكال ولكننا سنستعمل:

add (int groupId, int itemId, int order, CharSequence title)

حيث أن أول عنصر يدل على رقم المجموعة الخاصة بخيارات القوائم، وافترضت أنهم في مجموعة واحدة، لذلك قمت بوضع 0 عند استدعاء الدالة كما هو الحال في عنصر order حيث أنني لا أهتم بترتيب الخيارات. itemId هو ما يهمني لذلك استخدمت الترقيم لمعرفة هوية الخيار.

الدالة onCreateOptionsMenu تقوم بتعبئة الخيارات في القائمة عند تشغيل البرنامج. لذلك، سنقوم بإعادة كتابة دالة أخرى موجودة في Activity والتي يتم استدعاؤها بمجرد اختيار أي خيار في القائمة وهي onOptionsItemSelected. في هذه الدالة، سنستخدم Switch المعروفة وذلك لاطلاق النشاط المقترن بالخيار الذي اختير من قبل المستخدم على النحو التالي:

public boolean onOptionsItemSelected (MenuItem item)

{

switch (item.getItemId())

{

case 0:

return true;

case 1:

return true;

}

return true;

}

الشكل النهائي لملف:

package android.programming.series.ArdroidMultiActs;

import android.app.Activity;

import android.os.Bundle;

import android.view.Menu;

import android.view.MenuItem;

public class ArdroidMultiActs extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

}

@Override

public boolean onCreateOptionsMenu(Menu menu)

{

super.onCreateOptionsMenu(menu);

menu.add(0, 0, 0, "Act1");

menu.add(0, 1, 0, "Act2");

return true;

}

public boolean onOptionsItemSelected (MenuItem item)

{

switch (item.getItemId())

{

case 0:

return true;

case 1:

return true;

}

return true;

}

}

٣- كيفية عمل تطبيق متعدد الأنشطة.

لنتذكر قضية مهمة وهي أن كل نشاط له ملف مصدري .java وله ملف .xml خاص بتصميمه. وهذا ما سنفعله. سنقوم بإنشاء ملف xml للنشاط الأول تحت اسم act1.xml في res/layout وليكن كالتالي:

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_height="fill_parent"

android:layout_width="fill_parent"

android:padding="30dip"

android:background="#8123f555"

>

<AutoCompleteTextView android:id="@+id/act1Test"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

/>

</LinearLayout>

ثم نقوم بإنشاء ملف Act1.java داخل ال Package في src. المطلوب من النشاط هو عرض مربع النص التلقائي وهو الذي يقوم باقتراح عدة خيارات للمستخدم (نقوم بتحديدها مسبقا) ليكمل عنه الكلمة بدلا من كتابتها كاملة. سنقوم بوضع ما يلي في الملف:

package android.programming.series.ArdroidMultiActs;

import android.app.Activity;

import android.os.Bundle;

import android.widget.ArrayAdapter;

import android.widget.AutoCompleteTextView;

public class Act1 extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.act1);

//android.R.layout.simple_dropdown_item_1line is an existing file that contains a style of presenting the list in the application

ArrayAdapter<String> monthArray = new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line,months);

final AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.act1Test);

textView.setAdapter(monthArray);

}

static final String[] months = new String[] {"January","February","March",

"April","May", "June","July","August","September","October","November",

"December"};

}

بالنسبة للنشاط الثاني، نقوم بإنشاء ملف act2.xml :

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_height="fill_parent"

android:layout_width="fill_parent"

>

<CheckBox android:id="@+id/act2CheckBox"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="Act2 checkbox"

/>

<Button android:id="@+id/act2ColorButton"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="Change Text Color"

/>

</LinearLayout>

والنشاط الثاني يقوم بعرض Check Box وزر خاص بتغيير لون النص. نقوم بوضع الكود التالي في Act2.java:

package android.programming.series.ArdroidMultiActs;

import android.app.Activity;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

import android.graphics.Color;

import android.widget.CheckBox;

public class Act2 extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.act2);

final CheckBox checkbox = (CheckBox) this.findViewById(R.id.act2CheckBox);

final Button changeButton = (Button) this.findViewById(R.id.act2ColorButton);

changeButton.setOnClickListener(new Button.OnClickListener(){

public void onClick(View v)

{

changeColor(checkbox);

}

public void changeColor(CheckBox checkbox)

{

checkbox.setTextColor(Color.RED);

}

}

);

}

}

نعود الآن الى ملف ArdroidMultiActs.java لنضيف ما يلي لجملة ال Switch:

public boolean onOptionsItemSelected (MenuItem item)

{

switch (item.getItemId())

{

case 0:

showAct1();

return true;

case 1:

showAct2();

return true;

}

return true;

}

ونقوم الآن بكتابة الدالتين showAct1 و showAct2. بداية، دعوني أصحح أحد المفاهيم التي كنت قد مررت عليها وهو مفهوم النوايا Intents. كنت قد ذكرت التالي:

النوايا Intents بكل بساطة هي وسيلة لتمرير المعلومات من نشاط لآخر وبكلمات أخرى، تمرير ما ينوي فعله المبرمج بين الأنشطة. ولكنها تستخدم فقط في حالة وددنا استخدام نشاط خارج التطبيق الذي نعمل عليه. مثلا، اذا أراد المبرمج من تطبيقه أن يأخذ كلمة معينة من المستخدم ليبحث عنها بين ملفات النظام فإنه سيقوم بتصميم نشاط تحتوي واجهته على حقل نصي يمكن للمستخدم الكتابة فيها، وما يتم ادخاله يتم تمريره الى نظام الأندرويد تحت نية عمل بحث في ملفات النظام (وال Intent اسمه في هذه الحالة: SEARCH_ACTION) الذي يستقبل الطلب ويفهم النية\المعلومة المرغوب تحقيقها ويستدعي بدوره نشاط البحث Search Activity. نلاحظ أن النية تم تمريرها الى نشاط خارج التطبيق، وهو نشاط يقوم عليه نظام التشغيل. بالنسبة للأنشطة التي ذكرتها في معرض حديثي عن تطبيق الرسائل النصية، فهي أنشطة داخل التطبيق الواحد ولا يتم استخدام مفهوم النوايا Intents عليها (سنرى كيفية التعامل معها في الدرس القادم).

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

public void showAct1()

{

Intent autocomplete = new Intent(this, Act1.class);

startActivity(autocomplete);

}

public void showAct2()

{

Intent autocomplete2 = new Intent(this, Act2.class);

startActivity(autocomplete2);

}

يصبح ملف ArdroidMultiActs.java كاملا:

package android.programming.series.ArdroidMultiActs;

import android.app.Activity;

import android.content.Intent;

import android.os.Bundle;

import android.view.Menu;

import android.view.MenuItem;

public class ArdroidMultiActs extends Activity {

/** Called when the activity is first created. */

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

}

@Override

public boolean onCreateOptionsMenu(Menu menu)

{

super.onCreateOptionsMenu(menu);

menu.add(0, 0, 0, "Act1");

menu.add(0, 1, 0, "Act2");

return true;

}

public boolean onOptionsItemSelected (MenuItem item)

{

switch (item.getItemId())

{

case 0:

showAct1();

return true;

case 1:

showAct2();

return true;

}

return true;

}

public void showAct1()

{

Intent autocomplete = new Intent(this, Act1.class);

startActivity(autocomplete);

}

public void showAct2()

{

Intent autocomplete2 = new Intent(this, Act2.class);

startActivity(autocomplete2);

}

}

يبقى لدينا إضافة ما يسمى بفلتر النوايا Intents Filter وهو عبارة عن كود XML يتم وضعه في ArdroidMultiActs Manifest ومهمته تمرير النوايا الى لنشاط المقترن بها وتمييزها عن الآخرين بشكل صحيح. نقوم بإضافة ما يلي:

<activity android:name=".Act1"

android:label="activity 1">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

<activity android:name=".Act2"

android:label="activity 2">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

ليصبح الملف كاملا:

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

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="android.programming.series.ArdroidMultiActs"

android:versionCode="1"

android:versionName="1.0">

<application android:icon="@drawable/icon" android:label="@string/app_name">

<activity android:name=".ArdroidMultiActs"

android:label="@string/app_name">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

<activity android:name=".Act1"

android:label="activity 1">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

<activity android:name=".Act2"

android:label="activity 2">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

</application>

<uses-sdk android:minSdkVersion="6" />

</manifest>

نقوم بتشغيل التطبيق لنحصل على:

الدرس القادم سيكون عبارة عن عدد من الأمثلة المتنوعة التي سأختارها من هنا وهناك وأعرضها عليكم.

تحياتي لكم 🙂

وائل العلواني

وائل العلواني.. مدون سوري ومطور تطبيقات أندرويد.. مهتم بالتقنية وآخر تطوراتها.. يعمل في شركة خاصة في مجال تقصي الأعمال BI وتعدين البيانات Data Mining

التعليقات: 21 ضع تعليقك

fromq8 يقول:

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

أهلا بك fromq8 ونشكر لك متابعتك الدائمة لموقع أردرويد.
انا أفكر دائما بهذا الموضوع، ولكنني مازلت أبحث عن الفكرة المناسبة..
تحياتي لك.

محمد علي يقول:

نشكركم على هذا الدرس المفيد

قرأت الان نباء بيع نيكسوس واحد في الوطن العربي http://arandroid.com هل هذا صحيح ؟

وشكراً

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

تحياتي لك.

adel يقول:

amazing effort
keep up the great work

Thanks Adel for your words..

Cheers

Mr.Xprt يقول:

فعلا مجهود رائع يا شباب .. بارك الله فيكم 🙂

عبدالعزيز يقول:

تسلم على الدرس الممتاز ، بس عندي ملاحظه

بما ان الدروس هذي معنيه للعرب ، ياليت لو تكون الدروس لبرامج عربيه ، والكلام يكون عربي ، يعني بدا مايكون may تكون مايو

Mohd يقول:

أخي وائل

بالنسبة للخطوة الأولى التي قمنا بها لدي فيها مشكلة

عند كتابة الرقم في الحقل بصيغة 01-1234567 أو 1234567 يخرج لي رسالة FORCE CLOSE
أما بالنسبة لرسالة الخطأ فشغالة بالشكل المطلوب التي وصفت

مارأيك

Mohd يقول:

تم حل المشكلة

نسيت أن أضيف على ملف AndroidManifest.xml

Mohd يقول:

معذرة على الازعاج

لدي خطأ في الكود
ArrayAdapter<String> monthArray = new ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line,months);

ورسالة الخطأ
Multiple markers at this line
– String cannot be resolved
– gt cannot be resolved
– Syntax error on token “new”, delete this token
– lt cannot be resolved
– ArrayAdapter cannot be resolved
– Syntax error on token “&”, invalid AssignmentOperator
– ArrayAdapter cannot be resolved
– gt cannot be resolved
– Constructor call must be the first statement in a
constructor
– lt cannot be resolved
– monthArray cannot be resolved
– Syntax error on token “;”, this expected after this token
– Syntax error on token “&”, invalid AssignmentOperator
– String cannot be resolved
– Syntax error on token “&”, invalid AssignmentOperator

وأيضاً
textView.setAdapter(monthArray);

والرسالة monthArray cannot be resolved

كما أتمنى أن تشرح فكرة عمل الكود

Mohd يقول:

تم حل المشكلة
حيث أني للتوا فهمت صياغة الكود

aboanas يقول:

بوركت وبورك مسعاك ننتظر المزيد

عبدالمجيد يقول:

السلام عليكم,,,, لكم جزيل الشكر على هذه المجهودات الرائعة.. و اسأل الله أن تكون في موازين حسناتكم

في الملف المصدري الذي يبدأ بـ: اذا يصبح الملف المصدري ArdroidCaller.java كاملا:
في السطر رقم 85…
بما أن هذه اول تجربة لي مع الجافا,, و أني لم ادرسها من قبل … فأنه و أثناء تنفيذي لبرنامجكم قد واجهني خظأ -أظنه بسيط-. لكني لم اعرف كنهه بسهولة.. و لكن بعد التمحيص عرفت انت يجب أن يتم استبدال
(AndroidPhoneDialer.this)
بـ
(activityname.this)

كوثر يقول:

الدروس ممتازة …….قليل ما نحصل موقع يشرح الكود كامل …امنى لك التوفيق اكثر

كوثر يقول:

بس كان عندي سؤال …في مشكلة في برنامجي انه ما يسمح لي في ايجاد tabhost
Could not create tab content because could not find view with id -1
ويأدي الى ان الxml كله يتسكر

RainTear يقول:

السلام عليكم…
اخي وائل هل ممكن مساعدة وطرح درس لكتابة رسالة نصيه..
اريد هذا البرنامج ضروري..

سمية يقول:

شرح رائع و مفيد نتوقع الاحسن و المزيد وشكرا

سمية يقول:

شرح رائع و مفيد نتوقع الاحسن و المزيد ارجو نشر باقي الدروس
وشكرا

نوره يقول:

هلا كيف الحال..طرح مميز
هل ممكن طرح كودات بالجافا ليرنامج تشغيل لعبه فيها نك نيم والباسورد والايميل ضروووري

Leave a Reply

Your email address will not be published. Required fields are marked *