Initiating List<String> inside of AsyncTask in Android - java

I'm trying to initiate List<String> inside of AsyncTask and the whole task is no longer called, no errors though.
Just to be clear, the only reason I am after the List is that it gives me an opportunity to cut big chunk of elements at once using sublist.
If there's an easy way or you spotted a bug, please share.
protected void updateTask()
{
runOnUiThread(new Runnable()
{
public void run()
{
PatternTask myTask = new PatternTask();
myTask.execute();
}
});
}
private class PatternTask extends AsyncTask<String, Void, String> {
int eyes_closed;
int eyes_opened;
int eyes_avarage;
String response = "NO DATA";
protected String doInBackground(String... patterns) {
String[] looper = getPattern().split("\n");
List<String> patternList = new ArrayList<String>();
for (int i = 0; i < looper.length; i++)
{
patternList.add(looper[i]);
}
if (patternList.size() > 1200)
{
patternList.subList(0, patternList.size() - 1200).clear();
...
...
}
else
return response;
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(FdActivity.this, result, Toast.LENGTH_LONG).show();
}
}

Related

Repeat Volley Request Every x-seconds Java

Alright - Before you say this is a duplicate, I've looked over every stack overflow article I can find, and none of them work and/or answer the question properly/simply. All I need is to repeat a function with a volley request inside of it every x-seconds.
Basically, I have a fairly simple Volley request inside a function, which works absolutely perfectly on one call.
Volley function:
private void SetBusPositions() {
TextView textE = (TextView) findViewById(R.id.FirstInfo);
RequestQueue Queue = ServerRequestsQueue.getInstance(context.getApplicationContext()).getRequestQueue();
int SendMethod = Request.Method.GET;
String ServerURL = "my url";
JsonArrayRequest JOR = new JsonArrayRequest(SendMethod, ServerURL, null, new Listener<JSONArray>() {
#Override
public void onResponse(JSONArray resp) {
textE.setText(resp.toString());
System.out.println("Response is: " + resp.toString());
//for each object in JSON Array
for (int i = 0; i < resp.length(); i++) {
}
}
}, new Response.ErrorListener() {
public void onErrorResponse(VolleyError error) {
//process
}
});
Queue.add(JOR);
}
I just want to call this function periodically, to receive data from the server and update my bus-position data. There has to be a fairly simple way to do this? I know I must be missing something, but none of the other answers seem to help.
Also, as I'm using Google maps, my class is already extending FragmentActivity. I've seen methods that extend Runnable to get this working -- but my Java is a bit rusty here. I've been doing too much JS.
private final class RepeatedOperation extends AsyncTask<Map, Void, String> {
#Override
protected String doInBackground(Map... params) {
SetBusPosition(params[0]);
}
#Override
protected void onPostExecute(String result) {
}
}
private void callAsynchronousTask() {
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
RepeatedOperation performBackgroundTask = new RepeatedOperation();
// RepeatedOperation this class is the class that extends AsyncTask
performBackgroundTask.execute(map);
} catch (Exception e) {
// TODO Auto-generated catch block
}
}
});
}
};
timer.schedule(doAsynchronousTask, 0, 50000); //execute in every 50000 ms
}
Try this out and add this in the same scope as SetBusPosition()

get TextView from another class

