Как работать с MySQL в Android? Часть 2

В данном уроке я покажу как можно на Android работать с MySQL базой данных на основе JSON формата.

В этой части данного урока мы перейдем не посредственно к созданию самого Android приложения, так как backend мы написали в прошлом уроке  ‘Как работать с MySQL в Android? Часть 1‘, где мы сделали серверную часть на PHP которая получает данные с БД и формирует ответ в качестве JSON формата.

Шаг 1. Создание Android приложение

Создаем Androi приложение File->New Project :

После создания проекта создайте следующий список классов:

Шаг 2. Настраиваем Manifest

Теперь заходим в AndroidManifest.xml и прописываем там все наши только что созданные классы, все кроме класса JSONPaser, так как все эти классы будут Activity.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.devcolibri.androidandmysql"
          android:versionCode="1"
          android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8"/>
    <application android:label="@string/app_name">
        <activity android:name=".MainScreenActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- All Product Activity -->
        <activity
                android:name=".AllProductsActivity"
                android:label="All Products" >
        </activity>

        <!-- Add Product Activity -->
        <activity
                android:name=".NewProductActivity"
                android:label="Add New Product" >
        </activity>

        <!-- Edit Product Activity -->
        <activity
                android:name=".EditProductActivity"
                android:label="Edit Product" >
        </activity>
    </application>

    <!--  Internet Permissions -->
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>

Шаг 3. Создание layout

Теперь для каждого класса Activity создадим layout.

Первый будет main_screen.xml для Activity MainScreenActivity:

<?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:orientation="vertical"
              android:gravity="center_horizontal">

    <!--  Эта кнопка будет открывать окно для просмотра всех продуктов -->
    <Button android:id="@+id/btnViewProducts"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/btn_viewproduct"
            android:layout_marginTop="25dip"/>

    <!--  Эта кнопка будет открывать окно для создания нового продукта -->
    <Button android:id="@+id/btnCreateProduct"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/btn_addnewproduct"
            android:layout_marginTop="25dip"/>

</LinearLayout>

Выглядеть она должна так:

Теперь создадим layout all_products.xml для AllProductsActivity:

<?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:orientation="vertical">
    <!--
        Главный ListView
        Всегда давайте значение идентификатора
        в виде списка(@android:id/list)
    -->
    <ListView
            android:id="@android:id/list"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"/>

</LinearLayout>

и вторая дополнительная list_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:orientation="vertical" >

    <!--
        Идентификатор продукта id
        (pid) - будет HIDDEN - используется для передачи в другой activity -->
    <TextView
            android:id="@+id/pid"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:visibility="gone" />

    <TextView
            android:id="@+id/name"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:paddingTop="6dip"
            android:paddingLeft="6dip"
            android:textSize="17dip"
            android:textStyle="bold" />

</LinearLayout>

Выглядит она так:

Следующая add_product.xml для NewProductActivity:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" >

    <TextView android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:text="Product Name"
              android:paddingLeft="10dip"
              android:paddingRight="10dip"
              android:paddingTop="10dip"
              android:textSize="17dip"/>

    <EditText android:id="@+id/inputName"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:layout_margin="5dip"
              android:layout_marginBottom="15dip"
              android:singleLine="true"/>

    <TextView android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:text="Price"
              android:paddingLeft="10dip"
              android:paddingRight="10dip"
              android:paddingTop="10dip"
              android:textSize="17dip"/>

    <EditText android:id="@+id/inputPrice"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:layout_margin="5dip"
              android:layout_marginBottom="15dip"
              android:singleLine="true"
              android:inputType="numberDecimal"/>

    <TextView android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:text="Description"
              android:paddingLeft="10dip"
              android:paddingRight="10dip"
              android:paddingTop="10dip"
              android:textSize="17dip"/>

    <EditText android:id="@+id/inputDesc"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:layout_margin="5dip"
              android:layout_marginBottom="15dip"
              android:lines="4"
              android:gravity="top"/>

    <Button android:id="@+id/btnCreateProduct"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Create Product"/>

</LinearLayout>

Выглядит она так:

И последний это edit_product.xml для EditProductActivity:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" >

    <TextView android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:text="Product Name"
              android:paddingLeft="10dip"
              android:paddingRight="10dip"
              android:paddingTop="10dip"
              android:textSize="17dip"/>

    <EditText android:id="@+id/inputName"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:layout_margin="5dip"
              android:layout_marginBottom="15dip"
              android:singleLine="true"/>

    <TextView android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:text="Price"
              android:paddingLeft="10dip"
              android:paddingRight="10dip"
              android:paddingTop="10dip"
              android:textSize="17dip"/>

    <EditText android:id="@+id/inputPrice"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:layout_margin="5dip"
              android:layout_marginBottom="15dip"
              android:singleLine="true"
              android:inputType="numberDecimal"/>

    <TextView android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:text="Description"
              android:paddingLeft="10dip"
              android:paddingRight="10dip"
              android:paddingTop="10dip"
              android:textSize="17dip"/>

    <EditText android:id="@+id/inputDesc"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:layout_margin="5dip"
              android:layout_marginBottom="15dip"
              android:lines="4"
              android:gravity="top"/>

    <LinearLayout android:layout_width="fill_parent"
                  android:layout_height="wrap_content"
                  android:orientation="horizontal">
        <Button android:id="@+id/btnSave"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="Save Changes"
                android:layout_weight="1"/>

        <Button android:id="@+id/btnDelete"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:text="Delete"
                android:layout_weight="1"/>
    </LinearLayout>

</LinearLayout>

Выглядит так:

Шаг 4. Пишем Activity

Начнем с самого главного MainScreenActivity:

package com.devcolibri.androidandmysql;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainScreenActivity extends Activity {

    Button btnViewProducts;
    Button btnNewProduct;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_screen);

        btnViewProducts = (Button) findViewById(R.id.btnViewProducts);
        btnNewProduct = (Button) findViewById(R.id.btnCreateProduct);

        // обработчик на нажатиЯ кнопки View Products
        btnViewProducts.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                // Запускаем Activity вывода всех продуктов
                Intent i = new Intent(getApplicationContext(), AllProductsActivity.class);
                startActivity(i);

            }
        });

        // обработчик на нажатия кнопки Add New Products
        btnNewProduct.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                // Запускаем Activity создания нового продукта
                Intent i = new Intent(getApplicationContext(), NewProductActivity.class);
                startActivity(i);

            }
        });
    }
}

В комментариях к коду я старался объяснить код, что будет не понятно в комментарии к этому уроку задавайте ваши вопросы.

Следующий это AllProductsActivity:

package com.devcolibri.androidandmysql;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import com.devcolibri.parser.JSONParser;
import org.apache.http.NameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;

public class AllProductsActivity extends ListActivity {

    private ProgressDialog pDialog;

    // Создаем JSON парсер
    JSONParser jParser = new JSONParser();

    ArrayList<HashMap<String, String>> productsList;

    // url получения списка всех продуктов
    private static String url_all_products = "http://test.devcolibri.com/get_all_products.php";

