title: Android Studio java.net.MalformedURLException: Protocol not found:
body: <p>I am working on the sunshine app from udacity tutorials. I am somewhere on lesson2. When I try to run a feature of the app I get this errors:</p>
  
  <pre><code>04-29 12:21:13.311  22025-22424/name.company.sunshine.app E/FetchWeatherTask﹕ Error
      java.net.MalformedURLException: Protocol not found: "http://api.openweathermap.org/data/2.5/forecast/daily?q=94043&amp;mode=json&amp;units=metric&amp;cnt=7
              at java.net.URL.&lt;init&gt;(URL.java:176)
              at java.net.URL.&lt;init&gt;(URL.java:125)
              at name.company.sunshine.app.ForecastFragment$FetchWeatherTask.doInBackground(ForecastFragment.java:144)
              at name.company.sunshine.app.ForecastFragment$FetchWeatherTask.doInBackground(ForecastFragment.java:101)
              at android.os.AsyncTask$2.call(AsyncTask.java:288)
              at java.util.concurrent.FutureTask.run(FutureTask.java:237)
              at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
              at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
              at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
              at java.lang.Thread.run(Thread.java:841)
  04-29 12:21:13.321  22025-22025/name.company.sunshine.app D/AbsListView﹕ unregisterIRListener() is called
  04-29 12:21:13.321  22025-22025/name.company.sunshine.app E/ViewRootImpl﹕ sendUserActionEvent() mView == null 
  </code></pre>
  
  <p>line 144 is </p>
  
  <pre><code> URL url = new URL(builtUri.toString());
  </code></pre>
  
  <p>I will provide the entire class if you need it. </p>
  
  <p>And something else, I have this in the manifest </p>
  
  <pre><code>&lt;uses-permission android:name="android.permission.INTERNET" /&gt; 
  </code></pre>
  
  <p>but when I install the app it never asks for permission.</p>
  
  <p>This is the file : </p>
  
  <pre><code>package name.company.sunshine.app;
  
  import android.net.Uri;
  import android.os.AsyncTask;
  import android.os.Bundle;
  import android.support.v4.app.Fragment;
  import android.text.format.Time;
  import android.util.Log;
  import android.view.LayoutInflater;
  import android.view.Menu;
  import android.view.MenuInflater;
  import android.view.MenuItem;
  import android.view.View;
  import android.view.ViewGroup;
  import android.widget.ArrayAdapter;
  import android.widget.ListView;
  
  import org.json.JSONArray;
  import org.json.JSONException;
  import org.json.JSONObject;
  
  import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.net.HttpURLConnection;
  import java.net.URL;
  import java.text.SimpleDateFormat;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.List;
  
  /**
   * A placeholder fragment containing a simple view.
   */
  public class ForecastFragment extends Fragment {
  
      private ArrayAdapter&lt;String&gt; mForecastAdapter;
  
      public ForecastFragment() {
  
      }
  
  
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setHasOptionsMenu(true);
      }
  
  
      @Override
      public void onCreateOptionsMenu(Menu menu,MenuInflater inflater) {
          inflater.inflate(R.menu.forecastfragment, menu);
      }
  
      @Override
      public boolean onOptionsItemSelected(MenuItem item) {
          // Handle action bar item clicks here. The action bar will
          // automatically handle clicks on the Home/Up button, so long
          // as you specify a parent activity in AndroidManifest.xml.
          int id = item.getItemId();
  
          if(id == R.id.action_refresh){
           FetchWeatherTask weatherTask =   new FetchWeatherTask();
              weatherTask.execute("94043");
              return true;
          }
  
          return super.onOptionsItemSelected(item);
      }
  
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container,
                               Bundle savedInstanceState) {
          View rootView = inflater.inflate(R.layout.fragment_main, container, false);
  
          // These two need to be declared outside the try/catch
          // so that they can be closed in the finally block.
  
          String forecastArray[]  = {
                  "Today-Sunny-88/63",
                  "Tuesday-Foggy-14/32",
                  "Wednesday-Cloudy-22/33"
          };
  
  
          List&lt;String&gt; weekForecast = new ArrayList&lt;String&gt;(
                  Arrays.asList(forecastArray));
  
  
          mForecastAdapter = new ArrayAdapter&lt;String&gt;(getActivity(),R.layout.list_item_forecast,R.id.list_item_forecast_textview,weekForecast);
  
  
          ListView listView = (ListView) rootView.findViewById(R.id.listview_forecast);
          listView.setAdapter(mForecastAdapter);
  
          return rootView;
      }
  
      public class FetchWeatherTask extends AsyncTask&lt;String, Void, String[]&gt; {
  
          private final String LOG_TAG = FetchWeatherTask.class.getSimpleName();
  
          @Override
          protected String[] doInBackground(String... params) {
  
              //If there's no zip code, there's nothing to look up. Verify size of params
              if(params.length == 0){
                  return null;
              }
  
              // These two need to be declared outside the try/catch
              // so that they can be closed in the finally block.
              HttpURLConnection urlConnection = null;
              BufferedReader reader = null;
  
              // Will contain the raw JSON response as a string.
              String forecastJsonStr = null;
  
              String format = "json";
              String units = "metric";
              int numDays = 7;
  
              try {
                  // Construct the URL for the OpenWeatherMap query
                  // Possible parameters are avaiable at OWM's forecast API page, at
                  // http://openweathermap.org/API#forecast
                  final String FORECAST_BASE_URL =
                          "\"http://api.openweathermap.org/data/2.5/forecast/daily?";
                  final String QUERY_PARAM = "q";
                  final String FORMAT_PARAM = "mode";
                  final String UNITS_PARAM = "units";
                  final String DAYS_PARAM = "cnt";
  
                  Uri builtUri = Uri.parse(FORECAST_BASE_URL).buildUpon()
                          .appendQueryParameter(QUERY_PARAM,params[0])
                          .appendQueryParameter(FORMAT_PARAM,format)
                          .appendQueryParameter(UNITS_PARAM,units)
                          .appendQueryParameter(DAYS_PARAM,Integer.toString(numDays)).build();
  
                  Log.v(LOG_TAG,"Built URI"+builtUri.toString());
  
                  URL url = new URL(builtUri.toString());
  
                  // Create the request to OpenWeatherMap, and open the connection
                  urlConnection = (HttpURLConnection) url.openConnection();
                  urlConnection.setRequestMethod("GET");
                  urlConnection.connect();
  
                  // Read the input stream into a String
                  InputStream inputStream = urlConnection.getInputStream();
                  StringBuffer buffer = new StringBuffer();
                  if (inputStream == null) {
                      // Nothing to do.
                      return null;
                  }
                  reader = new BufferedReader(new InputStreamReader(inputStream));
  
                  String line;
                  while ((line = reader.readLine()) != null) {
                      // Since it's JSON, adding a newline isn't necessary (it won't affect parsing)
                      // But it does make debugging a *lot* easier if you print out the completed
                      // buffer for debugging.
                      buffer.append(line + "\n");
                  }
  
                  if (buffer.length() == 0) {
                      // Stream was empty.  No point in parsing.
                      return null;
                  }
                  forecastJsonStr = buffer.toString();
              } catch (IOException e) {
                  Log.e(LOG_TAG, "Error ", e);
                  // If the code didn't successfully get the weather data, there's no point in attemping
                  // to parse it.
                  return null;
              } finally {
                  if (urlConnection != null) {
                      urlConnection.disconnect();
                  }
                  if (reader != null) {
                      try {
                          reader.close();
                      } catch (final IOException e) {
                          Log.e(LOG_TAG, "Error closing stream", e);
                      }
                  }
              }
  
              try{
                  return getWeatherDataFromJson(forecastJsonStr,numDays);
              } catch (JSONException e){
                  Log.e(LOG_TAG,e.getMessage(),e);
                  e.printStackTrace();
              }
              return null;
          }
  
          /* The date/time conversion code is going to be moved outside the asynctask later,
          * so for convenience we're breaking it out into its own method now.
                  */
          private String getReadableDateString(long time){
              // Because the API returns a unix timestamp (measured in seconds),
              // it must be converted to milliseconds in order to be converted to valid date.
              SimpleDateFormat shortenedDateFormat = new SimpleDateFormat("EEE MMM dd");
              return shortenedDateFormat.format(time);
          }
  
          /**
           * Prepare the weather high/lows for presentation.
           */
          private String formatHighLows(double high, double low) {
              // For presentation, assume the user doesn't care about tenths of a degree.
              long roundedHigh = Math.round(high);
              long roundedLow = Math.round(low);
  
              String highLowStr = roundedHigh + "/" + roundedLow;
              return highLowStr;
          }
  
          /**
           * Take the String representing the complete forecast in JSON Format and
           * pull out the data we need to construct the Strings needed for the wireframes.
           *
           * Fortunately parsing is easy:  constructor takes the JSON string and converts it
           * into an Object hierarchy for us.
           */
          private String[] getWeatherDataFromJson(String forecastJsonStr, int numDays)
                  throws JSONException {
  
              // These are the names of the JSON objects that need to be extracted.
              final String OWM_LIST = "list";
              final String OWM_WEATHER = "weather";
              final String OWM_TEMPERATURE = "temp";
              final String OWM_MAX = "max";
              final String OWM_MIN = "min";
              final String OWM_DESCRIPTION = "main";
  
              JSONObject forecastJson = new JSONObject(forecastJsonStr);
              JSONArray weatherArray = forecastJson.getJSONArray(OWM_LIST);
  
              // OWM returns daily forecasts based upon the local time of the city that is being
              // asked for, which means that we need to know the GMT offset to translate this data
              // properly.
  
              // Since this data is also sent in-order and the first day is always the
              // current day, we're going to take advantage of that to get a nice
              // normalized UTC date for all of our weather.
  
              Time dayTime = new Time();
              dayTime.setToNow();
  
              // we start at the day returned by local time. Otherwise this is a mess.
              int julianStartDay = Time.getJulianDay(System.currentTimeMillis(), dayTime.gmtoff);
  
              // now we work exclusively in UTC
              dayTime = new Time();
  
              String[] resultStrs = new String[numDays];
              for(int i = 0; i &lt; weatherArray.length(); i++) {
                  // For now, using the format "Day, description, hi/low"
                  String day;
                  String description;
                  String highAndLow;
  
                  // Get the JSON object representing the day
                  JSONObject dayForecast = weatherArray.getJSONObject(i);
  
                  // The date/time is returned as a long.  We need to convert that
                  // into something human-readable, since most people won't read "1400356800" as
                  // "this saturday".
                  long dateTime;
                  // Cheating to convert this to UTC time, which is what we want anyhow
                  dateTime = dayTime.setJulianDay(julianStartDay+i);
                  day = getReadableDateString(dateTime);
  
                  // description is in a child array called "weather", which is 1 element long.
                  JSONObject weatherObject = dayForecast.getJSONArray(OWM_WEATHER).getJSONObject(0);
                  description = weatherObject.getString(OWM_DESCRIPTION);
  
                  // Temperatures are in a child object called "temp".  Try not to name variables
                  // "temp" when working with temperature.  It confuses everybody.
                  JSONObject temperatureObject = dayForecast.getJSONObject(OWM_TEMPERATURE);
                  double high = temperatureObject.getDouble(OWM_MAX);
                  double low = temperatureObject.getDouble(OWM_MIN);
  
                  highAndLow = formatHighLows(high, low);
                  resultStrs[i] = day + " - " + description + " - " + highAndLow;
              }
  
              for (String s : resultStrs) {
                  Log.v(LOG_TAG, "Forecast entry: " + s);
              }
              return resultStrs;
  
          }
      }
  
  }
  </code></pre>
  
  <p>Now I don t have the error anymore after deleting "<code>/"</code> ", but this line is not being printed </p>
  
  <pre><code>for (String s : resultStrs) {
                      Log.v(LOG_TAG, "Forecast entry: " + s);
                  }
  </code></pre>
  
  <p>probably it fails to connect or something. I can't see anything in logCat for some reason .</p>