I want to display this textview "txtCalculate" which comes from the class CustomerMapActivity which is displayed in the activity_map_customer layout in another layout which is activity_bon_de_commande, of the class BonDeCommande.
the problem is I don't know how to do it
I'm new to java programming
thank you
public void readValues(){
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
Query lastQuery = ref.child("ride_info").orderByKey().limitToLast(1);
lastQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()){
double value0_float = ds.child("pickup").child("lat").getValue(Double.class);
double value1_float = ds.child("pickup").child("lng").getValue(Double.class);
double value2_float = ds.child("destination").child("lat").getValue(Double.class);
double value3_float = ds.child("destination").child("lng").getValue(Double.class);
String pickupLat = String.valueOf(value0_float);
String pickupLng = String.valueOf(value1_float);
String destiLat = String.valueOf(value2_float);
String destiLng = String.valueOf(value3_float);
String requestUrl=null;
try {
requestUrl = "https://maps.googleapis.com/maps/api/directions/json?"+
"mode=driving&"
+"transit_routing_preference=less_driving&"
+"origin="+pickupLat+","+pickupLng+"&"
+"destination="+destiLat+","+destiLng+"&"
+"key="+getResources().getString(R.string.google_maps_key);
Log.e("LINK",requestUrl);
mService.getPath(requestUrl).enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
try {
JSONObject jsonObject = new JSONObject(response.body().toString());
JSONArray routes = jsonObject.getJSONArray("routes");
JSONObject object = routes.getJSONObject(0);
JSONArray legs = object.getJSONArray("legs");
JSONObject legsObject = legs.getJSONObject(0);
//Get distance
JSONObject distance = legsObject.getJSONObject("distance");
String distance_text = distance.getString("text");
//use regex to extract double from string
//This regex will remove all text not digit
Double distance_value= Double.parseDouble(distance_text.replaceAll("[^0-9\\\\.]+",""));
//Get Time
JSONObject time = legsObject.getJSONObject("duration");
String time_text = time.getString("text");
Integer time_value = Integer.parseInt(time_text.replaceAll("\\D+",""));
String final_calculate = String.format("%.2f €",
TypeObject.getPrice(distance_value,time_value));
HERE -----> txtCalculate.setText(final_calculate);
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<String> call, Throwable t) {
mCurrentRide.cancelRide();
endRide();
}
});
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
mCurrentRide.cancelRide();
endRide();
}
});
}
screenshot of my screen
You need to Create an Interface with an update method, declare in your Activity and after, pass as parameter to your handler object that gets the data.
Don't forget If you're getting the data in a different Thread, you need to update your views always in an UI Thread or in the Main Thread.
Here Follow some example code:
Your Activity or Fragment
public class MainActivity extends AppCompatActivity
implements UpdateViewCallback { // implement the interface here
private TextView textView = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
textView = findViewById(R.id.textView);
// Pass the interface in your Object that makes the async work
final AsyncWork asyncWork = new AsyncWork(this);
// Running
Thread thread = new Thread(asyncWork);
thread.start();
}
/**
* UpdateViewCallback
* #param result
*/
#Override
public void updateView(final String result) {
// Always update View on MainThread or an UI Thread, or else issues will start to happening
this.runOnUiThread(new Runnable() {
public void run() {
// Check if View is null since you're updating in a thread async
if (textView != null) {
textView.setText(result);
}
}
});
}
}
Your Interface:
public interface UpdateViewCallback {
void updateView(String result);
}
Your Object to handle the Async Work:
public class AsyncWork implements Runnable {
private UpdateViewCallback updateViewCallback;
public AsyncWork(UpdateViewCallback updateViewCallback) {
this.updateViewCallback = updateViewCallback;
}
/**
* Async Work here
*/
#Override
public void run() {
// Do some Work and after update using the interface you passed in the constructor
updateViewCallback.updateView("This is a test");
}
}

Android: String array becomes null when I pass it back to MapsActivity from a class which uses an async task