    // JSON Node names
    private static final String TAG_SUCCESS = "success";
    private static final String TAG_PRODUCTS = "products";
    private static final String TAG_PID = "pid";
    private static final String TAG_NAME = "name";

    // тут будет хранится список продуктов
    JSONArray products = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.all_products);

        // Hashmap for ListView
        productsList = new ArrayList<HashMap<String, String>>();

        // Загружаем продукты в фоновом потоке
        new LoadAllProducts().execute();

        // получаем ListView
        ListView lv = getListView();

        // на выбор одного продукта
        // запускается Edit Product Screen
        lv.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) {
                // getting values from selected ListItem
                String pid = ((TextView) view.findViewById(R.id.pid)).getText()
                        .toString();

                // Запускаем новый intent который покажет нам Activity
                Intent in = new Intent(getApplicationContext(), EditProductActivity.class);
                // отправляем pid в следующий activity
                in.putExtra(TAG_PID, pid);

                // запуская новый Activity ожидаем ответ обратно
                startActivityForResult(in, 100);
            }
        });

    }

    // Ответ из Edit Product Activity
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        // если результующий код равен 100
        if (resultCode == 100) {
            // если полученный код результата равен 100
            // значит пользователь редактирует или удалил продукт
            // тогда мы перезагружаем этот экран
            Intent intent = getIntent();
            finish();
            startActivity(intent);
        }

    }

    /**
     * Фоновый Async Task для загрузки всех продуктов по HTTP запросу
     * */
    class LoadAllProducts extends AsyncTask<String, String, String> {

        /**
         * Перед началом фонового потока Show Progress Dialog
         * */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(AllProductsActivity.this);
            pDialog.setMessage("Загрузка продуктов. Подождите...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(false);
            pDialog.show();
        }

        /**
         * Получаем все продукт из url
         * */
        protected String doInBackground(String... args) {
            // Будет хранить параметры
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            // получаем JSON строк с URL
            JSONObject json = jParser.makeHttpRequest(url_all_products, "GET", params);

            Log.d("All Products: ", json.toString());

            try {
                // Получаем SUCCESS тег для проверки статуса ответа сервера
                int success = json.getInt(TAG_SUCCESS);

                if (success == 1) {
                    // продукт найден
                    // Получаем масив из Продуктов
                    products = json.getJSONArray(TAG_PRODUCTS);

                    // перебор всех продуктов
                    for (int i = 0; i < products.length(); i++) {
                        JSONObject c = products.getJSONObject(i);

                        // Сохраняем каждый json елемент в переменную
                        String id = c.getString(TAG_PID);
                        String name = c.getString(TAG_NAME);

                        // Создаем новый HashMap
                        HashMap<String, String> map = new HashMap<String, String>();

                        // добавляем каждый елемент в HashMap ключ => значение
                        map.put(TAG_PID, id);
                        map.put(TAG_NAME, name);

                        // добавляем HashList в ArrayList
                        productsList.add(map);
                    }
                } else {
                    // продукт не найден
                    // Запускаем Add New Product Activity
                    Intent i = new Intent(getApplicationContext(),
                            NewProductActivity.class);
                    // Закрытие всех предыдущие activities
                    i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                    startActivity(i);
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

            return null;
        }

        /**
         * После завершения фоновой задачи закрываем прогрес диалог
         * **/
        protected void onPostExecute(String file_url) {
            // закрываем прогресс диалог после получение все продуктов
            pDialog.dismiss();
            // обновляем UI форму в фоновом потоке
            runOnUiThread(new Runnable() {
                public void run() {
                    /**
                     * Обновляем распарсенные JSON данные в ListView
                     * */
                    ListAdapter adapter = new SimpleAdapter(
                            AllProductsActivity.this, productsList,
                            R.layout.list_item, new String[] { TAG_PID,
                            TAG_NAME},
                            new int[] { R.id.pid, R.id.name });
                    // обновляем listview
                    setListAdapter(adapter);
                }
            });

        }

    }

}

После идет activity NewProductActivity:

package com.devcolibri.androidandmysql;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import com.devcolibri.parser.JSONParser;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

public class NewProductActivity extends Activity {

    private ProgressDialog pDialog;

    JSONParser jsonParser = new JSONParser();
    EditText inputName;
    EditText inputPrice;
    EditText inputDesc;

    private static String url_create_product = "http://test.devcolibri.com/create_product.php";

    private static final String TAG_SUCCESS = "success";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.add_product);

        inputName = (EditText) findViewById(R.id.inputName);
        inputPrice = (EditText) findViewById(R.id.inputPrice);
        inputDesc = (EditText) findViewById(R.id.inputDesc);

        Button btnCreateProduct = (Button) findViewById(R.id.btnCreateProduct);

        btnCreateProduct.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View view) {
                new CreateNewProduct().execute();
            }
        });
    }

    /**
     * Фоновый Async Task создания нового продукта
     **/
    class CreateNewProduct extends AsyncTask<String, String, String> {

        /**
         * Перед согданием в фоновом потоке показываем прогресс диалог
         **/
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(NewProductActivity.this);
            pDialog.setMessage("Создание продукта...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(true);
            pDialog.show();
        }

        /**
         * Создание продукта
         **/
        protected String doInBackground(String[] args) {
            String name = inputName.getText().toString();
            String price = inputPrice.getText().toString();
            String description = inputDesc.getText().toString();

            // Заполняем параметры
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("name", name));
            params.add(new BasicNameValuePair("price", price));
            params.add(new BasicNameValuePair("description", description));

            // получаем JSON объект
            JSONObject json = jsonParser.makeHttpRequest(url_create_product, "POST", params);

            Log.d("Create Response", json.toString());

            try {
                int success = json.getInt(TAG_SUCCESS);

                if (success == 1) {
                    // продукт удачно создан
                    Intent i = new Intent(getApplicationContext(), AllProductsActivity.class);
                    startActivity(i);

                    // закрываем это окно
                    finish();
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

            return null;
        }

        /**
         * После оконачния скрываем прогресс диалог
         **/
        protected void onPostExecute(String file_url) {
            pDialog.dismiss();
        }

    }

}

Последний EditProductActivity:

package com.devcolibri.androidandmysql;

import java.util.ArrayList;
import java.util.List;

