Android Webservices

Android Webservices بالعربية – الدرس السادس

فى الدرس السابق Android Webservices بالعربية – الدرس الخامس  قمنا بالتحدث عن حذف البيانات وتحديث البيانات بالاضافة لكيفية ارسال معلومة او قيمة ويستقبلها ملف php ويتعامل معها اثناء تنفيذ أمر الـ SQL وعرفنا ان هناك طريقتين لارسال المعلومات طريقة الـ GET وطريقة الـ POST ووضحنا ان طريقة الـ GET يتم ارسال القيم لملف php عن طريق الرابط أما POST يتم ارسال القيم عن طريق الـ body الخاص بالـ http request وسنتحدث عن الـ http request بالتفصيل فى تدوينة اخرى ان شاء الله المهم الان ان تعرف ان هناك طريقتين هما الـ POST والـ GET  وسنتعلم فى هذا الدرس كيفية ارسال القيم اثناء الاتصال بملف php من داخل تطبيق الأندرويد  عن طريق الـ GET والـ POST   .

 

بالعودة للدرس الثانى Android Webservices بالعربية – الدرس الثانى كنا قد اتصلنا بملف php موجود online على الاستضافة أو السيرفر بهذا الكود وشرحناه بالتفصيل (ماعدا الـ Runnable والـ Thread  سنتحدث عنهم لاحقا فى سلسلة الـ Multi Threading ) :

                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {

                        try {
                            
                            URL hellofileurl = new URL("http://developerhendy.16mb.com/hello.php");
                            HttpURLConnection myfirstconnection = (HttpURLConnection) hellofileurl.openConnection();
                            InputStreamReader stream = new InputStreamReader(myfirstconnection.getInputStream());
                            BufferedReader ourstreamreader = new BufferedReader(stream);
                            final String hello = ourstreamreader.readLine();
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    text.setText(hello);
                                }
                            });


                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                };

                Thread thread = new Thread(runnable);
                thread.start();

 

اما فى درس اليوم سنقوم بالاتصال بملف الـ php insertuser المسؤول عن تسجيل الاعضاء  او اضافة اعضاء جديدة لجدول الـ users الموجود فى قاعدة البيانات mysql الخاصة بنا

قم بعمل تصميم مشابه للتالى يحتوى على عدة حقول EditText هى الاسم والباسورد والعنوان والايميل  مع زر التسجيل  .

لقد قمت بعمل هذا التصميم البسيط لنقوم بالتطبيق عليه فى هذا الدرس

Appp

سوف نقوم باعطاء ID لكل Edittext وتعريفه فى الجافا كما نفعل فى الوضع العادى وكذلك الـ Button  كالتالى :

defineedittext

 

ونقوم بتعريف الـ Button وعمل setOnClickListener والذى سنقوم بداخله بتنفيذ كود تسجيل عضو جديد

android button

 

 

سوف ابدأ باستقبال ما بداخل الـ Edittexts فى Strings كالتالى :

edittext

فى الدرس السابق كنت أستدعى هذا الرابط من المتصفح  لأقوم بتسجيل عضو جديد كالتالى :

http://developerhendy.16mb.com/insertuser.php?username=Ahmed&password=123123&email=ahmed@hendiware.16mb.com&adress=Egypt

 

وسنتعلم اليوم كيفية استدعاء هذا الرابط من خلال تطبيق الأندرويد الخاص بنا وذلك باستخدام طريقة الـ GET وطريقة الـ POST  .

 

طريقة الـ GET  

سأبدا  بوضع الرابط فى أندرويد ستوديو مع مراعاة ان استبدل القيم  بالـ Strings التى اخذتها من الـ Edittexts  :

url

 

نفوم الان بانشاء اتصال بهذه الـ url كما فعلنا فى الدرس الثانى من السلسلة

http

 

طبعا كل السطور السابقة شرحناها فى الدرس الثانى وساذكركم بها سريعة السطر الاول إنشاء كائن Url من الرابط سيقوم بالتعرف على مكونات الرابط ومعالجتها

وفى السطر الثانى قمنا بفتح الاتصال بكائن الـ url ومسك هذا الاتصال بالـ HttpURLConnection واسناد مهمة ادارة الاتصال بالـ url اليه .

