for loop until button is pressed in Android? - android

I am new to Android. How can I run this For loop until the button is pressed? I am writing saved data of array into CSV file and storing it onto SDcard. I want to keep the loop running until I press writeFileBtn and it saves the data into CSV.
import com.opencsv.CSVWriter;
public class MainActivity extends Activity {
Button getTimeBtn, writeFileBtn;
ArrayList<String> entries;
String[] entriesArr;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
entries = new ArrayList<String>();
getTimeBtn = (Button) findViewById(R.id.get_time);
writeFileBtn = (Button) findViewById(R.id.write_file);
getTimeBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
for (int i = 0; i <= 10; i++) {
entries.add(String.valueOf(System.nanoTime()));
entriesArr = entries.toArray(new String[entries.size()]);
}
}
});
writeFileBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
CSVWriter writer = null;
try
{
writer = new CSVWriter(new FileWriter(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + "myfile.csv"), ',');
//String[] entries = "first#second#third".split("#"); // array of your values
writer.writeNext(entriesArr);
writer.close();
}
catch (IOException e)
{
Toast.makeText(MainActivity.this, "Error",
Toast.LENGTH_LONG).show();
}
}
});
}
}

You should use an AsyncTask to do this work on background.
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
AsynkTask provides you a isCancelled() that can be used by your button.

Related

TextWatcher skipping characters during api call

Below code is part of search box in my android app.
LoadCatalog is a async task for the api call, problem is whenever it is being called the editText stops taking new character for a fraction of second(skips a character in middle).
for ex- if the user want to enter "The book of leaves"...
it only sometimes take "The boo of " or "The bookof "
It skips the character, pls suggest what's wrong in my code.
private TextWatcher productEntered = new TextWatcher() {
long lastChange = 0;
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence enteredSequence, int start, int before, int count) {
searchbarActionClear.setVisibility(View.VISIBLE);
enteredText = enteredSequence;
if (CommonUtils.isConnectingToInternet(DashboardActivity.this)) {
if (enteredText.length() > 3) {
new Handler().postDelayed(new Runnable() {
public void run() {
if (System.currentTimeMillis() - lastChange >= 600) {
resetList();
toolbarSuggestionEditText.setTag(toolbarSuggestionEditText.getKeyListener());
toolbarSuggestionEditText.setKeyListener(null);
new LoadCatalog().execute(String.valueOf(enteredText));
}
}
}, 600);
lastChange = System.currentTimeMillis();
}
}
}
public void afterTextChanged(Editable s) {
}
};
private class LoadCatalog extends AsyncTask<String, Void, CustomResponse> {
#Override
protected CustomResponse doInBackground(String... params) {
String url;
if (categoryItem != null) {
url = String.format(AppConstants.URLs.SEARCH_WITH_CATEGORY, params[0], categoryItem);
} else {
url = String.format(AppConstants.URLs.SEARCH, params[0]);
}
CustomResponse response = HttpRequest.GET_REQUEST(url, DashboardActivity.this);
return response;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onPostExecute(CustomResponse result) {
try {
if (result.getResponseCode() == 200) {
JSONArray jsonArray = null;
jsonArray = new JSONArray(result.getResponseBody());
Suggestion suggestion = null;
if (jsonArray.length() > 0) {
suggestionList.clear();
suggestionList.add(new Suggestion(null, Suggestion.TYPE_SUGGESTION_HEADER));
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
suggestion = new Suggestion(jsonObject.getString("name"),
jsonObject.getString("category"),
Suggestion.TYPE_SUGGESTION);
suggestionList.add(suggestion);
suggestionAdapter.notifyDataSetChanged();
}
toolbarSuggestionEditText.setKeyListener((KeyListener) toolbarSuggestionEditText.getTag());
} else {
toolbarSuggestionEditText.setKeyListener((KeyListener) toolbarSuggestionEditText.getTag());
Toast.makeText(DashboardActivity.this, "No item match with your search", Toast.LENGTH_SHORT).show();
suggestionList.clear();
}
} else {
toolbarSuggestionEditText.setKeyListener((KeyListener) toolbarSuggestionEditText.getTag());
}
} catch (JSONException e) {
toolbarSuggestionEditText.setKeyListener((KeyListener) toolbarSuggestionEditText.getTag());
e.printStackTrace();
}
}
}