import com.devcolibri.parser.JSONParser;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class EditProductActivity extends Activity {

    EditText txtName;
    EditText txtPrice;
    EditText txtDesc;
    Button btnSave;
    Button btnDelete;

    String pid;

    private ProgressDialog pDialog;

    JSONParser jsonParser = new JSONParser();

    // url для получения одного продукта
    private static final String url_product_detials = "http://test.devcolibri.com/get_product_details.php";

    // url для обновления продукта
    private static final String url_update_product = "http://test.devcolibri.com/update_product.php";

    // url для удаления продукта
    private static final String url_delete_product = "http://test.devcolibri.com/delete_product.php";

    // JSON параметры
    private static final String TAG_SUCCESS = "success";
    private static final String TAG_PRODUCT = "product";
    private static final String TAG_PID = "pid";
    private static final String TAG_NAME = "name";
    private static final String TAG_PRICE = "price";
    private static final String TAG_DESCRIPTION = "description";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.edit_product);

        btnSave = (Button) findViewById(R.id.btnSave);
        btnDelete = (Button) findViewById(R.id.btnDelete);

        // показываем форму про детальную информацию о продукте
        Intent i = getIntent();

        // получаем id продукта (pid) с формы
        pid = i.getStringExtra(TAG_PID);

        // Получение полной информации о продукте в фоновом потоке
        new GetProductDetails().execute();

        // обрабочик на кнопку сохранение продукта
        btnSave.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // запускаем выполнение задачи на обновление продукта
                new SaveProductDetails().execute();
            }
        });

        // обработчик на кнопку удаление продукта
        btnDelete.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // удалем продукт в фоновом потоке
                new DeleteProduct().execute();
            }
        });

    }

    /**
     * Фоновая асинхронная задача для получения полной информации о продукте
     **/
    class GetProductDetails extends AsyncTask<String, String, String> {

        /**
         * Перед началом показать в фоновом потоке прогресс диалог
         **/
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(EditProductActivity.this);
            pDialog.setMessage("Loading product details. Please wait...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(true);
            pDialog.show();
        }

        /**
         * Получение детальной информации о продукте в фоновом режиме
         **/
        protected String doInBackground(String[] params) {

            // обновляем UI форму
            runOnUiThread(new Runnable() {
                public void run() {
                    // проверяем статус success тега
                    int success;
                    try {
                        // Список параметров
                        List<NameValuePair> params = new ArrayList<NameValuePair>();
                        params.add(new BasicNameValuePair("pid", pid));

                        // получаем продукт по HTTP запросу
                        JSONObject json = jsonParser.makeHttpRequest(url_product_detials, "GET", params);

                        Log.d("Single Product Details", json.toString());

                        success = json.getInt(TAG_SUCCESS);
                        if (success == 1) {
                            // Успешно получинна детальная информация о продукте
                            JSONArray productObj = json.getJSONArray(TAG_PRODUCT);

                            // получаем первый обьект с JSON Array
                            JSONObject product = productObj.getJSONObject(0);

                            // продукт с pid найден
                            // Edit Text
                            txtName = (EditText) findViewById(R.id.inputName);
                            txtPrice = (EditText) findViewById(R.id.inputPrice);
                            txtDesc = (EditText) findViewById(R.id.inputDesc);

                            // покаываем данные о продукте в EditText
                            txtName.setText(product.getString(TAG_NAME));
                            txtPrice.setText(product.getString(TAG_PRICE));
                            txtDesc.setText(product.getString(TAG_DESCRIPTION));

                        }else{
                            // продукт с pid не найден
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            });

            return null;
        }

        /**
         * После завершения фоновой задачи закрываем диалог прогресс
         **/
        protected void onPostExecute(String file_url) {
            // закрываем диалог прогресс
            pDialog.dismiss();
        }
    }

    /**
     * В фоновом режиме выполняем асинхроную задачу на сохранение продукта
     **/
    class SaveProductDetails extends AsyncTask<String, String, String> {

        /**
         * Перед началом показываем в фоновом потоке прогрксс диалог
         **/
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(EditProductActivity.this);
            pDialog.setMessage("Saving product ...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(true);
            pDialog.show();
        }

        /**
         * Сохраняем продукт
         **/
        protected String doInBackground(String[] args) {

            // получаем обновленные данные с EditTexts
            String name = txtName.getText().toString();
            String price = txtPrice.getText().toString();
            String description = txtDesc.getText().toString();

            // формируем параметры
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair(TAG_PID, pid));
            params.add(new BasicNameValuePair(TAG_NAME, name));
            params.add(new BasicNameValuePair(TAG_PRICE, price));
            params.add(new BasicNameValuePair(TAG_DESCRIPTION, description));

            // отправляем измененные данные через http запрос
            JSONObject json = jsonParser.makeHttpRequest(url_update_product, "POST", params);

            // проверяем json success тег
            try {
                int success = json.getInt(TAG_SUCCESS);

                if (success == 1) {
                    // продукт удачно обнавлён
                    Intent i = getIntent();
                    // отправляем результирующий код 100 чтобы сообщить об обновлении продукта
                    setResult(100, i);
                    finish();
                } else {
                    // продукт не обновлен
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

            return null;
        }

        /**
         * После окончания закрываем прогресс диалог
         **/
        protected void onPostExecute(String file_url) {
            // закрываем прогресс диалог
            pDialog.dismiss();
        }
    }

    /**
     * Фоновая асинхронная задача на удаление продукта
     **/
    class DeleteProduct extends AsyncTask<String, String, String> {

        /**
         * На начале показываем прогресс диалог
         **/
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(EditProductActivity.this);
            pDialog.setMessage("уДАЛЕМ ПРОДУКТ...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(true);
            pDialog.show();
        }

        /**
         * Удаление продукта
         **/
        protected String doInBackground(String[] args) {

            int success;
            try {
                List<NameValuePair> params = new ArrayList<NameValuePair>();
                params.add(new BasicNameValuePair("pid", pid));

                // получение продукта используя HTTP запрос
                JSONObject json = jsonParser.makeHttpRequest(url_delete_product, "POST", params);

                Log.d("Delete Product", json.toString());

                success = json.getInt(TAG_SUCCESS);
                if (success == 1) {
                    // Продукт удачно удален
                    Intent i = getIntent();
                    // отправляем результирующий код 100 для уведомления об удалении продукта
                    setResult(100, i);
                    finish();
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }

            return null;
        }

        /**
         * После оконачния скрываем прогресс диалог
         **/
        protected void onPostExecute(String file_url) {
            pDialog.dismiss();
        }
    }
}

Шаг 5. Добавим название некоторых кнопок

Давайте теперь добавим название кнопок главного Activity в string.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">AndroidAndMySQL</string>
    <string name="btn_viewproduct">View Products</string>
    <string name="btn_addnewproduct">Add New Products</string>
</resources>

Шаг 6. Добавим нужные библиотеки

После того как вы сделаете все что описано выше вы увидите, что фрагменты кода которые работают с JSON не определяются, правильно ведь мы еще не добавили нужную библиотеку json.jar его вы найдете вы прикрепленном исходнике к этому посту.

Давайте добавим эту библиотеку к нашему проекту.

Для начало скиньте её в корень проекта папку libs/json-20090211.jar.

После в Intellij IDEA зайдите в Project Structure:

После того как вы добавите библиотеку нажмите Ok.

Шаг 7. Запускаем.

Теперь смотри, что же получилось.

Урок создан: 10 мая 2013 | Просмотров: 74775 | Автор: Александр Барчук | Правила перепечатки


Добавить комментарий

Добавить комментарий

Ваш e-mail не будет опубликован.

Комментарии:

  • 11 мая 2013 в 12:45

    Сергей

    Пробуем! Спасибо

    • 27 января 2015 в 00:09

      Рукожоп

      Ув. Александр, забросили ли вы этот проект? проблемы есть, как ниже заметили из-за невозможности работать с сетями в главном потоке не работает подробный вывод продуктов, при установке targetsdk=8 ошибка пропадает, форма edit product открывается однако данные из базы не получает, No product found, succes:0

      • 28 января 2015 в 01:58

        Александр Барчук

        Здравствуйте, не проект не заброшен, в группе вк мы про это писали, мы его перезапускаем, уже совсем скоро.

  • 11 мая 2013 в 17:19

    Сергей

    Скажите, столкнулся с такой задачей. На эмуляторе работает, но когда переношу на телефон, не редактирует запись. Выбивает приложение. Подскажите пожалуйста, как с этим справиться?

    • 11 мая 2013 в 17:35

      Александр Барчук

      Опишите, что именно происходит? Только не редактирует, но добавляет и удаляет, или ничего не делает? И какой backend вы используете мой или у себя подняли все?

      • 11 мая 2013 в 17:50

        Сергей

        Да, все делет, кроме обновления записей. Это ошибка здесь «SaveProductDetails» данные отправляет.Данные на сервер уходят, но потом получении ответа, приложение закрываеться с ошибкой.

        • 11 мая 2013 в 17:51

          Сергей

          Главное на эмуляторе ошибок никаких не выводит в лог.

          • 11 мая 2013 в 17:52

            Сергей

            Сервер использовал свой, но с вашими классами

        • 11 мая 2013 в 18:08

          Александр Барчук

          Сергей, напишите мне на почту свой скайп пообщаемся, по этому поводу.

          • 11 мая 2013 в 18:26

            Сергей

            Я отправил Вам письмо на почту Александр.

            • 11 мая 2013 в 20:52

              Александр Барчук

              Сергей, залил у себя на Device работает нормально без сбоев. В чем может быть дело пока не понятно..

              • 12 мая 2013 в 01:20

                Сергей

                Я понял. Спасибо за оперативную помощь) попрбую на другом телефоне, может реально что то с телефоном..

                • 02 апреля 2014 в 12:02

                  Madi

                  Сергей, у вас похоже слишком навороченный телефон — последние версии Андроид не дружат с программой. Александр, как я понял, программа была написана во времена Android 2.3?

      • 27 апреля 2015 в 23:17

        Евгений

        та же проблема сел писать курсовую а тут такой облом

  • 27 мая 2013 в 18:26

    Игорь

    Помогите пожалуйста)
    метод httpClient.execute(httpPost); выдает IOException ошибку…
    сервер WAMP, PHP коды аналогичны вашим

    • 27 мая 2013 в 22:14

      Александр Барчук

      Что именно пишет. Можете полностью ошибку показать? Вы исходники с сайта качали, они работают?

      • 28 мая 2013 в 11:47

        Игорь

        исправил IOException (просто забыл добавить разрешение доступа в интернет)
        но теперь приложение просто выбивает…
        посмотрел по логам — выбивает в строке HttpResponse response = client.execute(post);
        PHP коды работают нормально (проверял- добавлял формы с нужными методами)
        может быть все от того что мой сервер — WAMP?

        • 28 мая 2013 в 12:16

          Александр Барчук

          Хм. Исходник этой статьи в чистом виде запускали работают? Из-за Wamp не должно, хотя сам им не пользовался.

          • 28 мая 2013 в 20:56

            Игорь

            запустил, не заработало(

            • 28 мая 2013 в 22:02

              Александр Барчук

              В скачанных исходниках поменяйте host на ваш я свой удалил и он уже не работает.

              • 28 мая 2013 в 22:18

                Игорь

                host то есть url?

                • 29 мая 2013 в 09:17

                  Александр Барчук

                  Да. Поменяйте его на ваш WAMP сервер.

                  • 29 мая 2013 в 11:39

                    Игорь

                    я менял. менял на 192.168.0.101/… и на localhost/… все равно не сработало(

                  • 29 мая 2013 в 12:34

                    Александр Барчук

                    Пишите мне на Emai будем разбираться.

                    • 29 мая 2013 в 17:56

                      Игорь

                      написал

                    • 13 июня 2013 в 20:13

                      Сергей

                      А можно причину в студию, ибо такая же точно проблема. Выпадает с ошибкой на строке с execute()

          • 25 января 2016 в 20:41

            Вадим

            Добрый вечер. Спасибо большое за урок, но у меня есть проблема. Приложение собрал. К БД подключился. Через форму добавляет, но потом зразу выдает ошибку приложения и закрывается, при этом данные в БД пишутся. То же самое происходит при попытке вывести данные на экран. Помогите пожалуйста разобраться в чем может быть проблема!!!

  • 30 мая 2013 в 12:52

    Игорь

    все работает, спасибо) но как быть с русским текстом?)

    • 30 мая 2013 в 13:29

      Александр Барчук

      Как я понял у вас русские слова выводит так [ ??????? ] правильно?

    • 30 мая 2013 в 13:32

      Александр Барчук

      В этом случаем попробуйте добавить в php файлы где происходит запись в БД эту строку:
      mysql_query(‘SET names cp1251’);
      или проверьте чтобы кодировка БД была cp1251(это лучше, после этого не надо выполнять запрос тот, что выше)

      • 12 августа 2013 в 06:17

        Сергей Миронов

        Извените за глупий ворос, скажите пожайлуста куда конкретней надо вставлять mysql_query(‘SET names cp1251′); базу я менял и создавал непомогает

        • 12 августа 2013 в 11:04

          Александр Барчук

          туда где происходит коннект к БД.

          • 12 августа 2013 в 12:44

            Сергей Миронов

            прошу прощения а можно по конкретней, между какими строчками вставить, прошу непинайте я в PHP полний 0 вот в 35 пришлось учить новый язик. Буду очень благодарен за ответ, так сказать за тычёк носом в строчку

            0) {
            $response[«products»] = array();

            while ($row = mysql_fetch_array($result)) {
            $product = array();
            $product[«pid»] = $row[«pid»];
            $product[«name»] = $row[«name»];
            $product[«price»] = $row[«price»];
            $product[«created_at»] = $row[«created_at»];
            $product[«updated_at»] = $row[«updated_at»];

            array_push($response[«products»], $product);
            }
            $response[«success»] = 1;

            echo json_encode($response);
            } else {
            $response[«success»] = 0;
            $response[«message»] = «No products found»;

            echo json_encode($response);
            }
            ?>

            • 12 августа 2013 в 12:46

              Сергей Миронов

              или где то здесь?

              $response = array();

              require ‘db_connect.php’;

              $db = new DB_CONNECT();

              mysql_query(‘SET names cp1251’);

              $result = mysql_query(«SELECT *FROM products») or die(mysql_error());

              if (mysql_num_rows($result) > 0) {

              • 12 августа 2013 в 15:09

                Александр Барчук

                Да все верно!

                • 12 августа 2013 в 19:24

                  Сергей Миронов

                  Не помогло и базу новую создал и в запрос вставлял одним словом в тупике, на сервер данние передаються «??????»

    • 16 августа 2013 в 13:46

      v0r0n

      пример отличный. вот только с русским языком пришлось бубнов оттанцевать,..

      1. Вся структура на мускуле создается в utf8_general_ci
      2. в файл db_connect.php после строки
      $con = mysql_connect(DB_SERVER, DB_USER, DB_PASSWORD) or die(mysql_error());
      вставляем строку:
      mysql_set_charset(‘utf8’, $con);

      это решает получение данных но пока еще не вставку

      шаманим далее:
      3. В классе NewProductActivity заменяем
      params.add(new BasicNameValuePair(«name», name));
      на
      params.add(new BasicNameValuePair(«name», URLEncoder.encode(name, «UTF-8»))));

      с подключением соответствующих библиотек я думаю справитесь сами.

      с обновлением тоже самое.

      • 16 августа 2013 в 13:49

        v0r0n

        забыл :(
        в файл create_products.php
        строки типа: $description = $_POST[‘description’];
        заменяем на : $description = urldecode($_POST[‘description’]);
        Все остальное по аналогии. Вот теперь все

      • 17 ноября 2013 в 18:31

        User

        После добавления и правки строки (неправильные кавычки и лишняя закрывающая скобка) Eclipse ругается вот так:
        Unhandled exception type UnsupportedEncodingException
        т.е. UTF-8 не поддерживается? Или нужно изменить написание UTF-8?

        • 02 апреля 2014 в 12:05

          Madi

          Не нужно менять на URLEncoder.encode(name, «UTF-8»), достаточно поменять на URLEncoder.encode(name)

  • 30 мая 2013 в 13:28

    Александр Барчук

    Ребята как выяснилось одним из читателей урока, WAMP сервер лучше не использовать.

    • 30 мая 2013 в 17:02

      Игорь

      Почему же?) можно использовать, только нужно добавлять :80 после строки «localhost»

      • 30 мая 2013 в 18:15

        Александр Барчук

        А, понятно. Я не так первый раз вас понял.

        • 13 июня 2013 в 15:21

          Талгат

          Здравствуйте! хотел спросить
          List params = new ArrayList();
          params.add(new BasicNameValuePair(«pid», pid)); что озночает nameValuePair
          заранее большое спасибо!

          • 13 июня 2013 в 19:03

            Александр Барчук

            Пара ключ значение. Для дальнейшей записи в БД. Первое ключ — колонка в бд, второе значение.

  • 13 июня 2013 в 21:52

    volchenko

    Интересная особенность работы execute метода. В том виде, в котором он описан выше работает только до sdk 9.0. При равном или большем вызывает ошибку android.os.StrictMode$AndroidBlockGuardPolicy
    Решается проблема тремя путями. 1. Установить target_sdk=8 или 2. установить strictMode правильно
    if (android.os.Build.VERSION.SDK_INT > 9) {
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
    }
    или 3. Переписать код выше с использованием многопоточности и отделить UI поток, от сетевых потоков.

    Как мне кажется третий путь будет более правильный.
    Ждем новую статью реализованную по третьему пути. :)

    • 03 апреля 2014 в 06:47

      Madi

      Добрый день! Хотелось бы переписать под kitkat — какие наводки по 3 пункту?

  • 16 июня 2013 в 16:15

    Faust

    Выдает ошибку в этой строчке:
    new LoadAllProducts().execute();

  • 17 сентября 2013 в 22:43

    Игорь

    К сожалению, приложение вылетает, останавливается в new LoadAllProducts().execute();

    • 18 сентября 2013 в 11:26

      Александр Барчук

      Вы описали Server-Side или просто запустили exaple с этого урока?

      • 23 сентября 2013 в 23:50

        Игорь

        Свой сервер и все пути переписал соответственно.

        • 25 января 2016 в 20:55

          Вадим

          Напишите пожалуйста как решили проблему!

  • 06 октября 2013 в 14:08

    Александр

    Добрый день. Отличный урок, как раз то что искал. Возникла проблема, добавил json библиотеку в проект, но при компиляции все равно выдает ошибку на строке
    JSONParser jParser = new JSONParser();
    ошибка
    java: cannot find symbol
    symbol: class JSONParser
    location: class ru.feenix.orders.loginActivity

    Не могу понять почему он не видит этот тип. Проект под андроид 4.0

  • 14 ноября 2013 в 09:59

    Юрий

    Люди, дайте пример с использованием многопоточности и отделением UI потока, от сетевых потоков.

    • 14 ноября 2013 в 17:30

      Юрий

      Извините, я так понял — многопоточность уже реализована.

      • 24 ноября 2013 в 00:24

        archie

        С чего вы взяли, что многопоточность здесь реализована?

  • 15 ноября 2013 в 09:37

    Ок

    Подскажите, что я делаю не так, если у меня вот такая ошибка:
    Error parsing data org.json.JSONException: Value <table of type java.lang.String cannot be converted to JSONObject
    Все сделал точно по уроку

    • 03 ноября 2014 в 00:02

      alex

      у меня в db_config.php для базы стоял пароль, но денвер поставил все с пустым паролем для mysql. После редактирования db_config.php (‘DB_PASSWORD’, «»). все заработало, спасибо за урок

  • 25 ноября 2013 в 11:30

    Нурик

    у меня не получается соединение с сервером , как можно ? Скажите пожалуйста !!!

    • 25 ноября 2013 в 11:55

      Нурик

      я написал так : private static String url_all_products = «http://127.0.0.1/androidTestLessons/admin/get_all_products.php»;

      • 25 ноября 2013 в 11:59

        Александр Барчук

        Тут нужно смотреть, какая именно ошибка. Попробуйте скачать исходники, и проверить их.

        • 25 ноября 2013 в 12:25

          Нурик

          я этот же приложений запускал через Wamp сервер , все отлично работает
          код: private static String url_all_products = «http://10.0.2.2/androidTestLessons/admin/get_all_products.php»;
          В общем я хочу сделать админку с php , админка будут добавить , изменить , удалить уроки.А приложение будут только читать из базы.Приложение работает через wamp server , но админка нет(админка через Denwer работают )) ),что мне делать?

  • 21 декабря 2013 в 11:00

    Дмитрий

    я на Oracle VM VirtualBox развернул виртуалку с андроидом, в настройках сети тип подключения прописал — виртуальный адаптер хоста. Андроид пингует 192.168.56.1., далее я в db_config.php прописал свой адрес

    и на виртуалке у меня ошибка :((
    The application AndroidAndMySQL (process com.devcolibri.androidandmysql) has stopped unexpectedly. Please try again.

    что я не так сделал?

    • 21 декабря 2013 в 13:05

      Дмитрий

      пробовал и так define(‘DB_SERVER’, «192.168.56.1»); и так define(‘DB_SERVER’, «192.168.3.64»);, ошибка таже :(

  • 31 декабря 2013 в 14:06

    giddig1@tut.by

    Скажите пожалуйста, как выглядит общая структура работы приложения? Android приложение>Apache сервер>PHP скрипт>MySQL. Не ругайтесь громко, я не силён в этом:(

  • 15 января 2014 в 17:19

    Владимир

    Я вам очень благодарен за статью, она мне нереально помогла!

  • 26 января 2014 в 20:43

    archie

    Код в исходных файлах, в некоторых местах отличается от статьи.

  • 30 января 2014 в 17:42

    Александр

    Выдает ошибку JSONParser cannot be resolved to a type

  • 08 февраля 2014 в 10:49

    Алексей

    Извините, не понял, где найти исходники, прикрепленные к посту?

  • 16 февраля 2014 в 15:50

    Максим

    Как правильно делать подобного рода действия во ViewPager с фрагментами(JSON парсинг и прочее)
    Заранее спасибо за ответ!

  • 16 февраля 2014 в 22:05

    Даниил

    Народ! Помогите пожалуйста, замучился уже. Проблема такая приложение запускатся но когда нажимаешь на View Product выдает ошибку в приложении и выкидывает. Базу сделал на Локалке на Денвере. Работаю в Еклипс. Ругается на com.devcolibri.androidandmysql .В Андроиде и Джава недавно. Что я делаю не правильно? Все делал по уроку по уроку.

    • 02 апреля 2014 в 12:12

      Madi

      Наверно вам wamp тут не поможет, нужно вставить фактический адрес в файле db_config.php. Эти данные видны только для того браузера через чей ip хост был развернут. При эмуляции android получает другой ip.

  • 25 марта 2014 в 17:17

    Madi

    Приложение вылетает при попытке соединения с mysql. В самом браузере все открывается, и я подумал, что ошибка в коде приложения. Так и оказалось. После проверки всех функции try-catch-ом, выяснил, что во всех активити проблема кроется в protected String doInBackground(String… args). Как решить эту проблему?

    • 27 марта 2014 в 21:05

      Madi

      Все исправил, это из-за виртуального хоста wamp. Перекинул файлы на сервер хостинга — все работает (видит весь список, добовляет), кроме обновление данных, после выбора пункта, этот(EditProduct) activity вылетает. Попробовал изменить все варианты get_product_details.php, и скорее всего, дело в EditProductActivity.
      P.S. Будет правильно писать mysql_query(‘SET names utf8’);
      после $db = new DB_CONNECT();

      • 27 марта 2014 в 23:47

        Александр Барчук

        Спасибо за помощь. На основании всех комментариев, мы перепишем данный урок.

        • 28 марта 2014 в 21:28

          Madi

          Цены этой статье не будет, если добавите форму авторизации и исправите все ошибки.
          P.S. Я начал изучать json и php ради android-а. Эх, как же все было бы просто, если работала JDBC…

        • 11 апреля 2014 в 14:58

          AndroidProgrammer

          Можно ли сделать так чтобы всех записи можно просмотреть но не редактировать Ну например есть кнопка «просмотр» нажимаеш на кнопку а там ListView все записи которые мы создали и там выбераем нужную нам информацию только для просмотра

          • 24 мая 2014 в 11:42

            Madi

            да, меняешь нужные edittext на textview и имена соответственно.

  • 26 апреля 2014 в 17:19

    Дмитрий

    JSONObject json = jParser.makeHttpRequest(url_all_products, «GET», params); — ругается на эту строку в чем может быть причина

    • 26 апреля 2014 в 17:47

      Александр Барчук

      Нужно смотреть на что именно ругается.

      • 27 апреля 2014 в 05:54

        Дмитрий

        На makehttpRequest

    • 09 сентября 2016 в 18:36

      Денис

      Происходит запуск runOnUiThread(new Runnable(), выполнение кода в UI-потоке, а потом сетевые запросы, а этого делать нельзя.
      Убираем эту часть.

  • 14 мая 2014 в 01:47

    Ярослав

    Здравствуйте! Такой вопрос, когда при обновлении продукта что-то не получается и мы переходим по else к логическому «продукт не обновлен» не получается вывести об этом сообщение при помощи Toast. Прога тут же вылетает с ошибкой! Как это можно решить?

    • 20 мая 2014 в 19:53

      Максим М.

      Toast надо ставить в метод который закрывает диалоговое окно. У меня так работает.

  • 19 мая 2014 в 14:42

    Максим М.

    Спасибо очень полезный урок. И главное РНР описан. Подскажите пожалуйста как можно сделать кнопку обновления продуктов когда находишся в окне просмотра всех продуктов или лучше, чтоб продукты обновлялись (добовлались, идалялись) по мере появления/удаления их на сервере. Т.е. если один человек видит список и ктото добавил/удалил продукт, продукт в списке автоматом появился/исчез.

    • 20 мая 2014 в 08:59

      Александр Барчук

      В этом случае вам каждый раз нужно получать JSON с сервера, и обновлять весь список.

      • 20 мая 2014 в 19:51

        Максим М.

        Это сильно загрузит устройство? Подскажите как это сделать, пожалуйста. Я пробовал делать кнопку в AllProducts.xml с запуском new LoadAllProducts().execute(); , но список дополняется темже списком поверх кнопки и кнопку уже не видно.

      • 31 мая 2014 в 22:13

        Иван

        А можно код? А то я не совсем понял работу AsyncTask и приложение вылетает. Каким образом обновлять ListView в активити по заданому времени?

  • 24 июня 2014 в 11:09

    Дмитрий

    Доброе время суток!
    Ошибка такая:
    06-24 08:01:55.115: E/Buffer Error(4586): Error converting result java.lang.NullPointerException: lock == null
    06-24 08:01:55.255: E/JSON Parser(4586): Error parsing data org.json.JSONException: End of input at character 0 of

    Какие мысли есть по этому поводу?

    • 24 июня 2014 в 11:11

      Дмитрий

      Приложение крэшится с этой ошибкой при попытке прочитать базу и при попытке создать новый продукт

    • 24 июня 2014 в 12:01

      Дмитрий

      с той ошибкой понятно стало — эмулятор не коннектился к локалхосту.
      Со смарта другая ошибка:
      06-24 15:59:40.955: E/JSON Parser(7762): Error parsing data org.json.JSONException: Value Access of type java.lang.String cannot be converted to JSONObject
      06-24 15:59:40.956: W/dalvikvm(7762): threadid=12: thread exiting with uncaught exception (group=0x40d439a8)
      06-24 15:59:40.958: E/AndroidRuntime(7762): FATAL EXCEPTION: AsyncTask #1
      06-24 15:59:40.958: E/AndroidRuntime(7762): java.lang.RuntimeException: An error occured while executing doInBackground()
      06-24 15:59:40.958: E/AndroidRuntime(7762): at android.os.AsyncTask$3.done(AsyncTask.java:299)

      • 09 апреля 2015 в 12:02

        Han

        Кто-нибудь решил проблему: at android.os.AsyncTask$3.done(AsyncTask.java:278)

  • 02 июля 2014 в 23:26

    Александр

    Подскажите, пожалуйста, как решить проблему с вылетом программы при выборе продукта в All Products?

    • 08 февраля 2015 в 12:26

      Ирина

      Юзать эмулятор с android 2.2 или переписать код с использованием AsyncTask.

  • 03 августа 2014 в 09:58

    Yustas

    Здравствуйте. Я новичок в Дроид среде. 2 дня мучаюсь на Вашем примере отобразить картинки в ListView c URL взятые с базы. Буду премного благодарен за любую помощь.

  • 13 октября 2014 в 19:32

    Sergiy

    Здравствуйте, у меня проблема с кодировкой кирилиці: сервер Денвер, кодировка БД ut8_general_ci. При подключении к БД ставлю кодировку cp1251, в результате:
    {
    «id»: «2»,
    «url»: «about»,
    «title»: null
    },
    {
    «id»: «3»,
    «url»: «new_student»,
    «title»: null
    },
    вместо украинских символов получаю null

    • 10 января 2015 в 04:25

      Мимо проходил

      Спасибо большое, за проделанную работу!!!
      Несколько советов, тем кто делает отправку прием данных на php сервер:
      1) Здесь приложение обращается к серверу посредством POST и GET запросов. Если будете делать с реальным сайтом приложение, то на бэкэнде надо проверять чтобы в этих запросах не было символов которые могут получить доступ к БД.
      2) Все кодировки ставьте utf8, не один час времени был потрачен на исправлении этой мелочи. Если на сервере utf8 то и на клиентской части выбираете utf8
      3) В комментариях иногда пишут не корректные ответы. Поэтому советую прежде, чем воспользоваться этим советом прочитайте о том или ином методе(функции) в интернете.
      4) Упорствуйте и будет Вам счастье.
      Александру Большое Спасибо, за Ваш труд.

  • 29 октября 2014 в 16:10

    Владимир

    Спасибо за статью. Но у меня не работает подробный вывод продукта, добавление и вывод всех работает, а вот подробное нет. Вот все ошибки при переходе на определенный продукт. Нашел что из за ошибки NetworkOnMainThreadException нельзя работать с инет в главном потоке(

    10-29 16:05:44.705: E/AndroidRuntime(29044): FATAL EXCEPTION: main
    10-29 16:05:44.705: E/AndroidRuntime(29044): Process: com.devcolibri.androidandmysql, PID: 29044
    10-29 16:05:44.705: E/AndroidRuntime(29044): android.os.NetworkOnMainThreadException
    10-29 16:05:44.705: E/AndroidRuntime(29044): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1239)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at libcore.io.IoBridge.connect(IoBridge.java:112)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at java.net.Socket.connect(Socket.java:873)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:125)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:144)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:367)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:519)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:497)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at com.devcolibri.parser.JSONParser.makeHttpRequest(JSONParser.java:68)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at com.devcolibri.androidandmysql.EditProductActivity$GetProductDetails$1.run(EditProductActivity.java:127)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at android.os.Handler.handleCallback(Handler.java:733)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at android.os.Handler.dispatchMessage(Handler.java:95)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at android.os.Looper.loop(Looper.java:157)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at android.app.ActivityThread.main(ActivityThread.java:5867)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at java.lang.reflect.Method.invokeNative(Native Method)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at java.lang.reflect.Method.invoke(Method.java:515)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:674)
    10-29 16:05:44.705: E/AndroidRuntime(29044): at dalvik.system.NativeStart.main(Native Method)

    • 11 декабря 2014 в 21:32

      Аноним

      Та же ситуация

    • 11 декабря 2014 в 21:48

      Vlad

      Попробуй в onPostExecute() задать текст для Edit’ов

    • 07 февраля 2015 в 14:44

      Ирина

      та же ситуация! кто справился, поделитесь решением проблемы, диплом горит :(

    • 23 марта 2015 в 01:59

      Алексей

      Проблема все еще актуальная, был бы признателен за помощь :)

      • 16 июня 2016 в 00:03

        Роман

        Такая же ерунда, кто решил???

  • 05 января 2015 в 15:02

    Александр

    у создаваемого jsonParser нет метода makeHttpRequest, и соответственно он подсвечивается красным, что делать? пишу в android studio

    • 25 января 2015 в 15:29

      Ирина

      +++ та же ситуация. и вообще не могу понять, как в андроид студии подключить json. распишите по шагам, пожалуйста.

      • 07 февраля 2015 в 14:39

        Ирина

        Разобралась с подключением. В Gradle добавляется новый библиотечный модуль.

  • 25 января 2015 в 16:29

    paranur

    У меня Unfortunately, AndroidAndMySQL has stopped. Что это?

    • 07 февраля 2015 в 14:38

      Ирина

      Выбивает при попытке перехода к деталям продукта. Юзаю Ваши файлы, может там есть какие-то недочеты? Все остальное работает! Прошу помощи тех, у кого работают исходники.

      • 05 июля 2015 в 22:07

        Виктор

        Решили как то эту проблему? У меня тоже вылетает.

  • 06 марта 2015 в 12:01

    Артём

    Читал комменты и думал, что у меня НЕ получится… т.к. я не создал ни одного приложения для андроида самостоятельно. Мало того я и эклипс то кое-как настроил. Но представьте, как я рад, когда увидел, что всё работает. И записи в БД на хостинге обновляются и добавляются)))
    Большое спасибо автору!

  • 22 марта 2015 в 04:15

    Алексей

    Добрый день, подскажите как подключить JSONParser, добавил в Gradle » compile files(‘libs/AndroidAndMySQL/libs/json-20090211.jar’)» но почему то не работает.

    Везде ругается на на JSONParser jParser = new JSONParser(); -> Cannot resolve symbol ‘JSONParser’

    И та же проблема «import net.netai.socium.parser.JSONParser;» ругается на фразу parser. Помогите решить проблему пожалуйста :)

    С Уважением Алексей

    • 22 апреля 2015 в 09:01

      Amrel

      Такая же проблема Android Studio ругается на строку: JSONObject json = jParser.makeHttpRequest(url_all_products, «GET», params); библиотеку 20090211.jar подключил. Кто нибудь решил эту проблему? В eclipse’е все работает.

      • 19 мая 2015 в 14:57

        Max

        Решил проблему созданием нового класса JSONParser.
        Содержание класса:
        package *адрес Вашего пакета*;

        import android.util.Log;
        import org.apache.http.HttpEntity;
        import org.apache.http.HttpResponse;
        import org.apache.http.NameValuePair;
        import org.apache.http.client.ClientProtocolException;
        import org.apache.http.client.entity.UrlEncodedFormEntity;
        import org.apache.http.client.methods.HttpGet;
        import org.apache.http.client.methods.HttpPost;
        import org.apache.http.client.utils.URLEncodedUtils;
        import org.apache.http.impl.client.DefaultHttpClient;
        import org.json.JSONException;
        import org.json.JSONObject;

        import java.io.*;
        import java.util.List;

        public class JSONParser {

        static InputStream is = null;
        static JSONObject jObj = null;
        static String json = «»;

        // constructor
        public JSONParser() {

        }

        // function get json from url
        // by making HTTP POST or GET method
        public JSONObject makeHttpRequest(String url, String method,
        List params) {

        // Making HTTP request
        try {

        // check for request method
        if(method == «POST»){
        // request method is POST
        // defaultHttpClient
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setEntity(new UrlEncodedFormEntity (params));

        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        is = httpEntity.getContent();

        }else if(method == «GET»){
        // request method is GET
        DefaultHttpClient httpClient = new DefaultHttpClient();
        String paramString = URLEncodedUtils.format (params, «utf-8»);
        url += «?» + paramString;
        HttpGet httpGet = new HttpGet(url);

        HttpResponse httpResponse = httpClient.execute(httpGet);
        HttpEntity httpEntity = httpResponse.getEntity();
        is = httpEntity.getContent();
        }

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

        try {
        BufferedReader reader = new BufferedReader(new InputStreamReader (
        is, «iso-8859-1»), 8);
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null) {
        sb.append(line + «\n»);
        }
        is.close();
        json = sb.toString();
        } catch (Exception e) {
        Log.e («Buffer Error», «Error converting result » + e.toString ());
        }

        // try parse the string to a JSON object
        try {
        jObj = new JSONObject (json);
        } catch (JSONException e) {
        Log.e(«JSON Parser», «Error parsing data » + e.toString());
        }

        // return JSON String
        return jObj;

        }
        }

        • 19 мая 2015 в 14:59

          Max

          П.С. Работает на реальном сервере :) парсит данные из приложения в базу и обратно

        • 21 мая 2015 в 20:10

          Роман

          Кто-нибудь подскажет? У меня Android Studio и с этим классом тоже пишет E/JSON Parser﹕ Error parsing data org.json.JSONException: Value <!DOCTYPE of type java.lang.String cannot be converted to JSONObject.
          Ругается получается вот на это:
          try {
          BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
          StringBuilder sb = new StringBuilder();
          String line = null;
          while ((line = reader.readLine()) != null) {
          sb.append(line).append("\n");
          }
          is.close();
          json = sb.toString();
          } catch (Exception e) {
          Log.e("Buffer Error", "Error converting result " + e.toString());
          }

          // пробуем распарсит JSON объект
          try {
          jObj = new JSONObject(json);
          } catch (JSONException e) {
          Log.e("JSON Parser", "Error parsing data " + e.toString());
          }
          Это без блока try в AllProductsActivity.java, а если блок try расскоментирую, то вылетает с ошибкой при нажатии на просмотр продуктов.

  • 27 апреля 2015 в 23:03

    Евгений

    помогите очень нужен данный проект. на емуляторе работает а на девайсе нет не могу понять в чем проблема.

  • 01 мая 2015 в 19:38

    Юлий

    Помогите плз, мне нужно получить по id json строку с сервера. Серверную часть сделал. А вот как конкретно отправить и получить json строку?

  • 14 мая 2015 в 09:10

    AI

    Спасибо большое. Супер. Могли бы такое приложение на андроиде с применением протобуф (Google Protcol Buffers) выпустить показать.

    Благодарю.

  • 04 июня 2015 в 12:25

    Askai

    За материал огромнейшее спасибо! Эта тема не потеряла своей актуальности до сих пор)

    Совет тем, кто только начал работать через Android с MySQL:
    в php скриптах за пределами пхп кода не должно быть никаких тегов html

  • 02 июля 2015 в 18:29

    Дима

    Подскажите проблема которая не раз описывалась, андроид студия ругается на строку JSONObject json = jParser.makeHttpRequest(url_all_products, «GET», params);
    Библиотеку подключил, в JSONObject нет метода makeHttpRequest.

    Как это исправить?

  • 02 июля 2015 в 19:58

    Виктор

    Кто то может выложить сборку, под сервер на UTF.

  • 05 июля 2015 в 22:04

    Виктор

    Подскажите, у всех работает форма редактирование элемента списка listview. У меня вылетает на этом.

  • 09 ноября 2015 в 14:22

    антон

    Подскажите люди добрые начинающему, в каком моменте листвью(lv который) присваивает данные которые мы парсим?

  • 03 февраля 2016 в 20:18

    Артем

    Здравствуйте! Подскажите пожалуйста, в какой программе создавать андроид приложения? Спасибо!

    • 20 марта 2016 в 19:58

      Арсланали

      АндроидСтудио используйте

  • 09 февраля 2016 в 01:59

    антон

    Здравствуйте! Помогите пожалуйста, с сайта выходит такого вида строка {«otdel»:[{«_id»:»1″},{«_id»:»2″},{«_id»:»3″}],»success»:1}{«dolzno»:[{«_id»:»1″},{«_id»:»2″},{«_id»:»4″}]}{«spec»:[{«_id»:»1″},{«_id»:»2″},{«_id»:»3″}],»success»:1} , когда я ее пытаюсь распарсить то получается вытащить только первый объект (otdel), если очередность поменять в php файле, то программа перестанет отображать данные пока не начнешь обращаться именно к первому объекту json(от его названия не зависит, проверял). Все голову себе сломал уже((

  • 09 февраля 2016 в 23:52

    Алексей

    Подскажите, на телефоне вылетает при просмотре списка:
    E/Buffer Error﹕ Error converting result java.lang.NullPointerException: lock == null
    E/JSON Parser﹕ Error parsing data org.json.JSONException: End of input at character 0 of
    E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
    Process: com.devcolibri.androidandmysql, PID: 28551
    java.lang.RuntimeException: An error occured while executing doInBackground()

  • 25 февраля 2016 в 06:42

    AlexTank

    Добрый день всем! Спасибо за подробные уроки авторам проекта.
    Начал пробовать делать этот урок и не могу подключить библиотеку к Android Studio из приложения. Когда выбираю ее из project structure в папке libs не отображается ни одного файла. Когда вручную ее прописал, она там появилась, но все равно при компиляции вылазит ошибка Error:(7, 29) error: package com.devcolibri.parser does not exist
    Помогите разобраться что к чему.

  • 07 марта 2016 в 13:29

    Косня

    Здравствуйте, Александр. Спасибо вам за столь хорошие уроки, благодаря вашим уроком написал курсовую на JAVA. И вот решил что диплом мой будет на Android, но возникла огромная проблема: не мог найти грамотных уроков взаимодействия Android и MySQL. В итоге наткнулся на эту статью, но по какой то причине некоторые библиотеки не импортируются, да и вообще некоторые куки кода не совсем понятны. Я хотел спросить будет ли видео переиздание этой статьи?

  • 29 марта 2016 в 22:51

    Сева Сивимурдиев

    Для тех, у кого не работает EditProductActivity:
    В этом классе, в методе onCreate, оберните вызов «new GetProductDetails().execute()» в новый поток — создаете new Thread,а execute() запихиваете в run(). Джава ругается, т.к. происходит работа с сетью в основном потоке, что может привести к замедлению выполнения всей программы.
    Еще, скорее всего, вам придется повозиться с классом сохранения в этой же активности. Там необходимо инициализировать ваши Edit поля. Думаю, вы справитесь, успехов! c:

    • 06 августа 2016 в 00:07

      tilesto

      Спасибо, а можно продолжение?) Ругается что-то то на одно, то на другое. Эти потоки явно перехимичены. Может кто-нибудь решится и обновит статью?)

  • 06 августа 2016 в 10:22

    Альберт

    Error:(4, 23) java: package org.apache.http does not exist ( Не пойму что за пак нужно добавлять ?)

    • 08 сентября 2016 в 19:57

      Денис

      Открываем Gradle Script->build.gradle(Module: app)-> дописываем в android {…
      useLibrary ‘org.apache.http.legacy’