UDACITY Sunshine Android App Error - java.io.FileNotFoundException - java

Im a beginner in Android Development and i have been following the SUNSHINE App. Everything seemed to be going great until today that I ran the App and found an Error: java.io.FileNotFoundException:http://api.openweathermap.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7
I did my research and it appears The Openweathermap api now requires an API key.
As a beginner I do not know how to implement this to my current app so as I can continue with my course. I'm simply STUCK because of this.and I would appreciate any work through/help to overcome this:(THANK YOU)
Here is my ForecastFragment.java:
package com.example.android.sunshine.app;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
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.Date;
import java.util.List;
/**
* A placeholder fragment containing a simple view.
*/
public class ForecastFragment extends Fragment {
private ArrayAdapter<String> 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){
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);
String[] data = {
"Today - Sunny - 88/63",
"Tommorow-Foggy-70/40",
"weds - Cloudy - 72/63",
"Thurs - Asteroids - 75/65",
"Fri - Heavy Rains - 65/56",
"Sat - HELP TRAPPED IN WEATHERSATION - 60/51",
"Sun - Sunny - 80/68"
};
List<String> weekForecast = new ArrayList<String>(Arrays.asList(data));
mForecastAdapter =
new ArrayAdapter<String>(
getActivity(), R.layout.list_item_forcast,
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<String, Void, String[]> {
private final String LOG_TAG = FetchWeatherTask.class.getSimpleName();
private String getReadableDateString(long time){
Date date = new Date(time*1000);
SimpleDateFormat format = new SimpleDateFormat("E,MMM d");
return format.format(date).toString();
}
private String formatHighLows(double high,double low){
long roundedHigh = Math.round(high);
long roundedLow = Math.round(low);
return null;
}
private String[] getWeatherDataFromJson(String forecastJsonStr, int numDays)
throws JSONException{
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_DATETIME = "dt";
final String OWM_DESCRIPTION = "main";
JSONObject forecastJson = new JSONObject(forecastJsonStr);
JSONArray weatherArray = forecastJson.getJSONArray(OWM_LIST);
String[] resultStrs = new String[numDays];
for (int i=0; i < weatherArray.length(); i++){
String day;
String description;
String highAndLow;
JSONObject dayForecast = weatherArray.getJSONObject(i);
long dateTime = dayForecast.getLong(OWM_DATETIME);
day = getReadableDateString(dateTime);
JSONObject weatherObject = dayForecast.getJSONArray(OWM_WEATHER).getJSONObject(0);
description = weatherObject.getString(OWM_DESCRIPTION);
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;
}
#Override
protected String[] doInBackground(String... params){
if (params.length == 0){
return null;
}
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
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();
URL url = new URL(builtUri.toString());
Log.v(LOG_TAG,"Built URI" + 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.
forecastJsonStr = 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.
forecastJsonStr = 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.
forecastJsonStr = 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;
}
#Override
protected void onPostExecute(String[] result) {
if (result !=null){
mForecastAdapter.clear();
for (String dayForecastStr : result){
mForecastAdapter.add(dayForecastStr);
}
}
}
}
}

To add the API key you just need to append the parameter to the end of the query:
http://api.openweathermap.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7&appid=[your_api_key]
If you click through the examples on their page, you'll see that they've updated their samples to include an API key: http://openweathermap.org/forecast5

First sign up for an API key here
Then add the API key to the end of the query:
http://api.openweathermap.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=7&appid=[your_api_key]

Related

org.json.JSONException: No value for senses

I am trying to make an English Dictionary using the Oxford API. I made this according to docs and resources found on the web. But I got this issue "org.json.JSONException: No value for senses" and I don't why. Wherever I looked I couldn't find reason of this issue. I'll give you my MainActivity and request class. Can anyone help me?
MainActiviy:
package com.alitalhacoban.english_dictionary;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
TextView textView;
EditText editText;
private String url;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
editText = findViewById(R.id.editText);
url = dictionaryEntries();
}
public void find(View view){
MyDictionaryRequest myDictionaryRequest = new MyDictionaryRequest(this);
myDictionaryRequest.execute(url);
}
private String dictionaryEntries() {
final String language = "en-gb";
final String word = "Ace";
final String fields = "pronunciations";
final String strictMatch = "false";
final String word_id = word.toLowerCase();
return "https://od-api.oxforddictionaries.com:443/api/v2/entries/" + language + "/" + word_id + "?" + "fields=" + fields + "&strictMatch=" + strictMatch;
}
}
Request class:
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.Toast;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
public class MyDictionaryRequest extends AsyncTask<String, Integer, String> {
Context context;
MyDictionaryRequest(Context context) {
this.context = context;
}
final String app_id = "127ae33f";
final String app_key = "e42c0fccfe30223fb9ec02e12ae8c8a9";
#Override
protected String doInBackground(String... params) {
try {
URL url = new URL(params[0]);
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.setRequestProperty("app_id", app_id);
urlConnection.setRequestProperty("app_key", app_key);
BufferedReader reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
return stringBuilder.toString();
} catch (Exception e) {
e.printStackTrace();
return e.toString();
}
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
String def = "";
try {
JSONObject js = new JSONObject(result);
JSONArray results = js.getJSONArray("results");
for (int i = 0; i < results.length(); i++) {
JSONObject lentries = results.getJSONObject(i);
JSONArray la = lentries.getJSONArray("lexicalEntries");
for (int j = 0; j < la.length(); j++) {
JSONObject entries = la.getJSONObject(j);
JSONArray e = entries.getJSONArray("entries");
for (int k = 0; k < e.length(); k++) {
JSONObject senses = e.getJSONObject(k);
JSONArray s = senses.getJSONArray("senses");
JSONObject d = e.getJSONObject(0);
JSONArray de = d.getJSONArray("definitions");
def = de.getString(0);
}
}
}
Log.e("def", def);
} catch (JSONException e) {
e.printStackTrace();
}
}
}
try to validate the "senses" with senses.has("senses") before use it and then parse it with optjsonarray or optjsonobject for this type and check this key or check at backend side from where what value getting in json response.

