android.os.NetworkOnMainThreadException into AsyncTask - java

I have the following class:
class CargaImgsParaAmpliar extends AsyncTask<Void, Void, Bitmap> {
final ProgressDialog progressDialog = new ProgressDialog(imagen.this);
protected void onPreExecute() {
progressDialog.setTitle("");
progressDialog.setMessage("Cargando Imagen...");
progressDialog.show();
}
protected Bitmap doInBackground(Void... params) {
Bitmap mIcon1 = null;
URL url_value;
try {
url_value = new URL(StrUrl);
mIcon1 = BitmapFactory.decodeStream(url_value.openConnection().getInputStream());
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return mIcon1;
}
protected void onPostExecute(Bitmap imagen) {
m_imageView.setImageBitmap(urlImageToBitmap(StrUrl));
progressDialog.dismiss();
}
}
I am doing internet discharge processes within AsyncTask and it still gives me the exception android.os.NetworkOnMainThreadException.
How can I fix this isse?

It seems to me that urlImageToBitmap accesses the network but is executed from onPostExecute (which is run on the UI task).
And you don't seem to be doing anything with imagen parameter in onPostExecute. So the image retrieved in doInBackground is basically lost.

Related

Get AsyncTask's result without blocking the thread

I have the code that sends requests to REST API in AsyncTask.
Also, I have a ProgressDialog initialization in preExecute() and its dismission in postExecute().
I want ProgressDialog to show an indeterminate spinner (you know, that loading animation), but I need to get a result too. get() blocks the main thread where I'm invoking it in - what's the workaround for that case?
Main thread (main activity)
LoginTask task_login = new LoginTask();
AsyncTask<String, Void, JSONObject> response = task_login.execute(et_username.getText().toString(), et_password.getText().toString());
try {
JSONObject json = response.get();
Toast.makeText(MainActivity.this, json.toString(), Toast.LENGTH_SHORT).show();
} catch (InterruptedException e) {
Toast.makeText(MainActivity.this, "Interrupted.", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
AsyncTask (dummy doInBackground):
public class LoginTask extends AsyncTask<String, Void, JSONObject> {
private LoginTask self = this;
private ProgressDialog progressDialog;
#Override
protected JSONObject doInBackground(String... params) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = ProgressDialog.show(MainActivity.context,
"Logging in...", "");
progressDialog.setButton(DialogInterface.BUTTON_NEUTRAL,
MainActivity.context.getResources().getResourceEntryName(R.string.dialog_button_cancel), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
self.cancel(true);
}
});
}
#Override
protected void onPostExecute(JSONObject jsonObject) {
super.onPostExecute(jsonObject);
progressDialog.dismiss();
}
}
You can use AsyncTask's onProgressUpdate() method to perform the actions on the UI thread (such as showing or updating a loading animation) while doInBackGround() does the background work on another thread.
Basically you invoke the publishProgress() method from within doInBackGround(), which in turn calls onProgressUpdate().
Check out the Android reference page on AsyncTask for an example.
Please look at the usage of AsyncTask https://developer.android.com/reference/android/os/AsyncTask#usage
There is a callback function onPostExecute which returns (as parameter) the value you requested:
private class RestTask extends AsyncTask<Object, Object, String> {
protected String doInBackground(Object... args) {
// this happend on background thread
return downloadData();
}
protected void onPreExecute() {
// this happend on UI thread
showSpinner();
}
protected void onPostExecute(String result) {
// this happend on UI thread
hideSpinner();
doSomethingWithDownloadResult(result);
}
}
Usage:
new RestTask().execute()
As you edited the question, this:
try {
JSONObject json = response.get();
Toast.makeText(MainActivity.this, json.toString(), Toast.LENGTH_SHORT).show();
} catch (InterruptedException e) {
Toast.makeText(MainActivity.this, "Interrupted.", Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
should be called in previous Tasks onPostExecute method, this way you will not block you UI with get method waiting on login result.
1 - You can use a callback method.
but keep in mind you should call it in your main thread.
2 - you can use LocalBroadcastManager in order to send your result through Intent.
3 - you might want to use in application messaging libraries which are more reliable in my opinion. one example which I use very often is EventBus.

Unable to cancel async task execution

Am getting exception when the user continuously clicking the button on which am calling the async task.
So is there any way to cancel the execution of first async task execution on second time pressing the button.
I hope u understand the problem.
The codes am using is given below.
On button click am using the following code
GetData obj= new GetData();
String urls="http://pathramonline.com/?cat=46";
obj.execute(urls);
My async task
public class GetData extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
BufferedReader reader =null;
String data =null;
try{
HttpClient client = new DefaultHttpClient();
URI uri=new URI(params[0]);
HttpGet get =new HttpGet(uri);
HttpResponse response= client.execute(get);
InputStream stream=response.getEntity().getContent();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer =new StringBuffer("");
String line="";
String newLine= System.getProperty("line.separator");
while((line=reader.readLine())!=null){
buffer.append(line+newLine);
}
reader.close();
data = buffer.toString();
return data;
}
catch(URISyntaxException e){
e.printStackTrace();
}
catch(ClientProtocolException f){
f.printStackTrace();
}
catch(IOException g){
g.printStackTrace();
}
catch(Exception e)
{
//
}
finally{
if(reader!=null){
try{
reader.close();
}
catch(Exception e){
}
}
}
return null;
}
#Override
protected void onCancelled() {
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
//TextView t3=(TextView)findViewById(R.id.textView3);
if(result==null)
{
Intent home = new Intent(MainActivity.this,NoConnection.class);
MainActivity.this.startActivity(home);
MainActivity.this.finish();
}
//Some actions
}
}
I would suggest another method instead of cancelling the asynctask.
In your onPreExecute() method disable the button click
button.setEnabled(false);
And in onPostExecute() method enable back the button
button.setEnabled(true);
If you explicitly want to know that button is disabled then while the asynctask is being executed you can change the background color of the button to another color or background, so that the user will know that some function is being carried out and he needs to wait..
Another approach is
new AsyncTask<Void, Void, Void>() {
String result = "";
ProgressDialog progressDialog = null;
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
progressDialog = new ProgressDialog(getActivity());
progressDialog.setMessage("Loading , Please wait...");
progressDialog.setIndeterminate(true);
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.show();
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
String url = "your link comes here"
JSONObject jsonObject = jpass.getJSONFromUrl(url);
try {
//do your work here
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void a) {
// TODO Auto-generated method stub
progressDialog.dismiss();
if (result.equals("success")) {
//on success do some work here
}
else
{
//on failure do some work here
}
super.onPostExecute(a);
}
}.execute();
Instead of cancelling the AsyncTask just set your button's click listener to null and then again set it inside onPostExecute of your AsyncTask. It would be even better if you display a ProgressBar when your doInBackground() code is executing.

