0

I am trying to make my Android project work with LAMP server, but JSON request keep returning null. LAMP server is working properly, my request is reaching php files on it.

Here is my code:

class GetEntryData extends AsyncTask<String, String, String> {

private static JSONParser jsonParser;
private List<NameValuePair> entry_data;

private static String server_address;
private static String server_db;
private static String db_table;
private static int id;
public static String TAG = "LogDebug";

private static final String TAG_SUCCESS = "success";

public  GetEntryData(String server_address, String server_db, String db_table, int id) {
    this.server_address = server_address;
    this.server_db = server_db;
    this.db_table = db_table;
    this.id = id;
}

@Override
protected String doInBackground(String[] params) {

    Log.d(TAG, "Sending JSON request");
    jsonParser = new JSONParser();
    int success;
        entry_data = new ArrayList<NameValuePair>();
        entry_data.add(new BasicNameValuePair("id", String.valueOf(id)));
        Log.d(TAG, "server address: " + server_address + "   enrty data: " + entry_data.toString());
        JSONObject json = jsonParser.makeHttpRequest(server_address, "GET", entry_data);
        try {
        Log.d(TAG, json.toString());

        success = json.getInt(TAG_SUCCESS);
        if (success == 1) {
            JSONArray productObj = json.getJSONArray(db_table);
            JSONObject entry = productObj.getJSONObject(0);
            return entry.toString();
        } else {
            return null;
        }
    } catch (NullPointerException e) {
        return e.getMessage();
    }catch (JSONException e){
            return e.getMessage();
        }
}
@Override
protected void onPostExecute(String result) {
    Log.d(TAG, "Entry data was written with the result: " + result);
}

}

My JSON class:

public class JSONParser {

static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
public JSONParser() {

}
public JSONObject makeHttpRequest(String url, String method, List<NameValuePair> params) {
    try {
        if(method == "POST"){
            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"){
            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 {
        jObj = new JSONObject(json);
    } catch (JSONException e) {
        Log.e("JSON Parser", "Error parsing data " + e.toString());
    }
    return jObj;

}}

And my php code:

<?php

$response = array();

require 'db_connect.php';

$db = new DB_CONNECT();

if (isset($_GET["id"])) {
$pid = $_GET['id'];

$result = mysqli_query("SELECT *FROM marker_data WHERE id = $id");

if (!empty($result)) {
    if (mysqli_num_rows($result) > 0) {

        $result = mysqli_fetch_array($result);

        $entry = array();
        $entry["id"] = $result["id"];
        $entry["title"] = $result["title"];
        $entry["address"] = $result["address"];
        $entry["image"] = $result["image"];
        $entry["working_hours"] = $result["working_hours"];
        $entry["product_range"] = $result["product_range"];
        $entry["comments"] = $result["comments"];
        $entry["confirmation_status"] = $result["confirmation_status"];
        $entry["latitude"] = $result["product_range"];
        $entry["longitude"] = $result["longitude"];


        $response["entry"] = array();

        array_push($response["entry"], $entry);

        echo json_encode($response);
    } else {
        $response["success"] = 0;
        $response["message"] = "No entry found";

        echo json_encode($response);
    }
} else {
    $response["success"] = 0;
    $response["message"] = "No entry found";

    echo json_encode($response);
}
} else {
$response["success"] = 0;
$response["message"] = "Required field(s) is missing";

echo json_encode($response);
}
?>

db_connect.php:

<?php

class DB_CONNECT {

function __construct() {
    $this->connect();
}

function __destruct() {
    $this->close();
}

function connect() {
    require 'db_config.php';

    $con = mysqli_connect(DB_SERVER, DB_USER, DB_PASSWORD) or die(mysqli_error());

    $db = mysqli_select_db(DB_DATABASE) or die(mysqli_error()) or die(mysqli_error());

    return $con;
}

function close() {
    mysqli_close();
}

}

?>

What I get in Logcat is: Error parsing data org.json.JSONException: End of input at character 0 of Entry data was written with the result: Attempt to invoke virtual method 'java.lang.String org.json.JSONObject.toString()' on a null object reference

There is an entry with id = 1 (which I am trying to get), and all the variable names (like server, database, php files and etc) are set properly.

Rodion
  • 25
  • 1
  • 5
  • could you paste the JSON from your server? – diegoveloper Nov 21 '17 at 20:46
  • Your code is vulnerable to [**SQL injection**](https://en.wikipedia.org/wiki/SQL_injection) attacks. You should use prepared statements with bound parameters, via either the [**mysqli**](https://secure.php.net/manual/en/mysqli.prepare.php) or [**PDO**](https://secure.php.net/manual/en/pdo.prepared-statements.php) drivers. [**This post**](https://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php) has some good examples. – Alex Howansky Nov 21 '17 at 20:49
  • You set `$pid` but use `$id` in your query. – Alex Howansky Nov 21 '17 at 20:50
  • @AlexHowansky thank you for the examples, I'll take a look at it – Rodion Nov 21 '17 at 21:57

2 Answers2

1

My advice is also to use rather PDO

So db_connect, maybe something like this:

<?php

try {
    $conn = new PDO("mysql:host=localhost;dbname=test;", 'root', 'test');
} catch (PDOException $e) {
    die("Error occurred: " . $e->getMessage());
}

$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

header('Content-Type: text/html; charset=utf-8');

?>

getMarkerData.php

<?php

require 'DBConnect.php'; //PHP file for connect to database
header('Content-Type: application/json'); //You want answers in json 
$header = apache_request_headers(); //set headers

if (isset($header['authorization'])) { //if ID is posted than do stuffs

    $id = $header['authorization']; //save ID in some variable

    //You can put user id in marker_data table and then get values from there, but for easier testing you can firstly check if user ID is found in users table and if is not than just answer in json user not found
    $stmt = $conn->prepare("SELECT id FROM users WHERE id = :id");
    $stmt->bindParam(":id", $id);
    $stmt->execute();
    $row = $stmt->fetch(PDO::FETCH_ASSOC);

    if ($row < 1) {
        $error['success'] = 0; //Success is for easier handling on Android to know what to do next
        $error['message'] = 'Access denied!';

        die(json_encode($error));
    } else {
       //so user is found and we now want data for that user
        $sql = $conn->prepare("SELECT * FROM marker_data WHERE userid = :uid);
        $sql->bindParam(":uid", $id);
        $sql->execute();
        $data = $sql->fetch(PDO::FETCH_ASSOC);

        if ($data > 0) {
            //So here you choose which data you want to fetch
            $error['success'] = 1;
            $error['product_range'] = $data['product_range'];
            $error['working_hours'] = $data['working_hours'];

            echo json_encode($error);
        }

    }

} else {
    $error["success"] = 0;
    $error["message"] = "Access denied!";

    die(json_encode($error));
}

?>

And for android and example of JSON

public class CheckingDatabase extends AsyncTask<String, Integer, Integer> {
        //Add your ID for identification
        public CheckingDatabase(String postID) {
            postID = id;
        }

        @Override
        protected Integer doInBackground(String... params) {

            try {
                //Objects of HttpClient and HttpPost
                HttpClient httpClient = new DefaultHttpClient();
                HttpPost httpPost = new HttpPost("http://localhost/PHPScripts/getMarkerData.php");
                HttpParams httpParams = new BasicHttpParams();
                int timeoutConnection = 5000;
                HttpConnectionParams.setConnectionTimeout(httpParams, timeoutConnection);
                int timeoutSocket = 7000;
                HttpConnectionParams.setSoTimeout(httpParams, timeoutSocket);
                httpPost.setHeader("authorization", id); //ID

                //Post request
                try {
                    HttpResponse httpResponse = httpClient.execute(httpPost);
                    HttpEntity httpEntity = httpResponse.getEntity();
                    InputStream inputStream = null;
                    inputStream = httpEntity.getContent();
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
                    StringBuilder stringBuilder = new StringBuilder();

                    String line = null;
                    while ((line = bufferedReader.readLine()) != null) {
                        stringBuilder.append(line + "\n");
                    }
                    String result = null;
                    result = stringBuilder.toString();
                    json = result;
                } catch (ClientProtocolException cpe) {
                    cpe.printStackTrace();
                    Log.d("URIException", cpe.getMessage());
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                    Log.d("IOException", ioe.getMessage());
                }

                Thread.sleep(1000);
            } catch (InterruptedException ie) {
                ie.printStackTrace();
                Log.d("InterruptedException", ie.getMessage());
            }

            //JSON response
            try {
                JSONObject jsonObject = new JSONObject(json);
                success = jsonObject.getInt("success");

                if (success == 1) { //If success is 1 get data
                    product_range = jsonObject.getString("product_range");
                    working_hours = jsonObject.getString("working_hours");
                }
            } catch (JSONException je) { //Otherveis exception
                je.printStackTrace();
                Log.d("JSONException", je.getMessage());
            }

            return success;
        }

        @Override
        protected void onPostExecute(Integer integer) {
            integer = success;

            if (integer == 1) {
                checkForChanges(); //Now you can call some another method to do some other things with data or something else, or even you don't need this :D
            }
        }
    }

Maybe just in advice to use another one random generated ID for user identification. And also for testing if is really OK php scripts you can use ARC (extension for Chrome, is OK for tests).

elvirt
  • 111
  • 1
  • 5
  • Thank you for your hard work! Well, I tried to use your code, tried to use Postman (same as ARC), but it didn't solve my problem. Logcat is the same. But I noticed that if I try to post inappropriate values, I get a "Required fields are missing" message and Postman says that connection is "Keep-alive", and if every value is ok, I get nothing and connection "close" – Rodion Nov 22 '17 at 13:10
  • Are you posting header in arc? Header with value of user ID? And content value application/x-www-form-urlencoded? – elvirt Nov 22 '17 at 13:21
  • Yes, I post id value in header, but what do I need to do with application/x-www-form-urlencoded? – Rodion Nov 22 '17 at 13:26
  • Also, I noticed that when I'm trying to acces db_connect.php - everything is ok, "echo" command send response. But when I require this file in others or just copypast code from it (or even write echo ".....";), nothing happens. I write file names correctly, I've checked it. – Rodion Nov 22 '17 at 18:15
  • Well, I did a lot of changes, don't know what exactly caused the problem (user permissions, server settings etc.), but with your code (except for changing header to GET method) it worked! Thank you a lot, if it were not for your code and advices, it would take another 3 days for me to deal with issue. P.S. Sorry for bad English – Rodion Nov 22 '17 at 19:31
0

You need to act on the comments left regarding the sql injection. Use PDO.

Nt enough information to help you entirely. Line numbers for the error would help or even the full logcat output.

You could try returning some valid json from your php. This would prevent the error and you would be sure the PHP code is returning what you expect. Once you are happy you can put the json back to how you need - perhaps format it yourself rather than rely json_encode() of an associative array.