How to fetch data from net faster and display in listView?

I have a news app. My app takes so much time to fetch data from server and display it on the listView.But i have seen that apps like flipboard,facebook and Game News which has more data to fetch than mine does it faster.I think my app loads the entire data and displays the entire list together.Is there a way to display the list such that it loads the items in listView one by one?I do the fetching using a AsyncTaskLoader in the background.Also how to display a large list of news like 100 in a list .
MainActivity:
package com.example.android.gametalks;
import android.app.LoaderManager;
import android.content.Intent;
import android.content.Loader;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<GameNews>> {
//IGN url
final String ign_url = "https://newsapi.org/v1/articles?source=ign&sortBy=top&apiKey=679f6fb918d34343b18590ca70f7fcde";
final String google_url = " https://newsapi.org/v1/articles?source=google-news&sortBy=top&apiKey=679f6fb918d34343b18590ca70f7fcde";
final String engadget_url = "https://newsapi.org/v1/articles?source=engadget&sortBy=top&apiKey=679f6fb918d34343b18590ca70f7fcde";
GameAdapter adapter ;
private View progressBar;
final private int game_loader = 0;
ArrayList<String> urls = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
urls.add(ign_url);
urls.add(google_url);
urls.add(engadget_url);
//Getting listView
ListView gameListView = (ListView) findViewById(R.id.listView);
//progress bar finding
progressBar = findViewById(R.id.progress_bar);
ArrayList<GameNews> gameList = new ArrayList<>();
//Making a new arrayAdapter
adapter = new GameAdapter(this,gameList);
//Connecting ArrayAdapter to ListView
gameListView.setAdapter(adapter);
getLoaderManager().initLoader(game_loader, null, this);
//ListView item click listner
gameListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
GameNews currentEarthquake = adapter.getItem(i);
String url = currentEarthquake.getUrl();
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
startActivity(intent);
}
});
}
#Override
public Loader<List<GameNews>> onCreateLoader(int i, Bundle bundle) {
return new GameLoader(this,urls);
}
#Override
public void onLoadFinished(Loader<List<GameNews>> loader, List<GameNews> games) {
progressBar.setVisibility(View.INVISIBLE);
adapter.clear();
if(games == null)
{
return;
}
adapter.addAll(games);
}
#Override
public void onLoaderReset(Loader<List<GameNews>> loader) {
adapter.clear();
}
}
GameLoader:
package com.example.android.gametalks;
import android.content.AsyncTaskLoader;
import android.content.Context;
import java.util.ArrayList;
import java.util.List;
/**
* Created by apple on 9/8/17.
*/
public class GameLoader extends AsyncTaskLoader<List<GameNews>> {
private ArrayList<String> Urls = new ArrayList<>();
public GameLoader(Context context, ArrayList<String> Url) {
super(context);
Urls = Url;
}
#Override
protected void onStartLoading()
{
forceLoad();
}
#Override
public List<GameNews> loadInBackground() {
if(Urls == null)
{
return null;
}
// Perform the HTTP request for earthquake data and process the response.
List<GameNews> games = QueryUtils.FetchEarthquakeData(Urls);
return games;
}
}
QueryUtils(Here the network fetching takes place):
package com.example.android.gametalks;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
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.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* Helper methods related to requesting and receiving earthquake data from USGS.
*/
public final class QueryUtils {
private static final String LOG_TAG = QueryUtils.class.getSimpleName();
/**
* Create a private constructor because no one should ever create a {#link QueryUtils} object.
* This class is only meant to hold static variables and methods, which can be accessed
* directly from the class name QueryUtils (and an object instance of QueryUtils is not needed).
*/
private QueryUtils() {
}
public static List<GameNews> FetchEarthquakeData(ArrayList<String> Url) {
List<GameNews> games ;
List<GameNews> Total = new ArrayList<>();
URL url;
Log.d(LOG_TAG,Url.get(0));
for(int i = 0 ; i < Url.size(); i++) {
url = createUrl(Url.get(i));
try {
//Make http request
String jsonResponse = makeHttpRequest(url);
games = extractFeatureFromJson(jsonResponse);
Total.addAll(games);
} catch (IOException e) {
Log.e("IOException", "" + e);
}
}
return Total;
}
private static URL createUrl(String stringUrl) {
URL url = null;
try {
url = new URL(stringUrl);
} catch (MalformedURLException e) {
Log.e(LOG_TAG, "Error with creating URL ", e);
}
return url;
}
private static String makeHttpRequest(URL url) throws IOException {
String jsonResponse = "";
InputStream inputStream = null;
HttpURLConnection urlConnection = null;
try {
urlConnection = (HttpURLConnection) url.openConnection();
if (urlConnection.getResponseCode() == 200) {
inputStream = urlConnection.getInputStream();
jsonResponse = readInputStream(inputStream);
} else {
Log.e(LOG_TAG, "" + urlConnection.getResponseCode());
return null;
}
} catch (IOException e) {
Log.d(LOG_TAG, "" + e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (inputStream != null) {
// function must handle java.io.IOException here
inputStream.close();
}
}
return jsonResponse;
}
private static String readInputStream(InputStream inputStream) throws IOException {
StringBuilder output = new StringBuilder();
if (inputStream != null) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, Charset.forName("UTF-8"));
BufferedReader reader = new BufferedReader(inputStreamReader);
String line = reader.readLine();
while (line != null) {
output.append(line);
line = reader.readLine();
}
}
return output.toString();
}
private static ArrayList<GameNews> extractFeatureFromJson(String jsonResponse) {
ArrayList<GameNews> games = new ArrayList<>();
try {
JSONObject jsonObject = new JSONObject(jsonResponse);
JSONArray articles = jsonObject.getJSONArray("articles");
for (int i = 0; i < articles.length(); i++) {
JSONObject currentGame = articles.getJSONObject(i);
// Extract the value for the key called "mag"
String title = currentGame.getString("title");
// Extract the value for the key called "place"
String description = currentGame.getString("description");
// Extract the value for the key called "url"
String url = currentGame.getString("url");
//Extract value from key called urlToImage
String urlToImage = "nn";
urlToImage = currentGame.getString("urlToImage");
URL urlOfImage = null;
Bitmap bmp = null;
try {
urlOfImage = new URL(urlToImage);
} catch (MalformedURLException e) {
e.printStackTrace();
}
try {
bmp = BitmapFactory.decodeStream(urlOfImage.openConnection().getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
// Create a new {#link Earthquake} object with the magnitude, location, time,
// and url from the JSON response.
GameNews game = new GameNews(title, description,bmp,url);
// Add the new {#link Earthquake} to the list of earthquakes.
games.add(game);
}
} catch (JSONException e) {
Log.d(LOG_TAG, "" + e);
}
return games;
}
}
Thanks in advance.

Arrayadapter add method not accepting string values

I am running an app on Android Studio and while adding string values to arrayadapter object, I get null pointer exception. My exact relevant code is:
protected void onPostExecute(String[] result) {
List<String> wordList = new ArrayList<>();
wordList = Arrays.asList(result);
if(wordList!= null)
{
for(String forecast: wordList)
{
Log.v(LOG_TAG,"forecast value: "+forecast);
mForecastAdapter.add(forecast);
}
// mForecastAdapter.addAll(wordList);
}
Log.v(LOG_TAG,"Sorry!! Result is null");
}
I tried with addAll() method as well, but for that I need to upgrade to API 11. So that is not an option. For Information: This result variable is not empty and in logs, I do get correct value of forecast every time I execute this set of code.
The exception that I get is:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ArrayAdapter.add(java.lang.Object)' on a null object reference
Here's my code:
package com.example.khatri.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;
public class ForecastFragment extends Fragment {
String[] resultfinal = new String[100];
public ForecastFragment() {
}
ArrayAdapter<String> mForecastAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Add this line in order for this fragment to handle menu events.
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.forecastfragment, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_refresh) {
FetchWeatherTask fetchWeatherTask = new FetchWeatherTask();
fetchWeatherTask.execute("94043");
}
return super.onOptionsItemSelected(item);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
List<String> weekForecast = new ArrayList<String>();
weekForecast.add("Today-Sunny-88/63");
weekForecast.add("Tomorrow FOggy 77/46");
weekForecast.add("Day after sunny again 45/34");
weekForecast.add("Thur-foggy again 65/34");
weekForecast.add("Fri afternoon rainy 76/32");
weekForecast.add("Sat happy sat 65/12");
weekForecast.add("Day after sunny again 45/34");
weekForecast.add("Thur-foggy again 65/34");
weekForecast.add("Fri afternoon rainy 76/32");
weekForecast.add("Sat happy sat 65/12");
ArrayAdapter<String> mForecastAdapter = new ArrayAdapter<String>(
getContext(),
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<String, Void, String[]> {
private final String LOG_TAG = FetchWeatherTask.class.getSimpleName();
protected String[] doInBackground(String... params) {
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;
String appid = "c70ffaa8bf3c10556dc3e82d72d23677";
try {
final String FORECAST_BASE_URL = "http://api.openweathermap.org/data/2.5/forecast/daily?";
final String FORMAT_PARAM = "mode";
final String QUERY_PARAM = "q";
final String UNITS_PARAM = "units";
final String DAYS_PARAM = "cnt";
final String APPID_PARAM = "appid";
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))
.appendQueryParameter(APPID_PARAM, appid)
.build();
URL url = new URL(builtUri.toString());
Log.v(LOG_TAG, "Built URI " + 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.
forecastJsonStr = null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
forecastJsonStr = null;
}
forecastJsonStr = buffer.toString();
Log.v(LOG_TAG, "forecast JSON string: " + forecastJsonStr);
} catch (Exception e) {
Log.e("PlaceholderFragment", "Error ", e);
forecastJsonStr = null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
resultfinal = getWeatherDataFromJson(forecastJsonStr, numDays);
reader.close();
} catch (final IOException e) {
Log.e("PlaceholderFragment", "Error closing stream", e);
}
catch (JSONException jsonexception)
{
Log.e(LOG_TAG,"JSON Exception",jsonexception);
}
}
}
return resultfinal;
}
private String getReadableDateString(long time) {
SimpleDateFormat shortenedDateFormat = new SimpleDateFormat("EEE MMM dd");
return shortenedDateFormat.format(time);
}
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;
}
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);
Time dayTime = new Time();
dayTime.setToNow();
int julianStartDay = Time.getJulianDay(System.currentTimeMillis(), dayTime.gmtoff);
dayTime = new Time();
String[] resultStrs = new String[numDays];
for(int i = 0; i < 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);
}
//onPostExecute(resultStrs);
return resultStrs;
}
#Override
protected void onPostExecute(String[] result) {
List<String> wordList = new ArrayList<>();
wordList = Arrays.asList(result);
if(wordList!= null)
{
// mForecastAdapter.add(result.toString());
for(String forecast: wordList)
{
Log.v(LOG_TAG,"forecast value: "+forecast);
mForecastAdapter.add(forecast);
}
// mForecastAdapter.addAll(wordList);
}
Log.v(LOG_TAG,"Sorry!! Reuslt is null");
}
}
}
when you take global variable then you just initialize first time and you use in you whole class. I hope this will help you and you got your solution.
public class ForecastFragment extends Fragment {
ArrayAdapter<String> mForecastAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
......
mForecastAdapter = new ArrayAdapter<String>(
getContext(),
R.layout.list_item_forecast,
R.id.list_item_forecast_textview,
weekForecast);
.....
}
}
You initialised the local mForecastAdapter variable in oncreateView() and adding values to global mForecastAdapter which is not initialized. Thats why it is giving you null pointer.
the point is the lifeCycle of fragment.
Can you ensure that the onCreteView() method has been called be before you call the onOptionsItemSelected() menthod ?
I suggest you to add some log code or set some breadpoints to see which method has been called first.
I got the answer for this from another thread:
clear the arrayadapter, mforecastAdapter.clear() then,
add values to this adapter and then,
mForecastAdapter.notifyDataSetChanged();
This depicted the change in my list view :)

