0

So today I have got a dynamic JSON file "json.php" which changes it's content depending on if the user is logged in or not. I want to parse this JSON file in my android app.

My Problem: I am unable to parse the dynamic value of "id" within my JSON file. Current Problem: Does not really matter if the user is logged in or not, the output of json.php is always as of the logged out state. I want to add session support within my current JSON parsing method just like my Web View.

Have a look at json.php

json.php

<?php
session_start();
if (isset($_SESSION['access_token'])) {
    echo '{"userinfo": [{"status": "loggedin","id": "1"}]}';
} else {
    echo '{"userinfo": [{"status": "loggedout","id": "0"}]}';
}
?>

So, If the user is logged in the output of json.php will be this and vice versa:

{"userinfo": [{"status": "loggedin","id": "1"}]}

Coming to the Android part:

MainActivity.java

package com.example.app;
import ...

public class MainActivity extends AppCompatActivity {
private WebView MywebView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Firing up the fetchData.java process
        fetchData process = new fetchData();
        process.execute();

        MywebView = (WebView) findViewById(R.id.main); //Assigning WebView to WebView Frame "main".
        MywebView.loadUrl("https://example.com/"); //the url that app is going to open
        MywebView.setWebViewClient(new WebViewClient());

        //set and tweak webview settings from here
        WebSettings MywebSettings = MywebView.getSettings();
        MywebSettings.setJavaScriptEnabled(true);
        MywebSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
    }
}

fetchData.java

We parse the JSON here as a background process in this file. We convert the "id" into a string so that we can use it further. I took the help of this tutorial.

package com.example.app;
import ...

public class fetchData extends AsyncTask<Void, Void, Void> {
    @Override
     protected Void doInBackground(Void... voids) {
         HttpHandler sh = new HttpHandler();
         String url = "https://example.com/json.php";
         String jsonStr = sh.makeServiceCall(url);
         String webUserID;
         if (jsonStr != null) {
             try {
                 JSONObject jsonObj = new JSONObject(jsonStr);
                 JSONArray info = jsonObj.getJSONArray("userinfo");
                     JSONObject c = info.getJSONObject(0);
                     webUserID = c.getString("id");
             } catch (final JSONException e) {
                 Log.e("TAG", "Json parsing error: " + e.getMessage());
             }
         } else {
             Log.e("TAG", "Couldn't get JSON from server.");
         }
         //here I do whatever I want with the string webUserID
         //Generally used to set OneSignal External ID
         return null;
     }
}

HttpHandler.java

Additionally we have got a HTTP handler file handing all of our requests.

package com.example.app;
import ...

class HttpHandler {

    private static final String TAG = HttpHandler.class.getSimpleName();

    HttpHandler() {
    }

    String makeServiceCall(String reqUrl) {
        String response = null;
        try {
            URL url = new URL(reqUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            // read the response
            InputStream in = new BufferedInputStream(conn.getInputStream());
            response = convertStreamToString(in);
        } catch (MalformedURLException e) {
            Log.e(TAG, "MalformedURLException: " + e.getMessage());
        } catch (ProtocolException e) {
            Log.e(TAG, "ProtocolException: " + e.getMessage());
        } catch (IOException e) {
            Log.e(TAG, "IOException: " + e.getMessage());
        } catch (Exception e) {
            Log.e(TAG, "Exception: " + e.getMessage());
        }
        return response;
    }

    private String convertStreamToString(InputStream is) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();

        String line;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line).append('\n');
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return sb.toString();
    }
}

So, what are the possible ways of getting what I want? Your help is very much appreciated. Thanks.


Additionally, I am adding the index.php and home.php just in case it helps.

index.php

<?php
session_start();
if (isset($_SESSION['access_token'])) {
    header('Location: home.php');
    exit();
} elseif (!isset($_SESSION['access_token']) && isset($_COOKIE['access_token'])) {
    $_SESSION['access_token'] = $_COOKIE['access_token'];
    header('Location: home.php');
    exit();
}
if (isset($_POST['login'])) {
    setcookie("access_token", "123456", time()+60*60*24*30);
    $_SESSION['access_token'] = "123456";
    header("Location: home.php");
    exit;
}
?>
<html>
    <head>
        <title>Internal Testing Site</title>
    </head>
    <body>
        <h1>Internal cache testing website</h1>
        <hr>
        <p>You are currently logged out.</p>
        <form method="POST">
            <button name="login">Click me to login</button>
        </form>
    </body>
</html>

home.php

<?php
session_start();
if (!isset($_SESSION['access_token'])) {
    header('Location: index.php');
    exit();
}
?>
<html>
    <head>
        <title>Internal Testing Site</title>
    </head>
    <body>
        <h1>internal cache testing website</h1>
        <hr>
        <p><b>You are currently logged in.</b></p>
        <a href="json.php">See JSON</a>
    </body>
</html>

The Solution: Even if this answer solves the problem, it comes with it's own set of problems. Even if you choose to just take the Web View cookies and scrape the data from it, the app might crash when there is no internet connection. You can follow up this thread here for more information.