استقبلنا الناتج من getInputStream الخاصة بالـ HttpURLConnection داخل InputStreamReader ليقوم بتحويل الـ ByteStream الى  character stream  واستقبلنا الـ character stream  بالـ Buffer reader لنستطيع قراءة النص وقمنا بذلك باستخدام readline() . واستخدمنا الميثود runOnUIThread();  لاننا لا يمكن الوصول للـ main thread بشكل مباشر من thread اخر (موضوع سنناقشه لاحقا فى الـ MultiThreading هو والـ Runnable ) .

 

نقوم الان بتجربة التطبيق

Screen Shot 2016-02-04 at 11.04.19 PM

 

اذا تم  الارسال بنجاح فبالتأكيد لم تقم بكتابة البيانات السابقة فى هذا المثال فلقد تعمدت فى Steve Jobs  أن يكون هناك مسافة بين الكلمتين وبذلك ستحدث مشكلة ولن يتم الارسال وستجد  رسالة الـ No Parameters عائدة من ملف الـ php وتظهر فى الـ Toast كالتالى :

php connect error

اى لم يتم ارسال الـ parameters أما اذا ازلت المسافات بين كلمة Steveو Jobs وبين New و Yourk لتصبح كالتالى :

input

واذا ما ضغطنا على register لتنفيذ الكود السابق فان العملية ستتم بنجاح  واذا كتبت كلمة Steve فقط فستتم بنجاح ايضا

success

 

حسنا ما المشكلة فى المسافات ؟

كما ذكرنا سابقا أن فتح الرابط من خلال المتصفح ليس كما هو الحال عند التعامل مع الـ URL مباشرة  فالمتصفح يعالج الكثير من الامور اثناء ارسال الـرابط وعند تمرير الرابط لكلاس الـ URL فإنه لا يقوم بمعالجة الـمسافات بين النصوص وبالتالى لا يقوم بارسال الـ prarameters وبالتالى يرد علينا ملف php بـ no parameters التى قمنا بعملها اذا لم يكن هنا set للبارامتيرز او القيم الذاهبة لملف php

حتى اذا قمت باستدعاء الرابط عبر المتصفح وبه مسافة فستجد ان المتصفح بدلها تلقائيا بـ ٪20  * قم بطلب الرابط من المتصفح كما فعلنا فى الدرس السابق وستلاحظ ذلك

link in browser

لذلك عند ارسال الرابط بطريقة الـ GET كما نفعل الان يجب علينا معالجة مشكلة المسافة يدويا ويمكننا عمل ذلك بطريقتين  :-

1- استخدام  الميثود replaceAll الموجوده فى كلاس الـ String

لتبديل كل المسافات الموجودة بالرابط  بعلامة %20 كالتالى :

سننشىء String للـ url بعد التعديل وسنسميها modified url  وسنقوم فيها باستقبال الـ url العادية وتبديل كل المسافات ” ” ب %20

ht

 

واذا قمت بالتجربة الان ستجد أن الكود يعمل بنجاح عند وضع مسافات

android input feild

ملحوظة : ترسل الـ url عبر الانترنت باستخدام مجموعة حروف ورموز الـ ASCII و اى حروف تكون غير تابعة للـ ASCII يتم عمل Encode لها لتصبح بصيغة الـ ASCII وبالرغم من أن المسافة ” ” تعتبر من الـ ASCII إلا أنها تصنف على أنها من الحروف الغير أمنة لانها احد الفواصل فى الـ http request header لذلك يتم تحويلها فى الروابط إما الى %20 أو + .

والطريقة السابقة لا يمكن الاعتماد عليها بشكل كلى اذا كان هناك احتمال ان يقوم المستخدم بإدخال شىء اخر غير المسافات على سبيل المثال اثناء الباسورد قد يقوم المستخدم بكتابة الرموز كجزء من الباسورد مثل 55٪&*cairo او #33#? وغيرها سنفاجأ بان هناك Exeption هل تتذكر أننا اضطررنا لعمل try  فى الدرس الثانى ووضحنا ان الـ url يمكن ان تكون غير صحيحة او بها مشكلة

encoding

