How to execute onMapReady() callback after all the AsyncTasks are completed? - java

I am having trouble with my code where i have my Activity which i use to call google api's and retrieve jsons, deserialize them and use it's Polylines to draw on the map.
The problem is that getMapAsync() which sends the callback for onMapReady() (which is used to create the map) is executed immediately after executing my Async Tasks which retrieves necessary data to create the map.
How can i make this happen without stopping the UI thread? I tried doing this calling .execute.get() which freeze the UI thread. But if i do that, i won't be able to use ProgressDialog to inform the users about the delay for fetching data from the servers, which they will be exposed to a frozen UI until the task is complete. How can i do this?
public class RouteAssistantActivity extends Activity implements OnMapReadyCallback{
public GoogleMapsDirectionsResponse dirRes;
public GoogleMapsDistanceResponse disRes;
public String jsonString;
private String mapsAPIKey;
private String directionsBaseURL;
private String distanceBaseURL;
MapFragment mapFragment;
private ProgressDialog progress;
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ra_route_assisstant);
mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.ra_map);
progress = new ProgressDialog(RouteAssistantActivity.this);
progress.setTitle("Please Wait");
progress.setMessage("Retrieving Data from the Server");
progress.setIndeterminate(true);
try {
ApplicationInfo appInfo = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
if (appInfo.metaData != null) {
mapsAPIKey = appInfo.metaData.getString("com.google.android.maps.v2.API_KEY");
directionsBaseURL = appInfo.metaData.getString("com.google.android.maps.directions.baseURL");
distanceBaseURL = appInfo.metaData.getString("com.google.android.maps.distance.baseURL");
}
} catch (PackageManager.NameNotFoundException e) {
Log.e("Meta Error", "Meta Data not found. Please check the Manifest and the Meta Data Package Names");
e.printStackTrace();
}
//Test
String directionsURL = directionsBaseURL+"origin=6.948109,79.858191&destination=6.910176,79.894347&key="+mapsAPIKey;
String distanceURL = distanceBaseURL+"units=metric&origins=6.948109,79.858191&destinations=6.910176,79.894347&key="+mapsAPIKey;
Log.e("CA Debug","URL : " + directionsURL);
Log.e("CA Debug","URL : " + distanceURL);
new configurationSyncTask().execute(distanceURL,"distance");
new configurationSyncTask().execute(directionsURL, "direction");
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
LatLng rajagiriya = new LatLng(6.910176, 79.894347);
String points = dirRes.getRoutes().get(0).getOverviewPolyline();
List<LatLng> list = PolyUtil.decode(points);
googleMap.setMyLocationEnabled(true);
googleMap.getUiSettings().setRotateGesturesEnabled(true);
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(rajagiriya, 13));
googleMap.addMarker(new MarkerOptions()
.title("Rajagiriya")
.snippet("My Place")
.position(rajagiriya));
googleMap.addPolyline(new PolylineOptions()
.geodesic(false)
.addAll(list)
.color(Color.RED)
.width(25));
}
private class configurationSyncTask extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
progress.show();
}
#Override
protected String doInBackground(String... params) {
String url = params[0];
String type = params[1];
Log.d("CA Debug", getClass().getSimpleName() + " --> Real URL : " + url);
Log.d("CA Debug", getClass().getSimpleName() + " --> doInBackground requesting content");
jsonString = requestContent(url);
// if the output is null, stop the current task
if (jsonString == null) {
Log.d("CA Debug", getClass().getSimpleName() + " --> Stopping Async Task");
this.cancel(true);
Log.d("CA Debug", getClass().getSimpleName() + " --> Async Task Stopped");
}
return type;
}
#Override
protected void onPostExecute(String types) {
if (types.equalsIgnoreCase("distance")) {
disRes = GMapsDistanceResponseJSONDeserializer.deserialize(jsonString);
} if (types.equalsIgnoreCase("directions")) {
dirRes = GMapsDirectionsResponseJSONDeserializer.deserialize(jsonString);
}
progress.dismiss();
}
}
public String requestContent(String url) {
Log.d("CA Debug",getClass().getSimpleName()+" --> URL : "+url);
try {
URL urlObj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) urlObj.openConnection();
con.setChunkedStreamingMode(0);
con.setRequestMethod("GET");
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null,null, new SecureRandom());
con.setSSLSocketFactory(sc.getSocketFactory());
InputStream clientResponse;
String jsonString;
int status = con.getResponseCode();
if(status >= HttpURLConnection.HTTP_BAD_REQUEST){
Log.d("CA Debug", getClass().getSimpleName()+" --> Bad Request");
jsonString = null;
} else {
Log.d("CA Debug", getClass().getSimpleName()+" --> converting Stream To String");
clientResponse = con.getInputStream();
jsonString = convertStreamToString(clientResponse);
}
Log.d("CA Debug", getClass().getSimpleName()+" --> JSON STRING : " + jsonString);
return jsonString;
} catch (IOException | NoSuchAlgorithmException | KeyManagementException e) {
Log.d("CA Debug", getClass().getSimpleName()+" --> Error when creating an Input Stream");
e.printStackTrace();
}
return null;
}
public String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
} finally {
try {
is.close();
} catch (IOException e) {
}
}
return sb.toString();
}
}

