I've tried connecting my android app to online mySQL databse using this tutorial: http://www.androidhive.info/2012/05/how-to-connect-android-with-php-mysql/ but I am getting an error that says
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String org.json.JSONObject.toString()' on a null object reference
in the doInBackground
portion where i try to call json.ToString()
:
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://lewspage.hostei.com/scripts/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()); //Crashes here
// 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();
}
}
}
The PHP script at "http://lewspage.hostei.com/scripts/create_product.php" is as follows:
<?php
/*
* Following code will create a new product row
* All product details are read from HTTP Post Request
*/
require_once('db_connect.php');
$host='mysql10.000webhost.com';
$user='myusername';
$pass='mypassword';
if ( !mysql_connect($host,$user,$pass) ||
!mysql_select_db('a7390942_test') )
echo 'ERROR';
else
echo 'OKKKK';
// 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);
}
?>
Basically , I used 000wehost to host the mysql database as well as the php scripts. I tried to run the create_product script on its own and it has no problem connecting to the database.I have already ensured that my databse contains the fields name,price,description. However, I don't know why it doesn't seem to fill the JSON object properly .
Thanks
Change the line where you have json.toString() to below. This is because makeHttpRequest
can return null:
Log.d("Create Response", ((json == null) ? "" :json.toString());
Also make sure the JsonParser
object you initialized is the one you are using.
The main problem that you are having is that the URL you provided does not return proper JSON. This is probably due to an error in your PHP script or the free webhost that you are using is injecting content in your response.
In any case you should never trust the result of an http call and always test that you do get back the result you expect before using the data.
You can use a tool like postman to test calls to http services and examine the actual result. In your case when I test your URL what returns is not JSON.
When I accessed the url you provided, it isn't a valid string because your 'db_connect.php' script did not open properly.
?php /* * All database connection variables */ define('DB_USER', "replace"); // db user define('DB_PASSWORD', "replace"); // db password (mention your db password here) define('DB_DATABASE', "replace"); // database name define('DB_SERVER', "replace"); // db server ?>OKKKK{"success":0,"message":"Required field(s) is missing"}
This is what the response is from the url. I'm assuming the code below is your db_connect.php script
?php /* * All database connection variables */ define('DB_USER', "replace"); // db user define('DB_PASSWORD', "replace"); // db password (mention your db password here) define('DB_DATABASE', "replace"); // database name define('DB_SERVER', "replace");?>
You are lacking a < in your php opening tag. Also, considering removing some of the echo function that may hinder your json.
I'll break it down for you. You might noticed OKKKK because the database is successfully connected based on your script:
if ( !mysql_connect($host,$user,$pass) ||
!mysql_select_db('a7390942_test') )
echo 'ERROR';
else
echo 'OKKKK';
You need to remove those echo because it will make your webpage response not conforming to JSON standard. Next, your db_connect script probably didn't open correctly, thus exposing all your database definition.
Note: It is recommended to use prepare statement for mysqli due to the fact that you are inserting the table with user input. Without prepare statement, your sql will be injectable.
Suggestion to you is that since you're using free webhost provider, you can't be sure whether they append any text to your response. You could possibly enclosed your json text within a html element and give it a class. In your android, get all the html response, convert to string and then substring text after your class and before it closes.
Example:
<div class="jsonTxt">{"success":"1"}</div>
So I would read the string after and then read the index of the from the substring-ed text and then remove anything after it.