Как работать с 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 | Просмотров: 84784 | Автор: Александр Барчук | Правила перепечатки


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

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

Ваш 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’]);
        Все остальное по аналогии. Вот теперь все

        • 24 мая 2017 в 23:26

          Аноним

          Провел весь день в поисках косяка у себя, ибо использовал похожую конструкцию, облазил фигову тучу статей, и под ночь наткнул на твой коммент, спасибо тебе, ты спас мой сон

      • 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 февраля 2017 в 18:50

      Александр

      Не помогло, все равно кидает ошибку, как её решить, при переходе на любой активити с всепродукты?

  • 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’

  • 31 января 2017 в 14:46

    Дмитрий

    Доброго времени суток
    Скачал ваш проект,поднял denwer не могу подключиться к базе
    private static String url_all_products = «http://127.0.0.1/test1/get_all_products.php»;
    подскажите как с виртуального девайса подключиться к базе.Все стоит на локалке

  • 09 февраля 2017 в 05:51

    Александр

    Всем привет!
    Ошибка NetworkOnMainThreadException есть решение в активити ЕдитПродукт.
    Там на самом деле две ошибки, возможно на предыдущих версиях андроид, они не выходили, но сейчас на 6 версии ексепшены кидает.
    Остальные модули вроде в порядке, а в EditProductActivity: нужно парочку изменений сделать в class GetProductDetails:
    1 . убрать блок % runOnUiThread(new Runnable() { public void run() { %(не забудьте про закрывающие скобки.
    2. перенести инициализацию // продукт с pid найден
    // Edit Text
    txtName = (EditText) findViewById(R.id.inputName);
    txtPrice = (EditText) findViewById(R.id.inputPrice);
    txtDesc = (EditText) findViewById(R.id.inputDesc);
    в public void onCreate(.

    3. Перенести // покаываем данные о продукте в EditText
    txtName.setText(product.getString(TAG_NAME));
    txtPrice.setText(product.getString(TAG_PRICE));
    txtDesc.setText(product.getString(TAG_DESCRIPTION));
    Из protected String doInBackground(String[] args) в protected void onPostExecute(.

    После этих манипуляций все должно работать, я еще на всякий случай добавил в catch NetworkOnMainThreadException, в случае его срабатывания переходить обратно на Активити AllProductsActivity, но это не обязательно.

  • 18 апреля 2017 в 22:54

    Сергеевских

    Добавил Вашу либу в структуру проекта, пишу импорт, о идет ругань на com.devcolibri.parser.JSONParser; — подчеркивает красным . Где я туплю?

  • 26 апреля 2017 в 18:04

    Александр

    Коллеги, в упор не вижу ссылку с библиотекой json.jar. Где ее взять?

    • 12 мая 2017 в 16:22

      Аноним

      Кнопка «скачать» в самом верху этой страницы, там в архиве этот класс лежит

      • 12 мая 2017 в 17:12

        Мах

        Могу только с сожалением привести сообщение отладчика An error occured while executing doInBackground(). Как дальше отлаживаться? Если в браузере ввожу строку url_all_products, то получаю номальный ответ от сервера в формате json, а вот эмулятор андройда в студии пишет, что «к несчастью приложение закрылось»… что делать?

  • 13 мая 2017 в 19:52

    Владимир

    ошибка
    Error:The processing instruction target matching «[xX][mM][lL]» is not allowed.
    Error:Exception while parsing the supplied manifest file C:\Users\ven\AndroidStudioProjects\AndroidAndMySQL\app\src\main\AndroidManifest.xml
    > The processing instruction target matching «[xX][mM][lL]» is not allowed.
    Помогите пожалуйста

  • 23 августа 2017 в 21:31

    boss.rus

    скачал файлы проекта по ссылке сверху страницы. первым делом начал ругаться на то, что в protected String doInBackground мы обращаемся к элементам UI из асинхронного потока:
    String name = inputName.getText().toString();
    String price = inputPrice.getText().toString();
    String description = inputDesc.getText().toString();
    выдаёт ошибку «Method getText must be called from the UI thread, currently inferred thread is worker less… (Ctrl+F1)
    This inspection looks at Android API calls that have been annotated with various support annotations (such as RequiresPermission or UiThread) and flags any calls that are not using the API correctly as specified by the annotations.»

    ну да это ладно. для текста просто присвоил переменным явные значения…

    и всё равно фигу. выдаёт следующее:

    !!! JUnit version 3.8 or later expected:

    java.lang.NoClassDefFoundError: junit/textui/TestRunner
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at com.intellij.rt.execution.junit.JUnitStarter.getAgentClass(JUnitStarter.java:275)
    at com.intellij.rt.execution.junit.JUnitStarter.junitVersionChecks(JUnitStarter.java:231)
    at com.intellij.rt.execution.junit.JUnitStarter.canWorkWithJUnitVersion(JUnitStarter.java:216)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:75)
    Caused by: java.lang.ClassNotFoundException: junit.textui.TestRunner
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    … 18 more

    Process finished with exit code -3