Quick and somewhat dirty solution would be to execute both AsyncTasks on a single AsyncTask and then on its onPostExecute code invoke getMapAsync. this way you will be sure your tasks finished before you dealing with map's readyness.

Firstly, run tasks after onMapReady because you will get rid of
concern of ready map.
Your async tasks are not parallel, they working on background but second one will be executed after first one completed, check this link
Move some parts of onMapReady to onPostExecute, something like below
Move
#Override
protected void onPostExecute(String types) {
if (types.equalsIgnoreCase("distance")) {
disRes = GMapsDistanceResponseJSONDeserializer.deserialize(jsonString);
}if (types.equalsIgnoreCase("directions")) {
dirRes = GMapsDirectionsResponseJSONDeserializer.deserialize(jsonString);
String points = dirRes.getRoutes().get(0).getOverviewPolyline();
List<LatLng> list = PolyUtil.decode(points);
googleMap.addPolyline(new PolylineOptions()
.geodesic(false)
.addAll(list)
.color(Color.RED)
.width(25)
);
}
}

AsyncTask.SERIAL_EXECUTOR is used to force AsyncTask to execute in Serial Fashion.
More over for your case a little trick will do the job.
Create call back for same AsyncTask and pass different parameters to differentiate the functions.
Now in the second call back initiate mapFragment.getMapAsync(this);
public class MainFragment ...
{
DataDownloader dataDownloader;
int processCount=1;
void initiateProcessFirst(){
new DataDownloader(this,processCount ).execute();
}
public void initiateSecondProcess(){
processCount++;
new DataDownloader(this,processCount ).execute();
}
public void secondProcessCompleted(){
mapFragment.getMapAsync(this);
}
}
AsyncTask Logic goes like the below
public class DataDownloader extends AsyncTask<Void,Void,Boolean> {
MainFragment context;
int processCount;
public DataDownloader(MainFragment context ,int processCount){
this.context=context;
this.processCount=processCount;
}
#Override
protected Boolean doInBackground(Void... params) {
boolean status=false;
// Do logic according to the Process Count
return status;
}
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
if(processCount==1)
context.initiateSecondProcess();
else
context.secondProcessCompleted();
}
}

Related

Android - My onPostExecute in AsyncTask is not getting called

