3

I'm having trouble with JSON transfer in Android. I receive the following error in LogCat.

04-29 04:47:11.362: E/Trace(851): error opening trace file: No such file or directory (2)
04-29 04:47:12.243: I/System.out(851): 1
04-29 04:47:12.243: I/System.out(851): 2
04-29 04:47:12.303: W/System.err(851): java.lang.IllegalArgumentException: Illegal character in query     at index 42: http://SOME_WEBSITE/api/api.php?package=    {"key":"SOME_KEY","info":{"type":"user","login":{"password":"some_password","email":"test@gmail.    com"}},"request":"info"}
04-29 04:47:12.313: W/System.err(851):  at java.net.URI.create(URI.java:727)
04-29 04:47:12.333: W/System.err(851):  at org.apache.http.client.methods.HttpGet.<init>(HttpGet.    java:75)
04-29 04:47:12.333: W/System.err(851):  at com.example.jsontest.MainActivity.onCreate(MainActivity.    java:47)
04-29 04:47:12.333: W/System.err(851):  at android.app.Activity.performCreate(Activity.java:5104)
04-29 04:47:12.333: W/System.err(851):  at android.app.Instrumentation.callActivityOnCreate(    Instrumentation.java:1080)
04-29 04:47:12.333: W/System.err(851):  at android.app.ActivityThread.performLaunchActivity(    ActivityThread.java:2144)
04-29 04:47:12.343: W/System.err(851):  at android.app.ActivityThread.handleLaunchActivity(    ActivityThread.java:2230)
04-29 04:47:12.343: W/System.err(851):  at android.app.ActivityThread.access$600(ActivityThread.    java:141)
04-29 04:47:12.343: W/System.err(851):  at android.app.ActivityThread$H.handleMessage(ActivityThread.    java:1234)
04-29 04:47:12.343: W/System.err(851):  at android.os.Handler.dispatchMessage(Handler.java:99)
04-29 04:47:12.343: W/System.err(851):  at android.os.Looper.loop(Looper.java:137)
04-29 04:47:12.343: W/System.err(851):  at android.app.ActivityThread.main(ActivityThread.java:5041)
04-29 04:47:12.343: W/System.err(851):  at java.lang.reflect.Method.invokeNative(Native Method)
04-29 04:47:12.402: W/System.err(851):  at java.lang.reflect.Method.invoke(Method.java:511)
04-29 04:47:12.402: W/System.err(851):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(    ZygoteInit.java:793)
04-29 04:47:12.402: W/System.err(851):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
04-29 04:47:12.402: W/System.err(851):  at dalvik.system.NativeStart.main(Native Method)
04-29 04:47:12.402: I/System.out(851): Something is wrong

This the Android code that I am trying to run

public class MainActivity extends Activity 
{       
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView the_text_view = (TextView) findViewById(R.id.name);

        //Construct the JSON
        JSONObject json = new JSONObject();
        JSONObject info_json = new JSONObject();
        JSONObject login_info = new JSONObject();

        try
        {    
            login_info.put("email", "test@gmail.com");
            login_info.put("password", "some_password");

            info_json.put("type", "user");
            info_json.put("login", login_info);

            json.put("key", "SOME_KEY");
            json.put("request", "info");
            json.put("info", info_json);

            HttpClient httpClient = new DefaultHttpClient();
            System.out.println("1");
            String requestLink = "http://SOME_WEBSITE/api/api.php?package="+json.toString();
            System.out.println("2");        
            HttpGet httpGet = new HttpGet(requestLink);
            System.out.println("3");
            HttpResponse httpResponseGet = httpClient.execute(httpGet);
            System.out.println("4");
            HttpEntity resEntityGet = httpResponseGet.getEntity();
            System.out.println("5");

            if (resEntityGet != null) 
            {
                String response = EntityUtils.toString(resEntityGet);             
                JSONObject json_response = new JSONObject(response);             
                System.out.println(json.toString());
            }

            System.out.println("Looks alright");
        }
        catch (Exception e) 
        {
            e.printStackTrace();  
            System.out.println("Something is wrong");
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}

It has to be something with the GET call. I'm not sure what exactly it is, but all my System.out print up to that part of the program...

Thanks in advance for any help!

Ahmad Azwar Anas
  • 1,289
  • 13
  • 22
nathansizemore
  • 3,028
  • 7
  • 39
  • 63

6 Answers6

4

First You are passing a query string that has spaces in it, which will break the url. Tehrefore, you need to perform an encode before sending:

String requestLink = "http://SOME_WEBSITE/api/api.php?package="+Encoder.encode(json.toString(),"UTF-8");

Second

You are trying to perform network operation on UI Thread, which will not be allowed in Android 3.0+ and will throw NetworkOnMainThreadException. Use AsyncTask or a separate thread to perform the Network Operation.

Laur Ivan
  • 4,117
  • 3
  • 38
  • 62
Pragnani
  • 20,075
  • 6
  • 49
  • 74
  • I wish the tutorials and examples around would have mentioned this. Not one that I have read has had an example of `AsyncTask` used when doing anything network related. Thanks. – nathansizemore Apr 29 '13 at 17:05
2

Try :

String requestLink = "http://SOME_WEBSITE/api/api.php?package="+json.toString();
String finalRequestString = URLEncoder.encode(requestLink,"UTF-8");
AllTooSir
  • 48,828
  • 16
  • 130
  • 164
1
java.lang.IllegalArgumentException: Illegal character in query

There as a character in your get request which is not legal in a URL. You must URL Encode strings before you pass them in a GET request. For further details, see:

https://en.wikipedia.org/wiki/Percent-encoding

Aurand
  • 5,487
  • 1
  • 25
  • 35
1

I hope this will help you. In this class both method is coded. In this you can also pass your required parameters.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.util.ArrayList;

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.HttpClient;
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.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.json.JSONException;
import org.json.JSONObject;

public class JsonClient {