ولذلك تعالى نتعرف على الطريقة الثانية لمعالجة الـ url

2- استخدام كلاس الـ URLEncoder

يمكننا استخدام هذا الكلاس لعمل encoding  لاى من المدخلات وتحويل قيم المدخلات لقيم مقبولة ليتم تمريرها عبر الـ url بأمان سواء كانت مسافة ام رموز اخرى سواء # او ٪#$ او &^*٪^ او اى رموز اخرى

توفر لنا كلاس الـ URLEncoder ميثود تسمى encode وفى الحقيقة هى الميثود الوحيده فى هذا الكلاس 😀  وهى static لذلك نستيطع مناداتها مباشرة بدون عمل new Object من الكلاس وهى تأخذ بارمترين كالتالى :

URLEncoder.encode(thing you want encode , encode type)

البارامتر الأول يكون نصى وهو عباره عن الـ شىء المراد عمل encode او ترميز له ويكون String

البارامتر الثانى يكون عباره عن نوع الـ encode حيث هناك أكثر من نوع encode لكن أشهرها والمتوافق مع اغلب اللغات بما فيها العربية  هو  UTF-8 وهو ما سنستخدمه

الان سوف نقوم بتقسيم الرابط الى Strings  ونضع كل key فى String باسمه   والـ values هى عباره عن الـ username,password,email,adress كما هى سابقا كالتالى :

paramter string

 

ثم نقوم بعمل String وسنسميه final url اى الـ url النهائية وسنقوم فيه بجمع الـ keys مع الـ values لكن باستخدام URLEncoder لكل value . كالتالى

url encode

 

لا تنصدم من طول الـ url فما هى الا الـ url القديمة التى استخدمناها فى المتصفح لكن هنا وضعنا url بعدها كل key يليله الـ value الخاص به لكن بعد عمل encode لكل key   .

وبالنسبة للـ خط الأحمل فهو يطالبنا بعمل try catch لان الـ URLEncoder قد تواجه بارامتر لا يمكن عمل له encode بطريقة UTF-8 مثلا كأن تدخل حروف لغة غير مدعومة من UTF-8 أو اى خطأ اخر يسبب فشل الـ encoding

لذلك سوف نقوم بعمل try catch  كالتالى :

try catch

 