So I have been trying to fetch JSON objects in my Django REST Framework API. The algorithm for this called within the onPostExecute of my AsyncTask but it seems that it is not being called as when I debug it doesn't go there. Nothing fatal seems to be appearing in my logcat except that there is nothing in my array that should contain data from the DRF API.
I have two activities that calls my AsyncTask from my WSAdapter class. One is for logging in and the other is for listing all posts once logged in.
The logging in works just fine but listing the posts doesn't.
My code is below:
Posts.java
public class Posts extends AppCompatActivity {
TextView postsSect;
Button postsDoneBtn;
WSAdapter.SendAPIRequests PostsHelper;
StringBuilder postsBuffer = new StringBuilder();
#Override
protected void onResume(){
super.onResume();
PostsDetails postDetailsHelper = new PostsDetails();
postDetailsHelper.ListPosts();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_posts);
PostsDetails postDetailsHelper = new PostsDetails();
postsDoneBtn = (Button) findViewById(R.id.PostsDoneButton);
postDetailsHelper.callPostDetails("192.168.0.18:8000/api");
postDetailsHelper.ListPosts();
postDetailsHelper.postDetailsCalled('n');
postsDoneBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(Posts.this, MainActivity.class));
}
});
}
public class PostsDetails {
//String post_title, post_content;
ArrayList<Integer> post_id = new ArrayList<Integer>();
ArrayList<String> post_title = new ArrayList<String>();
ArrayList<String> post_content = new ArrayList<String>();
boolean isPDCalled;
// sets if Post details are called
boolean postDetailsCalled(char called) {
if (called == 'y'){
return true;
}
return false;
}
// checks if postsDetails functions are called for AsyncTask
boolean getIsPDCalled(){
return isPDCalled;
}
// calls the execute for AsyncTask
private void callPostDetails(String theurl){
PostsHelper = new WSAdapter.SendAPIRequests();
// sets if post details are called
postDetailsCalled('y');
// executes AsyncTask
PostsHelper.execute(theurl);
}
// sets values for the posts arrays
public void setPost(int p_id, String p_title, String p_content) {
post_id.add(p_id);
post_title.add(p_title);
post_content.add(p_content);
}
// Lists the posts from the database
public void ListPosts() {
/////////// add functionality if a post was deleted and was clicked
postsSect = (TextView) findViewById(R.id.PostsSection);
postsSect.setText(post_title.get(post_title.size()) + "\n");
for (int i = post_id.size() - 1; i > 0; i--)
{
postsSect.append(post_title.get(i));
}
}
}
}
WSAdapter.java
public class WSAdapter extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
static public class SendAPIRequests extends AsyncTask<String, String, String> {
// Add a pre-execute thing
#Override
protected String doInBackground(String... params) {
Log.e("TAG", params[0]);
Log.e("TAG", params[1]);
String data = "";
HttpURLConnection httpURLConnection = null;
try {
// Sets up connection to the URL (params[0] from .execute in "login")
httpURLConnection = (HttpURLConnection) new URL(params[0]).openConnection();
// Sets the request method for the URL
httpURLConnection.setRequestMethod("POST");
// Tells the URL that I am sending a POST request body
httpURLConnection.setDoOutput(true);
// To write primitive Java data types to an output stream in a portable way
DataOutputStream wr = new DataOutputStream(httpURLConnection.getOutputStream());
// Writes out a byte to the underlying output stream of the data posted from .execute function
wr.writeBytes("postData=" + params[1]);
// Flushes the postData to the output stream
wr.flush();
wr.close();
// Representing the input stream
InputStream in = httpURLConnection.getInputStream();
// Preparing input stream bytes to be decoded to charset
InputStreamReader inputStreamReader = new InputStreamReader(in);
StringBuilder dataBuffer = new StringBuilder();
// Translates input stream bytes to charset
int inputStreamData = inputStreamReader.read();
while (inputStreamData != -1) {
char current = (char) inputStreamData;
inputStreamData = inputStreamReader.read();
// concatenates data characters from input stream
dataBuffer.append(current);
}
data = dataBuffer.toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
// Disconnects socket after using
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
}
Log.e("TAG", data);
return data;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// expecting a response code fro my server upon receiving the POST data
Log.e("TAG", result);
Posts.PostsDetails postsHelper = new Posts().new PostsDetails();
// For posts
try {
if (postsHelper.getIsPDCalled()){
JSONObject pJObj = new JSONObject(result);
JSONArray pJObjArray = pJObj.getJSONArray("posts");
for (int i = 0; i < pJObjArray.length(); i++) {
JSONObject pJObj_data = pJObjArray.getJSONObject(i);
postsHelper.setPost(pJObj_data.getInt("id"), "post_title", "post_content");
}
}
} catch (JSONException e) {
//Toast.makeText(JSonActivity.this, e.toString(), Toast.LENGTH_LONG).show();
Log.d("Json","Exception = "+e.toString());
}
}
}
}
Login.java
public class Login extends AppCompatActivity {
Button LoginButton;
EditText uUserName, uPassWord;
WSAdapter.SendAPIRequests AuthHelper;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
//SetupHomeBtn = (ImageButton) findViewById(R.id.SetupHomeBtn);
LoginButton = (Button) findViewById(R.id.LoginButton);
uUserName = (EditText) findViewById(R.id.LoginUserBox);
uPassWord = (EditText) findViewById(R.id.LoginPassBox);
//AuthHelper = new WSAdapter().new SendDeviceDetails();
// Moves user to the main page after validation
LoginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// gets the username and password from the EditText
String strUserName = uUserName.getText().toString();
String strPassWord = uPassWord.getText().toString();
// API url duh
String APIUrl = "http://192.168.0.18:8000/token-auth/";
// If the user is authenticated, then transfer to the MainActivity page
if (APIAuthentication(strUserName, strPassWord, APIUrl)){
startActivity(new Intent(Login.this, Posts.class));
}
}
});
}
private boolean APIAuthentication(String un, String pw, String url){
// when it wasn't static -> AuthHelper = new WSAdapter().new SendAPIRequests();
AuthHelper = new WSAdapter.SendAPIRequests();
JSONObject postData = new JSONObject();
try {
// Attempt to input info to the Django API
postData.put("username", un);
postData.put("password", pw);
// Putting the data to be posted in the Django API
AuthHelper.execute(url, postData.toString());
return true;
} catch (JSONException e) {
e.printStackTrace();
}
return false;
}
}
I was expecting my onPostExecute to be called and store data for my posts arrays.
Okay this is a nice example of async tasks. The problem here is when you call an async task then the code below will continue to execute even when the async task hasn't finished. So what happens in your case:
You fetch the posts and then ask to display them on the exact moment that the async function is still getting the posts. So of course the List is empty.
You can fix this by using the await keyword. This keyword stops the rest of your code from executing until that line has been executed. So change:
postDetailsHelper.callPostDetails("192.168.0.18:8000/api");
to:
await postDetailsHelper.callPostDetails("192.168.0.18:8000/api");
Now the reason that the login does work is because you call that function within the if statement. If you would store the return value of that function in a boolean first then it wouldn't work either.

