I have been working on ListView and ArrayAdapter. Now I got Stuck while making change in my ArrayAdapter.
I'm using an AsyncTack to update the UI element i.e. ListView, an adapter to the ListView is set in onCreate() method initially, but I'm about to change the array adapter in onPostExecute() method of AsyncTask.
Here is the code bellow
ListView mListView = (ListView)findViewById(R.id.dataListView);
vAdapter = new ArrayAdapter(getActivity(), R.layout.list_item_data,strings);
mLisstView.setAdapter(vAdapter);
AsyncTask
public class getDataFromServer extends AsyncTask<String,Void,String[]>{
public getDataFromServer() {
super();
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String[] doInBackground(String... parm) {
// These two need to be declared outside the try/catch
// so that they can be closed in the finally block.
if(parm.length == 0){
return null;
}
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
// Will contain the raw JSON response as a string.
String getJsonStr = null;
try {
final String FORECAST_BASE_URL="http://myUrlToServer?";
final String QUERY_PARAM ="query";
final String FORMAT_PARAM ="mode";
final String UNITS_PARAM ="units";
Uri baseUri = Uri.parse(FORECAST_BASE_URL).buildUpon()
.appendQueryParameter(QUERY_PARAM,parm[0])
.appendQueryParameter(FORMAT_PARAM, format)
.appendQueryParameter(UNITS_PARAM,units)
.build();
Log.v("build Url: ",baseUri.toString());
URL url = new URL(baseUri.toString());
// Create the request 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) {
buffer.append(line + "\n");
}
if (buffer.length() == 0) {
// Stream was empty. No point in parsing.
return null;
}
getJsonStr = buffer.toString();
} catch (IOException e) {
return null;
} finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("Found in trouble", "Error closing stream", e);
}
}
}
try {
return getWeatherDataFromJson(getJsonStr,numDays);
}catch(JSONException ex){
ex.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String[] strings) {
super.onPostExecute(strings);
for(String s : strings)
Log.v("# onPostExecute",s);
vAdapter = new ArrayAdapter(getActivity(), R.layout.list_item_data,strings);
vAdapter.notifyDataSetChanged();
/*if(strings != null){
vAdapter.clear();
for(String dayForecast : strings){
vAdapter.add(dayForecast);
}
}*/
}
}
NOTE: the commented code in onPostExecute() method is also correct by means of logic but generating exception as UnsupportedOperationException while vAdapter.clear()
You can do this way:
onPostExecute() should looks like below:
#Override
protected void onPostExecute(String[] strings) {
super.onPostExecute(strings);
for(String s : strings)
Log.v("# onPostExecute",s);
vAdapter.clear();
vAdapter.addAll(strings);
vAdapter.notifyDataSetChanged();
}
That's it.
finally I found the solution.
I have used array while creating adapter in onCreate() method and trying to clear the adapter as vAdapter.clear() which is not possible. so to do this I just change the array with the List
at onCreate() method
String[] mArray = {"element1","element2",.....};
List<String> mList = new ArrayList<String>(Arrays.asList(mArray));
vAdapter = new ArrayAdappter(getActivity(),R.layout.list_item_data,mList);
at onPostExecute() method
vAdapter.clear();
vAdapter.addAll(strings);
thank you to all.
Related
I have a problem with parsing a tag inside a Json object.
My json code is structured like that:
{"giocatori":[{"nome":"Giovanni","cognome":"Muchacha","numero":"1","ruolo":"F-G"},
{"nome":"Giorgio","cognome":"Rossi","numero":"2","ruolo":"AG"},
{"nome":"Andrea","cognome":"Suagoloso","numero":"3","ruolo":"P"},
{"nome":"Salvatore","cognome":"Aranzulla","numero":"4","ruolo":"G"},
{"nome":"Giulio","cognome":"Muchacha","numero":"5","ruolo":"F"}]}
I got the code that let me get the Json file from here: Get JSON Data from URL Using Android? and I'm trying to parse a tag (for example the "nome" tag) into a Json object.
This is the code I got:
public class MainActivity extends AppCompatActivity {
Button btnHit;
TextView txtJson;
ProgressDialog pd;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnHit = (Button) findViewById(R.id.btnHit);
txtJson = (TextView) findViewById(R.id.tvJsonItem);
btnHit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new JsonTask().execute("https://api.myjson.com/bins/177dpo");
}
});
}
private class JsonTask extends AsyncTask<String, String, String> {
protected void onPreExecute() {
super.onPreExecute();
pd = new ProgressDialog(MainActivity.this);
pd.setMessage("Please wait");
pd.setCancelable(false);
pd.show();
}
protected String doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(params[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line+"\n");
Log.d("Response: ", "> " + line);
}
return buffer.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (pd.isShowing()){
pd.dismiss();
}
txtJson.setText(result);
}
}
}
I've never worked with this type of file so I'll really appreciate your help!
You can use something like this:
try {
String servResponse = response.toString();
JSONObject parentObj = new JSONObject(servResponse);
JSONArray parentArray = parentObj.getJSONArray("giocatori");
if (parentArray.length() == 0) {
//if it's empty, do something (or not)
} else {
//Here, finalObj will have your jsonObject
JSONObject finalObj = parentArray.getJSONObject(0);
//if you decide to store some value of the object, you can do like this (i've created a nomeGiocatori for example)
nomeGiocatori = finalObj.getString("nome");
}
} catch (Exception e) {
Log.d("Exception: ", "UnknownException");
}
I use this kind of code all the time, works like a charm.
I want to receive and send data with a web server but the code does not work
What do I do for this code to work?
Note this code inside onCreate
try {
URL url = new URL("http://myweb.com/");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream Stream = connection.getInputStream();
InputStreamReader reader = new InputStreamReader(Stream);
BufferedReader b = new BufferedReader(reader);
StringBuilder s = new StringBuilder();
String str ="";
while ((str = b.readLine())!=null) {
s.append(str);
}
String data = s.toString();
TextView myText = (TextView) findViewById(R.id.Text);
myText.setText(data);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Make sure that you do network-related tasks on a separate thread in Android. Also, check that you have the INTERNET permission set.
If you want to then update the UI from another thread, you have to use
runOnUiThread (new Runnable () {
public void run() {
//update ui in here
}
}
All your code runs in Main thread which should be always used for setting up the UI and to listen for UI events such as on click listeners.
Network calls are not allowed on this thread as they might take long time. Use AsyncTask API of android which is designed for running code in separate thread.
Create a class like one below for all GET request tasks.
public class DownloadTask extends AsyncTask<String, Void, Integer> {
private String TAG = "InDownloadTask";
private DownloadCallback callback;
private String data;
public DownloadTask(DownloadCallback cb){
callback = cb;
}
#Override
protected Integer doInBackground(String... params) {
Integer result = 0;
HttpURLConnection urlConnection;
try {
URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
int statusCode = urlConnection.getResponseCode();
if (statusCode == 200) {
BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
response.append(line);
}
data = response.toString();
result = 1;
} else {
result = 0;
}
} catch (Exception e) {
Log.d(TAG, e.getLocalizedMessage());
}
return result;
}
#Override
protected void onPostExecute(Integer integer) {
super.onPostExecute(integer);
callback.onFinishDownload(data, integer);
}
}
Create a callback interface that we use for the above class.
public interface DownloadCallback {
public void onFinishDownload(String data, Integer result);
}
Now from your activity onCreate
String url = "http://myweb.com/";
new DownloadTask(new DownloadCallback() {
public void onFinishDownload(String data, Integer result) {
if(result == 1)
myText.setText(data);
else
myText.setText("Error");
}
}).execute(url);
If you have many network related operations, use a Network library such as Volley which will take care of this.
I try to execute an AsyncTask like this
private static final String REQUESTED_URL = "//my url";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.earthquake_activity);
EarthQuakeAsyncTask task = new EarthQuakeAsyncTask();
task.execute(REQUESTED_URL); //this is where the error is
}
but Android Studio said that it cannot resolve method execute(String). I'm having a tutorial from Udacity, their sample is pretty much similar
/** URL for earthquake data from the USGS dataset */
private static final String USGS_REQUEST_URL =
"//url";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EarthquakeAsyncTask task = new EarthquakeAsyncTask();
task.execute(USGS_REQUEST_URL); //it works
}
Can someone tell me why this possibly occurs?
Edit: this is my EarthQuakeAsyncTask class:
private class EarthQuakeAsyncTask extends AsyncTask<URL,Void,ArrayList<EarthQuake>> {
#Override
protected ArrayList<EarthQuake> doInBackground(URL... urls) {
if(urls.length==0||urls[0]== null){
return null;
}
// Create URL object
URL url = createUrl(REQUESTED_URL);
try {
jsonResponse = makeHttpRequest(url);
} catch (IOException e) {
// TODO Handle the IOException
}
ArrayList<EarthQuake> earthquake = QueryUtils.extractEarthquakes(jsonResponse);
return earthquake;
}
#Override
protected void onPostExecute(ArrayList<EarthQuake> earthquake) {
if (earthquake == null) {
return;
}
updateUi();
}
private URL createUrl(String stringUrl) {
URL url;
try {
url = new URL(stringUrl);
} catch (MalformedURLException exception) {
Log.e(LOG_TAG, "Error with creating URL", exception);
return null;
}
return url;
}
private String makeHttpRequest(URL url) throws IOException {
// If the URL is null, then return early.
if (url == null) {
return jsonResponse;
}
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setReadTimeout(10000 /* milliseconds */);
urlConnection.setConnectTimeout(15000 /* milliseconds */);
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// If the request was successful (response code 200),
// then read the input stream and parse the response.
if (urlConnection.getResponseCode() == 200) {
inputStream = urlConnection.getInputStream();
jsonResponse = readFromStream(inputStream);
} else {
Log.e(LOG_TAG, "Error response code: " + urlConnection.getResponseCode());
}
} catch (IOException e) {
Log.e(LOG_TAG, "Problem retrieving the earthquake JSON results.", e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (inputStream != null) {
inputStream.close();
}
}
return jsonResponse;
}
private String readFromStream(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();
}
}
}
Your class signature suggests that you are expecting a URL type as parameter, but you are passing a String type in the execute() method. All you need to do is to change your class signature to expect a String as in the one in this code.
private class EarthQuakeAsyncTask extends AsyncTask<String,Void,ArrayList<EarthQuake>> {
#Override
protected ArrayList<EarthQuake> doInBackground(String... urls) {
if(urls.length==0||urls[0]== null){
return null;
}
// Create a URL object from the String passed to the execute method
URL url = createUrl(urls[0]);
try {
jsonResponse = makeHttpRequest(url);
} catch (IOException e) {
// TODO Handle the IOException
}
ArrayList<EarthQuake> earthquake = QueryUtils.extractEarthquakes(jsonResponse);
return earthquake;
}
#Override
protected void onPostExecute(ArrayList<EarthQuake> earthquake) {
if (earthquake == null) {
return;
}
updateUi();
}
private URL createUrl(String stringUrl) {
URL url;
try {
url = new URL(stringUrl);
} catch (MalformedURLException exception) {
Log.e(LOG_TAG, "Error with creating URL", exception);
return null;
}
return url;
}
private String makeHttpRequest(URL url) throws IOException {
// If the URL is null, then return early.
if (url == null) {
return jsonResponse;
}
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setReadTimeout(10000 /* milliseconds */);
urlConnection.setConnectTimeout(15000 /* milliseconds */);
urlConnection.setRequestMethod("GET");
urlConnection.connect();
// If the request was successful (response code 200),
// then read the input stream and parse the response.
if (urlConnection.getResponseCode() == 200) {
inputStream = urlConnection.getInputStream();
jsonResponse = readFromStream(inputStream);
} else {
Log.e(LOG_TAG, "Error response code: " + urlConnection.getResponseCode());
}
} catch (IOException e) {
Log.e(LOG_TAG, "Problem retrieving the earthquake JSON results.", e);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (inputStream != null) {
inputStream.close();
}
}
return jsonResponse;
}
private String readFromStream(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();
}
}
}
That is because your AsyncTask class isn't defined in a manner to handle the execute method with a String parameter. Let me explain myself.
The AsyncTask class you develop will look like this:
private class MyAsyncTask extends AsyncTask<TYPE1, TYPE2, TYPE3> {
protected TYPE3 doInBackground(TYPE1... type1_variables) {
// Do some long process here..
return variable_of_type_TYPE3;
}
protected void onPostExecute(TYPE3 result) {
// Do something here
}
}
So for you to call task.execute(REQUESTED_URL); you'd need to implement your AsyncTask class correctly.
For example it might look like this:
private class EarthQuakeAsyncTask extends AsyncTask<String, Void, Void> {
...
}
I am trying to download an html of a webpage via AsyncTask and then, show that html in the LOGs.
This is my code. However, when I run the code, loop never stops.
public class MainActivity extends AppCompatActivity {
public class DownloadTask extends AsyncTask<String,Void,String>{
#Override
protected String doInBackground(String... urls) {
String result = "";
HttpURLConnection connection = null;
URL myUrl;
try{
myUrl = new URL(urls[0]);
connection = (HttpURLConnection) myUrl.openConnection();
InputStream in = connection.getInputStream();
InputStreamReader reader = new InputStreamReader(in);
int data = reader.read();
while(data != -1){
char current = (char) data;
result += current;
data = reader.read();
}
return result;
}
catch(Exception e){
e.printStackTrace();
return "Failed";
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DownloadTask task = new DownloadTask();
try {
String result = task.execute("http://www.posh24.com/celebrities").get();
Log.i("asd",String.valueOf(result));
}
catch(Exception e){
e.printStackTrace();
}
}
}
My Logs get filled with:
D/dalvikvm: GC_FOR_ALLOC freed 297K, 20% free 2582K/3200K, paused 4ms, total 4ms
Any Idea whats wrong with the code?
The problem with your code is data will not change after you initialized it with a single read() call, so it will never be -1 (hence the infinite loop).
You need to call read() inside the loop.
Replace the following:
int data = reader.read();
while(data != -1){
// ...
With something like this:
int data;
while ((data = reader.read()) != -1) {
// ...
To make things faster you could use a BufferedReader:
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = null;
StringBuilder builder = new StringBuilder();
while((line = reader.readLine()) != null) {
builder.append(line);
}
String data = builder.toString();
Probably because of creating a new string on every character received. Do NOT do this:
result += current;
Instead, create a StringBuilder and append to it.
Or, better yet, do not read one character at a time, but create a BufferedReader and read into a buffer of a considerable size, e.g. 1024 bytes.
I am able to get the data with your code. I believe you already add internet permission when testing.
But your code blocks UI thread because of task.execute().get(). I changed it a bit:
public class DownloadTask extends AsyncTask<String, Void, String> {
private Listener mListener;
DownloadTask(Listener listener) {
mListener = listener;
}
#Override
protected String doInBackground(String... urls) {
String result = "";
HttpURLConnection connection = null;
URL myUrl;
try {
myUrl = new URL(urls[0]);
connection = (HttpURLConnection) myUrl.openConnection();
InputStream in = connection.getInputStream();
InputStreamReader reader = new InputStreamReader(in);
int data = reader.read();
while (data != -1) {
char current = (char) data;
result += current;
data = reader.read();
}
return result;
} catch (Exception e) {
e.printStackTrace();
return "Failed";
}
}
#Override
protected void onPostExecute(String s) {
mListener.deliverResult(s);
}
public interface Listener {
void deliverResult(String result);
}
}
And the code in Activity looks like:
DownloadTask task = new DownloadTask(new DownloadTask.Listener() {
#Override
public void deliverResult(String result) {
Log.i("asd",String.valueOf(result));
}
});
task.execute("http://www.posh24.com/celebrities");
I have the following assynctask implemented. Its usage is pretty simple, and so works as intended so far. get a url, post to it, get its contents, write them to a file. the hard part begins now
QUESTION:
I require reusage of this piece of code multiple times for multiple different files. How can i pass the file as a variable on assynctask call alongside the url?
//class to call a url and save it to a local file
private class url_to_file extends AsyncTask<String, Integer, String> {
protected String[] doInBackground(String... input) {
//function to call url and postback contents
return callpost(input[0]);
}
protected void onProgressUpdate(Integer... progress) {
//Yet to code
}
protected void onPostExecute(String result) {
//function to write content to text file
writeStringAsFile( result, "file.xml" ,getApplicationContext());
}
}
EDIT:
Purelly as reference, the function i use to read, write from file and call url
//saves a txt (etc, xml as well) file to directory,replacing previous. if directory is left empty, save to assets
public static void writeStringAsFile(final String fileContents, String fileName ,Context context) {
try {
FileWriter out = new FileWriter(new File(context.getFilesDir(), fileName));
out.write(fileContents);
out.close();
} catch (IOException e) {
}
}
//read file, returns its contents
public static String readFileAsString(String fileName,Context context) {
StringBuilder stringBuilder = new StringBuilder();
String line;
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(new File(context.getFilesDir(), fileName)));
while ((line = in.readLine()) != null) stringBuilder.append(line);
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
return stringBuilder.toString();
}
//calls a page. Returns its contents
public String callpost (String... strings)
{
StringBuilder content = new StringBuilder();
try
{
// create a url object
URL url = new URL(strings[0]);
// create a urlconnection object
URLConnection urlConnection = url.openConnection();
// wrap the urlconnection in a bufferedreader
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String line;
// read from the urlconnection via the bufferedreader
while ((line = bufferedReader.readLine()) != null)
{
content.append(line + "\n");
}
bufferedReader.close();
}
catch(Exception e)
{
e.printStackTrace();
}
return content.toString();
}
EDIT:
Removed second question as it had nothing to do with the rest and would just confuse people to see the thread
Kudos #FirstOne for his help up at comments
this made it for me
//class to call a url and save it to a local file
private class url_to_file extends AsyncTask<String, Integer, String> {
protected String file;
public void setFile(String input)
{
file=input;
}
protected String[] doInBackground(String... input) {
//function to call url and postback contents
return callpost(input[0]);
}
protected void onProgressUpdate(Integer... progress) {
//Yet to code
}
protected void onPostExecute(String result) {
//function to write content to text file
writeStringAsFile( result, file ,getApplicationContext());
}
}