I am creating an android application that uses async task to login and send data(HTTP Post Request. The application works fine when internet connection is good but when logging and it takes too long to post data due to slow connection the application force closes. i would like to display a toast "Error in Connection" when this happens. Please Help
Your application probably crashes, because you are trying to show Toast not in a UI Thread. That is you always should make any changes to UI by using Handler, or within onPostExecute() method, which also runs in UI Thread.
How to catch exceptions in doInBackground's thread and represent them in UI Thread is another question, I can suggest you this solution:
private class LoginTask extends
AsyncTask<Void, Integer, JSONArray[]> {
private static final int NETWORK_NO_ERROR = -1;
private static final int NETWORK_HOST_UNREACHABLE = 1;
private static final int NETWORK_NO_ACCESS_TO_INTERNET = 2;
private static final int NETWORK_TIME_OUT = 3;
// You can continue this list...
Integer serverError = NETWORK_NO_ERROR;
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog.show(); // Don't forget to create it before
}
#Override
protected JSONArray[] doInBackground(Void... v) {
JSONArray[] result = null;
try {
result = NetworkManager.login(/* All params you need */);
} catch (JSONException e) {
return null;
} catch (ConnectException e) {
serverError = NETWORK_NO_ACCESS_TO_INTERNET;
return null;
} catch (UnknownHostException e) {
serverError = NETWORK_HOST_UNREACHABLE;
return null;
} catch (SocketTimeoutException e) {
serverError = NETWORK_TIME_OUT;
return null;
} catch (URISyntaxException e) {
// ..
return null;
} catch (ClientProtocolException e) {
// ..
return null;
} catch (Exception e) {
// ..
return null;
}
return result;
}
#Override
protected void onPostExecute(JSONArray[] result) {
progressDialog.dismiss();
if (result != null) {
processAndShowResult(result);
} else {
switch (serverError) {
case NETWORK_NO_ERROR:
Toast.makeText(YourActivity.this, "Probably, invalid response from server", Toast.LENGTH_LONG).show();
break;
case NETWORK_NO_ACCESS_TO_INTERNET:
// You can customize error message (or behavior) for different type of error
case NETWORK_TIME_OUT:
case NETWORK_HOST_UNREACHABLE:
Toast.makeText(YourActivity.this, "Error in Connection", Toast.LENGTH_LONG).show();
break;
}
}
}
}
By this means, you can flexibly control network errors and undertake appropriate actions, according to these errors.
Related
I would like to show ProgressDialog during another asynctask.
I write ProgressDialog . one AsyncTask
and I write another AsyncTask in PostExecute method.
but ProgressDialog doesn't run... I'd appreciate your kind help.
AsyncTask code:
public class SavingProgressTask extends AsyncTask<Void, Void, Void> {
private Context mContext;
private ProgressDialog progDialog = null;
public SavingProgressTask(Context context) {
mContext = context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progDialog = new ProgressDialog(mContext);
progDialog.setMessage("saving...");
progDialog.setIndeterminate(false);
progDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progDialog.setCancelable(false);
progDialog.show();
}
#Override
protected Void doInBackground(Void... params) {
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if(isUpdateStore) {
try {
int storeResponseMessage = new StoreUpdateTask(SettingActivity.this).execute(fc_code).get();
if(storeResponseMessage == 1) {
Store updateStore = new StoreDetailTask(SettingActivity.this, false).execute(fc_code).get();
mAuthUser.setStore(updateStore);
UserAuthUtil.saveUserObject(SettingActivity.this, mAuthUser);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
int userinfoResponseMessage;
int userinfosex;
if(mSexTextView.getText().toString().equals("남자")) {
userinfosex = 1;
} else if (mSexTextView.getText().toString().equals("여자")){
userinfosex = 2;
} else {
userinfosex = 2;
}
if(isUpdateBirthday) {
if(isUpdateSex) {
try {
userinfoResponseMessage = new UserUpdateTask(SettingActivity.this, true, "TWICE").execute(tempBirthDay, String.valueOf(userinfosex)).get();
if(userinfoResponseMessage == 1) {
mAuthUser.getUser().setBirthday(tempBirthDay);
mAuthUser.getUser().setSex(userinfosex);
UserAuthUtil.saveUserObject(SettingActivity.this, mAuthUser);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
} else {
try {
userinfoResponseMessage = new UserUpdateTask(SettingActivity.this, true, "BIRTHDAY").execute(tempBirthDay).get();
if(userinfoResponseMessage == 1) {
mAuthUser.getUser().setBirthday(tempBirthDay);
UserAuthUtil.saveUserObject(SettingActivity.this, mAuthUser);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
} else {
if(isUpdateSex) {
try {
userinfoResponseMessage = new UserUpdateTask(SettingActivity.this, true, "SEX").execute(String.valueOf(userinfosex)).get();
if(userinfoResponseMessage == 1) {
mAuthUser.getUser().setSex(userinfosex);
UserAuthUtil.saveUserObject(SettingActivity.this, mAuthUser);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
} else {
}
}
if(progDialog != null) {
progDialog.dismiss();
Intent intent = new Intent(mContext, HomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
mContext.startActivity(intent);
}
}
in click listener:
SavingProgressTask saveTask = new SavingProgressTask(SettingActivity.this);
saveTask.execute();
As far as I know starting another async task from the post execute of previous async task is not that good idea.
When I had a similar problem in one of my projects I had followed the following process.
1) Create an interface with a method like notifyUIThread().
2) Implement this interface from the activity, which calls the async task.
3) While creating the async task, pass 'this' as a parameter to the constructor of the async task.
4) In the post execute of async task call the this.notifyUIThread() method.
5) In the overridden method notifyUIThread(), make a call to the next async task.
Coming to the progress dialog, make it global variable, show it in the pre execute method of the first async task, dismiss it in the post execute of the second async task.
You can also do make the progress dialog local to the async task, show in pre execute and dismiss in post execute of both the async tasks.
But a small advice here is, keep the app responsive. Showing the progress dialog for a long time is not advisable.
Does anyone know how to create folder programatically using dropbox api for android??I am not using sync api.I have managed to upload images and files but I am unable to create folder.
This is my upload asynctask:
public class UploadFile extends AsyncTask<Void, Long, Boolean> {
private DropboxAPI<?> mApi;
private String mPath;
private File mFile;
private long mFileLen;
private UploadRequest mRequest;
private Context mContext;
private ProgressDialog mDialog;
final static private String ACCOUNT_PREFS_NAME = "prefs";
private String mErrorMsg;
public UploadFile(Context context, DropboxAPI<?> api, String dropboxPath,
File file) {
mContext = context;
mFileLen = file.length();
mApi = api;
mPath = dropboxPath;
mFile = file;
mDialog = new ProgressDialog(context);
mDialog.setMax(100);
mDialog.setMessage("Uploading " + file.getName());
mDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mDialog.setProgress(0);
mDialog.setButton("Cancel", new OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// This will cancel the putFile operation
mRequest.abort();
}
});
mDialog.show();
}
#Override
protected Boolean doInBackground(Void... params) {
try {
// By creating a request, we get a handle to the putFile operation,
// so we can cancel it later if we want to
FileInputStream fis = new FileInputStream(mFile);
String path = mPath + mFile.getName();
mRequest = mApi.putFileOverwriteRequest(path, fis, mFile.length(),
new ProgressListener() {
#Override
public long progressInterval() {
// Update the progress bar every half-second or so
return 500;
}
#Override
public void onProgress(long bytes, long total) {
publishProgress(bytes);
}
});
if (mRequest != null) {
mRequest.upload();
return true;
}
} catch (DropboxUnlinkedException e) {
// This session wasn't authenticated properly or user unlinked
mErrorMsg = "This app wasn't authenticated properly.";
} catch (DropboxFileSizeException e) {
// File size too big to upload via the API
mErrorMsg = "This file is too big to upload";
} catch (DropboxPartialFileException e) {
// We canceled the operation
mErrorMsg = "Upload canceled";
} catch (DropboxServerException e) {
// Server-side exception. These are examples of what could happen,
// but we don't do anything special with them here.
if (e.error == DropboxServerException._401_UNAUTHORIZED) {
// Unauthorized, so we should unlink them. You may want to
// automatically log the user out in this case.
} else if (e.error == DropboxServerException._403_FORBIDDEN) {
// Not allowed to access this
} else if (e.error == DropboxServerException._404_NOT_FOUND) {
// path not found (or if it was the thumbnail, can't be
// thumbnailed)
} else if (e.error == DropboxServerException._507_INSUFFICIENT_STORAGE) {
// user is over quota
} else {
// Something else
}
// This gets the Dropbox error, translated into the user's language
mErrorMsg = e.body.userError;
if (mErrorMsg == null) {
mErrorMsg = e.body.error;
}
} catch (DropboxIOException e) {
e.printStackTrace();
// Happens all the time, probably want to retry automatically.
mErrorMsg = "Network error. Try again.";
} catch (DropboxParseException e) {
// Probably due to Dropbox server restarting, should retry
mErrorMsg = "Dropbox error. Try again.";
} catch (DropboxException e) {
// Unknown error
mErrorMsg = "Unknown error. Try again.";
} catch (FileNotFoundException e) {
}
return false;
}
#Override
protected void onProgressUpdate(Long... progress) {
int percent = (int) (100.0 * (double) progress[0] / mFileLen + 0.5);
mDialog.setProgress(percent);
}
#Override
protected void onPostExecute(Boolean result) {
mDialog.dismiss();
if (result) {
showToast("Successfully uploaded");
// mApi.getSession().unlink();
//
// // Clear our stored keys
// clearKeys();
} else {
showToast(mErrorMsg);
}
}
private void showToast(String msg) {
Toast error = Toast.makeText(mContext, msg, Toast.LENGTH_LONG);
error.show();
}
private void clearKeys() {
SharedPreferences prefs = mContext.getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
Editor edit = prefs.edit();
edit.clear();
edit.commit();
}
}
Please help.
According to dropbox documentation
try {
// creating folder
val fo = client.files().createFolderV2(File.separator + folderPath)
} catch (ex: CreateFolderErrorException) {
if (ex.errorValue.isPath && ex.errorValue.pathValue.isConflict) {
// folder already exist
}
}
You can simply give like this for creating a folder! its very simple
dropbox.putFile("Mynumber2/myregion2/"+"/"+"A"+"/"+"B"+"/"+"ENTRY.db", fileInputStream,file.length(), null, null);
if you do, mynumber2-->myregion2-->A-->B will be your folder structure created on dropbox!
You want the createFolder method of DropboxAPI. See https://www.dropbox.com/static/developers/dropbox-android-sdk-1.6.1-docs/com/dropbox/client2/DropboxAPI.html#createFolder(java.lang.String).
Use the following for DIR:
"/your_folder_name/"
I'm using OSMdroid Mapview and using AsyncTask class to get some data, and I create overlays and try to redraw every time I get a msg.
Unfortunately I'm able to get data from a client and I'm able to create overlays to in onProgressUpdated, I've even called invalidate(); But nothing seems to happen. Not sure what is the problem?
Here's my AsyncTask:
public class TaskManager extends AsyncTask<Void, GeoPoint, Void>{
.....
public TaskManager(Master master,MapView mapview) {
//Construtor
}
#Override
protected Void doInBackground(Void... arg0) {
if(Constance.TCPIP) {
Log.d("APP","Inside TCPIP");
//Creation of TCPIP Sockets
try {
m_ssocket = new ServerSocket(Constance.PORT_NO);
Log.d("APP","ServerSocket: "+m_ssocket);
m_socket = m_ssocket.accept();
Log.d("APP","Accepted: "+m_socket);
} catch (IOException e) {
e.printStackTrace();
}
}
else if (Constance.UDPIP) {
//Creation of UDP Sockets
try {
m_dsocket = new DatagramSocket(Constance.PORT_NO);
} catch (SocketException e) {
e.printStackTrace();
}
}
else if (Constance.MCUDP) {
//Lock Wifi multicast
mMultiCastLock = new MultiCastLock(mMaster.getBaseContext());
mMultiCastLock.setMultiCastAcquire();
//Creation of MC-UDP Sockets
try {
m_mcsocket = new MulticastSocket(Constance.PORT_NO);
InetAddress address = InetAddress.getByName(Constance.GROUP_ADDR);
m_mcsocket.joinGroup(address);
} catch (IOException e) {
e.printStackTrace();
}
}
// Create a buffer to read datagrams into.
byte[] mSocketbuffer = new byte[Constance.DGRAM_LEN];
if(Constance.TCPIP) {
try {
m_inSocketData = new BufferedReader(new InputStreamReader(m_socket.getInputStream()));
Log.d("APP","Reading");
} catch (IOException e) {
e.printStackTrace();
}
} else {
// Create a packet to receive data into the buffer
m_inPacket = new DatagramPacket(mSocketbuffer, mSocketbuffer.length);
}
//prepare overlay items
prepareItemizedOverlay();
// Now loop forever, waiting to receive packets and printing them.
if(m_ssocket!=null || m_dsocket!=null || m_mcsocket!=null)
while (true) {
if (isCancelled()) break;
//Get Data
parseData();
//Make Packet Object
if(mMSG!=null) {
make(mMSG);
}
if(m_inPacket!=null && !Constance.TCPIP) {
// Reset the length of the packet before reusing it.
m_inPacket.setLength(mSocketbuffer.length);
}
}
return null;
}
#Override
protected void onProgressUpdate(GeoPoint... geoPoints){
OverlayItem overlayItem = new OverlayItem("Name", "Description", geoPoints[0]);
mItemizedOverlay.addOverlay(overlayItem);
mMapView.getOverlays().add(mItemizedOverlay);
mMapView.getController().animateTo(geoPoints[0]);
mMapView.invalidate();
}
#Override
protected void onCancelled() {
super.onCancelled();
if(Constance.TCPIP) {
if(m_ssocket!=null && m_socket!=null){
try {
m_ssocket.close();
m_socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} else if(Constance.UDPIP) {
if(m_dsocket!=null)
m_dsocket.close();
} else if(Constance.MCUDP) {
if(m_mcsocket!=null)
m_mcsocket.close();
}
Log.d("APP","Task Ended");
}
private void parseData() {
if(Constance.TCPIP) {
// Wait to receive a socket data
try{
mMSG = m_inSocketData.readLine();
} catch (IOException e) {
e.printStackTrace();
}
} else {
// Wait to receive a datagram
try {
m_dsocket.receive(m_inPacket);
// Convert the contents to a string, and display them
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void make(String plot) {
//Make Object
mMSG = new MSG(plot);
//Overlay
mGeoPoint = mMSG.getGeoPoint();
publishProgress(mMSG.getGeoPoint());
}
private void prepareItemizedOverlay() {
/* itemized overlay */
Drawable newMarker = mMaster.getResources().getDrawable(R.drawable.ic_sensor);
mItemizedOverlay = new PlotItemOverlay(mMaster,mItemList,newMarker,
new ItemizedIconOverlay.OnItemGestureListener<OverlayItem>() {
#Override
public boolean onItemSingleTapUp(int index, OverlayItem item) {
Log.d("APP","HERE");
return true;
}
#Override
public boolean onItemLongPress(int index, OverlayItem item) {
return true;
}
}, mResourceProxy);
}
}
Everything seems to work, but nothing seems to happen, not sure what is the problem?
Finally resolved it. I was actually replacing my MapFragment class which led to all this loss of Object and a new object created was interfacing the old one, and so the data received to interfacing to the older MapFragment and not the new MapFragment. Got it resolved, once I found the logically analyzing the code. Anyways, thanks for the support #kurtzmarc you have been very helpful until now. I will continue same with OSMdroid to see any more things that I come up with.
I have 2 Asynctask, 1 for get data (location) from server then set a marker on map with this location and another call 1st Asyntask in a loop for updating location.
Here my code:
public class AsynComp extends AsyncTask<Void, Void, Void> {
ProgressDialog taxiDialog;
#Override
protected Void doInBackground(Void... params) {
jsonComp = new JSONComp(find_url);
find_status = jsonComp.getJsonStatus(txt_search);
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
if (find_status.equals("2013")) {
Toast.makeText(getBaseContext(), "no result",
Toast.LENGTH_SHORT).show();
} else if (find_status.equals("2012")) {
for (Marker marker:markers){
if(marker.getTitle().equals(compFollow)){
marker.remove();
}
}
for (int i=0; i<number;i++){
comp = new Comp(jsonComp.getJsondata(i));
SetMarkerComp(comp);
try {
Thread.sleep(1400);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public class AsynFollow extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
if (!taxiFollow.equals("")) {
number = 1;
txt_search = compFollow;
find_url = "http://192.111.125.80:8001/Default.aspx?username="
+ Id + "&password=" + Pass + "&sohieuxe="+txt_search;
while (!stop){
new AsynComp().execute();
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
taxiFollow = "";
}
return null;
}
protected void onPostExecute(Void result) {
super.onPostExecute(result);
if (!compFollow.equals("")) {
Toast.makeText(getBaseContext(), "Follow "+compFollow, Toast.LENGTH_SHORT).show();
} else {
iv_theodoi.setVisibility(View.VISIBLE);
iv_theodoif.setVisibility(View.GONE);
Toast.makeText(getBaseContext(), "Plz choose a marker", Toast.LENGTH_SHORT).show();
}
}
}
And i have 2 buuton, 1 to call AsynFollow.execute(), another to stop it.
This code can run but app will force close after awhile.
Any solution? thanks.
P/s: i'm a newbie in android.
You shoulnd you asyncTask for this. For repetitive action, like changing status in some interval, use Timer class. In this way you can implement repetitive action which can be repeated in intervals.
In this way you can stop this time by on click listener. You can run two times and specify it's realtions using other variables.
If you're newbe, you should read about multitasking in Android: Timer, AsyncTask, Handler.
In my opinion this docs will tell you much more than thousands of comments in stackoverflow.
i have created one simple login application which takes user name and password from sqlserver..it works fine...
i want during login process one progeress bar should be displayed using asyntask...
but i am unaware to use parameters in asyntask...if some one plzz tell me how to put my method in doInbackground of asyntask and what param should i use....
my code is;.....
public void save(){
initilize();
ResultSet rs = null;
String mylog=id.getText().toString();
String mypass=pass.getText().toString();
try{
Statement statement=connect.createStatement();
rs=statement.executeQuery("LOGIN '"+mylog+"', '"+mypass+"'");
}catch(Exception e){
e.printStackTrace();
}
if(mylog.equals("")||mypass.equals("")){
Toast.makeText(getApplicationContext(), "empty fields", Toast.LENGTH_SHORT).show();
} else
try {
if(rs.next()){
Intent i=new Intent(getApplicationContext(),Act2.class);
startActivity(i);
}
else if(rs.next()==false){
Toast.makeText(getApplicationContext(), "incorrect login", Toast.LENGTH_SHORT).show();
id.setText("");
pass.setText("");
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if it is possible that same method save() be kept inside doInbackground() of asyntask...
making a fast refactorization (note that this as it stand it's really bad practice and coding, you MUST refactor this code to be more maintanable and to avoid duplication):
public class MyAsyncTask extends AsyncTask<> {
private Activity activity;
boolean result;
private String myLog;
private String myPass;
private Connection connect;
public MyAsyncTask(Activity activity, Connection connect) {
this.activity = activity;
this.connect = connect;
}
#Override
protected void onPreExecute() {
//show your progress dialog
}
#Override
protected Object doInBackground(Object[] objects) {
ResultSet rs = null;
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
initilize();
mylog=id.getText().toString();
mypass=pass.getText().toString();
}
});
try{
Statement statement=connect.createStatement();
rs=statement.executeQuery("LOGIN '"+mylog+"', '"+mypass+"'");
}catch(Exception e){
e.printStackTrace();
}
if(mylog.equals("")||mypass.equals("")){
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(activity.getApplicationContext(), "empty fields", Toast.LENGTH_SHORT).show();
}
});
} else
try {
if(rs.next()){
result = true;
}
else if(rs.next()==false){
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(activity.getApplicationContext(), "incorrect login", Toast.LENGTH_SHORT).show();
id.setText("");
pass.setText("");
}
});
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Object o) {
//hide your progress dialog
if(result == Boolean.TRUE){
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
Intent i=new Intent(activity.getApplicationContext(),Act2.class);
activity.startActivity(i);
}
});
}
}
}
then in your Activity you do this:
MyAsyncTask a = new MyAsyncTask(this, connect); //im guessing "connect" is your Connection object
a.execute();
As i said i made this fast refactoring for the code to work but best practice and good implementation is not in consideration here.
Maybe, you could use a timer, to check if your
login is ready. As long as it is not, you Show your progress Bar. If its ready, you can close the Bar and start a new activity or anything. timers run can run on u UI thread.
regards :)