Asking the user for a URL to receive a JSON

Just as a practicing exercise i'm trying to make an app that fetches a JSON from a URL.
I found the following code in other thread here in stackoverflow and it works just fine. My problem is that the URL is hardcoded, and i need it to be an input by the user. What should i change/add?
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("Url address here");
}
});
}
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); //here u ll get whole response..... :-)
}
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);
}
}
}
This is the thread where i got that code from:
Get JSON Data from URL Using Android?
Create a constructor in your async Task
private class JSONTask extends AsyncTask<String, String, String> {
String url;
public JSONTask(String url){
this.url=url;
}
use the url string in place of params[0]
And wherever you call your async task do it like this
new JSONTask(textView.getText()).execute()
This should solve it.
Else you can directly use the do in background variable params.
So the problem is that you are using a TextView. TextView does not recieve inputs.
EditText does.
Make these Changes:
TextView txtJson;
In your OnCreate change this:
txtJson = (EditText) findViewById(R.id.tvJsonItem);
btnHit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new JsonTask().execute(txtJson.getText());
}
});
Now in your xml file change the Button to EditText.
Hope this helps.

AsyncTask setting priority

I have an AsyncTask(.execute()) with an onPostExecute method. This method starts another AsyncTask(.execute()) that needs to be done before continuing the execution of the first onPostExecute. Is it possible to pause the first thread and to wait for the second thread to finish? I need the result from the second postExecute method in order to finish the first postExecute.
An example below:
public class RetrieveData extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... strings) {
HttpURLConnection conn = null;
try {
URL url = new URL(strings[0]);
conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String linieNoua = "";
String crlf = System.getProperty("line.separator");
StringBuilder sb = new StringBuilder();
while((linieNoua = br.readLine()) != null) {
sb.append(linieNoua);
sb.append(crlf);
}
conn.disconnect();
return sb.toString();
} catch (Exception e){
e.printStackTrace();
}
return null;
}
}
RetrieveData retrieveData = new RetrieveData() {
#Override
protected void onPostExecute(String s) {
if (s != null) {
retrieveTransport(transportRegNr);
} else {
Toast.makeText(getApplicationContext(), R.string.login_server_error, Toast.LENGTH_LONG).show();
}
}
};
retrieveData.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"http://192.168.0.101:3000/route/" + prefs.getString("email",null));
}
private void retrieveTransport(String regNr){
RetrieveData retrieveData = new RetrieveData() {
#Override
protected void onPostExecute(String s) {
if (s != null) {
try {
JSONObject jsonObject = new JSONObject(s);
String model = jsonObject.getString("model");
String regNr = jsonObject.getString("regNr");
int type = jsonObject.getInt("type");
int seats = jsonObject.getInt("seats");
t = new Transport(model,regNr,null,seats,type);
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Toast.makeText(getApplicationContext(), R.string.login_server_error, Toast.LENGTH_LONG).show();
}
}
};
retrieveData.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"http://192.168.0.101:3000/transport/registryNr/" + regNr);
}
If I use the execute method, onPostExecute from retrieveTransport(String regNr) is never called. If I use executeOnExecutor, they are running simultaneously, and that's not good, either. I need to finish the first retrieveTransport; without that, I can't continue the first onPostExecute.
use
getStatus()
checks whether the the AsyncTask is pending, running, or finished.and when finsh start your new task.like:
if(retrieveTransport.getStatus() == AsyncTask.Status.PENDING){
// My AsyncTask has not started yet
}
if(retrieveTransport.getStatus() == AsyncTask.Status.RUNNING){
// My AsyncTask is currently doing work in doInBackground()
}
if(retrieveTransport.getStatus() == AsyncTask.Status.FINISHED){
// START NEW TASK HERE
}
example for your app:
if (retrieveTransport!= null && retrieveTransport.getStatus() == AsyncTask.Status.FINISHED) {
//START retrieveData TASK HERE
}
else
{
//IGNORE
}

