I'm new to android, please halp.
This is a really simple scenario, there's an actionbar, and when a tab is selected, I need to send an http request to get an article list, when the response arrives, update a listview and here's where I got this exception.
I'm aware that I should isolate network operations from UI thread, so I implement the network functions in an AsyncTask class.
The most weird part is, before I try to get the article list, I have actually called a network function once to log in, and that just works fine, no exceptions! And guess what, if I replace the get article list call with log in call, it works fine, too. All the code are just the same, except the arguments differ.
Here's how I do it, since too many modules will use the network module, I use a static wrapper:
UI -> Static Factory -> New AsyncTask -> Response arrives -> Call Static callback function in Static Factory -> Call callback function in UI
AsyncTask doInBackground
#Override
protected HttpResponse doInBackground(String... params) {
// TODO Auto-generated method stub
String uri = params[0];
HttpGet get = new HttpGet(uri);
try {
return _client.execute(get);
}
catch(Exception e) {
e.printStackTrace();
return null;
}
}
AsyncTask post execute
#Override
protected void onPostExecute(HttpResponse result) {
//Do something with result
if (result != null) {
try {
JSONObject json = FormJsonFromResponse();
Command.OnTaskComplete(json);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
static wrapper code:
#Override
public static void OnTaskComplete(JSONObject json) {
// TODO Auto-generated method stub
if(_callback != null) {
_callback.OnCommandComplete(json);
}
}
Here's how I call asynctask in static wrapper:
public static void LogIn(String user, String pass) {
new NetworkTask().execute(_uriPrefix + login, _user, _pass);
}
Revise your AsyncTask following this pattern:
#Override
protected JSONObject doInBackground(String... params) {
// TODO Auto-generated method stub
String uri = params[0];
HttpGet get = new HttpGet(uri);
try {
HttpResponse response = _client.execute(get);
return FormJsonFromResponse();
}
catch(Exception e) {
e.printStackTrace();
return null;
}
}
AsyncTask post execute
#Override
protected void onPostExecute(JSONObject result) {
//Do something with result
if (result != null) {
try {
Command.OnTaskComplete( result );
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Related
I want to load a data using JSON from php and then parsing it in android. I'm trying to implement asynctask in this process. And the return is in string. I got an error in
"Type mismatch : cannot convert from AsyncTask<String,String,String> to String in
ProsesTampil p = new ProsesTampil();
xResult = p.execute(urltampil);
The xResult is supposed to be the string value I got from php.
Here's the complete codes :
public void tampilkanData() {
try {
String nama = URLEncoder.encode(Login.usernameP, "utf-8");
urltampil += "?" + "&nama=" + nama;
txtNama.setText("");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ProsesTampil p = new ProsesTampil();
xResult = p.execute(urltampil);
try {
parse();
} catch (Exception e) {
e.printStackTrace();
}
}
private void parse() throws Exception {
//jObject = new JSONObject(xResult);
JSONArray menuitemArray = new JSONArray(xResult);
jObject=menuitemArray.getJSONObject(0);
String sret="";
txtBerat.setText(jObject.getString("berat_badan"));
txtNama.setText(jObject.getString("username"));
// txtUsia.setText(jObject.getString("usia"));
txtTinggi.setText(jObject.getString("tinggi_badan"));
//System.out.println(jObject.getString("jenis_kelamin").equalsIgnoreCase("female"));
if(jObject.getString("jenis_kelamin").equalsIgnoreCase("female")){
radioFemale.setSelected(true);
radioMale.setSelected(false);
}else{
radioMale.setSelected(true);
radioFemale.setSelected(false);
}
}
public String getRequestData(String UrlTampil){
String sret="";
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(UrlTampil);
try{
HttpResponse response = client.execute(request);
sret =request(response);
}catch(Exception ex){
Toast.makeText(this,"Gagal "+sret, Toast.LENGTH_SHORT).show();
}
System.out.println(sret);
return sret;
}
class ProsesTampil extends AsyncTask<String, String, String>{
#Override
protected String doInBackground(String... params) {
return getRequestData(params[0]);
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
}
I'm sorry for my bad english. thanks in advance
The propose of an AsyncTask is execute some code in a separate thread (different from UI thread), but the result from that code, when ready, will be delivered in onPostExecute.i.e. The method execute returns the AynscTask itself,not String so change your code as
ProsesTampil p = new ProsesTampil();
xResult = p.execute(urltampil);
to
ProsesTampil p = new ProsesTampil();
p.execute(urltampil);
And get xResult in onPostExecute method as
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
xResult = result;
}
First Thing You can not return value from onPostExecute() because return type is void
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
}
Second Your class doesn't Return any value...
So if you want to get value of result try to get value from onPostExecute().
I mean to say do as follow..
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
xResult = result;
super.onPostExecute();
}
You can't do it because AsyncTask works in background thread.
Your result will come in UI thread after background has done self work:
#Override
protected void onPostExecute(String result) {
//String result - that what you need
}
execute() doesn't return a string. So you can't assign it like that. AsyncTasks are asynchronous- they don't finish until later. Any code you'd want to run on the result of an AsyncTask should be placed in the onPostExecute() function of the AsyncTask.
Yo can use
String results = yourAsyntask.get() instead of using yourAsyntask.execut()e method, it will return you result. same as Result get you in onPostExecute method;
But it will block your main thread.
I am trying to call AsyncTask from a loop.It is working properly but the issue is it taking quite more time to execute all the request.Please suggest me how could i make it more fast .
for (int i = 0; i < 6; i++) {
response = requestWeatherUpdate(location);
}
requestWeatherUpdate
private WeatherResponse requestWeatherUpdate(String location) {
url = ""+ location;
Log.d("URL for Weather Upadate", url);
WeatherUpdateAsyncTask weatherReq = new WeatherUpdateAsyncTask();
String weatherRequestResponse = "";
try {
weatherRequestResponse = weatherReq.execute(url).get();
if (weatherRequestResponse != "") {
parsedWeatherResponse = ParseWeatherResponseXML
.parseMyTripXML(weatherRequestResponse);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return parsedWeatherResponse;
}
Used CallBack
public class WeatherUpdateAsyncTask extends AsyncTask<String, Void, String> {
Context context;
CallBack callBack;
public WeatherUpdateAsyncTask(CallBack callBack) {
this.callBack = callBack;
}
#Override
protected String doInBackground(String... arg0) {
String responseString = "";
HttpClient client = null;
try {
client = new DefaultHttpClient();
HttpGet get = new HttpGet(arg0[0]);
client.getParams().setParameter("http.socket.timeout", 6000);
client.getParams().setParameter("http.connection.timeout", 6000);
HttpResponse responseGet = client.execute(get);
HttpEntity resEntityGet = responseGet.getEntity();
if (resEntityGet != null) {
responseString = EntityUtils.toString(resEntityGet);
Log.i("GET RESPONSE", responseString.trim());
}
} catch (Exception e) {
Log.d("ANDRO_ASYNC_ERROR", "Error is " + e.toString());
}
Log.d("ANDRO_ASYNC_RESPONSE", responseString.trim());
client.getConnectionManager().shutdown();
return responseString.trim();
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
callBack.run(result);
}
}
requestWeatherUpdate
private WeatherResponse requestWeatherUpdate(String location) {
url = ""
+ location;
Log.d("URL for Weather Upadate", url);
WeatherUpdateAsyncTask weatherReq = new WeatherUpdateAsyncTask(new CallBack() {
#Override
public void run(Object result) {
try {
String AppResponse = (String) result;
response = ParseWeatherResponseXML
.parseMyTripXML(AppResponse);
} catch (Exception e) {
Log.e("TAG Exception Occured",
"Exception is " + e.getMessage());
}
}
});
weatherReq.execute(url);
return response;
}
Frm here i calling
for (int i = 0; i < 4; i++) {
inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
RelativeLayout layout = (RelativeLayout) inflater.inflate(
R.layout.sector_details, depart_arrivals_details, false);
depart_time = (TextView)layout.findViewById(R.id.depart_time);
depart_airport_city = (TextView)layout.findViewById(R.id.depart_airport_city);
temprature = (TextView)layout.findViewById(R.id.temprature);
humidity = (TextView)layout.findViewById(R.id.humidity);
flight_depart_image = (ImageView)layout.findViewById(R.id.flight_depart_image);
depart_time.setText("20:45");
depart_airport_city.setText("Mumbai");
/*
* This part will be updated when we will se the request and get the response
* then we have to set the temp and humidity for each city that we have recived
* */
temprature.setText("");//Here i have set the values from the response i recived from the AsynkTask
humidity.setText("");//Here i have set the values from the response i recived from the AsynkTask
flight_depart_image.setImageResource(R.drawable.f1);
depart_arrivals_details.addView(layout, i);
}
Calling get() on an AsyncTask blocks the calling thread. Don't do that. Instead pass the results to the caller in onPostExecute().
Starting with Honeycomb, the default implementation executes asynctasks sequentially on a serial executor. To run asynctasks parallely, use executeOnExecutor(THREAD_POOL_EXECUTOR, ...) instead of execute(...).
You should not use get() . Calling get() does not make the call asynchronous. Instead use execute
weatherRequestResponse = weatherReq.execute(url).get();
get()
public final Result get ()
Added in API level 3
Waits if necessary for the computation to complete, and then retrieves its result.
Returns
The computed result.
Throws
CancellationException If the computation was cancelled.
ExecutionException If the computation threw an exception.
InterruptedException If the current thread was interrupted while waiting.
For parallel execution use executeOnExecutor
weatherReq.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
If your asynctask is an inner class of your activity class you can update ui in onPostExecute. If its not you can use a interface as a callback.
Retrieving a returned string from AsyncTask in Android
How do I return a boolean from AsyncTask?
From the discussion you get NUllPointerException # temprature.setText(parsedWeatherResponse.getTempInC()+(char) 0x00B0);
You have not initialized parsedWeatherResponse. You have only declared it
parsedWeatherResponse = new WeatherResponse();
use executeOnExecutor(THREAD_POOL_EXECUTOR, ...) to run asynctasks parallely. also you can use HttpURLConnection instead of DefaultHttpClient/HttpGet
If you want to connect with network from UI thread , it is quitly difficult. "The exception that is thrown when an application attempts to perform a networking operation on its main thread.
This is only thrown for applications targeting the Honeycomb SDK or higher. Applications targeting earlier SDK versions are allowed to do networking on their main event loop threads, but it's heavily discouraged. See the document Designing for Responsiveness."
If you want to overcome this difficulty then following bellow instruction:
The solution is given below. I found it from another answer. It is working for me. And below import statement into your java file.
import android.os.StrictMode;
Write below code into onCreate
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
I can't explain why onPostExecute is not being called in my code. I have successfully used almost this exact code with a different app before. It prints 'onPreExecute' and the successful result of the JSON fetch from doInBackground just before return result; but then onPostExecute doesn't print anything - with the super call or not - and moreover doesn't return my string to the UI thread. Any ideas?
public class PrivateLoadFromServer extends AsyncTask<String, Integer, String> {
InputStream is = null;
String result = null;
String error_text="";
JSONObject j = null;
String url;
SQLiteOpenHelper helper;
CustomActivity activity;
private Context context;
private ProgressDialog dialog;
private int count;
String employee;
String text;
public PrivateLoadFromServer(CustomActivity activity,String employee,String url){
this.url=url;
this.employee=employee;
this.activity=activity;
}
#Override
protected void onPreExecute() {
system.out.println("onPreExecute");
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
System.out.println("onPostExecute");
activity.setJSONResult(result);
/*
if(result!=null){
System.out.println("Task reported successful");
taskHandler.taskSuccessful(this.result);
activity.setJSONResult(this.result);
} else {
taskHandler.taskFailed();
}
*/
//return;
}
#Override
protected String doInBackground(String... params) {
System.out.println("Running aSyncTask");
// Successful code to get JSON result string from server omitted.
System.out.println("Raw at doInBackground: " + result);
return result;
EDIT: Should've posted this originally, I call it as an inner class in CustomActivity like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
helper=new DBHelper(this);
loadBasicData();
}
private void loadBasicData() {
// If you can encode all of these into one JSON Object, cool.
String url="*****" //Omitted URL.
String employee=null;
PrivateLoadFromServer syncTask = new PrivateLoadFromServer(this,employee,url);
syncTask.execute();
try {
syncTask.get(15000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TimeoutException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("JSONResult at Activity:"+jsonResult); // jsonResult is null
}
}
public void setJSONResult(String result){
System.out.println("setJSONResult"+result);
this.jsonResult=result; // jsonResult is a field in the Activity.
}
Because you are calling get, the JSON result is also returned from this method (see the source code of AsyncTask.java. So you can call your method directly on the output.
try {
setJSONResult(syncTask.get(15000, TimeUnit.MILLISECONDS));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
Check if your are explicitly cancelling AsyncTask somewhere in the code before it could postExecute.
onPostExecute() is called on the main UI thread. If its not getting called, it means your UI thread is blocked doing something else.
I am getting the exception android.os.NetworkOnMainThreadException when I tried to use the following codes:
public class CheckServer extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
Runnable runn = null;
HttpTask.execute(runn);
}
private class HttpTask extends AsyncTask<String, String, String>
{
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
HttpURLConnection urlConnection = null;
URL theURL = null;
try {
theURL = new URL("http://192.168.2.8/parkme/Client/clientquery.php?ticket=66t");
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
urlConnection = (HttpURLConnection) theURL.openConnection();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String response = null;
try {
response = readInputStream(urlConnection.getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return response;
}
private String readInputStream(InputStream is) {
// TODO Auto-generated method stub
String line = "";
StringBuilder total = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
try {
while ((line = rd.readLine()) != null) {
total.append(line);
}
} catch (Exception e) {
e.printStackTrace();
}
return total.toString();
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), result, Toast.LENGTH_LONG).show();
}
}}
If possible can someone tell me how to use it inside an Async Task and get the output? I tried but can't seem to get anywhere.
NetworkOnMainThread Exception occurs because you are running a network related operation on the main UI Thread.This is only thrown for applications targeting the Honeycomb SDK or higher
You should be using asynctask.
http://developer.android.com/reference/android/os/AsyncTask.html
In onCreate()
new TheTask().execute();
You can also pass parameters like url to the constructor of AsyncTask and use the same in doInBackground()
class TheTask extends AsyncTask<Void,Void,Void>
{
protected void onPreExecute()
{ super.onPreExecute();
//display progressdialog.
}
protected void doInBackground(Void ...params)//return result here
{
//http request. do not update ui here
return null;
}
protected void onPostExecute(Void result)//result of doInBackground is passed a parameter
{
super.onPostExecute(result);
//dismiss progressdialog.
//update ui using the result returned form doInbackground()
}
}
When an asynchronous task is executed, the task goes through 4 steps:
onPreExecute(), invoked on the UI thread before the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.
doInBackground(Params...), invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress...) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress...) step.
onProgressUpdate(Progress...), invoked on the UI thread after a call to publishProgress(Progress...). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.
onPostExecute(Result), invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter.
Ok, lets do it step by step ...
1) create private class extending AsyncTask
private class HttpUrlConnectionTask extends AsyncTask {
2) Override the doInBackground() method, this will do the heavy load
#Override
protected Object doInBackground(Object... params) {
// your HttpUrlConnection code goes here
return response;
3) Once the job is done and returns, the onPostExecute() method will be called. The result parameter contains the return value of doInBackground() - so response.
#Override
protected void onPostExecute(Object result) {
Within this method you can update your UI.
4) Finally lets have a look onto the HttpUrlConnection code
HttpURLConnection urlConnection = null;
URL theURL = new URL(url);
urlConnection = (HttpURLConnection) theURL.openConnection();
String response = readInputStream(urlConnection.getInputStream());
return response;
Hope this helps. Happy coding!
#Raghunandan comes with a really good explanation of how AsyncTask works
Here you go:
public static class InitializeTask extends MyAsyncTask<String, String, String> {
private Activity activity;
private ProgressDialog dialog;
public InitializeTask(Activity activity) {
this.activity = activity;
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(activity, result, Toast.LENGTH_SHORT).show();
}
#Override
protected String doInBackground(String... params) {
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet("http://192.168.2.8/localhost/parkme/Client/clientquery.php?ticket=");
try {
HttpResponse response = httpclient.execute(httpget);
if(response != null) {
String line = "";
InputStream inputstream = response.getEntity().getContent();
return convertStreamToString(inputstream);
} else {
return "Unable to complete your request";
}
} catch (ClientProtocolException e) {
return "Caught ClientProtocolException";
} catch (IOException e) {
return "Caught IOException";
}
}
private String convertStreamToString(InputStream is) {
String line = "";
StringBuilder total = new StringBuilder();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
try {
while ((line = rd.readLine()) != null) {
total.append(line);
}
} catch (Exception e) {
return "Stream Exception";
}
return total.toString();
}
}
A little side note, it is generally considered bad code to catch just Exception, since this will catch anything, and you are not accounting for what it is.
To use the AsyncTask in the Activity do this:
InitializeTask task = new InitializeTask(this)
task.execute()
Exactly as it says, network activity isn't allowed on the thread the activity ran in. Moving your code to an Asynctask is the way to do it properly. Though if you're just trying to get your concept working still you can do this...
//lazy workaround with newer than gingerbread
//normally UI thread can't get Internet.
if(Build.VERSION.SDK_INT >= 9){
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
And then the UI thread actually can. I wouldn't release anything like this however, I haven't even tried infact. It's just my lazy debugging move I use a lot.
I have almost finished my project, only one thing remain to improve.
My app is a music quiz, that retrieves all the informations about author, song title, previewUrl ecc. from the Itunes Store using the apposite Search API.
When a user choose a genre to play with, I must say to the user to wait for 4-5 seconds because of the computation that fills the List containing all the informations.
I call the Asynctask that retrieve these informations like this:
JsonCanzoni recuperoCanzoni = new JsonCanzoni(arrayGenere,Canzone.this);
try {
recuperoCanzoni.execute().get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
The class (extends Asynctask) that do these operation is the following:
class JsonCanzoni extends AsyncTask<Void, Void, Void>
{
List<String> canzoni = new ArrayList<String>(5);
ProgressDialog pDialog;
int[] arrayGenere;
Context context;
public JsonCanzoni(int[] arrayGenere,Context context)
{
this.arrayGenere = arrayGenere;
this.context = context;
}
#Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
pDialog.dismiss();
}
#Override
protected void onPreExecute()
{
super.onPreExecute();
pDialog = new ProgressDialog(context);
pDialog.setMessage("Preparazione round...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
protected Void doInBackground(Void... params)
{
try
{
int randomLookupId = 0;
JSONObject obj;
JSONArray jsonArray;
for(int i = 0; i < 10; i++)
{
canzoni = new ArrayList<String>();
Log.d("GENERE", arrayGenere.toString());
obj = getJSONObject(scegliClassifica(arrayGenere));
jsonArray = obj.getJSONArray("resultIds");
Log.d("dimensione JsonArray", String.valueOf(jsonArray.length()));
try
{
randomLookupId = new Random().nextInt(jsonArray.length()-1);
}
catch(IllegalArgumentException errore)
{
new AlertDialog.Builder(context)
.setTitle("Connessione non attiva!")
.setMessage("Connessione di rete debole, uscita dal programma!");
}
Log.d("randomLookupID", String.valueOf(randomLookupId));
JSONObject finalObj = getJSONObject("http://itunes.apple.com/lookup?id="+jsonArray.getString(randomLookupId));
Log.d("URL","http://itunes.apple.com/lookup?id="+jsonArray.getString(randomLookupId));
while(finalObj.getJSONArray("results").length() == 0)
{
Log.d("Array VUOTO!!","Non รจ possibile!!!!");
randomLookupId = new Random().nextInt(jsonArray.length()-1);
Log.d("randomID rigenerato", String.valueOf(randomLookupId));
finalObj = getJSONObject("http://itunes.apple.com/lookup?id="+jsonArray.getString(randomLookupId));
Log.d("URL Rigenerato","http://itunes.apple.com/lookup?id="+jsonArray.getString(randomLookupId));
}
JSONArray finalJsonArray = finalObj.getJSONArray("results");
JSONObject returnObj = finalJsonArray.getJSONObject(0);
Log.d("returnObj.length",String.valueOf(returnObj.length()));
canzoni.add(returnObj.getString("previewUrl"));
canzoni.add(returnObj.getString("artistName"));
canzoni.add(returnObj.getString("trackName"));
canzoni.add(returnObj.getString("artistViewUrl"));
canzoni.add(returnObj.getString("artworkUrl100"));
// GTTapp app=(GTTapp) ((Activity)context).getApplication();
// app.dieciCanzoni;
Canzone.dieciCanzoni.add(i, new ArrayList<String>(canzoni));
}
}
catch (JSONException ignored)
{
ignored.getCause();
}
catch (MalformedURLException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
private String scegliClassifica(int[] arrayGenere)
{
int randomArrayPosition = new Random().nextInt(arrayGenere.length);
return "http://itunes.apple.com/WebObjects/MZStoreServices.woa/ws/charts?cc=us&g="+arrayGenere[randomArrayPosition]+"&name=Songs&limit=200";
}
JSONObject getJSONObject(String url) throws IOException, MalformedURLException, JSONException
{
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
InputStream in = conn.getInputStream();
try
{
StringBuilder sb = new StringBuilder();
BufferedReader r = new BufferedReader(new InputStreamReader(new DoneHandlerInputStream(in)));
for (String line = r.readLine(); line != null; line = r.readLine())
{
sb.append(line);
}
return new JSONObject(sb.toString());
}
finally
{
in.close();
}
}
}
THE PROBLEM: Using the .get() method make the app waiting for the entire computation of the AsyncTask, but it block the UI thread too!! So the user will remain with a black screen for 5 secs or more, and that's not a good thing!
If I don't use the .get() method, I receive an IndexOutOfBounds Exception, because I begin to play the music stream but the list is has not been filled yet.
Can you suggest me a workarund for this situation?
Thank you!
remove .get() it will block the UI till completion of the task.
Start any task like (playing video) which is dependent on AsycTask in
#Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
pDialog.dismiss();
//You can start music stream here
}
The get() call is blocking. From the docs:
Waits if necessary for the computation to complete, and then retrieves its result.
What you should do is wait asynchronously the computation to finish before you start to play the music.
If you do not want to expose the asynctask outside your class, you can set a callback into your JSonCanzoni class to be called into the onPostExecute method of the asynctask.
Something like
public interface CanzoniDownloadedInterface {
public void onCanzoniDownloaded();
}
public JsonCanzoni(int[] arrayGenere, CanzoniDownloadedInterface callback, Context context){
this.arrayGenere = arrayGenere;
this.context = context;
this.callback = callback;
}
and in your onPostExecute():
#Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
this.callback.onCanzoniDownloaded();
pDialog.dismiss();
}
If you let your activity implement the interface, you can pass it to your class.
The onCanzoniDownloaded() implementation is where you need to start playing.
Finally I solved my problem, some advices were good and helped me a lot!
I simply moved the startActivity instruction to onPostExecute of JsonCanzoni AsyncTask, and changed some code to adapt to the new version and it's all right! ;)