sqlite database inserts the same value everytime error

Am displaying random checkboxes from remote server and if a user checks a checkbox then am storing that value in sqlite database and on the next loading am checking whether that value is present in database or not and if its present then bydefault it will check the checkbox. my problem is everytime i try to insert a value to sqlite it always takes the first checked checkbox value. But if I use a toast to check my code am getting the respective checkbox value. but that doesn't work with sqlite
Here is how am displaying a checkbox and setting on clicklistener
rl = (LinearLayout) getView().findViewById(R.id.linearmain);
HashMap<String, String> resultp = new HashMap<String, String>();
sqlcon = new SQLController(context);
sqlcon.open();
CheckBox[] cb = new CheckBox[arraylist.size()];
Cursor c = sqlcon.readEntry();
int rows = c.getCount();
int cols = c.getColumnCount();
for(int i = 0; i < arraylist.size(); i++) {
resultp = arraylist.get(i);
cb[i] = new CheckBox(getActivity());
cb[i].setText(resultp.get(Fltrsubfragment.SUB));
cb[i].setId(i);
cb[i].setOnClickListener(handleOnClick(cb[i]));
rl.addView(cb[i]);
for ( int ikv = 0; ikv < rows; ikv++) {
// inner for loop
for (int j = 0; j < cols; j++) {
String iv;
iv=c.getString(j);
if(iv==null){
Toast.makeText(context, " Empty " + rows, Toast.LENGTH_LONG).show();
}
else if(iv.equals(cb[i].getText().toString())){
cb[i].setChecked(true);
Toast.makeText(context, " Checked " + rows, Toast.LENGTH_LONG).show();
}
else{
cb[i].setChecked(false);
}
}
}
View.OnClickListener handleOnClick(final CheckBox button) {
return new View.OnClickListener() {
public void onClick(View v) {
if(button.isChecked()){
if(barraylist.contains(button.getText().toString())){
Toast.makeText(context, " Already added " + button.getText().toString(), Toast.LENGTH_LONG).show();
}
else {
brandarraylist.add(button.getText().toString());
name=button.getText().toString();
new MyAsync().execute();
Toast.makeText(context, " Stored " + button.getText().toString(), Toast.LENGTH_LONG).show();
}
}
else{
if(barraylist.contains(button.getText().toString()))
{
barraylist.remove(button.getText().toString());
name=button.getText().toString();
new MyAsyncS().execute();
sqlcon.deleteTData(button.getText().toString());
Toast.makeText(context, "Removed this " + button.getText().toString(), Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(context, "Unchecked this " + button.getText().toString(), Toast.LENGTH_LONG).show();
}
}
}
};
AsyncTask code to insert value
private class MyAsync extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
PD = new ProgressDialog(context);
PD.setMessage("Loading...");
PD.setCancelable(false);
PD.show();
}
#Override
protected Void doInBackground(Void... params) {
if(name==null){
return null;
}
// inserting data
else{
sqlcon = new SQLController(context);
sqlcon.open();
sqlcon.insertData(name);
sqlcon.close();
// BuildTable();
return null;
}
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
PD.dismiss();
}
}
here is the insertData code
public void insertData(String name) {
// TODO Auto-generated method stub
ContentValues cv = new ContentValues();
cv.put(MyDbHelper.LT_VAL, name);
database.insert(MyDbHelper.LTE, null, cv);
}
Please suggest where am making the mistake.
Inside new MyAsync().execute(); put name:
I recommend using .trim() on all user input. You could easily chain this to:
name=button.getText().toString().trim();
new MyAsync().execute(name);
Then get it by using:
#Override
protected String doInBackground(String... params) {
String name = params[0];
We ruled out context by changing the code to:
#Override
protected String doInBackground(String ... params) {
String name = params[0];
if(name==null){
return null;
}else{
return name;
}
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
sqlcon = new SQLController(context);
sqlcon.open();
sqlcon.insertData(result);
sqlcon.close();
// BuildTable();
PD.dismiss();
}

How to do a progress bar to show progress download of a big file with AndroidAnnotations?

I have an Android App and I want to download a big file.
REST API implementation is made with AndroidAnnotations. I need to show a progressbar with the download of a big file using this REST Client (made by AndroidAnnotations).
How I to do that?
Regards
Hello Its to late for answering this question but this will be helpful who are still finding ans with Android-annotation
You can check your image progress by little bit manipulation of code and here is what i have created my
Custom converter Class:-
public class CustomConverter extends FormHttpMessageConverter {
OnProgressListener mOnProgressListener;
public CustomConverter() {
super();
List<HttpMessageConverter<?>> partConverters = new ArrayList<HttpMessageConverter<?>>();
partConverters.add(new ByteArrayHttpMessageConverter());
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
stringHttpMessageConverter.setWriteAcceptCharset(false);
partConverters.add(stringHttpMessageConverter);
partConverters.add(new ProgressResourceHttpMessageConverter());
setPartConverters(partConverters);
}
// public ProgressFormHttpMessageConverter setOnProgressListener(OnProgressListener listener) {
// mOnProgressListener = listener;
// return this;
// }
class ProgressResourceHttpMessageConverter extends ResourceHttpMessageConverter {
#Override
protected void writeInternal(Resource resource, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
InputStream inputStream = resource.getInputStream();
OutputStream outputStream = outputMessage.getBody();
byte[] buffer = new byte[2048];
long contentLength = resource.contentLength();
int byteCount = 0;
int bytesRead = -1;
Log.d("<3 <3 <3", "called");
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
byteCount += bytesRead;
Log.d("<3 <3 <3 ** ", "progress" + String.valueOf((byteCount * 100) / contentLength));
if(mOnProgressListener != null) {
mOnProgressListener.onProgress(resource, byteCount, (int) contentLength);
}
}
outputStream.flush();
}
}
public interface OnProgressListener {
void onProgress(Resource resource, int downloaded, int downloadSize);
}
}
--> you can check your progress with log :)
Code Usage
-> Your rest class will be as follow:-
#Rest(rootUrl = CommonUtils.BASE_URL, converters = {ByteArrayHttpMessageConverter.class,
CustomConverter.class, StringHttpMessageConverter.class})
public interface CustomRest extends RestClientErrorHandling {
#Post(pUrlSignUp)
String _SignUp(MultiValueMap<String, Object> multiValueMap);
}
Of course, you will have to use AsyncTask for downloading purpose:
You can use its methods onPreExecute and onPostExecute for showing and dismissing the ProgressDialog respectively.
Example:
public class DownloadTask extends AsyncTask<String, Integer, String>
{
ProgressDialog pDialog;
Activity activity; //pass your activity reference while initialize this.
public DownloadTask (Activity activity){
this.activity = activity;
}
#Override
protected void onPreExecute()
{
pDialog = new ProgressDialog(activity);
pDialog.setMessage("Downloading file...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected String doInBackground(String... args)
{
//download file's code here
}
#Override
protected void onPostExecute(String result)
{
pDialog.dismiss();
}
}
Hope this helps.
> use AsyncTask method "on progressupdate " to show progress
public class download extends Activity {
public static final int DIALOG_DOWNLOAD_PROGRESS = 0;
private Button startBtn;
private ProgressDialog mProgressDialog;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startBtn = (Button)findViewById(R.id.startBtn);
startBtn.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
startDownload();
}
});
}
private void startDownload() {
String url = "http://farm1.static.flickr.com/114/298125983_0e4bf66782_b.jpg";
new DownloadFileAsync().execute(url);
}
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_DOWNLOAD_PROGRESS:
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage("Downloading file..");
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(false);
mProgressDialog.show();
return mProgressDialog;
default:
return null;
}
}
class DownloadFileAsync extends AsyncTask {
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialog(DIALOG_DOWNLOAD_PROGRESS);
}
#Override
protected String doInBackground(String... aurl) {
int count;
try {
URL url = new URL(aurl[0]);
URLConnection conexion = url.openConnection();
conexion.connect();
int lenghtOfFile = conexion.getContentLength();
Log.d("ANDRO_ASYNC", "Lenght of file: " + lenghtOfFile);
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream("/sdcard/some_photo_from_gdansk_poland.jpg");
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
publishProgress(""+(int)((total*100)/lenghtOfFile));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (Exception e) {}
return null;
}
protected void onProgressUpdate(String... progress) {
Log.d("ANDRO_ASYNC",progress[0]);
mProgressDialog.setProgress(Integer.parseInt(progress[0]));
}
#Override
protected void onPostExecute(String unused) {
dismissDialog(DIALOG_DOWNLOAD_PROGRESS);
}
}
}
With AndroidAnnotations, you can use background threads and publishing progress easily:
#EActivity
public class MyActivity extends Activity {
public void onCreate(Bundle icicle) {
super.onCreate(icicle)
doSomeStuffInBackground();
}
#Background
void doSomeStuffInBackground() { // will run on a background thread
publishProgress(0);
// Do some stuff
publishProgress(10);
// Do some stuff
publishProgress(100);
}
#UiThread
void publishProgress(int progress) { // will run on the UI thread
// Update progress views
}
}
Now you can only have to figure out how you can get progress events. This answer can give a great inspiration. Unfortunetaly AFAIK there is no built-in callback for that in Spring Android Rest Template.
I was looking to solve this same problem, its being two months now. Finally found a good example, I cant believe everybody copy paste the same in AndroidAnnotations docs, if that were enough, we wouldnt be here seeking for help.
Here is the link where you can see the example
I made some modifications my self, for the moment its working with some toasts, but I hope to comeback with an actual loading animation to share:
/*This background handles my main thread in UI and the progress publish*/
#Background
void thisGETJSON() {
publishProgress(0);
publishProgress(50);
publishProgress(100);
showJSONInUI();
}
/*Here the progress is published and the main UI thread is also called*/
#UiThread
void publishProgress(int progress) {
if (progress == 0) {
Toast toast = Toast.makeText(getApplicationContext(), "Just a sec please", Toast.LENGTH_SHORT);
toast.show();
} else if (progress == 50) {
Toast toast = Toast.makeText(getApplicationContext(), "Loading", Toast.LENGTH_SHORT);
toast.show();
} else if (progress == 100) {
Toast toast = Toast.makeText(getApplicationContext(), "Thanks for waiting", Toast.LENGTH_SHORT);
toast.show();
}
/*This is the main UI thread here I do cool stuff with the JSON objects*/
#UiThread
Void showJSONInUI(); {
//Here I do something with the objects in the JSON
}

The AsyncTask does not work as expected

In my android application, there is a app file at the sd card, and the same in our server, but the data in the server may be updated.
So I make an activity to check if latest data is avaiable.
This is an example, there is only one button "Check", when user hit this button, I will get the information of the local data, and then reqest to the server to check if it can be udpated.(THis is done by the CheckTask and a progress dialog will show up during the checking).
Then if a update is requred, I will provide a Dialog to tell the user, they can choose "Download Now" or "Download Later", if they choose "Download Now", a DownLoadTask will be executed,and a new ProgressDialog will be created to show the progress of the download.
Now I meet a problem:
Everything works well unless user click the "Download Now" and then cancel the download.
Then when user click the "Check" button, the CheckTask will not work normally.
This is the codes:
public class MyActivity extends Activity {
private DecimalFormat format = new DecimalFormat("0.#");
private final int Dialog_Offline_Check_HaveUpdate = 13;
private final int Dialog_Offline_Download = 14;
private CheckTask mCheckTask;
private ProgressDialog mCheckProgressDialog;
private DownloadTask mDownloadTask;
private ProgressDialog mDownloadProgressDialog;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
this.setupView();
}
private void setupView() {
mCheckProgressDialog = new ProgressDialog(this);
mCheckProgressDialog.setCanceledOnTouchOutside(false);
findViewById(R.id.check).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startCheckTask();
}
});
}
private void startCheckTask() {
if (mDownloadTask != null && !mDownloadTask.isCancelled()) {
showDialog(Dialog_Offline_Download);
} else {
//for debug
String data = String.format("{\"name\":\"%s\",\"size\":123455,\"lastModifiedTime\":\"2014-1-1\",\"hasUpdate\":false}", "Old Data");
AppData appData = null;
try {
appData = buildMapData(data);
} catch (JSONException e) {
e.printStackTrace();
}
if (mCheckTask != null) mCheckTask.cancel(true);
mCheckTask = new CheckTask();
mCheckTask.execute(String.format("http://xxxx?t=%s", appData.lastModifiedTime));
}
}
private void startDownLoadTask() {
if (mDownloadTask != null) {
mDownloadTask.cancel(true);
}
mDownloadTask = new DownloadTask();
mDownloadTask.execute("https://dl.google.com/android/adt/adt-bundle-windows-x86-20131030.zip"); //for debug
showDialog(Dialog_Offline_Download);
}
#Override
protected Dialog onCreateDialog(int id) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
switch (id) {
case Dialog_Offline_Check_HaveUpdate:
builder.setTitle("Check Update").setPositiveButton("Download Now", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
startDownLoadTask();
}
}).setNegativeButton("Download Later", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
}).setMessage("Latest Data avaiable!");
return builder.create();
case Dialog_Offline_Download:
mDownloadProgressDialog = new ProgressDialog(this);
mDownloadProgressDialog.setTitle("Download Latest Data");
mDownloadProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mDownloadProgressDialog.setMax(100);
mDownloadProgressDialog.setButton(DialogInterface.BUTTON_POSITIVE, "Do it in Background", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
}
});
mDownloadProgressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
if (mDownloadTask != null)
mDownloadTask.cancel(true);
}
});
mDownloadProgressDialog.setMessage("");
return mDownloadProgressDialog;
}
return null;
}
#Override
protected void onPrepareDialog(int id, Dialog dialog, Bundle args) {
switch (id) {
case Dialog_Offline_Check_HaveUpdate:
String msgg;
AppData appData1 = (AppData) args.getSerializable("data");
if (appData1 != null) {
msgg = String.format("%s\n%s: %s \n%s: %s\n%s: %s", "New Data Avaiable",
"Name", appData1.name,
"Size", makeFileSizeReadable(appData1.size),
"Last Update Time", appData1.lastModifiedTime);
} else {
msgg = "";
}
((AlertDialog) dialog).setMessage(msgg);
break;
}
}
private String makeFileSizeReadable(long size) {
double value;
String unit;
if (size < 1024) {
// < 1k
value = size;
unit = "Byte";
} else if (size < 1024 * 1024) {
// 1k,1M
value = size / 1024d;
unit = "Kb";
} else {
value = size / 1024d / 1024d;
unit = "Mb";
}
return String.format("%s %s", format.format(value), unit);
}
class CheckTask extends AsyncTask<String, Void, AppData> {
private String errorMsg;
private boolean cancel = false;
#Override
protected AppData doInBackground(String... urls) {
String url = urls[0];
//for debug
String response = String.format("{\"name\":\"%s\",\"size\":222222,\"lastModifiedTime\":\"2014-1-5\",\"hasUpdate\":true}", "New Data");
Log.d("map.setting", String.format("start parse result: [%s]", response));
AppData md = null;
try {
md = buildMapData(response);
} catch (JSONException e) {
e.printStackTrace();
Log.e("map.setting", "error when parse:" + e.getMessage());
}
Log.d("map.setting", "get md:" + md);
return md;
}
#Override
protected void onPreExecute() {
mCheckProgressDialog.setMessage("Checking...");
mCheckProgressDialog.show();
}
#Override
protected void onPostExecute(AppData appData) {
mCheckProgressDialog.dismiss();
if (appData == null) {
return;
}
if (appData.hasUpdate) {
Bundle bd = new Bundle();
bd.putSerializable("data", appData);
showDialog(Dialog_Offline_Check_HaveUpdate, bd);
} else {
Toast.makeText(MyActivity.this, "Your data is the latest!", Toast.LENGTH_SHORT).show();
}
}
}
private AppData buildMapData(String response) throws JSONException {
JSONObject root = new JSONObject(response);
String name = root.getString("name");
long size = root.getLong("size");
String lastModifiedTime = root.getString("lastModifiedTime");
boolean hasUpdate = root.getBoolean("hasUpdate");
AppData md = new AppData();
md.name = name;
md.lastModifiedTime = lastModifiedTime;
md.size = size;
md.hasUpdate = hasUpdate;
return md;
}
class DownloadTask extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... sUrl) {
try {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(sUrl[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
// expect HTTP 200 OK, so we don't mistakenly save error report instead of the file
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return null;
}
int fileLength = connection.getContentLength();
// download the file
input = connection.getInputStream();
output = new FileOutputStream(Environment.getExternalStorageDirectory() + "/tmp.data", false);
byte data[] = new byte[4096];
int total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
if (fileLength > 0)
publishProgress(total * 100 / fileLength, total, fileLength);
output.write(data, 0, count);
}
} catch (Exception e) {
return null;
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
} finally {
// wl.release();
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
//progress current total
if (mDownloadProgressDialog != null) {
mDownloadProgressDialog.setProgress(values[0]);
String msg = String.format("Progress:%s/%s", makeFileSizeReadable(values[1]), makeFileSizeReadable(values[2]));
mDownloadProgressDialog.setMessage(msg);
}
}
#Override
protected void onPostExecute(String res) {
//map file downloaded replace the old file
}
#Override
protected void onCancelled() {
super.onCancelled();
}
}
}
class AppData implements Serializable {
public String name;
public String lastModifiedTime;
public long size;
public boolean hasUpdate;
}
Anyone can find what is the problem?
Is that you encounter AsynTask's bug after HONEYCOMB?
Order of execution
When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.
If you truly want parallel execution, you can invoke executeOnExecutor(java.util.concurrent.Executor, Object[]) with THREAD_POOL_EXECUTOR.
In our project we use AsynTask like this:
public void executeParallelly(Params... params) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
task.execute(params);
} else {
task.executeOnExecutor(AsynTask.THREAD_POOL_EXECUTOR, params);
}
}