Returning result from Asynctask

If I have this background worker file in my android application and it gets data from my database how can I pass the string 'result' to another class?
The background worker connects to my server and then using php it connects to a database.
public class BackgroundWorker extends AsyncTask<String,Void,String> {
Context context;
AlertDialog alertDialog;
BackgroundWorker (Context ctx) {
context = ctx;
}
#Override
public String doInBackground(String... params) {
String type = params[0];
String specials_url = "";
if(type.equals("venue click")) {
try {
//String user_name = params[1];
URL url = new URL(specials_url);
HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setDoOutput(true);
httpURLConnection.setDoInput(true);
OutputStream outputStream = httpURLConnection.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
// String post_data = URLEncoder.encode("user_name","UTF-8")+"="+URLEncoder.encode(user_name,"UTF-8");
// bufferedWriter.write(post_data);
bufferedWriter.flush();
bufferedWriter.close();
outputStream.close();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"iso-8859-1"));
String result="";
String line="";
while((line = bufferedReader.readLine())!= null) {
result += line;
}
bufferedReader.close();
inputStream.close();
httpURLConnection.disconnect();
return result;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPreExecute() {
alertDialog = new AlertDialog.Builder(context).create();
alertDialog.setTitle("Info");
}
#Override
protected void onPostExecute(String result) {
alertDialog.setMessage(result);
alertDialog.show();
// String temp = "login success";
// if (result.equals(temp)) {
// Intent intent = new Intent(context, Register.class);
// context.startActivity(intent);
// }
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
}
You need a listener. This will allow you to notify back when the AsyncTask is done.
Define the listener by creating an interface, like this:
public interface IListener
{
void onCompletedTask(String result);
}
On the task store a reference to the listener.
private IListener mListener;
// Pass the reference to the constructor.
public BackgroundWorker(IListener listener)
{
mListener = listener;
}
Then you notify the listener like this.
#Override
protected void onPostExecute(String result)
{
mListener.onCompletedTask(result);
}
Best way to get a callback from background thread is to use interfaces as a callback from AsyncTask for example:
create an interface that can be called in onPostExecute()
public interface ResponseCallback {
void onRespond(String result);
}
and before calling asynckTask define it like this:
ResponseCallback cpk = new ResponseCallback() {
#Override
public void onRespond(String result) {
//code to be done after calling it from onPostExecute
}
};
and pass cpk to the constructor of of the asynckTask and call it in onPostExecute like that:
if(cpk!=null){
cpk.onRespond(result);
}
of course you can modify the signature of the interface to what ever you want.

How do i set an ImageView to show an image from an image url?

When i try to set the ImageView variable "profilePicture" to the bitmap from the image url, it doesn't show anything. Please help!! I am getting the image url link from my database. This is what that async task result is.
System.out: Resulted Value: {"image":"http://www.myegotest.com/PhotoUpload/uploads/5.png"}
Here is my Java code
public class HomeActivity extends AppCompatActivity {
//View item variables
private TextView loggedUsersName;
private TextView successMessage;
private Button logoutButton;
private ImageView profilePicture;
//Other variables
private String getProfileImageURL = "http://www.myegotest.com/PhotoUpload/getAllImages.php";
private String firstName;
private String lastName;
private String email;
private Bitmap profilePicBitmap;
LocalDataBase mLocalDataBase;
Boolean imageSet;
Drawable d;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
//Get logged in user from LocalDataBase and
//Destroy Activity if user is logged out
mLocalDataBase = new LocalDataBase(this);
User user = mLocalDataBase.getLoggedInUserInfo();
if(!mLocalDataBase.userIsLoggedIn()){
HomeActivity.this.finish();
}
//Initialize view item variables.
loggedUsersName = (TextView)findViewById(R.id.login_user);
successMessage = (TextView)findViewById(R.id.message);
logoutButton = (Button)findViewById(R.id.logoutButton);
profilePicture = (ImageView)findViewById(R.id.profile_Picture);
//Get intent and values from the intent started this activity and
//Get loggedIn user values from the LocalDataBase .
Intent intent = getIntent();
String message = intent.getStringExtra("MESSAGE");
firstName = user.mFirstName;
lastName = user.mLastName;
email = user.mEmail;
//Set view values to equal values sent from intent.
loggedUsersName.setText(firstName + " " + lastName);
successMessage.setText(message);
netAsync();
}
//Call this method to execute the Async Task
private void netAsync() {
new NetCheck().execute();
}
//Async Task to check whether internet connection is working.
private class NetCheck extends AsyncTask {
private ProgressDialog mDialog;
//Create and show progress dialog box so user knows the app is trying to login.
#Override
protected void onPreExecute() {
super.onPreExecute();
mDialog = new ProgressDialog(HomeActivity.this);
mDialog.setTitle("Logging In...");
mDialog.setMessage("connecting to server");
mDialog.setIndeterminate(false);
mDialog.setCancelable(true);
mDialog.show();
}
//Gets current device state and checks for working internet connection by trying Google.
#Override
protected Boolean doInBackground(Object[] objects) {
ConnectivityManager mCM = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo myNetInfo = mCM.getActiveNetworkInfo();
if ( (myNetInfo != null) && (myNetInfo.isConnected())){
try {
URL url = new URL("http://google.com");
HttpURLConnection myConnection = (HttpURLConnection) url.openConnection();
myConnection.setConnectTimeout(3000);
myConnection.connect();
if (myConnection.getResponseCode() == 200){
return true;
}
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
#Override
protected void onPostExecute(Object o) {
super.onPostExecute(o);
//If successful internet connection start AsyncTask to register user info on server
if(o.equals(true)){
mDialog.dismiss();
new RegisterUser().execute(getProfileImageURL, email);
} else {
mDialog.dismiss();
Toast.makeText(getApplicationContext(), "Error in Network Connection", Toast.LENGTH_SHORT).show();
}
}
}
//AsyncTask to get profile pic url string from server
private class RegisterUser extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
try {
URL url = new URL(params[0]);
HttpURLConnection LucasHttpURLConnection = (HttpURLConnection)url.openConnection();
LucasHttpURLConnection.setRequestMethod("POST");
LucasHttpURLConnection.setDoOutput(true);
LucasHttpURLConnection.setDoInput(true);
LucasHttpURLConnection.setConnectTimeout(1000 * 6);
LucasHttpURLConnection.setReadTimeout(1000 * 6);
//OutputStream to get response
OutputStream outputStream = LucasHttpURLConnection.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream,"UTF-8"));
String data =
URLEncoder.encode("email", "UTF-8")+"="+URLEncoder.encode(params[1], "UTF-8");
bufferedWriter.write(data);
bufferedWriter.flush();
bufferedWriter.close();
outputStream.close();
//InputStream to get response
InputStream IS = LucasHttpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(IS, "iso-8859-1"));
StringBuilder response = new StringBuilder();
String json;
while( (json = bufferedReader.readLine()) != null){
response.append(json + "\n");
break;
}
bufferedReader.close();
IS.close();
LucasHttpURLConnection.disconnect();
return response.toString().trim();
} catch (MalformedInputException e){
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
//Print server AsyncTask response
System.out.println("Resulted Value: " + result);
//If null Response
if (result != null && !result.equals("")) {
String profilepic = returnParsedJsonObject(result);
new GetBitmapImageFromUrl().execute(profilepic);
profilePicture = (ImageView)findViewById(R.id.profile_Picture);
profilePicture.setImageBitmap(profilePicBitmap);
} else {
Toast.makeText(HomeActivity.this, "Sorry, there was an error. Please try again", Toast.LENGTH_LONG).show();
}
}
//Method to parse json result and get the value of the key "image"
private String returnParsedJsonObject(String result){
JSONObject resultObject = null;
String returnedResult = "";
try {
resultObject = new JSONObject(result);
returnedResult = resultObject.getString("image");
} catch (JSONException e) {
e.printStackTrace();
}
return returnedResult;
}
}
class GetBitmapImageFromUrl extends AsyncTask<String,Void,Bitmap>{
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Bitmap doInBackground(String... params) {
try {
profilePicBitmap = BitmapFactory.decodeStream((InputStream)new URL(params[0]).getContent());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
}
}
}
If you are seeing background white instead image. Out of memory exception by using bitmap.
You could use
Option 1
URL newurl = new URL(photo_url_str);
mIcon_val = BitmapFactory.decodeStream(newurl.openConnection() .getInputStream());
profile_photo.setImageBitmap(mIcon_val);
Picasso
Picasso.with(context).load("http://www.myegotest.com/PhotoUpload/uploads/5.png").into(profilePicture);
I would suggest to go with Piccasso. Since it will handle everything.

Categories

Resources