I already have seen this question. But couldn't figure out what's the issue.
I am sending an email in background using BackgroundMail in my ImageSyncReciever class. But when email is sent my app crashes while giving me the below error
FATAL EXCEPTION: main
Process: com.thumbsol.accuratemobileassetsmanagament, PID: 7480
java.lang.IllegalArgumentException: View=com.android.internal.policy.impl.PhoneWindow$DecorView{300e55de V.E..... R.....I. 0,0-0,0} not attached to window manager
at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:434)
at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:353)
at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:116)
at android.app.Dialog.dismissDialog(Dialog.java:382)
at android.app.Dialog.dismiss(Dialog.java:365)
at com.creativityapps.gmailbackgroundlibrary.BackgroundMail$SendEmailTask.onPostExecute(BackgroundMail.java:302)
at com.creativityapps.gmailbackgroundlibrary.BackgroundMail$SendEmailTask.onPostExecute(BackgroundMail.java:265)
at android.os.AsyncTask.finish(AsyncTask.java:636)
at android.os.AsyncTask.access$500(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:653)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5660)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:963)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:758)
Below is my code in which I am sending the email
if (response.body().getStatus().equals("OK")) {
snapManager.updateSnapStatus(AssetsManagementContract.SnapEntry.COLUMN_SITE_SNAP, snap.getSnapName(), Constants.SNAP_SYNCED);
Intent broadcastSyc = new Intent();
broadcastSyc.setAction(Common.GetSyncImageAction());
broadcastSyc.putExtra("STATUS", true);
mContext.sendBroadcast(broadcastSyc);
sendImage(mContext);
BackgroundMail.newBuilder(mContext)
.withUsername("gmail id")
.withPassword("pass")
.withMailto("gmail id")
.withType(BackgroundMail.TYPE_PLAIN)
.withSubject("New Meter Installation")
.withBody("Meter #" + msn + " is "+ com+ " and "+ status)
.send();
}
How can i resolve this issue? Any help would be highly appreciated
Note: The email is sent when the form is submitted and after saving I am not using any dialog.
Update 1
Below is the BackgroudMailer class function
public class SendEmailTask extends AsyncTask<String, Void, Boolean> {
private ProgressDialog progressDialog;
public SendEmailTask() { //error onPostExecute(BackgroundMail.java:265)
}
protected void onPreExecute() {
super.onPreExecute();
if(BackgroundMail.this.processVisibility) {
this.progressDialog = new ProgressDialog(BackgroundMail.this.mContext);
this.progressDialog.setMessage(BackgroundMail.this.sendingMessage);
this.progressDialog.setCancelable(false);
this.progressDialog.show();
}
}
protected Boolean doInBackground(String... arg0) {
try {
GmailSender sender = new GmailSender(BackgroundMail.this.username, BackgroundMail.this.password);
if(!BackgroundMail.this.attachments.isEmpty()) {
for(int i = 0; i < BackgroundMail.this.attachments.size(); ++i) {
if(!((String)BackgroundMail.this.attachments.get(i)).isEmpty()) {
sender.addAttachment((String)BackgroundMail.this.attachments.get(i));
}
}
}
sender.sendMail(BackgroundMail.this.subject, BackgroundMail.this.body, BackgroundMail.this.username, BackgroundMail.this.mailto, BackgroundMail.this.type);
} catch (Exception var4) {
var4.printStackTrace();
return Boolean.valueOf(false);
}
return Boolean.valueOf(true);
}
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
if(BackgroundMail.this.processVisibility) {
this.progressDialog.dismiss(); // error onPostExecute(BackgroundMail.java:302)
if(result.booleanValue()) {
if(!TextUtils.isEmpty(BackgroundMail.this.sendingMessageSuccess)) {
Toast.makeText(BackgroundMail.this.mContext, BackgroundMail.this.sendingMessageSuccess, 0).show();
}
if(BackgroundMail.this.onSuccessCallback != null) {
BackgroundMail.this.onSuccessCallback.onSuccess();
}
} else {
if(!TextUtils.isEmpty(BackgroundMail.this.sendingMessageError)) {
Toast.makeText(BackgroundMail.this.mContext, BackgroundMail.this.sendingMessageError, 0).show();
}
if(BackgroundMail.this.onFailCallback != null) {
BackgroundMail.this.onFailCallback.onFail();
}
}
}
}
}
The problem is I cannot edit it as the file is locked.
in onPostExecute you dismiss the dialog without checking if it is actually shown:
this.progressDialog.dismiss();
add a check of isShowing for that (and a null-check just in case..)
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
Also I see that you use static references to contexts. That can lead to memory leaks, but that is just a side note.
protected String doInBackground(String... params) {
int progress = 0;
publishProgress(progress += 10);
String[] link_list = new String[100];
Bitmap bmp ;
Document xmlDoc = Jsoup.parse(url, 3000);
Elements title = xmlDoc.select("div[class=meta]");
title_lenth = title.size();
for (int i = 0; i < title_lenth; i++) {
link_list[count] = title.get(i).text();
try{
JSONObject JObj_link ;
JObj_link = new JSONObject(link_list[count]);
link_list[count] = JObj_link.getString("ou");
Log.e("ou Content", link_list[count]);
}catch (Exception e){
Log.e("ou Content", e.toString());
}
System.out.print(titlelist[count]);
count ++ ;
}
setBmp(link_list);
publishProgress(progress += 15);
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
publishProgress(progress = 100);
return title_word;
}
I deleted some code Not critical
I want to do
-> setBmp(link_list);
link_list is a string array content urls (http://xxx.xx.jpg)
the setbmp can download pics and set imageview
now there is error messages
Logcat :
03-10 09:32:23.461 16218-16493/com.takepickpicturedemo E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
Process: com.takepickpicturedemo, PID: 16218
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:309)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6556)
at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:942)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:5081)
at android.view.View.invalidateInternal(View.java:12713)
at android.view.View.invalidate(View.java:12677)
at android.view.View.invalidate(View.java:12661)
at android.widget.AbsListView.resetList(AbsListView.java:1996)
at android.widget.GridView.setAdapter(GridView.java:194)
at com.takepickpicturedemo.MainActivity.setBmp(MainActivity.java:741)
at com.takepickpicturedemo.MainActivity$GetPredict.doInBackground(MainActivity.java:582)
at com.takepickpicturedemo.MainActivity$GetPredict.doInBackground(MainActivity.java:497)
at android.os.AsyncTask$2.call(AsyncTask.java:295)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
edit
so ..
Main thread cannot do Network
doInBackground cannot setting UI
How can I do to download & change UI
As I see, setBmp() method calls a UI update. A UI update should occur in the UI thread. You should know that doInBackground occurs in a background thread and not the UI thread.
Instead of calling it in the doInBackground method, try calling setBmp() from onPostExecute method of the AsyncTask.
NOTE: onPostExecute method is executed in the UI thread.
Error occurs because setBmp() somehow affects views, which is not allowed on other threads than UI thread. Wrappping it with runOnUiThread() will help. Replace the line
setBmp(link_list);
by:
runOnUiThread(new Runnable() {
#Override
public void run() {
setBmp(link_list);
}
});
To make it work, you also should make link_list final on creation:
final String[] link_list = new String[100]; // "final" added
Here is you setBmp(link_list); Method. May be this Method Try to show Image. **doInBackground** method do not created a view.
Thanks
I'm following a course on udacity 'Developing Android Apps'. Following is the code of ForecastFragment class which is suppose to get data in json format from the url(http://api.openweathermap.org/data/2.5/forecast/daily?q=Delhi,in&mode=json&cnt=7&units=metric).
public class ForecastFragment extends Fragment {
public ForecastFragment() {
}
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
String[] data = {
"Today-Sunny-34", "Tommorow-Rainy-233", "Wednesday-Cloudy-21", "Thursday-Monayblue-18", "Frida-Rainy-23", "Saturday-Rainy-22", "Sunday-Strorm-100"
};
List<String> weekForecast = new ArrayList<String>(Arrays.asList(data));
ArrayAdapter<String> mForecastAdapter = new ArrayAdapter<String>(getActivity(), R.layout.list_item_forecast, R.id.list_item_forecast_textview, weekForecast);
ListView listView = (ListView) rootView.findViewById(R.id.listview_forecast);
listView.setAdapter(mForecastAdapter);
return rootView;
}
public void onCreateOptionsMenu(Menu menu,MenuInflater inflater){
inflater.inflate(R.menu.forecastfragment, menu);
}
public boolean onOptionsItemSelected(MenuItem item){
int id = item.getItemId();
if(id==R.id.action_refresh){
FetchWeatherTask fetch = new FetchWeatherTask();
fetch.execute();
return true;}
return super.onOptionsItemSelected(item);
}
public class FetchWeatherTask extends AsyncTask<Void,Void,Void>{
private final String LOG_TAG = FetchWeatherTask.class.getSimpleName();
#Override
protected Void doInBackground(Void... params) {
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
String forecastJsonStr = null;
try {
URL url = new URL("http://api.openweathermap.org/data/2.5/forecast/daily?q=Delhi,in&mode=json&cnt=7&units=metric");
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) return null;
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
if (buffer.length() == 0) return null;
forecastJsonStr = buffer.toString();
Log.v(LOG_TAG,"Forecast Json String" + forecastJsonStr);
} catch (IOException e) {
Log.e(LOG_TAG, "Error", e);
return null;
} finally {
if (urlConnection != null) urlConnection.disconnect();
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("placeholder fragment", "error closing stream", e);
}
}
}
return null;
}
}
}
However, I'm repeatedly getting this error.
07-20 12:49:14.063 2392-2486/com.example.android.sunshine.app E/FetchWeatherTask﹕ Error
java.net.UnknownHostException: api.openweathermap.org
at java.net.InetAddress.lookupHostByName(InetAddress.java:512)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:300)
at java.net.InetAddress.getAllByName(InetAddress.java:259)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>(HttpConnection.java:69)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.<init>(HttpConnection.java:48)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection$Address.connect(HttpConnection.java:322)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnectionPool.get(HttpConnectionPool.java:89)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getHttpConnection(HttpURLConnectionImpl.java:285)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.makeConnection(HttpURLConnectionImpl.java:267)
at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:205)
at com.example.android.sunshine.app.ForecastFragment$FetchWeatherTask.doInBackground(ForecastFragment.java:119)
at com.example.android.sunshine.app.ForecastFragment$FetchWeatherTask.doInBackground(ForecastFragment.java:83)
at android.os.AsyncTask$2.call(AsyncTask.java:185)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
at java.lang.Thread.run(Thread.java:1027)
Following are the things I've already checked:-
mobile phone has internet access.
AndroidManifest.xml declares the permission for internet usage.
The url works fine in the browser,but I'm clueless as to why this error is coming up.
Also, I'm running the app on my android phone(api 10).
If anyone could please provide a solution or point me in the right direction,it would be great. Thank you.
I had the same issue. Yet I did not turn WiFi on on my mobile phone. Activating wifi solved the problem for me.
I copied your Async class as-is and ran it in a new project on a KitKat VM on my Mac machine. Here are the results:
07-19 14:40:32.070 1670-1683/centerorbit.com.myapplication V/FetchWeatherTask﹕ Forecast Json String{"city":{"id":1273294,"name":"Delhi","coord":{"lon":77.216667,"lat":28.666668},"country":"IN","population":0},"cod":"200","message":0.0095,"cnt":7,"list":[{"dt":1437285600,"temp":{"day":29,"min":28.21,"max":29,"night":28.21,"eve":29,"morn":29},"pressure":984.15,"humidity":88,"weather":[{"id":802,"main":"Clouds","description":"scattered clouds","icon":"03n"}],"speed":1.66,"deg":64,"clouds":36},{"dt":1437372000,"temp":{"day":29.15,"min":25.17,"max":31.21,"night":27.92,"eve":31.21,"morn":26.55},"pressure":986.25,"humidity":95,"weather":[{"id":501,"main":"Rain","description":"moderate rain","icon":"10d"}],"speed":3.22,"deg":86,"clouds":88,"rain":10.65},{"dt":1437458400,"temp":{"day":30.46,"min":25.15,"max":31.57,"night":27.94,"eve":31.1,"morn":25.15},"pressure":988.81,"humidity":83,"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10d"}],"speed":6.41,"deg":111,"clouds":68,"rain":0.45},{"dt":1437544800,"temp":{"day":30.63,"min":26.12,"max":32.69,"night":28.12,"eve":32.69,"morn":26.12},"pressure":991.01,"humidity":81,"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04d"}],"speed":3.57,"deg":118,"clouds":64},{"dt":1437631200,"temp":{"day":34.27,"min":25.81,"max":35.34,"night":27.1,"eve":33.11,"morn":25.81},"pressure":989.86,"humidity":78,"weather":[{"id":501,"main":"Rain","description":"moderate rain","icon":"10d"}],"speed":2.06,"deg":74,"clouds":8,"rain":3.94},{"dt":1437717600,"temp":{"day":31.12,"min":25.71,"max":31.12,"night":26.68,"eve":30.83,"morn":25.71},"pressure":991.3,"humidity":0,"weather":[{"id":501,"main":"Rain","description":"moderate rain","icon":"10d"}],"speed":1.06,"deg":184,"clouds":13,"rain":7.82},{"dt":1437804000,"temp":{"day":31.68,"min":25.88,"max":32.17,"night":27.01,"eve":32.17,"morn":25.88},"pressure":989.57,"humidity":0,"weather":[{"id":501,"main":"Rain","description":"moderate rain","icon":"10d"}],"speed":1.28,"deg":226,"clouds":52,"rain":5.89}]}
It appears that your code is fine, and something is not right with your system/network. I would recommend restarting your phone/computer to see if that fixes the issue. If not, try using a different network (disconnect from your home WiFi and use Cell network).
You have registered permission in androidManifest to access Internet
<uses-permission android:name="android.permission.INTERNET"/>
Append APIKey at the end of URL
To get APIKey you have to create acount on openweathermap.org
e.g. http://api.openweathermap.org/data/2.5/forecast/daily?q=Delhi,in&mode=json&cnt=7&units=metric&appid=yourapiid"
Detail Process to Get APIKey is
My app crashes every time I go to send the data gathered by the sensor. The error I am given is as follows:
06-20 14:50:00.784 22983-22983/com.example.adam.proj2 E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at com.example.adam.proj2.SensorActivity.onClick(SensorActivity.java:124)
at android.view.View.performClick(View.java:3549)
at android.view.View$PerformClick.run(View.java:14393)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:4944)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Here is the code for gathering the sensor data:
public void onSensorChanged(SensorEvent event) {
float x = event.values[0];
ArrayList<Float> enrolAcc = new ArrayList<>();
ArrayList<Float> authAcc = new ArrayList<>();
TextView textEnrol = (TextView) findViewById(R.id.textView);
if (choice == 1) {
mPreviousAcc = mCurrentAcc;
mCurrentAcc = (float) Math.sqrt((double) (x * x));
float delta = mCurrentAcc - mPreviousAcc;
mDiffAcc = mDiffAcc * 0.9f + delta;
if (enrolAcc.size() < 100) {
enrolAcc.add(x);
} else {
enrolAcc.remove(0);
enrolAcc.add(x);
}
walkData = enrolAcc.toString();
textEnrol.setText(walkData);
}
Here is the code for writing to the file (this happens onClick of a button):
public void onClick(View v) {
switch (v.getId()) {
case R.id.enrolBtn:
choice = 1;
Toast.makeText(this, "Enrolment Mode Selected", Toast.LENGTH_SHORT).show();
break;
case R.id.authBtn:
choice = 2;
Toast.makeText(this, "Authentication Service Starting", Toast.LENGTH_SHORT).show();
break;
case R.id.sendBtn:
choice = 3;
String baseDir = android.os.Environment.getExternalStorageDirectory().getAbsolutePath();
String fileName = "Walk Data.csv";
String filePath = baseDir + File.separator + fileName;
File f = new File(filePath);
FileOutputStream out = null;
try {
out = new FileOutputStream(f);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
out.write(walkData.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
android.net.Uri u1 = Uri.fromFile(f);
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM, u1);
sendIntent.setType("text/html");
startActivity(sendIntent);
break;
}
}
From what I can see the exception is generated by the out.write method?
The array list holding the sensor values is stored in the walkData string so that the string can be then written in the csv file stored on the external device storage. I would like the data to be in CSV format.
I am stumped and cannot figure out how to prevent this, any help would be much appreciated.
You get the error because you are trying to write to a READ ONLY file.
The line out = new FileOutputStream(f) throws an exception:
java.io.FileNotFoundException: /storage/sdcard/Walk Data.csv: open failed: EROFS (Read-only file system), but you actually ignore it, so out = NULL and then you get the other exception.
Move your file to a place where you can write to it -
String fileName = "Walk Data.csv";
String baseDir = getFilesDir() + "/" + fileName;
File f = new File(baseDir);
Look at the code:
try {
out = new FileOutputStream(f);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
out.write(walkData.getBytes());
The exception is thrown at the last line. So, what could possibly be wrong at that line?
out could be null. out will be null if the file is not found, since you catch that exception and pretend nothing wrong happened at the line before, leaving out as null. You shouldn't try to use outif you just failed to initialize it. The try block should ensclose all the lines using out, and not just the line initializing it.
walkDatacould also be null. But since we don't know where it comes from, we can't say. Use your debugger to know which is null. And whatever the answer is, fix your exception handling code. It should look like
FileOutputStream out = null;
try {
out = new FileOutputStream(f);
out.write(walkData.getBytes());
android.net.Uri u1 = Uri.fromFile(f);
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM, u1);
sendIntent.setType("text/html");
startActivity(sendIntent);
} catch (IOException e) {
// TODO signal the error to the user. Printing a stack trace is not enough
}
finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
// TODO signal the error to the user. Printing a stack trace is not enough
}
}
}
I've been looking all over the place for this, and the only answer I've had was "use Pair", but I can't get this to work either.
Here's what I need to:
In Asynctask I need to update both a progress bar, and text. Because of this my Asynctask generic cannot be just Integer and not just String, but both. This is so I can have both classes within the "onProgressUpdate" method.
Can somebody give me some example or links as to how I add the strings and increase the integer in "doInBackground", and how to implement this in the "onProgressUpdate"?
Thank you very much!
Can you create your own simple class to hold the variables and then pass that?
Or, what if you pass a string that you can parse and get the values you need? If you take your first string += ":" + int, then make use of something like
String myString = passedString.substring(0, passedString.lastIndexOf(":")))
int i = Integer.parseInt(passedString.substring(passedString.lastIndexOf(":")+1));
As far as I understand your question; there are mainly two things which you want to do:
1) Handle a UI thread while in the doIneBackground().
2) Implement the onProgressUpdate().
Basically we shouldn't try to access the UI thread while a background process is running.
The reason for that is very clear... # OS level there will be so many thread will be running.And in that case It will be chaos on the screen, if we can update UI from background thread.
For the 2nd one I would like recommend you to take a look at this example:
ProgressDialog mProgressDialog;
mProgressDialog = new ProgressDialog(YourActivity.this);
mProgressDialog.setMessage("A message");
mProgressDialog.setIndeterminate(true);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(true);
final DownloadTask downloadTask = new DownloadTask(YourActivity.this);
downloadTask.execute("the url to the file you want to download");
mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
downloadTask.cancel(true);
}
});
In the AsynTask:
private class DownloadTask extends AsyncTask<String, Integer, String> {
private Context context;
public DownloadTask(Context context) {
this.context = context;
}
#Override
protected String doInBackground(String... sUrl) {
// take CPU lock to prevent CPU from going off if the user
// presses the power button during download
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
getClass().getName());
wl.acquire();
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 "Server returned HTTP " + connection.getResponseCode()
+ " " + connection.getResponseMessage();
// this will be useful to display download percentage
// might be -1: server did not report the length
int fileLength = connection.getContentLength();
// download the file
input = connection.getInputStream();
output = new FileOutputStream("/sdcard/file_name.extension");
byte data[] = new byte[4096];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
// allow canceling with back button
if (isCancelled())
return null;
total += count;
// publishing the progress....
if (fileLength > 0) // only if total length is known
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
} catch (Exception e) {
return e.toString();
} 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;
}}
The method above (doInBackground) runs always on a background thread. You shouldn't do any UI tasks there. On the other hand, the onProgressUpdate and onPreExecute run on the UI thread, so there you can change the progress bar:
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog.show();
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
// if we get here, length is known, now set indeterminate to false
mProgressDialog.setIndeterminate(false);
mProgressDialog.setMax(100);
mProgressDialog.setProgress(progress[0]);
}
#Override
protected void onPostExecute(String result) {
mProgressDialog.dismiss();
if (result != null)
Toast.makeText(context,"Download error: "+result, Toast.LENGTH_LONG).show();
else
Toast.makeText(context,"File downloaded", Toast.LENGTH_SHORT).show();
}
Regards
Sathya