轉自:http://blog.csdn.net/welovesunflower/article/details/7776438
我們先來看一個簡單的Android app例子(這裏是一個商品存貨清單項目),在Android程序中,我們可以訪問(call)PHP腳本來執行簡單的CRUD操作(創建,讀取,更新,刪除)。爲了使你對它的體系結構有一個大概的瞭解,這裏先說一下它是怎麼工作的。首先你的Android項目訪問(call)PHP腳本來執行一條數據操作,我們稱它爲“創建”。然後PHP腳本連接MySQL數據庫來執行這個操作。這樣,數據從Android程序流向PHP腳本,最終存儲在MySQL數據庫中。
好了,讓我們來深入的看一下。
請注意:這裏提供的代碼只是爲了使你能簡單的連接Android項目和PHP,MySQL。你不能把它作爲一個標準或者安全編程實踐。在生產環境中,理想情況下你需要避免使用任何可能造成潛在注入漏洞的代碼(比如MYSQL注入)。MYSQL注入是一個很大的話題,不可能用單獨的一篇文章來說清楚,並且它也不在本文討論的範圍內,所以本文不以討論。
1. 什麼是WAMP Server
WAMP是Windows,Apache,MySQL和PHP,Perl,Python的簡稱。WAMP是一個一鍵安裝的軟件,它爲開發PHP,MySQL Web應用程序提供一個環境。安裝這款軟件你相當於安裝了Apache,MySQL和PHP。或者,你也可以使用XAMP。
2. 安裝和使用WAMP Server
你可以從http://www.wampserver.com/en/下載WAMP,安裝完成之後,可以從開始->所有程序->WampServer->StartWampServer運行該程序。
在瀏覽器中輸入http://localhost/來測試你的服務器是否安裝成功。同樣的,也可以打開http://localhost/phpmyadmin來檢驗phpmyadmin是否安裝成功。
3. 創建和運行PHP項目
現在,你已經有一個能開發PHP和MYSQL項目的環境了。打開安裝WAMP Server的文件夾(在我的電腦中,是C:\wamp\),打開www文件夾,爲你的項目創建一個新的文件夾。你必須把項目中所有的文件放到這個文件夾中。
新建一個名爲android_connect的文件夾,並新建一個php文件,命名爲test.php,嘗試輸入一些簡單的php代碼(如下所示)。輸入下面的代碼後,打開http://localhost/android_connect/test.php,你會在瀏覽器中看到“Welcome,I am connecting Android to PHP,MySQL”(如果沒有正確輸入,請檢查WAMP配置是否正確)
test.php
- <?php
- echo"Welcome, I am connecting Android to PHP, MySQL";
- ?>
在本教程中,我創建了一個簡單的只有一張表的數據庫。我會用這個表來執行一些示例操作。現在,請在瀏覽器中輸入http://localhost/phpmyadmin/,並打開phpmyadmin。你可以用PhpMyAdmin工具創建數據庫和表。
創建數據庫和表:數據庫名:androidhive,表:product
- CREATE TABLE products(
- pid int(11) primary key auto_increment,
- name varchar(100) not null,
- price decimal(10,2) not null,
- description text,
- created_at timestamp default now(),
- updated_at timestamp
- );
現在,真正的服務器端編程開始了。新建一個PHP類來連接MYSQL數據庫。這個類的主要功能是打開數據庫連接和在不需要時關閉數據庫連接。
新建兩個文件db_config.php,db_connect.php
db_config.php--------存儲數據庫連接變量
db_connect.php-------連接數據庫的類文件
db_config.php
- <?php
- /*
- * All database connection variables
- */
- define('DB_USER', "root"); // db user
- define('DB_PASSWORD', ""); // db password (mention your db password here)
- define('DB_DATABASE', "androidhive"); // database name
- define('DB_SERVER', "localhost"); // db server
- ?>
這裏的DB_USER DB_PASSWORD要換成自己數據庫對應的用戶名、密碼
db_connect.php
- <?php
- /**
- * A class file to connect to database
- */
- class DB_CONNECT {
- // constructor
- function __construct() {
- // connecting to database
- $this->connect();
- }
- // destructor
- function __destruct() {
- // closing db connection
- $this->close();
- }
- /**
- * Function to connect with database
- */
- function connect() {
- // import database connection variables
- require_once __DIR__ . '/db_config.php';
- // Connecting to mysql database
- $con = mysql_connect(DB_SERVER, DB_USER, DB_PASSWORD) or die(mysql_error());
- // Selecing database
- $db = mysql_select_db(DB_DATABASE) or die(mysql_error()) or die(mysql_error());
- // returing connection cursor
- return $con;
- }
- /**
- * Function to close db connection
- */
- function close() {
- // closing db connection
- mysql_close();
- }
- }
- ?>
- $db= new DB_CONNECT(); // creating class object(will open database connection)
在這部分,我將講述使用PHP對MySQL數據庫執行基本CRUD(創建,讀取,更新,刪除)操作。
如果你是PHP和MySQL新手,我建議你可以先學習PHP和SQL基礎知識。
6. a)在MYSQL中新建一行(創建一行新的產品)
在你的PHP項目中新建一個php文件,命名爲create_product.php,並輸入以下代碼。該文件主要實現在products表中插入一個新的產品。
在下面的代碼我使用POST來讀取產品數據並把他們存儲在products表中。
最後我會輸出一些JSON返回值,以便返回給客戶端(Android項目)
create_product.php
- <?php
- /*
- * Following code will create a new product row
- * All product details are read from HTTP Post Request
- */
- // array for JSON response
- $response = array();
- // check for required fields
- if (isset($_POST['name']) && isset($_POST['price']) && isset($_POST['description'])) {
- $name = $_POST['name'];
- $price = $_POST['price'];
- $description = $_POST['description'];
- // include db connect class
- require_once __DIR__ . '/db_connect.php';
- // connecting to db
- $db = new DB_CONNECT();
- // mysql inserting a new row
- $result = mysql_query("INSERT INTO products(name, price, description) VALUES('$name', '$price', '$description')");
- // check if row inserted or not
- if ($result) {
- // successfully inserted into database
- $response["success"] = 1;
- $response["message"] = "Product successfully created.";
- // echoing JSON response
- echo json_encode($response);
- } else {
- // failed to insert row
- $response["success"] = 0;
- $response["message"] = "Oops! An error occurred.";
- // echoing JSON response
- echo json_encode($response);
- }
- } else {
- // required field is missing
- $response["success"] = 0;
- $response["message"] = "Required field(s) is missing";
- // echoing JSON response
- echo json_encode($response);
- }
- ?>
當POST 參數丟失
- {
- "success": 0,
- "message": "Required field(s) is missing"
- }
- {
- "success": 1,
- "message": "Product successfully created."
- }
- {
- "success": 0,
- "message": "Oops! An error occurred."
- }
實際測試的時候,出現Required field(s) is missing php錯誤,我把$_POST換成$_GET就對了,對應的NewProductActivity也要換成GET方法
6. b)從MySQL中讀取一行信息(讀取產品詳細信息)
創建一個新的php文件,命名爲get_product_details.php,寫入以下代碼。
該文件通過傳遞產品id作爲POST參數獲得單個產品的詳細信息
get_product_details.php
- <?php
- /*
- * Following code will get single product details
- * A product is identified by product id (pid)
- */
- // array for JSON response
- $response = array();
- // include db connect class
- require_once __DIR__ . '/db_connect.php';
- // connecting to db
- $db = new DB_CONNECT();
- // check for post data
- if (isset($_GET["pid"])) {
- $pid = $_GET['pid'];
- // get a product from products table
- $result = mysql_query("SELECT *FROM products WHERE pid = $pid");
- if (!empty($result)) {
- // check for empty result
- if (mysql_num_rows($result) > 0) {
- $result = mysql_fetch_array($result);
- $product = array();
- $product["pid"] = $result["pid"];
- $product["name"] = $result["name"];
- $product["price"] = $result["price"];
- $product["description"] = $result["description"];
- $product["created_at"] = $result["created_at"];
- $product["updated_at"] = $result["updated_at"];
- // success
- $response["success"] = 1;
- // user node
- $response["product"] = array();
- array_push($response["product"], $product);
- // echoing JSON response
- echo json_encode($response);
- } else {
- // no product found
- $response["success"] = 0;
- $response["message"] = "No product found";
- // echo no users JSON
- echo json_encode($response);
- }
- } else {
- // no product found
- $response["success"] = 0;
- $response["message"] = "No product found";
- // echo no users JSON
- echo json_encode($response);
- }
- } else {
- // required field is missing
- $response["success"] = 0;
- $response["message"] = "Required field(s) is missing";
- // echoing JSON response
- echo json_encode($response);
- }
- ?>
- The json response for the above file will be
- When successfully getting product details
- {
- "success": 1,
- "product": [
- {
- "pid": "1",
- "name": "iPHone 4S",
- "price": "300.00",
- "description": "iPhone 4S white",
- "created_at": "2012-04-29 01:41:42",
- "updated_at": "0000-00-00 00:00:00"
- }
- ]
- }
- When no product found with matched pid
- {
- "success": 0,
- "message": "No product found"
- }
我們需要用json數據在Android設備上顯示所有的產品。
新建一個php文件,命名爲get_all_products.php,寫入以下代碼。
get_all_products.php
- <?php
- /*
- * Following code will list all the products
- */
- // array for JSON response
- $response = array();
- // include db connect class
- require_once __DIR__ . '/db_connect.php';
- // connecting to db
- $db = new DB_CONNECT();
- // get all products from products table
- $result = mysql_query("SELECT *FROM products") or die(mysql_error());
- // check for empty result
- if (mysql_num_rows($result) > 0) {
- // looping through all results
- // products node
- $response["products"] = array();
- while ($row = mysql_fetch_array($result)) {
- // temp user array
- $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"];
- // push single product into final response array
- array_push($response["products"], $product);
- }
- // success
- $response["success"] = 1;
- // echoing JSON response
- echo json_encode($response);
- } else {
- // no products found
- $response["success"] = 0;
- $response["message"] = "No products found";
- // echo no users JSON
- echo json_encode($response);
- }
- ?>
- And the JSON response for above code
- Listing all Products
- {
- "products": [
- {
- "pid": "1",
- "name": "iPhone 4S",
- "price": "300.00",
- "created_at": "2012-04-29 02:04:02",
- "updated_at": "0000-00-00 00:00:00"
- },
- {
- "pid": "2",
- "name": "Macbook Pro",
- "price": "600.00",
- "created_at": "2012-04-29 02:04:51",
- "updated_at": "0000-00-00 00:00:00"
- },
- {
- "pid": "3",
- "name": "Macbook Air",
- "price": "800.00",
- "created_at": "2012-04-29 02:05:57",
- "updated_at": "0000-00-00 00:00:00"
- },
- {
- "pid": "4",
- "name": "OS X Lion",
- "price": "100.00",
- "created_at": "2012-04-29 02:07:14",
- "updated_at": "0000-00-00 00:00:00"
- }
- ],
- "success": 1
- }
- When products not found
- {
- "success": 0,
- "message": "No products found"
- }
新建一個php文件,命名爲update_product.php。每一個產品通過pid標識。
update_product.php
- <?php
- /*
- * Following code will update a product information
- * A product is identified by product id (pid)
- */
- // array for JSON response
- $response = array();
- // check for required fields
- if (isset($_POST['pid']) && isset($_POST['name']) && isset($_POST['price']) && isset($_POST['description'])) {
- $pid = $_POST['pid'];
- $name = $_POST['name'];
- $price = $_POST['price'];
- $description = $_POST['description'];
- // include db connect class
- require_once __DIR__ . '/db_connect.php';
- // connecting to db
- $db = new DB_CONNECT();
- // mysql update row with matched pid
- $result = mysql_query("UPDATE products SET name = '$name', price = '$price', description = '$description' WHERE pid = $pid");
- // check if row inserted or not
- if ($result) {
- // successfully updated
- $response["success"] = 1;
- $response["message"] = "Product successfully updated.";
- // echoing JSON response
- echo json_encode($response);
- } else {
- }
- } else {
- // required field is missing
- $response["success"] = 0;
- $response["message"] = "Required field(s) is missing";
- // echoing JSON response
- echo json_encode($response);
- }
- ?>
- The json reponse of above code, when product is updated successfully
- {
- "success": 1,
- "message": "Product successfully updated."
- }
新建一個php文件,命名爲delete_product.php。該文件主要功能是從數據庫中刪除一個產品。
delete_product.php
- <?php
- /*
- * Following code will delete a product from table
- * A product is identified by product id (pid)
- */
- // array for JSON response
- $response = array();
- // check for required fields
- if (isset($_POST['pid'])) {
- $pid = $_POST['pid'];
- // include db connect class
- require_once __DIR__ . '/db_connect.php';
- // connecting to db
- $db = new DB_CONNECT();
- // mysql update row with matched pid
- $result = mysql_query("DELETE FROM products WHERE pid = $pid");
- // check if row deleted or not
- if (mysql_affected_rows() > 0) {
- // successfully updated
- $response["success"] = 1;
- $response["message"] = "Product successfully deleted";
- // echoing JSON response
- echo json_encode($response);
- } else {
- // no product found
- $response["success"] = 0;
- $response["message"] = "No product found";
- // echo no users JSON
- echo json_encode($response);
- }
- } else {
- // required field is missing
- $response["success"] = 0;
- $response["message"] = "Required field(s) is missing";
- // echoing JSON response
- echo json_encode($response);
- }
- ?>
- When product successfully deleted
- {
- "success": 1,
- "message": "Product successfully deleted"
- }
- When product not found
- {
- "success": 0,
- "message": "No product found"
- }
7. 新建一個Android應用程序
在Eclipse IDE中創建一個新項目,填寫所需的細節信息。
1. 新建項目,在菜單中選擇File->New->Android Project,把Activity類命名爲MainScreenActivity
2. 打開AndroidManifest.xml,添加以下代碼。我先在manifest文件中添加了所需的全部Activity類。同樣需要添加INTERNET連接權限(非常重要)
AndroidManifest.xml
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.example.androidhive"
- android:versionCode="1"
- android:versionName="1.0" >
- <uses-sdk android:minSdkVersion="8" />
- <application
- android:configChanges="keyboardHidden|orientation"
- android:icon="@drawable/ic_launcher"
- 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>
main_screen.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="fill_parent"
- android:orientation="vertical"
- android:gravity="center_horizontal">
- <!-- Sample Dashboard screen with Two buttons -->
- <!-- Button to view all products screen -->
- <Button android:id="@+id/btnViewProducts"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="View Products"
- android:layout_marginTop="25dip"/>
- <!-- Button to create a new product screen -->
- <Button android:id="@+id/btnCreateProduct"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="Add New Products"
- android:layout_marginTop="25dip"/>
- </LinearLayout>
4. 打開MainScreenActivity.java爲main_screen.xml文件裏的兩個按鈕添加點擊事件
MainScreenActivity.java
- package com.example.androidhive;
- 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);
- // Buttons
- btnViewProducts = (Button) findViewById(R.id.btnViewProducts);
- btnNewProduct = (Button) findViewById(R.id.btnCreateProduct);
- // view products click event
- btnViewProducts.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- // Launching All products Activity
- Intent i = new Intent(getApplicationContext(), AllProductsActivity.class);
- startActivity(i);
- }
- });
- // view products click event
- btnNewProduct.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- // Launching create new product activity
- Intent i = new Intent(getApplicationContext(), NewProductActivity.class);
- startActivity(i);
- }
- });
- }
- }
現在我們需要一個Activity來以列表的形式顯示所有產品。如我們所知,使用ListView需要兩個xml文件,一個是列表佈局,另一個是單個的列表項佈局。在res->layout文件夾下新建兩個xml文件:all_product.xml和list_item.xml
all_product.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="fill_parent"
- android:orientation="vertical">
- <!-- Main ListView
- Always give id value as list(@android:id/list)
- -->
- <ListView
- android:id="@android:id/list"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"/>
- </LinearLayout>
- <?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" >
- <!-- Product id (pid) - will be HIDDEN - used to pass to other activity -->
- <TextView
- android:id="@+id/pid"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:visibility="gone" />
- <!-- Name Label -->
- <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>
在下面的代碼中,
首先,在後臺AsyncTask線程中發送一個請求給get_all_products.php
然後,從get_all_products.php獲取JSON格式的數據,我爲json轉換了格式(parser),並使其顯示在ListView中。
如果沒有找到產品,會跳轉到AddNewProductActivity
AllProductActivity.java
- package com.example.androidhive;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- 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 {
- // Progress Dialog
- private ProgressDialog pDialog;
- // Creating JSON Parser object
- JSONParser jParser = new JSONParser();
- ArrayList<HashMap<String, String>> productsList;
- // url to get all products list
- private static String url_all_products = "http://api.androidhive.info/android_connect/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";
- // products JSONArray
- 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>>();
- // Loading products in Background Thread
- new LoadAllProducts().execute();
- // Get listview
- ListView lv = getListView();
- // on seleting single product
- // launching 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();
- // Starting new intent
- Intent in = new Intent(getApplicationContext(),
- EditProductActivity.class);
- // sending pid to next activity
- in.putExtra(TAG_PID, pid);
- // starting new activity and expecting some response back
- startActivityForResult(in, 100);
- }
- });
- }
- // Response from Edit Product Activity
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- // if result code 100
- if (resultCode == 100) {
- // if result code 100 is received
- // means user edited/deleted product
- // reload this screen again
- Intent intent = getIntent();
- finish();
- startActivity(intent);
- }
- }
- /**
- * Background Async Task to Load all product by making HTTP Request
- * */
- class LoadAllProducts extends AsyncTask<String, String, String> {
- /**
- * Before starting background thread Show Progress Dialog
- * */
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- pDialog = new ProgressDialog(AllProductsActivity.this);
- pDialog.setMessage("Loading products. Please wait...");
- pDialog.setIndeterminate(false);
- pDialog.setCancelable(false);
- pDialog.show();
- }
- /**
- * getting All products from url
- * */
- protected String doInBackground(String... args) {
- // Building Parameters
- List<NameValuePair> params = new ArrayList<NameValuePair>();
- // getting JSON string from URL
- JSONObject json = jParser.makeHttpRequest(url_all_products, "GET", params);
- // Check your log cat for JSON reponse
- Log.d("All Products: ", json.toString());
- try {
- // Checking for SUCCESS TAG
- int success = json.getInt(TAG_SUCCESS);
- if (success == 1) {
- // products found
- // Getting Array of Products
- products = json.getJSONArray(TAG_PRODUCTS);
- // looping through All Products
- for (int i = 0; i < products.length(); i++) {
- JSONObject c = products.getJSONObject(i);
- // Storing each json item in variable
- String id = c.getString(TAG_PID);
- String name = c.getString(TAG_NAME);
- // creating new HashMap
- HashMap<String, String> map = new HashMap<String, String>();
- // adding each child node to HashMap key => value
- map.put(TAG_PID, id);
- map.put(TAG_NAME, name);
- // adding HashList to ArrayList
- productsList.add(map);
- }
- } else {
- // no products found
- // Launch Add New product Activity
- Intent i = new Intent(getApplicationContext(),
- NewProductActivity.class);
- // Closing all previous activities
- i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(i);
- }
- } catch (JSONException e) {
- e.printStackTrace();
- }
- return null;
- }
- /**
- * After completing background task Dismiss the progress dialog
- * **/
- protected void onPostExecute(String file_url) {
- // dismiss the dialog after getting all products
- pDialog.dismiss();
- // updating UI from Background Thread
- runOnUiThread(new Runnable() {
- public void run() {
- /**
- * Updating parsed JSON data into 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 });
- // updating listview
- setListAdapter(adapter);
- }
- });
- }
- }
- }
7. 添加一個新產品(寫入)
創建一個新的view和activity來向MySQL數據庫添加新產品。
新建一個簡單的表單,創建提供輸入產品名稱,價格和描述的EditText
add_product.xml
- <?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" >
- <!-- Name Label -->
- <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"/>
- <!-- Input Name -->
- <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"/>
- <!-- Price Label -->
- <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"/>
- <!-- Input Price -->
- <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"/>
- <!-- Description Label -->
- <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"/>
- <!-- Input description -->
- <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 Create Product -->
- <Button android:id="@+id/btnCreateProduct"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="Create Product"/>
- </LinearLayout>
8. 新建一個Activity來處理向MySQL數據庫插入新產品。
新建名爲NewProductActivity.java的文件,輸入以下代碼。在下面的代碼中
首先,從EditText獲得用戶輸入的產品數據,格式化成基本參數格式
然後,向create_product.php發送請求,通過HTTP POST創建一個新的產品
最後,從create_product.php獲取json返回值,如果success值爲1,新得到的列表中就加入了新增的產品。
NewProductActivity.java
- package com.example.androidhive;
- import java.util.ArrayList;
- import java.util.List;
- import org.apache.http.NameValuePair;
- import org.apache.http.message.BasicNameValuePair;
- 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 NewProductActivity extends Activity {
- // Progress Dialog
- private ProgressDialog pDialog;
- JSONParser jsonParser = new JSONParser();
- EditText inputName;
- EditText inputPrice;
- EditText inputDesc;
- // url to create new product
- private static String url_create_product = "http://api.androidhive.info/android_connect/create_product.php";
- // JSON Node names
- private static final String TAG_SUCCESS = "success";
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.add_product);
- // Edit Text
- inputName = (EditText) findViewById(R.id.inputName);
- inputPrice = (EditText) findViewById(R.id.inputPrice);
- inputDesc = (EditText) findViewById(R.id.inputDesc);
- // Create button
- Button btnCreateProduct = (Button) findViewById(R.id.btnCreateProduct);
- // button click event
- btnCreateProduct.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- // creating new product in background thread
- new CreateNewProduct().execute();
- }
- });
- }
- /**
- * Background Async Task to Create new product
- * */
- class CreateNewProduct extends AsyncTask<String, String, String> {
- /**
- * Before starting background thread Show Progress Dialog
- * */
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- pDialog = new ProgressDialog(NewProductActivity.this);
- pDialog.setMessage("Creating Product..");
- pDialog.setIndeterminate(false);
- pDialog.setCancelable(true);
- pDialog.show();
- }
- /**
- * Creating product
- * */
- protected String doInBackground(String... args) {
- String name = inputName.getText().toString();
- String price = inputPrice.getText().toString();
- String description = inputDesc.getText().toString();
- // Building Parameters
- List<NameValuePair> params = new ArrayList<NameValuePair>();
- params.add(new BasicNameValuePair("name", name));
- params.add(new BasicNameValuePair("price", price));
- params.add(new BasicNameValuePair("description", description));
- // getting JSON Object
- // Note that create product url accepts POST method
- JSONObject json = jsonParser.makeHttpRequest(url_create_product,
- "POST", params);
- // check log cat fro response
- Log.d("Create Response", json.toString());
- // check for success tag
- try {
- int success = json.getInt(TAG_SUCCESS);
- if (success == 1) {
- // successfully created product
- Intent i = new Intent(getApplicationContext(), AllProductsActivity.class);
- startActivity(i);
- // closing this screen
- finish();
- } else {
- // failed to create product
- }
- } catch (JSONException e) {
- e.printStackTrace();
- }
- return null;
- }
- /**
- * After completing background task Dismiss the progress dialog
- * **/
- protected void onPostExecute(String file_url) {
- // dismiss the dialog once done
- pDialog.dismiss();
- }
- }
- }
你稍加註意就會發現,在AllProductsActivity.java中,選中列表的某一項,會進入EditProductActivity.java。
接下來新建一個名爲edit_product,xml的xml文件,創建類似create_product,xml的表單。
edit_product,xml
- <?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" >
- <!-- Name Label -->
- <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"/>
- <!-- Input Name -->
- <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"/>
- <!-- Price Label -->
- <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"/>
- <!-- Input Price -->
- <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"/>
- <!-- Description Label -->
- <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"/>
- <!-- Input description -->
- <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 Create Product -->
- <Button android:id="@+id/btnSave"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="Save Changes"
- android:layout_weight="1"/>
- <!-- Button Create Product -->
- <Button android:id="@+id/btnDelete"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:text="Delete"
- android:layout_weight="1"/>
- </LinearLayout>
- </LinearLayout>
在以下代碼中:
首先,從intent中讀取發送給ListView的產品id(pid)
然後,向get_product_details.php發送請求,獲得json格式的產品詳細信息,把它顯示在EditText中。
然後,當產品信息顯示在表單中後,如果用戶點擊保存按鈕,會向update_product.php發送另一個HTTP請求,更新數據庫中的產品信息
如果用戶點擊刪除按鈕,將會向delete_product.php發送請求,該產品慧聰MySQL數據庫中刪除,ListView刷新後顯示新的產品列表。
EditProductActivity.java
- package com.example.androidhive;
- import java.util.ArrayList;
- import java.util.List;
- 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;
- EditText txtCreatedAt;
- Button btnSave;
- Button btnDelete;
- String pid;
- // Progress Dialog
- private ProgressDialog pDialog;
- // JSON parser class
- JSONParser jsonParser = new JSONParser();
- // single product url
- private static final String url_product_detials = "http://api.androidhive.info/android_connect/get_product_details.php";
- // url to update product
- private static final String url_update_product = "http://api.androidhive.info/android_connect/update_product.php";
- // url to delete product
- private static final String url_delete_product = "http://api.androidhive.info/android_connect/delete_product.php";
- // JSON Node names
- 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);
- // save button
- btnSave = (Button) findViewById(R.id.btnSave);
- btnDelete = (Button) findViewById(R.id.btnDelete);
- // getting product details from intent
- Intent i = getIntent();
- // getting product id (pid) from intent
- pid = i.getStringExtra(TAG_PID);
- // Getting complete product details in background thread
- new GetProductDetails().execute();
- // save button click event
- btnSave.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View arg0) {
- // starting background task to update product
- new SaveProductDetails().execute();
- }
- });
- // Delete button click event
- btnDelete.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View arg0) {
- // deleting product in background thread
- new DeleteProduct().execute();
- }
- });
- }
- /**
- * Background Async Task to Get complete product details
- * */
- class GetProductDetails extends AsyncTask<String, String, String> {
- /**
- * Before starting background thread Show Progress Dialog
- * */
- @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();
- }
- /**
- * Getting product details in background thread
- * */
- protected String doInBackground(String... params) {
- // updating UI from Background Thread
- runOnUiThread(new Runnable() {
- public void run() {
- // Check for success tag
- int success;
- try {
- // Building Parameters
- List<NameValuePair> params = new ArrayList<NameValuePair>();
- params.add(new BasicNameValuePair("pid", pid));
- // getting product details by making HTTP request
- // Note that product details url will use GET request
- JSONObject json = jsonParser.makeHttpRequest(
- url_product_detials, "GET", params);
- // check your log for json response
- Log.d("Single Product Details", json.toString());
- // json success tag
- success = json.getInt(TAG_SUCCESS);
- if (success == 1) {
- // successfully received product details
- JSONArray productObj = json
- .getJSONArray(TAG_PRODUCT); // JSON Array
- // get first product object from JSON Array
- JSONObject product = productObj.getJSONObject(0);
- // product with this pid found
- // Edit Text
- txtName = (EditText) findViewById(R.id.inputName);
- txtPrice = (EditText) findViewById(R.id.inputPrice);
- txtDesc = (EditText) findViewById(R.id.inputDesc);
- // display product data in EditText
- txtName.setText(product.getString(TAG_NAME));
- txtPrice.setText(product.getString(TAG_PRICE));
- txtDesc.setText(product.getString(TAG_DESCRIPTION));
- }else{
- // product with pid not found
- }
- } catch (JSONException e) {
- e.printStackTrace();
- }
- }
- });
- return null;
- }
- /**
- * After completing background task Dismiss the progress dialog
- * **/
- protected void onPostExecute(String file_url) {
- // dismiss the dialog once got all details
- pDialog.dismiss();
- }
- }
- /**
- * Background Async Task to Save product Details
- * */
- class SaveProductDetails extends AsyncTask<String, String, String> {
- /**
- * Before starting background thread Show Progress Dialog
- * */
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- pDialog = new ProgressDialog(EditProductActivity.this);
- pDialog.setMessage("Saving product ...");
- pDialog.setIndeterminate(false);
- pDialog.setCancelable(true);
- pDialog.show();
- }
- /**
- * Saving product
- * */
- protected String doInBackground(String... args) {
- // getting updated data from EditTexts
- String name = txtName.getText().toString();
- String price = txtPrice.getText().toString();
- String description = txtDesc.getText().toString();
- // Building Parameters
- 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));
- // sending modified data through http request
- // Notice that update product url accepts POST method
- JSONObject json = jsonParser.makeHttpRequest(url_update_product,
- "POST", params);
- // check json success tag
- try {
- int success = json.getInt(TAG_SUCCESS);
- if (success == 1) {
- // successfully updated
- Intent i = getIntent();
- // send result code 100 to notify about product update
- setResult(100, i);
- finish();
- } else {
- // failed to update product
- }
- } catch (JSONException e) {
- e.printStackTrace();
- }
- return null;
- }
- /**
- * After completing background task Dismiss the progress dialog
- * **/
- protected void onPostExecute(String file_url) {
- // dismiss the dialog once product uupdated
- pDialog.dismiss();
- }
- }
- /*****************************************************************
- * Background Async Task to Delete Product
- * */
- class DeleteProduct extends AsyncTask<String, String, String> {
- /**
- * Before starting background thread Show Progress Dialog
- * */
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- pDialog = new ProgressDialog(EditProductActivity.this);
- pDialog.setMessage("Deleting Product...");
- pDialog.setIndeterminate(false);
- pDialog.setCancelable(true);
- pDialog.show();
- }
- /**
- * Deleting product
- * */
- protected String doInBackground(String... args) {
- // Check for success tag
- int success;
- try {
- // Building Parameters
- List<NameValuePair> params = new ArrayList<NameValuePair>();
- params.add(new BasicNameValuePair("pid", pid));
- // getting product details by making HTTP request
- JSONObject json = jsonParser.makeHttpRequest(
- url_delete_product, "POST", params);
- // check your log for json response
- Log.d("Delete Product", json.toString());
- // json success tag
- success = json.getInt(TAG_SUCCESS);
- if (success == 1) {
- // product successfully deleted
- // notify previous activity by sending code 100
- Intent i = getIntent();
- // send result code 100 to notify about product deletion
- setResult(100, i);
- finish();
- }
- } catch (JSONException e) {
- e.printStackTrace();
- }
- return null;
- }
- /**
- * After completing background task Dismiss the progress dialog
- * **/
- protected void onPostExecute(String file_url) {
- // dismiss the dialog once product deleted
- pDialog.dismiss();
- }
- }
- }
11. JSONParser類
我用一個JSONParser類從URL獲得JSON格式的數據。這個類支持兩種http請求,GET和POST方法從URL獲取JSON數據
JSONParser.java
- package com.example.androidhive;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.UnsupportedEncodingException;
- import java.util.List;
- 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 android.util.Log;
- 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 mehtod
- public JSONObject makeHttpRequest(String url, String method,
- List<NameValuePair> 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;
- }
- }
運行你的代碼,測試一下程序吧。你可能會遇到不少錯誤,經常使用LogCat來調試你的項目。
如果你不能解決那些錯誤,請在此留言。
原文鏈接:http://www.androidhive.info/2012/05/how-to-connect-android-with-php-mysql/
測試環境:WAMP: 2.4 Apache :2.4.4 PHP: 5.4.16
源碼下載地址: http://download.csdn.net/detail/welovesunflower/7383361