Souvik
  • 131
  • 1
  • 8
  • Hi, actually all looks good to me, but i cant seem to understand exact problem. Can you please explain what exactly is going wrong or what do you want to achieve? – Hardik Chauhan Aug 07 '19 at 10:13
  • Are you sure your server returns correct json for two situations? – faranjit Aug 07 '19 at 10:26
  • @HardikChauhan Well, As you can see the json.php it outputs different "id" and "state" when user is logged in. So, when I launch my app, login to the website "example.com/index.php" and reach "example.com/home.php", here at "example.com/json.php" also changes. But, within the JSON parser the output remains the same as if I never logged in. – Souvik Aug 07 '19 at 10:27
  • `isset($_SESSION['access_token']`, do you correctly set access_token? Maybe if you dont it returns loggedout state for every request. – faranjit Aug 07 '19 at 10:30
  • @faranjit Technically, when I open my app, login and then go to json.php from the app webview itself I am getting the output which I want. the JSON file shows I am logged in. But, within the JSON parser the JSON remains in a logged out state. I use PHP $_SESSION cookies. The JSON parser does not stores or accesses the session cookies which got saved from the webview I believe. Ideally, the JSON parser should read the logged in state in the next app launch just like WebView opens up index.php and finds cookie and redirects automatically to home.php – Souvik Aug 07 '19 at 10:33
  • Can you log the json result after this line `String jsonStr = sh.makeServiceCall(url);`? – faranjit Aug 07 '19 at 10:39
  • OK, I think I finally understood the problem. You can parse everything normally, but the "status" on JSON does not change? So if you make a request first, log in, then do the request again, the JSON still says logged out, correct? I would first try first try logging the raw response from the request to make sure the issue is not on your backend. – paulonogueira Aug 07 '19 at 11:10
  • @faranjit here is the logcat brother. Screenshot: http://prntscr.com/opibvy Note: changed the "id" to "xyz" when logged out and "abc" when logged in. Here is the json.php within WebView: http://prntscr.com/opid6r Added this line after the line that you mentioned: `Log.v("JSON", jsonStr);` – Souvik Aug 07 '19 at 11:11
  • Seems to me everything should be working, I just can't see how you are using the value you set on webUserID, as it is declared locally. – paulonogueira Aug 07 '19 at 11:16
  • yes @leparlon you got that correct. I'm currently not making any request after user logs in (cause I can't fetch when user logs in) (NOT A PROBLEM cause it should fetch the json.php on "logged in state" the next time app runs) but more or less everything else is correcrt. My **json.php** changes within the webview but not within the JSON parser. – Souvik Aug 07 '19 at 11:18
  • Could you try my answer? – faranjit Aug 07 '19 at 11:19
  • @leparlon if you are interested about webUserID I use that string to set OneSignalExternal ID (If you are familiar with it) and it just works fine. If you are worried if the string caches the data somehow (I don't know why but..) it really doesn't cause I am changing the ID values for testing purposes and on every new app start my OneSignalExternal ID changes successfully. – Souvik Aug 07 '19 at 11:23
  • Not the string caching, it is just that on your example code the value never goes anywhere. And I imagined that, maybe you are trying to access it from outside somewhere, and since the initial value is 0 and you probably initiated the value as zero.... I'm just guessing a really simple mistake, that you forgot to actually set the correct variable: ie. instead of webUserID = c.getString("id"); --> this.webUserID = c.getString("id"); not that this is right btw – paulonogueira Aug 07 '19 at 14:36
  • Nope, not the case here @leparlon everthing is fine within the code. I just needed to sync the **WebView cookies** with the HTTPClient's. And it works like a charm now. However while using this method, my app keeps crashing whenever there's no internet connection. Do you have a workaround for that? I have made a different thread siche it's a different problem. It'll be great if u can have a look at [this thread](https://stackoverflow.com/q/57400863/9198115) – Souvik Aug 07 '19 at 19:23

2 Answers2

1

Looks like your JSON on json.php is wrong

echo '{"userinfo": [{"status": "loggedout","id": "0": ""}]}';

should be

echo '{"userinfo": [{"status": "loggedout","id": "0"}]}';

paulonogueira
  • 2,684
  • 2
  • 18
  • 31
1

You store the infos about logged in or not in cookies or session via WebView but you want to access to that data from with a http client. I think it would be better you should sync cookies and session before access the json. To do this check this and this.

faranjit
  • 1,567
  • 1
  • 15
  • 22
  • Okay so I am supposed to sync the session and cookies of the web view with that of http client. Got that. Let me try this approach and get back to you shortly! Thank you very much for this lead. – Souvik Aug 07 '19 at 11:32
  • Hey, I was following [this](https://stackoverflow.com/a/28211560/9198115) thread and seems like I solved my "need" and now can successfully fetch user's ID. But, there's a new problem when we use this method. The app crashes if there is no internet connection. Do you have a workaround for that? Thanks! Since this is a different issue I've created a [different thread here](https://stackoverflow.com/q/57400863/9198115) – Souvik Aug 07 '19 at 19:25