why replace words to question mark in send data to server

I try send data to server but when I send Persian words it sends question marks, for example if I send "سلام" it sends "????"
How can I fix this ?
This is my FragmentForm.class :
package com.skyline.jimmy;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import com.skyline.jimmy.R;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings.Secure;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.RatingBar;
import android.widget.TextView;
import android.widget.Toast;
public class FragmentForm extends Fragment {
// An interface to display or dismiss of ProgressBar
public interface OnSendingRequestToServer {
public void DisplayLoding(boolean setVisibility);
}
private final String TAG = "FragmentForm";
private OnSendingRequestToServer onRequestToServer;
private Context context;
private EditText etName;
private EditText etComment;
private RatingBar ratingBar;
private ImageButton ibSubmit;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
onRequestToServer = (OnSendingRequestToServer) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnConnectingToServer interface.");
}
context = activity.getApplicationContext();
Log.d(TAG, "Fragment attached to activity.");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View view = inflater.inflate(R.layout.fragment_form, container, false);
etName = (EditText) view.findViewById(R.id.etName);
etComment = (EditText) view.findViewById(R.id.etComment);
ratingBar = (RatingBar) view.findViewById(R.id.ratingBar);
ibSubmit = (ImageButton) view.findViewById(R.id.ibSubmit);
//TextView tvcm = (TextView) view.findViewById(R.id.tvComment);
Log.d(TAG, "Fragment created.");
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
ibSubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String strName = etName.getText().toString().trim();
if(strName.length() <= 0) {
Toast.makeText(context, "نام خود را وارد کنید", Toast.LENGTH_LONG).show();
return;
}
String strComment = etComment.getText().toString().trim();
if(strComment.length() <= 0) {
Toast.makeText(context, "متن جک را وارد کنید", Toast.LENGTH_LONG).show();
return;
}
int rate = (int) ratingBar.getRating();
if(rate <= 0) {
Toast.makeText(context, "امتیاز جکتان را وارد کنید", Toast.LENGTH_LONG).show();
return;
}
String deviceId = getDeviceId();
new SendFormTask(deviceId, strName, rate, strComment).execute();
}
private TextView findViewById(int tvcomment) {
// TODO Auto-generated method stub
return null;
}
});
}
private String getDeviceId() {
return Secure.getString(context.getContentResolver(), Secure.ANDROID_ID);
}
/*----------------------------------------------------------------------------
* This method is responsible for creating another thread in parallel with
* main UI thread in order to send a request to server and get data (if any).
* ---------------------------------------------------------------------------*/
public class SendFormTask extends AsyncTask<Void, Void, Boolean> {
String deviceId, name, comment;
int rate;
SendFormTask(String deviceId, String strName, int rate, String strComment) {
this.deviceId = deviceId;
this.name = strName;
this.rate = rate;
this.comment = strComment;
}
#Override
protected void onPreExecute() {
Log.d(TAG, "SendFormTask is about to start....");
onRequestToServer.DisplayLoding(true);
}
#Override
protected Boolean doInBackground(Void... params) {
boolean status = false;
HttpURLConnection urlConnection = null;
try {
//URL url = new URL(LinkManager.getFormAPI(deviceId, name, rate, comment));
//URL url = new URL(LinkManager.getFormAPI(deviceId, name, rate, comment));
String url1 = LinkManager.getFormAPI(deviceId, name, rate, comment) ;
//String stUrl = URLEncoder.encode(url1, "UTF-8");
URL url = new URL(url1);
Log.d(TAG, "Try to open: " + url.toString());
urlConnection = (HttpURLConnection) url.openConnection();
int responseCode = urlConnection.getResponseCode();
Log.d(TAG, "Response code is: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader in = new BufferedReader(
new InputStreamReader(urlConnection.getInputStream())
);
if (in != null) {
StringBuilder strBuilder = new StringBuilder();
// Read character by character
int ch = 0;
while ((ch = in.read()) != -1)
strBuilder.append((char) ch);
// get returned message and show it
String response = strBuilder.toString();
Log.d("Server response:", response);
if(response.equalsIgnoreCase("1"))
status = true;
}
in.close();
}
}
catch(MalformedURLException e){
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
finally {
urlConnection.disconnect();
}
return status;
}
#Override
protected void onPostExecute(Boolean result) {
Log.d(TAG, "SendFormTask finished its task.");
onRequestToServer.DisplayLoding(false);
if(result)
Toast.makeText(context, "جک شما ارسال شد, منتظر تایید آن باشید", Toast.LENGTH_LONG).show();
else
Toast.makeText(context, "جک شما ارسال شد , منتظر تایید آن باشید", Toast.LENGTH_LONG).show();
}
}
}
and my LinkManager.class :
package com.skyline.jimmy;
public class LinkManager {
private final static String API_FORM = "http://jimmy.ir/jimmy/sendjoke.php?p1=###&p2=####&p3=#####&p4=######";
private final static String API_Comment = "http://jimmy.ir/jimmy/index.php?p1=###";
public static String getFormAPI(String deviceId, String name, int rate, String comment) {
String url = API_FORM;
url = url.replaceAll("###", deviceId);
url = url.replaceAll("####", name);
url = url.replaceAll("#####", Integer.toString(rate));
url = url.replaceAll("######", comment);
return url;
}
public static String getCommentAPI(String deviceId) {
String url = API_Comment;
url = url.replaceAll("###", deviceId);
return url;
}
}
See this link for accepted characters in URL. Persian characters are not supported as get parameters in a url. You can use http post for sending the data to the server.
first make sure that you are sending right word (persian ) from android side , maybe your java code not sending text in UTF-8 , then make sure that your server, database , and table collection are utf8_persian_ci
and change this
BufferedReader in = new BufferedReader(
new InputStreamReader(urlConnection.getInputStream()));
to this:
BufferedReader in = new BufferedReader(
new InputStreamReader(urlConnection.getInputStream(), "utf-8"),8);