    public enum RequestMethod{
        GET,
        POST
    }

    private ArrayList <NameValuePair> params;
    private ArrayList <NameValuePair> headers;

    private String url;

    private int responseCode;
    private String message;

    private JSONObject jsonResponse;

    public JSONObject getResponse() {
        return jsonResponse;
    }

    public String getErrorMessage() {
        return message;
    }

    public int getResponseCode() {
        return responseCode;
    }

    public JsonClient(String url)
    {
        this.url = url;
        params = new ArrayList<NameValuePair>();
        headers = new ArrayList<NameValuePair>();
    }

    public void addParam(String name, String value)
    {
        params.add(new BasicNameValuePair(name, value));
    }

    public void addHeader(String name, String value)
    {
        headers.add(new BasicNameValuePair(name, value));
    }

    public void execute(RequestMethod method) throws Exception
    {
        switch(method) {
        case GET:
        {
            //add parameters
            String combinedParams = "";
            if(!params.isEmpty()){
                combinedParams += "?";
                for(NameValuePair p : params)
                {
                    String paramString = p.getName() + "=" + URLEncoder.encode(p.getValue(),"UTF-8");
                    if(combinedParams.length() > 1)
                    {
                        combinedParams  +=  "&" + paramString;
                    }
                    else
                    {
                        combinedParams += paramString;
                    }
                }
            }

            HttpGet request = new HttpGet(url + combinedParams);

            //add headers
            for(NameValuePair h : headers)
            {
                request.addHeader(h.getName(), h.getValue());
            }

            executeRequest(request, url);
            break;
        }
        case POST:
        {
            HttpPost request = new HttpPost(url);

            //add headers
            for(NameValuePair h : headers)
            {
                request.addHeader(h.getName(), h.getValue());
            }

            if(!params.isEmpty()){
                request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
            }

            executeRequest(request, url);
            break;
        }
        }
    }

    private void executeRequest(HttpUriRequest request, String url)
    {
        HttpClient client = new DefaultHttpClient();

        HttpResponse httpResponse;

        try {
            httpResponse = client.execute(request);
            responseCode = httpResponse.getStatusLine().getStatusCode();
            message = httpResponse.getStatusLine().getReasonPhrase();

            HttpEntity entity = httpResponse.getEntity();

            if (entity != null) {

                InputStream instream = entity.getContent();
                String  response = convertStreamToString(instream);
                jsonResponse = new JSONObject(response);

                // Closing the input stream will trigger connection release
                instream.close();
            }

        } catch (ClientProtocolException e)  {
            client.getConnectionManager().shutdown();
            e.printStackTrace();
        } catch (IOException e) {
            client.getConnectionManager().shutdown();
            e.printStackTrace();
        }catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private static String convertStreamToString(InputStream is) {

        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();

        String line = null;
        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return sb.toString();
    }
}
anddev
  • 3,144
  • 12
  • 39
  • 70
1

If you want to use the JSON as a 'GET' (ie as part of the url) then you'll need to encode the string. For example, notice when you enter a whitespace in your browser, it converts it to a %20. This is because url cannot contain whitespace.

Check this post for how to encode your url: Java URL encoding of query string parameters

Community
  • 1
  • 1
tbkn23
  • 5,205
  • 8
  • 26
  • 46
1

The LogCat output shows some spaces in the requestLink string you are trying to use for the GET request. Here is the relevant bit from the LogCat

package=    {

You see the spaces between the equals sign and the opening curly brace?

You should probably trim the empty space from the JSON string before you concatenate it to the base URL. You should also consider using the Uri parse method to ensure all the characters are encoded properly, http://developer.android.com/reference/android/net/Uri.html#parse(java.lang.String).

Finally, are you sure you want to append a big JSON string to the base URL? That seems kind of strange but if the API calls for it the above advice should fix your problem.

Matt Accola
  • 4,090
  • 4
  • 28
  • 37
  • I don't really want to use it as a `GET`. I would rather use `POST`, but cannot really find a decent tutorial for this. Now that I've got the `GET` working, it will be easier to figure out the `POST` stuff once I find a decent tutorial – nathansizemore Apr 29 '13 at 17:02