I am fairly new to Android development and am creating an application which uses a Google map fragment. I am querying the Google Directions Api and retrieving JSON data using an AsyncTask method. I then decode the polyline and in turn gain a string array of LatLon pairs. I now would now like to use this string array back in my MainActivity. I have tried many ways to do this, however every single way has made the string array null.
Method tried = 1) using a static field 2) using Intent objects to transfer data 3) creating an interface.
Could someone please tell me as to how I should go around this and why it keeps becoming null in my MainActivity? Snippets of my code are below, thanks.
public class GetDirectionsData extends AsyncTask<Object, String,
String>
{
private GoogleMap mMap;
private Context context;
private String url , googleDirectionsData;
private String distance,duration;
private LatLng destinationLatLng;
private String[] directionsList;
public GetDirectionsData(Context context)
{
this.context = context;
}
#Override
protected String doInBackground(Object... objects)
{
mMap = (GoogleMap)objects[0];
url = (String)objects[1];
destinationLatLng = (LatLng)objects[2];
DownloadUrl downloadURL = new DownloadUrl();
try
{
googleDirectionsData = downloadURL.readUrl(url);
}
catch (IOException e)
{
e.printStackTrace();
}
return googleDirectionsData;
}
#Override
protected void onPostExecute(String s)
{
// uses other class DataParser to extract relevant JSONdata and
// displays polyline
DataParser directionParser = new DataParser();
directionsList = directionParser.parseDirections(s);
displayDirection(directionsList);
}
public void displayDirection(String[] directionsList)
{
int count = directionsList.length;
for(int i = 0; i < count; i++)
{
PolylineOptions options = new PolylineOptions();
options.color(Color.BLUE);
options.width(10);
options.addAll(PolyUtil.decode(directionsList[i])); // decode polylines
mMap.addPolyline(options);
}
}
I now want to pass directionsList string array back to MapsActivity Below
public class MapsActivity extends FragmentActivity
{
public void onClick(View v)
{
Object directionDataTransfer[];
// DIRECTIONS BUTTON
switch(v.getId())
{
case R.id.IB_search:
directionDataTransfer = new Object[3];
GetDirectionsData getDirectionsData = new GetDirectionsData(this);
String directionsUrl = getDirectionsUrl();
directionDataTransfer[0] = mMap;
directionDataTransfer[1] = directionsUrl;
directionDataTransfer[2] = new LatLng(//destination LatLon)
getDirectionsData.execute(directionDataTransfer);
Toast.makeText(MapsActivity.this, "Fetching directions", Toast.LENGTH_LONG).show();
}
}
private String getDirectionsUrl()
{
StringBuilder googleDirectionsUrl = new StringBuilder("https://maps.googleapis.com/maps/api/directions/json?");
googleDirectionsUrl.append("origin=" + originLat + "," + originLon);
googleDirectionsUrl.append("&destination=" + destinationLat + "," + destinationLon);
googleDirectionsUrl.append("&mode=" + modeOfTransport);
googleDirectionsUrl.append("&waypoints=via:" + waypointsLat + "," + waypointsLon);
googleDirectionsUrl.append("&key=" + googleApiKey);
return( googleDirectionsUrl.toString() );
}
}
Here is one of the example using Interface - hope this helps.
DummyAsyncTask.java
import android.os.AsyncTask;
public class DummyAsyncTask extends AsyncTask<Void, Void, String> {
private DummyInterface mListener = null;
DummyAsyncTask(DummyInterface listener) {
mListener = listener;
}
#Override
protected String doInBackground(Void... voids) {
return s; // return your string from doInBackground(it will be available as a parameter in onPostExecute())
}
#Override
protected void onPostExecute(String s) {
if(mListener != null) {
mListener.onCallback(s); // sending string s back to activity which registered for callback
}
}
}
DummyInterface.java
public interface DummyInterface {
void onCallback(String s); // callback API
}
DummyActivity.java
import android.app.Activity;
import android.os.Bundle;
public class DummyActivity extends Activity implements DummyInterface{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new DummyAsyncTask(this).execute();
}
#Override
public void onCallback(String s) {
System.out.println("String s = " + s);
}
}

Excessive Internal memory consumed while using two different asyncTask on same RealmObject Android

1.. If i run two methods create2YearsDatabse(); at one anpplication run session
then kill the program completely and then in the next run run the method :
updateAutoGeneratedCalendar();
then the result is as expected it takes about
2-3 MB of memory
2. But if i run create2YearsDatabse() and onSuccess() callback of async Task it is using then the memory it takes in internal memory suddenly goes to more than 400 MB.
// The methods are managed in this way:
public void create2YearsDatabase() {
new BGAsyncTasks(context, new ThreadCallBack() {
#Override
public void onSuccess() {
final SettingAndStatusDTO settingDto = realm.where(SettingAndStatusDTO.class).findFirst();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
//because two years has more or equal to 730 days
if (realm.where(CalendarDto.class).findAll().size() >= 730) {
settingDto.setIs2YearsFullDBCreated(true);
context.getSharedPreferences(context.getString(R.string.shared_pref_name),Context.MODE_PRIVATE).edit().putBoolean(SplashActivity.FIRST_TIME_RUN,false).apply();
}
}
});
SplashActivity.freshRun = false;
startDashBoard();
}
#Override
public void onFailure() {
}
}, BGAsyncTasks.CREATE_INITIALIZE_2_YEARS_CALENDAR).execute();
}
public void updateAutoGeneratedCalendar() {
new BGAsyncTasks(context, new ThreadCallBack() {
#Override
public void onSuccess() {
Log.i("datatest", "full data size" + realm.where(CalendarDto.class).findAll().size());
final SettingAndStatusDTO settingDto = realm.where(SettingAndStatusDTO.class).findFirst();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
if (realm.where(CalendarDto.class).findAll().size() >= 32000)
settingDto.setIs90YearsDBCreated(true);
}
});
}
#Override
public void onFailure() {
}
}, BGAsyncTasks.CREATE_AUTO_GENERATE_CALENDAR).execute();
}
And My Async Task Looks like this :
public class BGAsyncTasks extends AsyncTask<Void, Void, Void> {
// Intention variables
public static final int CREATE_INITIALIZE_2_YEARS_CALENDAR = 0;
public static final int CREATE_AUTO_GENERATE_CALENDAR = 1;
// Message from the Activity/Fragment.
ThreadCallBack callBack;
Context context;
int intention;
IParseData parser ;
//Constructor for bg processes.
public BGAsyncTasks(Context c, ThreadCallBack callBack, int DATA_TYPE_FROM_RES) {
this.callBack = callBack;
this.context = c;
this.intention = DATA_TYPE_FROM_RES;
this.parser = new ParseData(context);
}
#Override
protected Void doInBackground(Void... params) {
switch (intention) {
case CREATE_AUTO_GENERATE_CALENDAR: {
final Realm asyncRealm = Realm.getDefaultInstance();
for (int i = 2000; i <= 2090; i++) {
if (i < 2072 || i > 2073) {
for (int j = 0; j < 12; j++) {
parser.setOnemonthData(i, j);
}
}
Log.i("datatest", "year:" + i);
}
}
case CREATE_INITIALIZE_2_YEARS_CALENDAR: {
String thisMonthString;
for (int i = 2072; i <=2073; i++) {
for (int j = 0; j < 12; j++) {
thisMonthString = getStringByMonth(i, j);// returns the json string
parser.parseOneMonthData(fixFormatting(thisMonthString));
}
}
}
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
callBack.onSuccess();
}
}
And my Parse and saving to Database methods look like this:
public class ParseData implements IParseData {
Context context;
Realm realm;
CalendarDto mCalendarDto;
public ParseData(Context c) {
context = c;
mCalendarDto = new CalendarDto();
}
public void parseOneMonthData(String monthData) {
//parse json data of one month and return as DTO of size equal
//to no of days in that month
try {
JSONArray oneMonthJsonData = new JSONArray(monthData);
int length = oneMonthJsonData.length();
for (int i = 0; i < length; i++) {
saveOneDayData(oneMonthJsonData.optJSONObject(i));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
public void saveOneDayData(final JSONObject singleTouple) {
realm = Realm.getDefaultInstance();
// parsing the data of one day so that it can be used everywhere.
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
mCalendarDto.setDayInfo(singleTouple.optString(DataItems.DAY_INFO));
mCalendarDto.setMahina(singleTouple.optString(DataItems.MAHINA));
realm.copyToRealmOrUpdate(mCalendarDto);
}
});
}
// saving data by month and year
public void setOnemonthData(final int yr, final int mnt) {
realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
mCalendarDto.setMonthEnId(currentEngMonth);
mCalendarDto.setMonthNpId(month);
realm.copyToRealmOrUpdate(mCalendarDto);
}
}
});
}
}
Here is my Calendar Realm Object :
public class CalendarDto extends RealmObject {
public CalendarDto() {
}
#PrimaryKey
private int primaryDayId
private String sakey;
private String raja;
private String mantri;
private String nepalSambat;
// more variables and ...........
//// autogenerated getters and settetrs
////////
}
#Override
protected Void doInBackground(Void... params) {
switch (intention) {
case CREATE_AUTO_GENERATE_CALENDAR: {
final Realm asyncRealm = Realm.getDefaultInstance(); // <--- this line
and
public void saveOneDayData(final JSONObject singleTouple) {
realm = Realm.getDefaultInstance(); // <--- this line
and
public void setOnemonthData(final int yr, final int mnt) {
realm = Realm.getDefaultInstance(); // <--- this line
On background threads, you should close the Realm instance after using them in a finally block.
In this case, you are opening a new Realm instance for every single day twice, and you're not closing any of them.
On a background thread, best practice is to open only one Realm instance, and then close it after the execution is complete.
Realm realm = null;
try {
realm = Realm.getDefaultInstance();
//do things
} finally {
if(realm != null) {
realm.close();
}
}

android AsyncTask in foreach

Have the following AsyncTask code:
private class checkChangesTask extends AsyncTask<String, Void, String> {
protected ProgressDialog mProgressDialog2;
protected String _url = "", _idautor="", _idbook="";
#Override
protected void onPreExecute() {
super.onPreExecute();
this.mProgressDialog2 = new ProgressDialog(MainActivity.this);
this.mProgressDialog2.setMessage("Check changes ...");
this.mProgressDialog2.setIndeterminate(false);
this.mProgressDialog2.setCanceledOnTouchOutside(false);
this.mProgressDialog2.setCancelable(true);
this.mProgressDialog2.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
this.mProgressDialog2.setMax(100);
this.mProgressDialog2.setProgress(0);
this.mProgressDialog2.show();
}
#Override
protected String doInBackground(String... params) {
Document doc = null;
String _html = "";
_idautor = params[0];
_idbook = params[1];
_url = params[2];
try {
doc = Jsoup.connect(_url).userAgent("Mozilla").get();
Elements dd = doc.select("dd");
int size = dd.size();
int p = 1;
for (Element src : dd) {
this.mProgressDialog2.setProgress(p*100/size);
if (p <= size-1){
_html += src.outerHtml();
++p;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return Jsoup.clean(_html, Whitelist.basic());
}
#Override
protected void onPostExecute(String result) {
if(!result.equals("")){
String lastfile = readPageFile(_idautor + "_" + _idbook);
if(!lastfile.equals(result)){
savePageToFile(_idautor + "_" + _idbook, result);
}
}else{
Toast.makeText(MainActivity.this, "Error checkChangesTask", Toast.LENGTH_SHORT).show();
}
this.mProgressDialog2.dismiss();
}
the previous code I call in a loop:
public void checkChanges() {
String[][] db_books = db.selectAllBOOKS();
if (db_books.length>0){
for (int j = 0; j < db_books.length; j++){
new checkChangesTask().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, db_books[j][1], db_books[j][0], db_books[j][2]);
}
}
}
Everything works fine, but the dialog does not display the correct value. First, it is worth it to 0% and then abruptly switches to 100%.
AsyncTask called in sequence (...executeOnExecutor(AsyncTask.SERIAL_EXECUTOR...).
If you run a AsyncTask not in the loop, all the displays are just perfect!
android: targetSdkVersion = "14"
I ask your help.
You need to use onProgressUpdate() inside the AsyncTask. Something like this (at a guess)
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
this.mProgressDialog2.setProgress(progress[0] * 100/progress[1]);
}
And replace this line:
this.mProgressDialog2.setProgress(p*100/size);
With this:
publishProgress(new int[]{p,size})

Categories

Resources