Android - asynctask don't show image when a use get(time)

I try to do app which show elements. Each element should start showing when the before element was hidden. Each element is showing 2 seconds. I try a lot of way:
Android/java - How to do that loop wait to do action
And now I try with Asynctask. I find a way:
public class MainActivity extends Activity
{
ImageView image1,image2;
int id = 0;
AsyncTask.Status status;
TextView txt;
String status1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LongOperation task = new LongOperation();
status = task.getStatus();
status1 = String.valueOf(status);
txt = (TextView) findViewById(R.id.txt);
image1 = (ImageView)findViewById(R.id.image1);
image2 = (ImageView)findViewById(R.id.image2);
do{
new LongOperation().execute("");
id=id+1;
txt.setText(status1);
try
{
try
{
task.get(2500, TimeUnit.MILLISECONDS);
} catch (TimeoutException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}while(id<3);
}
private class LongOperation extends AsyncTask<String, Void, String>
{
#Override
protected void onPreExecute()
{
image1.setVisibility(View.VISIBLE);
image2.setVisibility(View.VISIBLE);
txt.setText(status1);
}
#Override
protected String doInBackground(String... params) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.interrupted();
}
return null;
}
#Override
protected void onPostExecute(String result) {
txt.setText("Executed");
image1.setVisibility(View.GONE);
image2.setVisibility(View.GONE);
}
#Override
protected void onProgressUpdate(Void... values) {}
}
(This is a example). App run and end after 7.5 sec (everything ok) but images aren't shown when I start. What should I do?
I think you are creating a deadlock situation with your threads. The main UI thread is blocking at the line task.get(), which in turn is preventing the AsyncTask from running properly; its onPreExecute method is posted onto the UI Thread, and the doInBackground doesn't run until onPreExecute completes.

