I have created a program that will connect to a database through PHP and echo back a response. My android program then makes a request to the PHP file and reads the echo in.
public class Read_Author extends AsyncTask<String, Void, String> {
String authorName = "";
#Override
public String doInBackground(String... params) {
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://localhost/scripts/read_information.php");
HttpResponse response = httpclient.execute(httppost);
authorName = String.valueOf(EntityUtils.toString(response.getEntity()));
String myStr = "ANSWER";
Log.v(myStr, authorName);
}
catch(Exception e){
}
return authorName;
}
public String returnAuthor(){
return authorName;
}
}
I successfully retrieve the echo string and put it in the author name string variable. But when I then try to call return author from my main activity I get no error but the code does not get run.
I call a function called "readValue" within my main activity and within that function, the execute function gets read and then what is supposed to happen is the returnauthor function is supposed to run. But instead, nothing happens
Main Activity Code:
public void returnAuthor(){
loadAuthor.execute();
String a = loadAuthor.returnAuthor();
Log.v("HIT ME", a);
}
If anyone has any suggestion on why this could be happening and how to fix it that will be very much appreciated!
You seem to have misconception about AsyncTask. The result of AsyncTask may not be available instantly, because the background task might not have been completed.
You need to override the method onPostExecute in your AsyncTask to perform some task after the background task has been completed.
First show a progressDialog before executing the AsyncTask
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Loading..");
progressDialog.setCancelable(false);
progressDialog.show();
Then in the onPostExecute:
#Override
protected void onPostExecute(String result) {
progressDialog.dismiss();
Log.d("author", result);
}
Related
am using pushy for push notifications but am not able to store the device token in the database.
private class RegisterForPushNotificationsAsync extends AsyncTask<Void, Void, Exception> {
protected Exception doInBackground(Void... params) {
try {
// Assign a unique token to this device
String deviceToken = Pushy.register(getApplicationContext());
// Log it for debugging purposes
Log.d("MyApp", "Pushy device token: " + deviceToken);
// Send the token to your backend server via an HTTP GET request
new URL("https://key}/register/device?token=" + deviceToken).openConnection();
} catch (Exception exc) {
// Return exc to onPostExecute
return exc;
}
// Success
return null;
}
#Override
protected void onPostExecute(Exception exc) {
// Failed?
if (exc != null) {
// Show error as toast message
Toast.makeText(getApplicationContext(), exc.toString(), Toast.LENGTH_LONG).show();
return;
}
// Succeeded, optionally do something to alert the user
}
}
I am using retrofit for the http requests and am not using any kind of backend system
What you're doing is well enough to get you a Device Token from Pushy service.
If you want to capture the returned device token and make it accessible to the AsyncTask class and the enclosing class in general (as you stated in the comments), then you can declare a global/instance String variable, say pushy_device_token, in the enclosing class.
Then in doInBackground() method of the AsyncTask, go ahead and assign the global variable as follows:
pushy_device_token = Pushy.register(getApplicationContext());
Complete code:
public class EnclosingClass {
String pushy_device_token;
// Additional class code
private class RegisterForPushNotificationsAsync extends AsyncTask<Void, Void, Exception> {
#Override
protected Exception doInBackground(Void... params) {
try {
// Assign a unique token to this device
pushy_device_token = Pushy.register(getApplicationContext());
// Log it for debugging purposes
Log.d("MyApp", "Pushy device token: " + deviceToken);
// Send the token to your backend server via an HTTP GET request
new URL("https://key}/register/device?token=" + deviceToken).openConnection();
} catch (Exception exc) {
// Return exc to onPostExecute
return exc;
}
// Success
return null;
}
#Override
protected void onPostExecute(Exception exc) {
// Failed?
if (exc != null) {
// Show error as toast message
Toast.makeText(getApplicationContext(), exc.toString(), Toast.LENGTH_LONG).show();
return;
}
// Succeeded, optionally do something to alert the user
}
}
}
Best practice recommendation:
It's best to have the result of processing in doInBackground(), returned in the onPostExecute() method, especially if you're going to do some UI work. So from onPostExecute(), you can do anything you want with the result, e.g. display to the user, report an error, etc.
To do this, you'll have to modify your doInBackground() method to return something as generic as Object. And so onPostExecute() will take in an Object as a parameter variable.
You'll modify by:
private class RegisterForPushNotificationsAsync extends AsyncTask<Void, Void, Object> { . . .
From this, you can check if the Object taken in by onPostExecute() is of type Exception, in which case, you'll display an error notification, or check if it's of type String, in which case you'll have the device token which you can then proceed to save in your DB (Firebase, SQLite, etc.).
After user press the button it fires up weather function. But it doesn't log any JSON data or any error. Should it be done in background? I've used gson libary to download JSON.
Edit: I edited my code but user must enter a city which is pasted to the link. So is it possible to run in background process when the button is tapped?
public class MainActivity extends AppCompatActivity {
public class Download extends AsyncTask<String,Void,String>{
#Override
protected String doInBackground(String... strings) {
try {
URL url = new URL("api.openweathermap.org/data/2.5/weather?q="+strings[0]+"&APPID=****");
URLConnection request = url.openConnection();
request.connect();
JsonParser jp=new JsonParser();
JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent()));
JsonObject rootobj = root.getAsJsonObject();
String weather = rootobj.getAsString();
Log.i("weather:",weather);
}
catch (Exception e){
e.printStackTrace();;
}
return null;
}
}
public void weather(View view){
TextView textView=(TextView) findViewById(R.id.editText);
String city=textView.getText().toString();
Download download=new Download();
download.execute(city);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
All io operation should be executed in background , because all this operations are time consuming . which means you will block your main thread if you donot execute these codes in background and may cause Android Not Respond exception. IO operation in ui thread generally lead to bad user experience . so i strongly advice you do this in background.
You should definitely load your data in the background. The Main Thread i.e. the UI Thread is the thread that renders the UI components so no heavy operation should be done there. If heavy operation is done in the UI Thread, it will freeze the UI.
You should look at the AsyncTask class to perform your loading in the background.
Here is some good tutorials:
https://alvinalexander.com/android/asynctask-examples-parameters-callbacks-executing-canceling
https://www.journaldev.com/9708/android-asynctask-example-tutorial
https://www.tutorialspoint.com/android-asynctask-example-and-explanation
I am trying to make a program that should work something like a catalog - I have a JSON array that I loop through and parse the JSON objects into a string containing the image link, and two strings for descriptions for each object. Now, when downloading the images from the internet with the link, I run into a problem at the same image every time, image number 93. I checked the link, and it's working, just the same as the others.
This happens:
W/MessageQueue: Handler (android.os.Handler) {f95f6fe} sending message to a Handler on a dead thread
java.lang.IllegalStateException: Handler (android.os.Handler) {f95f6fe} sending message to a Handler on a dead thread
at android.os.MessageQueue.enqueueMessage(MessageQueue.java:543)
at android.os.Handler.enqueueMessage(Handler.java:643)
at android.os.Handler.sendMessageAtTime(Handler.java:612)
at android.os.Handler.sendMessageDelayed(Handler.java:582)
at android.os.Handler.post(Handler.java:338)
at android.os.ResultReceiver$MyResultReceiver.send(ResultReceiver.java:57)
at com.android.internal.os.IResultReceiver$Stub.onTransact(IResultReceiver.java:58)
at android.os.Binder.execTransact(Binder.java:565)
This is how my AsyncTask looks:
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
This is how I call the AsyncTask:
new DownloadImageTask(imgProductPicture).execute(pictureLink);
layoutTest.addView(NewImgView);
In my code I make sure that no more than 5 of these are called at a time, and they all load without issue until reaching the object indexed 92. The object itself is fine, but the app shuts off at this point always. Does anyone have an idea why? I've tried downloading less images at a time (one by one) and it still fails at the same point. I'd appreciate any help.
AsyncTask uses handler of the main thread, to callback onPostExecute(). If the main thread is dead when to callback, system throws the exception. To avoid this, you have to keep the main thread alive until all the work completes.
I solved the problem by creating a new handler/runnable every time I called the DownloadImageTask. Thanks to all who have tried to help.
I have scoured the internet, and developed code that I thought would work to get the html of a website in readable form. However, I am still unable to make this work. Here is my code:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DownloadTask task = new DownloadTask();
task.execute("http://www.cnn.com");
}
private class DownloadTask extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... urls) {
HttpResponse response = null;
HttpGet httpGet = null;
HttpClient mHttpClient = null;
String s = "";
try {
if(mHttpClient == null){
mHttpClient = new DefaultHttpClient();
}
httpGet = new HttpGet(urls[0]);
response = mHttpClient.execute(httpGet);
s = EntityUtils.toString(response.getEntity(), "UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
return s;
}
#Override
protected void onPostExecute(String result){
final TextView textview1 = (TextView) findViewById(R.id.headline);
textview1.setText(result);
}
}
}
When I try this, the app crashes on startup, with the LogCat shown below:
07-26 16:13:42.561: W/dalvikvm(23584): threadid=12: thread exiting with uncaught exception (group=0x416dfda0)
07-26 16:13:42.561: E/AndroidRuntime(23584): FATAL EXCEPTION: AsyncTask #1
07-26 16:13:42.561: E/AndroidRuntime(23584): Process: com.app.firstapp, PID: 23584
07-26 16:13:42.561: E/AndroidRuntime(23584): java.lang.RuntimeException: An error occured while executing doInBackground()
I have no idea why this is happening, does anyone know how I can modify my code to make this work? Thanks in advance.
A library that might be helpful to you is jsoup.
Link: http://jsoup.org
To get a pages HTML in jsoup you just do:
Jsoup.connect("http://google.com").get();
And then from this HTML you can use Jsoup to parse whatever data from the HTML you need.
Link: http://jsoup.org/cookbook/extracting-data/dom-navigation
Edit: I miss read the question. I thought you were having trouble with getting the HTML instead of the fact that there was a problem in the backgrounding.
Make sure that you have included
<uses-permission android:name="android.permission.INTERNET"/>
in your Manifest file.
I'm writing an android app I use a background thread to pull a JSONArray from a web service. I then need to interact with that JSONArray inside the main activity. Here's what I'm doing now:
public class MainActivity extends Activity {
JSONArray stories;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new getAll().execute();
// try {
System.out.println("stories.length());
// } catch (JSONException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
//}
}
And the background thread:
private class getAll extends AsyncTask <Void, Void, JSONArray> {
private static final String url = "http://10.0.2.2:8080/CalibServer/webresources/storypkg.story/";
#Override
protected JSONArray doInBackground(Void... params) {
//set up client and prepare request object to accept a json object
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url);
httpget.addHeader("accept", "application/json");
HttpResponse response;
String resprint = new String();
try {
response = httpclient.execute(httpget);
// Get the response entity
HttpEntity entity = response.getEntity();
if (entity != null) {
// get entity contents and convert it to string
InputStream instream = entity.getContent();
String result= convertStreamToString(instream);
resprint = result;
// construct a JSON object with result
stories =new JSONArray(result);
// Closing the input stream will trigger connection release
instream.close();
}
}
catch (ClientProtocolException e) {System.out.println("CPE"); e.printStackTrace();}
catch (IOException e) {System.out.println("IOE"); e.printStackTrace();}
catch (JSONException e) { System.out.println("JSONe"); e.printStackTrace();}
System.out.println("FUCKYEAHBG: " + resprint);
// stories = object;
return stories;
}
My problem is that I'm getting a NullPointerException at the call to
System.out.println("stories.length());
It's acting like a didn't initialize the stories array, but should't that have been taken care of by the background thread (at the line: stories =new JSONArray(result); ) before that call is ever made?
I have a feeling this is because of the threading - perhaps there is another step I have to take to update the main activity after the AsyncTask runs?
You're initializing the variable in a background thread. That means that the line
System.out.println(stories.length());
is executed in parallel with the code initializing the variable. That thus means that there is a huge chance that the background thread has not had the time to initialize the variable yet when this line is executed.
Your code is similar to the following situation: you have an empty cup in front of you, and ask someone to go make some coffee and to fill your cup. And immediately after asking, you start drinking. There will be no coffee inside the cup, obviously.
Re-read the android documentation on how to execute asynchronous tasks.
You can't rely on stories to be initialized when a separate Thread that runs parallel to the UI Thread initializes and updates stories.
perhaps there is another step I have to take to update the main
activity after the AsyncTask runs?
onPostExecute() of the AsyncTask. Do whatever UI updates you need there. Since getAll is already a private inner class, you have full access to the Activity. You already return stories off to that (unoverriden) method, so this should be a minor change.
#Override
protected void onPostExecute (JSONArray stories)
{
//use the now initialized stories
}