ويكون الكود الكامل  داخل الـ ضغط الزر كالتالى :

                String username = usernameEdiTxt.getText().toString();
                String password = passwordEdiTxt.getText().toString();
                String email = emailEdiTxt.getText().toString();
                String adress = adressEdiTxt.getText().toString();

                String url = "http://developerhendy.16mb.com/insertuser.php";
                String usernamekey = "?username=";
                String passwordkey = "&password=";
                String emailkey = "&email=";
                String adresskey = "&adress=";

                try {
                    finalurl = url + usernamekey + URLEncoder.encode(username, "UTF-8") + passwordkey
                            + URLEncoder.encode(password, "UTF-8") +
                            emailkey+URLEncoder.encode(email,"UTF-8")+adresskey+URLEncoder.encode(adress,"UTF-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }


                Runnable runnable = new Runnable() {
                    public void run() {
                        try {

                            URL insertUserUrl = new URL(finalurl);
                            HttpURLConnection insertConnection = (HttpURLConnection) insertUserUrl.openConnection();
                            InputStreamReader resultStreamReader = new InputStreamReader(insertConnection.getInputStream());
                            BufferedReader resultReader = new BufferedReader(resultStreamReader);
                            final String result = resultReader.readLine();
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
                                }
                            });
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                };

                Thread thread = new Thread(runnable);
                thread.start();

 

وعند التشغيل يمكنك تجربة اى رموز تريدها داخل حقول الادخال وسيتم تسجيل المستخدم بنجاح

 

sucess user registration

 

 

 

الان اصبحت قادرا على الاتصال بملف php موجود اون لاين وارسال البياانات  له بطريقة الـ GET * وكذلك استقبال البيانات منه على هيئة نص عادى وعرضها فى الأندرويد .

ملحوظة : كلاس الـ HttpURLConnection يقوم بإستخدام طريقة الـ GET لإرسال البيانات افتراضيا .

 

طريقة الـ POST 

اول شىء قبل ارسال البيانات لملف الـ php يجب تهيئة هذا الملف ليستقبل البيانات بطريقة الـ POST ففى المقال السابق انتهينا الى ان يكون شكل الملف كالتالى :

php file insert user

 

 

فقط لنجعله مهيأ لاستقبال البيانات بطريقة الـ POST سنقوم بتغيير كل $_GET الى $_POST  فقط  كالتالى :

php post

قمت بحفظ الملف باسم insertuserwithpost.php وسأقوم برفعه للإستضافة الان لكى نتعامل معه من داخل تطبيق الأندرويد .

على سبيل التجربة سنقوم فقط بتغيير اسم الملف فى الـ url فى كود الاندرويد لنجد هل سيتم ارسال البيانات ام لا 😉

save

عند التجربة حصلنا على هذه النتيجة

Screen Shot 2016-02-05 at 7.10.45 AM

وذلك لأنه رغم لأنه كل شىء صحيح إلا ان ملف الـ php مهيأ ليستقبل البيانات بطريقة الـ POST ونحن نرسلها بالـ GET

أحد الفروق بين GET و POST أنه فى طريقة الـ GET يتم إرسال الـقيم عبر الـرابط url لكن فى الطريقه POST يتم إرسالها عبر الـ http request body  وبالتالى فهى لا تظهر فى المتصفح ولا تستطيع ارسال البيانات بطريقة الـ POST عبر الرابط url بل سنقوم بإرسالها بعد فتح الاتصال مع الـ url  .

ولذلك سوف نرسلها على هيئة Stream طالما انها سترسل بعد فتح الـ Connection مع الـ url .

وكما قمنا فى الدرس الثانى من السلسلة باستقبال البيانات على هيئة Byte Stream وحولناها الى Character Stream ثم الى text سنقوم هنا عند ارسال البيانات بعمل العكس حيث سنحول الـ text الى Character Stream ثم نحول الـ Character Stream الى Byte Stream

و كنا سنضطر لاستخدام  الـ BuffredWriter و الـ OutputStreamWriter  لتنفيذ عكس ما فعلناه فى الدرس السابق الا أن الكلاس String يوفر لنا ميثود رائعة تقوم بالمهمة اسمها getByte(); سنستخدمها اليوم .

الان سنقوم بتعديل الـ url ليتم تمرير رابط الصفحة فقط للـ connection كالتالى :

url connection android

بالنسبة للـ finalurl التى كنا صنعناها باستخدام الـ urlEncodeing سنحذف منها الـ url ونعيد تسمية المتغير الى paramters وسنقوم بحذف ? من البارامتر الاول والتى كانت تستخدم لفصل الرابط عن البارامترز عن الاتصال بالـ GET  .

url editing

سوف ننشىء مصفوفة  من النوع byte []  لنخزن فيها بيانات الـ connectionpramters (البيانات التى نريد ارسالها ) ونستخدم الـ method التى ذكرناها كالتالى

bytes paramters

ولقد أعطيناها نوع الـ encoding فى الـ paramter الخاص بها .

ولاحظ أننا وضعناها داخل الـ try catch لانها تقوم بعمل استثناء تمام كـ URLencoder

الان سوف نتجه للإتصال نفسه ونقوم بارسال  الـ paramters هذه عبر الاتصال كالتالى :

سوف نقوم بتحديد طريقة ارسال البيانات فى الاتصال عن طريق الميثود setRequestMethod والتى تأخذ بارامتر عباره عن String يمكن أن تعطيها GET أو POST وكما قلنا افتراضيا يكون الاتصال يتعامل بالطريقة GET اذا نخبره بهذه الميثود اننا سنستخدم POST بهذه الميثود (جرب ان  لا تقم بهذه الخطوة وراقب الـ logcat وانظر ماذا سيحدث )

وايضا سوف نقوم باستخدام الميثود getOutputStream() والتى ستعطينا صلاحية الوصول للـ output stream الخاص بالـ connection وسنقوم باستدعاء الميثود write ونمرر لها الـمصفوفة الخاصة بالبيانات او البارامترز التى نريد ارسالها كالتالى :

connection

ويكون الكود الكامل الخاص بالاتصال بـ POST كالتالى :

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;

public class MainActivity extends AppCompatActivity {
    EditText usernameEdiTxt, passwordEdiTxt, emailEdiTxt, adressEdiTxt;
    Button registerBtn;
    byte[] paramtersbyt;
    String connectionparamters;
    String url;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setElevation(0);
        usernameEdiTxt = (EditText) findViewById(R.id.usernameET);
        passwordEdiTxt = (EditText) findViewById(R.id.passwordET);
        emailEdiTxt = (EditText) findViewById(R.id.emailET);
        adressEdiTxt = (EditText) findViewById(R.id.adressET);
        registerBtn = (Button) findViewById(R.id.registerBTN);
        registerBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String username = usernameEdiTxt.getText().toString();
                String password = passwordEdiTxt.getText().toString();
                String email = emailEdiTxt.getText().toString();
                String adress = adressEdiTxt.getText().toString();
                url = "http://developerhendy.16mb.com/insertuserwithpost.php";
                String usernamekey = "username=";
                String passwordkey = "&password=";
                String emailkey = "&email=";
                String adresskey = "&adress=";
                try {
                    connectionparamters = usernamekey + URLEncoder.encode(username, "UTF-8") + passwordkey
                            + URLEncoder.encode(password, "UTF-8") +
                            emailkey + URLEncoder.encode(email, "UTF-8") + adresskey + URLEncoder.encode(adress, "UTF-8");

                    paramtersbyt = connectionparamters.getBytes("UTF-8");

                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }

                Runnable runnable = new Runnable() {
                    public void run() {
                        try {

                            URL insertUserUrl = new URL(url);
                            HttpURLConnection insertConnection = (HttpURLConnection) insertUserUrl.openConnection();
                            insertConnection.setRequestMethod("POST");
                            insertConnection.getOutputStream().write(paramtersbyt);
                            InputStreamReader resultStreamReader = new InputStreamReader(insertConnection.getInputStream());
                            BufferedReader resultReader = new BufferedReader(resultStreamReader);
                            final String result = resultReader.readLine();
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    Toast.makeText(MainActivity.this, result, Toast.LENGTH_SHORT).show();
                                }
                            });
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                };

                Thread thread = new Thread(runnable);
                thread.start();

            }
        });

 