Android radio streaming - on activity resume - plays again

I'm building a Android app that streams simple radio station.
EDIT: I added the OnCreate event and the init() function.
on create:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
play_or_pause();
}
the init() function:
public void init() {
mediaPlayer = new MediaPlayer();
stream_url = "http://the_radio_station.m3u8";
playing_now = false;
fb_error = "";
}
on created I'm calling the AsyncTask method:
play_or_pause();
the AsyncTask method:
public class play_or_pause_AsyncTask extends
AsyncTask<Boolean, Integer, String> {
#Override
protected String doInBackground(Boolean... params) {
// TODO Auto-generated method stub
if (!params[0]) {
fb_error = "";
try {
if (mediaPlayer.isLooping() || mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
mediaPlayer.reset();
fb_error = String.valueOf(mediaPlayer.isPlaying());
mediaPlayer.setDataSource(stream_url);
mediaPlayer.prepare();
mediaPlayer.start();
playing_now = true;
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
fb_error += e.toString();
} catch (SecurityException e) {
// TODO Auto-generated catch block
fb_error += e.toString();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
fb_error += e.getMessage();
} catch (IOException e) {
// TODO Auto-generated catch block
fb_error += e.toString();
}
} else {
mediaPlayer.stop();
playing_now = false;
}
return fb_error;
}
#Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
// Toast.makeText(MainActivity.this, fb_error, Toast.LENGTH_LONG).show();
}
}
when I'm opening another Activity and coming back to the MainActivity(which making the stream) its starting to run the streaming again without stooping the old one.
I reed many posts here, the only suggestion was to use:
if ( mediaPlayer.isPlaying()) mediaPlayer.stop();
but it ain't helping (someone wrote that the mediaPlayer object is strange, you cant tell what is the objecct real status - Like if the .isPlaying() is true / false).
so what I can do in this situation?
try this way i use everytime
#Override
public void onStop() {
super.onStop();
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
}

I Can't use my findViewById from AsyncClass

I Can't use findViewById() from my Kclass=( How can i use it? `
private class BackGroundTask extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
try {
//execute - means sending
response =httpClient.execute(request);
HttpEntity entity=response.getEntity();
String str=EntityUtils.toString(entity);
Log.v("Json=", str);
//adding new response to our Response Class
resp.addNewResponse(str);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
Log.e(TAG, "Exception caught: ", e);
}
return null;
}
protected void onPostExecute(Void result) {
super.onPostExecute(result);
httpClient.getConnectionManager().shutdown();
TextView textView = (TextView) findViewById(R.id.textView1);
textView.setText("Done");
}
}
}
please write an exact code. This class is in another .java file. Not in MainActivity.java
The easiest way would be to not use findViewById() at all since you are in a separate file and that is an Activity method.
You can simply use an interface to create a callback in onPostExecute() and send back the String result to your Activity. Then in your callback you can simply set the text as you wish.
This answer gives an example of using an interface with AsyncTask
You may pass Activity context(YourActivity.this) to your AsyncTask and use activity.findViewById(...);
EDIT
Some code:
Add to AsyncTask:
private Activity mActivity;
public YourAsyncTask(Activity activity){
this.mActivity = activity
}
...
....
protected void onPostExecute(Void result) {
super.onPostExecute(result);
httpClient.getConnectionManager().shutdown();
if(mActivity!=null){
TextView textView = (TextView) mActivity.findViewById(R.id.textView1);
}
textView.setText("Done");
}
private Activity activity;
and in constructor:
public BackGroundTask(Activity activity){
this.activity=activity;
}
and in post Execute:
protected void onPostExecute(Void result) {
super.onPostExecute(result);
httpClient.getConnectionManager().shutdown();
TextView textView = (TextView) activity.findViewById(R.id.textView1);
textView.setText("Done");
}
If creating new background class from activity class call:
BackGroundTask doItInBackGround = new BackGroundTask(this);
If in a click listener or any class inside Activity call:
BackGroundTask doItInBackGround = new BackGroundTask(ActivityName.this);

Categories

Resources