0

Here is my code. This is just a snippet of the whole application. It makes a HTTP request and gets train data from septa. The code is correct as it works in a java project. One note, when I try to do the simple http request part in a separate java class and run it as a java file. In the run it gives me a Fatal Error: Invalid Layout of java.lang.String at value. I tried looking at the thread at this forum. Nothing works. No idea why this is happening. The code was working before!

package com.cs275.septaassignment;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.HttpURLConnection;

import android.app.Activity;
import android.os.Bundle;
import android.os.AsyncTask;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.google.gson.*;

import java.util.ArrayList;

public class TrainInfo extends Activity
{
    protected static String startStation;
    protected static String endStation;

    private ListView listView;//ListView for the output
    private ArrayAdapter<String> adapter;//Adapter to interact with the ListView


    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.train_infolayout);

        startStation = this.getIntent().getExtras().getString("fromStation");
        endStation = this.getIntent().getExtras().getString("toStation");

        ArrayList<String> trainInfo = new ArrayList<String>();

        adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, trainInfo);//initializing the ArrayAdapter

        listView = (ListView)findViewById(R.id.train_listView);
        listView.setAdapter(adapter);//Linking the adapter      
        adapter.setNotifyOnChange(true);//This ensures that the changes in data so the UI components can refresh themselves     

        TrainData trainSchedule = new TrainData();
        trainSchedule.execute();
    }
    public class TrainData extends AsyncTask<Void,Void,Void>
    {
        ArrayList<String> nextTrains;

        protected void onPostExecute(Void arg0)//This method is called after the background process is complete 
        {
            adapter.clear();
            for(int i = 0;i<nextTrains.size();i++)
            {
                System.out.println(nextTrains.get(i));
                adapter.add(nextTrains.get(i));
            }
            adapter.add("Hello World");
            TextView updateMessage = (TextView) findViewById(R.id.train_list_info);
            updateMessage.setText("Here are the available trains for your trip from " + startStation + " to " + endStation);
            adapter.notifyDataSetChanged();//This send the signal that the data is changes and allows the UI components like the ListView to get updated.           

        }
        @Override
        protected Void doInBackground(Void... params) 
        {
            // TODO Auto-generated method stub
            try
            {
                String sURL = "http://www3.septa.org/hackathon/NextToArrive/"+ startStation + "/" + endStation + "/10"; 
                System.out.println(sURL);
                URL url = new URL(sURL);
                HttpURLConnection request = (HttpURLConnection) url.openConnection();
                request.connect();

                JsonParser jp = new JsonParser();//Json parsing tool
                JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent()));//Getting content in Json
                System.out.println("root:\n" + root);
                JsonArray rootArray = root.getAsJsonArray();

                nextTrains = new ArrayList<String>();
                if(rootArray.size() > 0)
                {
                    for(int i = 0;i<rootArray.size();i++)
                    {
                        JsonObject train = rootArray.get(i).getAsJsonObject();
                        String departureTime = train.get("orig_departure_time").getAsString();
                        String arrivalTime = train.get("orig_arrival_time").getAsString();
                        String delayTime = train.get("orig_delay").getAsString();
                        String trainNumber = train.get("orig_train").getAsString();

                        String result = "Train " + trainNumber + "\nDeparts from " + startStation + ": " + departureTime
                                        + "\nArrives at " + endStation + ": " + arrivalTime;
                        if(!delayTime.equals("On Time"))
                            result = result + "\nDelayed: " + delayTime;
                        nextTrains.add(result);
                    }
                }else
                {
                    nextTrains.add("No trains available from " + startStation + " to " + endStation);
                }


                }catch(Exception e)
                {
                    System.out.println("Unable to make http request!");
                }
            return null;
        }
        public void retrieveData()
        {

        }
    }
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
user3213348
  • 255
  • 1
  • 5
  • 14

3 Answers3

0

You should avoid possible threading issues by defining the AsyncTask as <Intent, Void, Void> and call its execute method like trainSchedule.execute(getIntent()); Change doInBackground(Void... params) to doInBackground(Intent... params) and get the extras from that intent before you setup the URL by using

String start = params[0].getExtras().getString("fromStation");
String end = params[0].getExtras().getString("toStation");
SDJMcHattie
  • 1,690
  • 1
  • 15
  • 21
0

Use the URLEncoder encode method to encode your URL which will change spaces to %20 and other necessary encoding

Update

As pointed out, the above method will actually encode spaces to + which is no good in this case because the server doesn't handle them well. You could also try Uri.encode which looks like it should encode spaces to %20 like you want.

Further Update

According to this answer you're going to have to encode the spaces yourself after using the URLEncoder like so: URLEncoder.encode(sURL, "UTF-8").replace("+", "%20")

Community
  • 1
  • 1
SDJMcHattie
  • 1,690
  • 1
  • 15
  • 21
0

run it as a java file. In the run it gives me a Fatal Error: Invalid Layout of java.lang.String at value

Run it as an Android application, not as a generic Java application.

laalto
  • 150,114
  • 66
  • 286
  • 303