وعند التجربة ستلاحظ أن العملية تمت بنجاح

sucess

والان اصبحت قادرا على الاتصال بملف php من الأندرويد  سواء بالـ GET أو الـ POST 

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

post

مقارنة POST VS GET 

GET POST
GET يتم فيها ارسال البيانات لملف php عبر الرابط  او فى الـ http request header

GET أسرع من POST

GET مناسبة للبيانات القصيرة  مثل ارسال اسم مستخدم او ارسال استعلام قصير

GET تكون البيانات ظاهرة اذا تم استخدامها فى المتصفح

POST يتم فيها ارسال البيانات لملف php عبر الـ http request body

POST أبطأ من GET

POST مناسبة للبيانات الطويلة مثل موضوع كتابى أو بوست او نص طويل الخ .

POST تكون البيانات مختفية اذا تم استخدامها فى المتصفح ولا تظهر فى الرابط

وهى أمنة اكثر من GET .

الى هنا تنتهى التدوينة سنتحدث فى التدوينة القادمة عن الـ JSON Parsing وكيفية جلب البيانات على هيئة JSON من ملف php .

الواجب : 

قم بإنشاء جدول باسم  posts  به اعمدة (id,postcontent,writer)فى قاعدة البيانات وقم بعمل ملف php باسم insertsposts وقم بعمل تطبيق أندرويد جديد  يحتوى على زرين

زر New Post يفتح لك أكتيتفى جديد به 2 Editext واحد لكتابة اسم الكاتب وواحد لكتابة بوست وزر ” Publish ” يقوم بنشر الـ post (ارساله الى قاعدة البياانات)

زر View Posts يفتح اكتيتفى جديد ويتصل بملف php باسم getposts ويقوم بعرض الـ posts على هيئة text  .والتى سنعمل المرة القادمة على عرض الـ posts كـ json واستقبالها فى الأندرويد .

اذا كان هناك اى شىء غير اضح او غير مفهوم او يحتاج الى تفسير قم بترك تعليق وسنجيبك .