autocomplete freeze when making searchs too fast

I have the next code to make search of artist and songs on the spotify servers. I have an autocomplete text but my problem is if I search for something, like "David Guetta" and I try to delete with backspace ( <-- ) everytime that I delete one character it makes a search, and if I do it so fast the app crashes (heavy usage?). I don't know really if it is for that question.
What can I do to fix this? With a wait time to search it can be fixed but I don't know how to do it.
Can you help me with this? Thank you.
This is my SearchMusic.java code.
public class SearchMusic extends Activity {
AutoCompleteTextView autoCompleteSongs;
String searchTerms;
String[] arrayArtist = new String[64];
String[] arrayTrack = new String[64];
ArrayAdapter<String> adapter;
List<String> songs;
List<String> lArtist;
List<String> lTrack;
boolean bothsearchs = false; // Controlamos que haya busqueda por artista y
// pista si uno no existe.
int nArtist = 0; // iterator
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_music);
autoCompleteSongs = (AutoCompleteTextView) findViewById(R.id.autoCompletePetition);
final ArrayAdapter<String> list = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line);
// autoCompleteSongs.setThreshold(1);
// autoCompleteSongs.addTextChangedListener(this);
// autoCompleteSongs.setAdapter(new
// ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line,
// item));
autoCompleteSongs.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before,
int count) {
if (s.length() > 3) {
searchTerms = s.toString();
searchTerms = searchTerms.replace(" ", "+");
// Buscamos por artista
AsyncHttpClient client = new AsyncHttpClient();
client.get("http://ws.spotify.com/search/1/artist.json?q="
+ searchTerms + "*", null,
new JsonHttpResponseHandler() {
public void onSuccess(JSONObject data) {
try {
// Hay artistas con ese nombre
if (data.length() > 0) {
JSONArray artist = new JSONArray(
data.getJSONArray("artists")
.toString());
for (int i = 0; i < 6; i++) {
JSONObject orden = artist
.getJSONObject(i);
String name = orden
.getString("name");
list.add(name);
arrayArtist[i] = name;
arrayTrack[i] = "";
nArtist++;
}
} else {
bothsearchs = true;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable arg0) {
}
});
// Buscamos por pista
client.get("http://ws.spotify.com/search/1/track.json?q="
+ searchTerms + "*", null,
new JsonHttpResponseHandler() {
public void onSuccess(JSONObject spoty) {
try {
JSONArray artist = new JSONArray(spoty
.getJSONArray("tracks")
.toString());
for (int i = nArtist; i < nArtist + 6 ; i++) {
JSONObject orden = artist
.getJSONObject(i);
String name = orden
.getString("name");
JSONArray nameArtist = new JSONArray(
orden.getJSONArray(
"artists")
.toString());
JSONObject namArt = nameArtist
.getJSONObject(0);
String nameArt = namArt
.getString("name");
list.add("[" + nameArt + "] "
+ name);
arrayArtist[i] = nameArt;
arrayTrack[i] = name;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable arg0) {
}
});
list.notifyDataSetChanged();
TextView text = (TextView) findViewById(R.id.petitionTextView);
for(int i = 0; i < 12; i++){
Log.i("AART", "" + arrayArtist[i]);
Log.i("ATRA", "" + arrayTrack[i]);
}
if(arrayArtist[0] == null && arrayTrack[0] == ""){
text.setText("No hay resultados");
}else{
for(int i = 0; i < 12; i++){
String register = "<font color=#64c7eb>" + arrayArtist[i] + "</font> <font color=#272527>" + arrayTrack[i] + "</font></br>";
text.setText(Html.fromHtml(register));
}
}
}
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void afterTextChanged(Editable s) {
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.search_music, menu);
return true;
}
}
If I am right, this the code that I need. The problem is how to stop it. ¬¬
//Declare the timer
Timer t = new Timer();
//Set the schedule function and rate
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//Called each time when 1000 milliseconds (1 second) (the period parameter)
}
},
//Set how long before to start calling the TimerTask (in milliseconds)
0,
//Set the amount of time between each execution (in milliseconds)
1000);
I think you are already giving a good solution.
Try wrapping the http request within a TimerTask and create a timer mechanism to cancel out the TimerTask.
Example (not tested):
public class SearchMusic extends Activity {
AutoCompleteTextView autoCompleteSongs;
String searchTerms;
String[] arrayArtist = new String[64];
String[] arrayTrack = new String[64];
ArrayAdapter<String> adapter;
List<String> songs;
List<String> lArtist;
List<String> lTrack;
//Declare and initialize the timer
Timer t = new Timer();
boolean bothsearchs = false; // Controlamos que haya busqueda por artista y
// pista si uno no existe.
int nArtist = 0; // iterator
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_music);
autoCompleteSongs = (AutoCompleteTextView) findViewById(R.id.autoCompletePetition);
final ArrayAdapter<String> list = new ArrayAdapter<String>(this,
android.R.layout.simple_dropdown_item_1line);
// autoCompleteSongs.setThreshold(1);
// autoCompleteSongs.addTextChangedListener(this);
// autoCompleteSongs.setAdapter(new
// ArrayAdapter<String>(this,android.R.layout.simple_dropdown_item_1line,
// item));
autoCompleteSongs.addTextChangedListener(new TextWatcher() {
public void onTextChanged(CharSequence s, int start, int before,
int count) {
if (s.length() > 3) {
// Cancel the Timer and all scheduled tasks
t.cancel();
t.purge();
t = new Timer();
//Set the schedule function and rate
t.schedule(new TimerTask() {
#Override
public void run()
{
//Called each time when 1000 milliseconds (1 second) (the period parameter)
searchTerms = s.toString();
searchTerms = searchTerms.replace(" ", "+");
// Buscamos por artista
AsyncHttpClient client = new AsyncHttpClient();
client.get("http://ws.spotify.com/search/1/artist.json?q="
+ searchTerms + "*", null,
new JsonHttpResponseHandler() {
public void onSuccess(JSONObject data) {
try {
// Hay artistas con ese nombre
if (data.length() > 0) {
JSONArray artist = new JSONArray(
data.getJSONArray("artists")
.toString());
for (int i = 0; i < 6; i++) {
JSONObject orden = artist
.getJSONObject(i);
String name = orden
.getString("name");
list.add(name);
arrayArtist[i] = name;
arrayTrack[i] = "";
nArtist++;
}
} else {
bothsearchs = true;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable arg0) {
}
});
// Buscamos por pista
client.get("http://ws.spotify.com/search/1/track.json?q="
+ searchTerms + "*", null,
new JsonHttpResponseHandler() {
public void onSuccess(JSONObject spoty) {
try {
JSONArray artist = new JSONArray(spoty
.getJSONArray("tracks")
.toString());
for (int i = nArtist; i < nArtist + 6 ; i++) {
JSONObject orden = artist
.getJSONObject(i);
String name = orden
.getString("name");
JSONArray nameArtist = new JSONArray(
orden.getJSONArray(
"artists")
.toString());
JSONObject namArt = nameArtist
.getJSONObject(0);
String nameArt = namArt
.getString("name");
list.add("[" + nameArt + "] "
+ name);
arrayArtist[i] = nameArt;
arrayTrack[i] = name;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable arg0) {
}
});
list.notifyDataSetChanged();
TextView text = (TextView) findViewById(R.id.petitionTextView);
for(int i = 0; i < 12; i++){
Log.i("AART", "" + arrayArtist[i]);
Log.i("ATRA", "" + arrayTrack[i]);
}
if(arrayArtist[0] == null && arrayTrack[0] == ""){
text.setText("No hay resultados");
}else{
for(int i = 0; i < 12; i++){
String register = "<font color=#64c7eb>" + arrayArtist[i] + "</font> <font color=#272527>" + arrayTrack[i] + "</font></br>";
text.setText(Html.fromHtml(register));
}
}
}
},
//Set how long before to start calling the TimerTask (in milliseconds)
0,
//Set the amount of time between each execution (in milliseconds)
1000);
}
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
public void afterTextChanged(Editable s) {
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.search_music, menu);
return true;
}
}
The best thing you can do is using a handler, this is a simple example with a button. But the button represents the backspace on your code.
The idea is to schedule the search action within 500 miliseconds but when someone hits the search button again, we reschedule the search action until the user stops hitting the search button.
Good luck!
public class MyActivity extends Activity implements OnClickListener
{
protected static final int MSG_SEARCH = 0;
protected Button buttonSearch;
protected Handler handler = new Handler()
{
public void handleMessage(android.os.Message msg)
{
switch (msg.what)
{
case MSG_SEARCH:
MyActivity.this.search();
break;
}
}
};
#Override
public void onClick(View inView)
{
if (inView == this.buttonSearch)
{
this.handler.removeMessages(MSG_SEARCH);
final Message message = Message.obtain(this.handler, MSG_SEARCH);
this.handler.sendMessageDelayed(message, 500);
}
}
protected void search()
{
// your seach code
}
}
I had the same problem when i was using GooglePlaceApi to get list of addresses. I used synchronized in the performFiltering(), publishResults() and also the method that does the rest call. It worked for me. Maybe you can give a try.
synchronized (input)
{
// Do something inside
}

Categories

Resources