AsyncTask doesn't call onPostExecute(Result result)

I m trying here to display a 7 day weather forecast from OWM API using AsyncTask.
doInBackground(String...param) method is also working fine. I have checked the LOGCAT.
After the async has finished the execution. I tried to refresh the ListView on refresh button in the menu. But it seems the onPostExecute() does care all about.
ForecastFragment.java
package com.example.sunshine;
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.Date;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
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;
/**
* A placeholder fragment containing a simple view.
*/
public class ForecastFragment extends Fragment {
private ArrayAdapter<String> mForeCastAdapter;
public String[] forecastArray;
public ForecastFragment() {
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.forecastfragment, menu);
}
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_refresh) {
new FetchWeatherTask().execute("44700");
return true;
}
return super.onOptionsItemSelected(item);
}
protected void onPostExecute(String[] result) {
if (result != null) {
Log.v("msg", result[0]);
mForeCastAdapter.clear();
// forecastArray = result;
for (String dayForecastStr : result) {
mForeCastAdapter.add(dayForecastStr);
// mForeCastAdapter.notifyDataSetChanged();
}
}
mForeCastAdapter.notifyDataSetChanged();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
String[] list = { "1", "2", "3" };
List<String> weekForeCast = new ArrayList<String>(
Arrays.asList(list));
mForeCastAdapter = new ArrayAdapter<String>(getActivity(),
R.layout.list_item_forecast, R.id.list_item_forecast_textview,
weekForeCast);
View rootView = inflater.inflate(R.layout.fragment_main, container,
false);
ListView weekList = (ListView) rootView
.findViewById(R.id.list_item_forecast);
weekList.setAdapter(mForeCastAdapter);
return rootView;
}
}
class FetchWeatherTask extends AsyncTask<String, Void, String[]> {
private final String LOG_TAG = FetchWeatherTask.class.getSimpleName();
protected ArrayAdapter<String> mForeCastAdapter;
/*
* 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.
Date date = new Date(time * 1000);
SimpleDateFormat format = new SimpleDateFormat("E, MMM d");
return format.format(date).toString();
}
/**
* 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_DATETIME = "dt";
final String OWM_DESCRIPTION = "main";
JSONObject forecastJson = new JSONObject(forecastJsonStr);
JSONArray weatherArray = forecastJson.getJSONArray(OWM_LIST);
String[] resultStrs = new String[numDays];
for (int i = 0; i < 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 = dayForecast.getLong(OWM_DATETIME);
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 Array : " + s);
}
}
return resultStrs;
}
#Override
protected String[] doInBackground(String... params)
{
// 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
// URL url = new
// URL("http://api.openweathermap.org/data/2.5/forecast/daily?" +
// "q=94043&mode=json&units=metric&cnt=7");
final String FORECAST_BASE_URL= ="http://api.openweathermap.org/
data/2.5/forecast/daily?";
final String QUERY_PARAM = "q";
final String MODE_PARAM = "mode";
final String UNIT_PARAM = "units";
final String DAYS_PARAM = "cnt";
Uri urlBuild = Uri
.parse(FORECAST_BASE_URL)
.buildUpon()
.appendQueryParameter(QUERY_PARAM, params[0])
.appendQueryParameter(MODE_PARAM, format)
.appendQueryParameter(UNIT_PARAM, units)
.appendQueryParameter(DAYS_PARAM, Integer.toString(numDays))
.build();
URL url = new URL(urlBuild.toString());
//Log.v(LOG_TAG, "Build URL " + urlBuild.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();
// Log.v(LOG_TAG, "Forecast JSON String" + forecastJsonStr);
}
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;
}
}
Try using the method onPostExecute in your AsyncTask class rather than your Fragment class. The AsyncTask class looks like this:
private class MyTask extends AsyncTask<String, Void, String[]> {
#Override
protected String[] doInBackground(String... params) {
}
#Override
protected void onPostExecute(String result[]) {
}
#Override
protected void onPreExecute() {
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
For your case, you will want to put the onPostExecute method inside your FetchWeatherTask class as such:
class FetchWeatherTask extends AsyncTask<String, Void, String[]> {
....
#Override
protected void onPostExecute(String result[]) {
if (result != null) {
Log.v("msg", result[0]);
mForeCastAdapter.clear();
//forecastArray = result;
for (String dayForecastStr : result) {
mForeCastAdapter.add(dayForecastStr);
//mForeCastAdapter.notifyDataSetChanged();
}
}
mForeCastAdapter.notifyDataSetChanged();
}
....
}
You should be overriding the OnPostExecute() in your FetchWeatherTask the same way you are overriding doInBackground()
The async task doesm't have an onPostExecute() method. You have a method called onPostExecute() in your fragment but not in asynctask.
Note that your IDE didn't auto-complete #Override there. If you added it there yourself, you'd get an error about not overriding a base class method.
First time solved the answer on my own by proper use of LogCat - This is great
The error was causing due to double declaration of public static ArrayAdapter<String> mForeCastAdapter=null.
Solved it using the line numbers given along each error.
P.S: I was searching for answers for about 4 hours before I posted the question. I guess it was for some good reason.

Categories

Resources