السابق
سلسلة Android Sensors بالعربية الدرس الثانى : LightSensor
التالي
الـ RecyclerView وما وراء الـ Adapters و الـ Models الجزء الأول

27 تعليق

أضف تعليقا

  1. علي زهير قال:

    شكرا
    عمل رائع
    جاري التطبيق

    1. Hendiware قال:

      نورت التدوينة يا على ^_^
      نتمنى لك تطبيقا ممتعا

  2. من احلا الشروحات وافيدها فريق العمل شكرا لكم من القلب <3

    1. Hendiware قال:

      نورتنا يا غازى شكرا لك .

  3. Basem Nasr قال:

    متألق دائما يا صديقي

    1. Hendiware قال:

      شكرا لك صديقى باسم نورت التدوينة

  4. احمد قال:

    برجاء شرح طريقة جلب البيانات اوتوماتيكيا كل فترة معينه

    1. Hendiware قال:

      هذا موضوع سابق لاوانه نحن الان نركز على اساسيات الويب سيرفس اولا هذا الموضوع سنغطيه فى وقت لاحق إن شاء الله

  5. Sw My قال:

    السلام عليكم… كيف اظهار رسالة مثل جاري التسجيل… اذا تاخر ارسال البيانات او فيه ضغط علئ السيرفر .. مثلا progres Dialog
    .. وشكرا علئ شروحاتكمم

    1. Hendiware قال:

      وعليكم السلام
      سوف تقوم بتعريف ProgressDialog dialog ; فى أول الكود
      عند بداية تنفيذ الكود ستقوم بعمل dialog = ProgressDialog.show(contextm,”dialog title” , “dialog message”,true ) ;
      وفى ميثود runOnUiThread() بداخلها سوف تقوم بعمل dialog.dismess();

  6. Ahmed Ali قال:

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

    1. Hendiware قال:

      نورتنا يا أحمد ربنا يوفقك .

  7. Mohammad Shoukal قال:

    جزاك الله خيراً على هذا الشرح الرائع 🙂
    فقط أردت التنويه على استخدام trim عند جلب string

  8. ghadeer قال:

    شكرااا جزيلا ع مجهودك وع الشرح الأكثر من رائع
    سويت الواجب ^^
    [url=https://www.0zz0.com][img]http://www8.0zz0.com/2016/03/06/00/329820131.png[/img][/url]

      1. عبدالله قال:

        ممكن الكود اللى بطبع فى الاكتفتي لما بتدوسي viewpost عشان عندى مش بيطبع كااااااامل ؟؟! اتمنى تردى

    1. Hendiware قال:

      جميل جدا ياغدير .. بالتوفيق ^_^

  9. asmaa قال:

    لو سمحت لو عندى id ك integer هل هيحصل e
    ncode اازاى

  10. islam قال:

    انا عملت كل شئ زى الدرس ده لكن عند الضغط على الزر يطبع لى no parameter !!! فى طريقة post

  11. elsayed قال:

    شكرا جدا علي الشرح الجميل

  12. mahmoud قال:

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

  13. عبوود قال:

    ياشيخ ربنا يرزقك ما احلا الشرح عسل عسل عسل

  14. amr قال:

    انا عملت الكود زى ما هو فى طريقه البوست وبيظهرلى ايرور كد فى الاندرويد استوديو
    D/NetworkSecurityConfig: No Network Security Config specified, using platform default
    وفى التطبيق بيقولى no parameters اللى هي بتبقى راجعه من ال url
    ومش عارف الحل

  15. timelancer قال:

    شكرا كل شئ واضح كوضوح الشمس
    و الواجب تم

  16. علي احمد قال:

    جزاك الله خيرا

  17. صخر قال:

    العمل رائع جدا
    شرح سلس وواضح
    شكرا لكم من القلب
    وبوركت العقول وزادكم الله ابداعا اكثر

  18. nur قال:

    تكون البيانات مختفية اذا تم استخدامها فى المتصفح ولا تظهر فى الرابط
    ممكن توضيح , ما فهمت كيف يعني ما تظهر ؟

اترك تعليقاً

This site uses Akismet to reduce spam. Learn how your comment data is processed.