Android Thread / AsyncTask, ExceptionInInitializerError and RuntimeException on "runOnUiThread" - android

I need your help with two Errors I´m getting on
Creating a Thread, where I`m creating a file
After the file stuff, a AsyncTask getting executed to send the file to a server (multipart/form-data)
Thats how the first part looks like:
public void startResultTransfer(final int timestamp, final int duration, final String correction, final float textSize, final int age, final int switch_count, final Activity activity){
synchronized(DataTransmission.class){
new Thread() {
public void run() {
FileWriter fw = null;
//1.Check if file exists
File file = new File(FILE_PATH);
if(!file.exists()){
//File does not exists, when we have to generate the head-line
try {
fw = new FileWriter(FILE_PATH);
fw.append("timestamp\tduration\tcorrection\ttext_size\tage\tswitch_count"); //Headline
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//2. Write Result
try {
if(fw == null)
fw = new FileWriter(FILE_PATH);
fw.append("\n"+String.valueOf(timestamp)+"\t");
fw.append(""+String.valueOf(duration)+"\t");
fw.append(""+correction+"\t");
fw.append(""+String.valueOf(textSize)+"\t");
fw.append(""+String.valueOf(age)+"\t");
fw.append(""+String.valueOf(switch_count)+"\t");
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//3. File Transfer
if(isOnline(activity))
transferFileToServer(activity);
}
}.start();
}
}
The function "transferFileToServer" looks like this:
public synchronized void transferFileToServer(Activity activity){
String id = id(activity);
File file = new File(FILE_PATH);
if(id != null && file.exists()){
final String url = URL+id;
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
TransmissionTask task = new TransmissionTask();
task.execute(url);
}
});
}
}
Now, I`m getting an "ExceptionInInitializerError" with the explanatory message
Caused by java.lang.RuntimeException Can't create handler inside thread that has not called Looper.prepare()"
at the line "activity.runOnUiThread".
In the first function I need to call "transferFileToServer" after some pre settings. But the function should be called unattached from the first function, too.
Should I maybe implement a MessageHandler for executing the AsyncTask at the end of Thread?
http://developer.android.com/reference/android/os/Looper.html
Or should I maybe Change the "AsyncTask" in the "transferFileToServer" function to a Thread, because I don`t do any UI operations?
Edit: The method started from the Async-Task
class TransmissionTask extends AsyncTask<String, Void, String> {
public TransmissionTask() {
}
#Override
protected String doInBackground(String... params) {
synchronized(DataTransmission.class){
try {
HttpURLConnection urlConn;
java.net.URL mUrl = new java.net.URL(params[0]);
urlConn = (HttpURLConnection) mUrl.openConnection();
urlConn.setDoOutput(true);
urlConn.setRequestMethod("POST");
String boundary = "---------------------------14737809831466499882746641449";
String contentType = "multipart/form-data; boundary="+boundary;
urlConn.addRequestProperty("Content-Type", contentType);
DataOutputStream request = new DataOutputStream(urlConn.getOutputStream());
request.writeBytes("\r\n--"+boundary+"\r\n");
request.writeBytes("Content-Disposition: form-data; name=\"userfile\"; filename=\""+FILE_NAME+"\"\r\n");
request.writeBytes("Content-Type: application/octet-stream\r\n\r\n");
File myFile = new File(FILE_PATH);
int size = (int) myFile.length();
byte[] bytes = new byte[size];
try {
BufferedInputStream buf = new BufferedInputStream(new FileInputStream(myFile));
buf.read(bytes, 0, bytes.length);
buf.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
request.write(bytes);
request.writeBytes("\r\n--"+boundary+"--\r\n");
request.flush();
request.close();
InputStream responseStream = new BufferedInputStream(urlConn.getInputStream());
BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream));
String line = "";
StringBuilder stringBuilder = new StringBuilder();
while ((line = responseStreamReader.readLine()) != null)
{
stringBuilder.append(line).append("\n");
}
responseStreamReader.close();
String response = stringBuilder.toString();
responseStream.close();
urlConn.disconnect();
return response;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if(result != null){
if(result.toLowerCase().contains("erfolgreich")){
//If successfull delete File
File file = new File(FILE_PATH);
file.delete();
}
}
}
}

Remove runOnUiThread:
public synchronized void transferFileToServer(Activity activity){
String id = id(activity);
File file = new File(FILE_PATH);
if(id != null && file.exists()){
final String url = URL+id;
TransmissionTask task = new TransmissionTask();
task.execute(url);
}
}
The main idea of AsyncTask to run background operation/logic without Threads or Handlers.
You don't need wrap AsyncTask with additional Thread and bind with UI Thread what you did
From your code:
public void startResultTransfer(/* ... */){
....
new Thread() {
.....
transferFileToServer(/* ... */); // its wrong!!!
....
}.start()
}
transferFileToServer starts your AsyncTask and you run it not in main UI Thread but in single Thread.
This is a problem.
Start your AsyncTask from Activity.

Related

How to use runOnUiThread in a class?

My code is designed to read a .txt file from a URL, and then display the text inside my textview. the problem is, I am using this code in a class. and getting this error- "cannot resolve method runOnUiThread". How do I fix this??
public class mydownloaderclass {
// this method is called from MainActivity
public static void checkForUpdates(Context context) {
new Thread() {
#Override
public void run() {
String path ="http://host.com/info.txt";
URL u = null;
try {
u = new URL(path);
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.connect();
InputStream in = c.getInputStream();
final ByteArrayOutputStream bo = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
in.read(buffer); // Read from Buffer.
bo.write(buffer); // Write Into Buffer.
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView text = (TextView) findViewById(R.id.TextView1);
text.setText(bo.toString());
try {
bo.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
}
I tried using asynctask
public class readtextfile extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... params) {
String result = "";
try {
URL url = new URL("https://www.dropbox.com/myfile.txt");
BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
String line = null;
while ((line = in.readLine()) != null) {
//get lines
result += line;
}
in.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(context, result, Toast.LENGTH_LONG).show();
}
}
Create a Handler instead to execute statements on Main Thread like this
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
//Write your RUN on UI Runnable code here
TextView text = (TextView) findViewById(R.id.TextView1);
text.setText(bo.toString());
try {
bo.close();
} catch (IOException e) {
e.printStackTrace();
} });
Try passing a view context. It can be the activity context where the text view is defined.
The runOnUiThread runs on the main looper so it required a UI context.
For that You can define a member field in the class where the Thread is defined and set it in the constructor. Or if the thread is in the activity itself. then simply set the context field in OnCreate and use it in the thread.
Hope this helps. :)
Let me know if this fixes it.
I would suggest you to use AsyncTask, android makes this class specially for doing some task on a working thread(doInBackgroung()) and then update UI in onPostExecute() method.

How Android Async Task Works with UrlConnection

I am new with the android. I am developing an app that will load content from target url in file. If the url didn't work, it will contact our server to request the correct url. If still fail, then it will ask the url from user input dialog. And it will try to initialize again. I have code like this:
if (initialize(target)!=true) {
JSONObject jsonParam = new JSONObject();
try {
jsonParam.put("sns", getSerial(PREF_NAME));
jsonParam.put("code", pwd);
} catch (JSONException e) {
e.printStackTrace();
}
target = getContent(samURL + "/sam_ip", jsonParam);
if (initialize(target)!=true) {
askIpUserDialog();
}
}
and the initialize() as follow
private boolean initialize(String url) {
Boolean success = false;
if ((!url.trim().startsWith("http://")) && (!url.trim().startsWith("https://"))) {
url = "http://" + url;
}
if (url.endsWith("/")) {
url = url.substring(0,url.length()-1);
}
String sUrl = url + "/android_view";
URL pUrl;
HttpURLConnection urlConn = null;
try {
DataOutputStream printout;
DataInputStream input;
pUrl = new URL (sUrl);
urlConn = (HttpURLConnection) pUrl.openConnection();
urlConn.setDoInput (true);
urlConn.setDoOutput (true);
urlConn.setUseCaches (false);
urlConn.setRequestProperty("Content-Type","application/json");
urlConn.setRequestProperty("Host", "android.schoolportal.gr");
urlConn.connect();
//Create JSONObject here
JSONObject jsonParam = new JSONObject();
jsonParam.put("snc", serialClient);
jsonParam.put("code", pwd);
printout = new DataOutputStream(urlConn.getOutputStream());
String str = jsonParam.toString();
byte[] data = str.getBytes("UTF-8");
printout.write(data);
printout.flush();
printout.close ();
int HttpResult = urlConn.getResponseCode();
if(HttpResult == HttpURLConnection.HTTP_OK){
success = true;
WebView view=(WebView) this.findViewById(R.id.webView);
view.setWebChromeClient(new WebChromeClient());
view.setWebViewClient(new WebViewClient());
view.getSettings().setJavaScriptEnabled(true);
view.loadUrl(sUrl);
}else{
success = false;
}
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally{
if(urlConn!=null)
urlConn.disconnect();
}
return success;
}
I just know that in android, url connection should run in separate thread. That's why I got the following error:
Caused by: android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork
My question is, how do I use AsyncTask to avoid the error?
I saw there is doInBackground() which I can put the initialize() function there.
I saw also there is onPostExecute() event which I can check the result from the doInBackground(), but I don't understand yet how do I retrieve the return of initialize() which placed inside doInBackground()?
Bonus question, later I'd like to place all this job inside an intentservice. Do I need to stil use the asynctask? Does intentservice itself is an asynctask?
you can try some thing like this and also u can use a different thread
final Handler h = new Handler();
Runnable r = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
final File file = new File(path);
Log.i("path",path);
downloadFile(url[j], file);
h.post(new Runnable(){
#Override
public void run() {
txt.setText(""+jp);
jp++;
}
});
}
}
};
new Thread(r).start();
}
private static void downloadFile(String url, File outputFile) {
try {
URL u = new URL(url);
URLConnection conn = u.openConnection();
int contentLength = conn.getContentLength();
Log.i("len","" + contentLength);
Log.i("url1","Streaming from "+url+ "....");
DataInputStream stream = new DataInputStream(u.openStream());
byte[] buffer = new byte[contentLength];
stream.readFully(buffer);
stream.close();
DataOutputStream fos = new DataOutputStream(new FileOutputStream(outputFile));
fos.write(buffer);
fos.flush();
fos.close();
} catch(FileNotFoundException e) {
Log.v("FileError" , e.toString());
return; // swallow a 404
} catch (IOException e) {
Log.v("FileError" , e.toString());
return; // swallow a 404
}
catch (Exception e) {
Log.v("FileError" , e.toString());
return; // swallow a 404
}
}
and also you cant access ui elements on different thread you have to use handler or run on ui thread.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try{
this.pd = ProgressDialog.show(this, "Loading..", "Please Wait...", true, false);
new AsyncAction().execute();
}catch (Exception e) {
e.printStackTrace();
}
}
private class AsyncAction extends AsyncTask<String, Void, String> {
protected Void doInBackground(String... args) {
//do your stuff here }
}
}
Network traffic (and all other logic which takes some time to process) should always be handled by a background thread and never on the Main thread.
Use an ASyncTask to execute the logic.
private class YourTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
// perform your network logic here
return "YourResult";
}
#Override
protected void onPostExecute(String result) {
// Update your screen with the results.
}
}
Call the ASyncTask in your code:
new YourTask().execute("");

HttpUrlConnection multipart file upload with progressBar

I want to check progress of uploading file by HttpUrlConnection. How I can do this? I've tried to calculate bytes when writing data in OutputStream but it's wrong, cause real uploading happens only when I call conn.getInputStream(), so I need somehow to check inputStream. Here is my code:
public static void uploadMovie(final HashMap<String, String> dataSource, final OnLoadFinishedListener finishedListener, final ProgressListener progressListener) {
if (finishedListener != null) {
new Thread(new Runnable() {
public void run() {
try {
String boundary = getMD5(dataSource.size()+String.valueOf(System.currentTimeMillis()));
MultipartEntityBuilder multipartEntity = MultipartEntityBuilder.create();
multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntity.setCharset(Charset.forName("UTF-8"));
for (String key : dataSource.keySet()) {
if (key.equals(MoviesFragmentAdd.USERFILE)) {
FileBody userFile = new FileBody(new File(dataSource.get(key)));
multipartEntity.addPart(key, userFile);
continue;
}
multipartEntity.addPart(key, new StringBody(dataSource.get(key),ContentType.APPLICATION_JSON));
}
HttpEntity entity = multipartEntity.build();
HttpURLConnection conn = (HttpsURLConnection) new URL(URL_API + "/video/addForm/").openConnection();
conn.setUseCaches(false);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept-Charset", "UTF-8");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Cache-Control", "no-cache");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
conn.setRequestProperty("Content-length", entity.getContentLength() + "");
conn.setRequestProperty(entity.getContentType().getName(),entity.getContentType().getValue());
OutputStream os = conn.getOutputStream();
entity.writeTo(os);
os.close();
//Real upload starting here -->>
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
//<<--
JsonObject request = (JsonObject) gparser.parse(in.readLine());
if (!request.get("error").getAsBoolean()) {
//do something
}
conn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
Because you have to deal with upload, I'd suppose most time is taken when doing entity.writeTo(os);. Maybe the first contact to the server takes some time as well (DNS resolution, SSL-handshake, ...). The markers you set for "the real upload" are not correct IMO.
Now it depends on your Multipart-library, whether you can intercept writeTo. If it is clever and resource-efficient, it's iterating over the parts and streams the content one-by-one to the output stream. If not, and the .build() operation is creating a big fat byte[], then you could take this array, stream it in chunks to the server and tell your user how many percent of the upload is already done.
From a resource perspective I'd prefer not really knowing what happens. But if feedback is that important and if the movies are only a few megabytes in size, you could stream the Multipart-Entity first to a ByteArrayOutputStream and then write little chunks of the created byte-array to the server while notifying your user about progress. The following code is not validated or tested (you can see it as pseudo-code):
ByteArrayOutputStream baos = new ByteArrayOutputStream();
entity.writeTo(baos);
baos.close();
byte[] payload = baos.toByteArray();
baos = null;
OutputStream os = conn.getOutputStream();
int totalSize = payload.length;
int bytesTransferred = 0;
int chunkSize = 2000;
while (bytesTransferred < totalSize) {
int nextChunkSize = totalSize - bytesTransferred;
if (nextChunkSize > chunkSize) {
nextChunkSize = chunkSize;
}
os.write(payload, bytesTransferred, nextChunkSize); // TODO check outcome!
bytesTransferred += nextChunkSize;
// Here you can call the method which updates progress
// be sure to wrap it so UI-updates are done on the main thread!
updateProgressInfo(100 * bytesTransferred / totalSize);
}
os.close();
A more elegant way would be to write an intercepting OutputStream which registers progress and delegates the real write-operations to the underlaying "real" OutputStream.
Edit
#whizzzkey wrote:
I've re-checked it many times - entity.writeTo(os) DOESN'T do a real upload, it does conn.getResponseCode() or conn.getInputStream()
Now it's clear. HttpURLConnection is buffering your upload data, because it doesn't know the content-length. You've set the header 'Content-length', but oviously this is ignored by HUC. You have to call
conn.setFixedLengthStreamingMode(entity.getContentLength());
Then you should better remove the call to conn.setRequestProperty("Content-length", entity.getContentLength() + "");
In this case, HUC can write the headers and entity.writeTo(os) can really stream the data to the server. Otherwise the buffered data is sent when HUC knows how many bytes will be transferred. So in fact, getInputStream() tells HUC that you're finished, but before really reading the response, all the collected data has to be sent to the server.
I wouldn't recommend changing your code, but for those of you who don't know the exact size of the transferred data (in bytes, not characters!!), you can tell HUC that it should transfer the data in chunks without setting the exact content-length:
conn.setChunkedStreamingMode(-1); // use default chunk size
Right this code in your activity...
public class PublishPostToServer extends AsyncTask implements
ProgressListenerForPost {
public Context pContext;
public long totalSize;
private String response;
public PublishPostToServer(Context context) {
pContext = context;
}
protected void onPreExecute() {
showProgressDialog();
}
#Override
protected Boolean doInBackground(Void... params) {
boolean success = true;
try {
response = NetworkAdaptor.getInstance()
.upLoadMultipartImageToServer(
"",
"",
"", this, this); // Add file path, Authkey, caption
} catch (Exception e) {
success = false;
}
return success;
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
//validateResponse(result, response);
}
#Override
protected void onProgressUpdate(Integer... values) {
try {
if (mProgressDialog != null) {
mProgressDialog.setProgress(values[0]);
}
} catch (Exception exception) {
}
}
#Override
public void transferred(long num) {
publishProgress((int) ((num / (float) totalSize) * 100));
}
}
private void showProgressDialog() {
try {
String dialogMsg = "Uploading Image...";
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage(dialogMsg);
mProgressDialog.setIndeterminate(false);
mProgressDialog.setMax(100);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(false);
mProgressDialog.show();
} catch (Exception exception) {
}
}
Now, Make a NetworkAdapter Class
public String upLoadMultipartImageToServer(String sourceFileUri,
String auth_key, String caption, ProgressListenerForPost listiner,
PublishPostToServer asyncListiner) {
String upLoadServerUri = "" + "upload_image";
HttpPost httppost = new HttpPost(upLoadServerUri);
File file = new File(sourceFileUri);
if (file.exists()) {
FileBody filebodyVideo = new FileBody(file);
CustomMultiPartEntity multipartEntity = new CustomMultiPartEntity(
HttpMultipartMode.BROWSER_COMPATIBLE, listiner);
try {
multipartEntity.addPart("auth_key", new StringBody(auth_key));
multipartEntity.addPart("caption", new StringBody(caption));
multipartEntity.addPart("image", filebodyVideo);
asyncListiner.totalSize = multipartEntity.getContentLength();
httppost.setEntity(multipartEntity);
}
catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
DefaultHttpClient mHttpClient = new DefaultHttpClient();
String response = "";
try {
response = mHttpClient.execute(httppost,
new MovieUploadResponseHandler());
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return response;
} else {
return null;
}
}
#SuppressWarnings("rawtypes")
private class MovieUploadResponseHandler implements ResponseHandler {
#Override
public Object handleResponse(HttpResponse response)
throws ClientProtocolException, IOException {
HttpEntity r_entity = response.getEntity();
String responseString = EntityUtils.toString(r_entity);
// DebugHelper.printData("UPLOAD", responseString);
return responseString;
}
}
public static boolean isValidResponse(String resultData) {
try {
} catch (Exception exception) {
//DebugHelper.printException(exception);
}
return true;
}
public String upLoadVideoToServer(String currentFilePath, String string,
PublishPostToServer publishPostToServer,
PublishPostToServer publishPostToServer2) {
// TODO Auto-generated method stub
return null;
}

Download files in android

I am trying to write an application that downloads files in the background. The code crashes when it tries to reenter doInBackground(). This happens when doing is set to false before returning. Code follows -
public class DownloadFile extends AsyncTask<String, Integer, String> {
private boolean doing;
private Activity activity;
private Intent intent;
private File beta;
private File alpha;
public DownloadFile(Activity act, Intent intent) {
this.activity = act;
this.intent = intent;
doing = false;
}
#Override
protected String doInBackground(String... sUrl) {
int fileCount = 0;
if (!download(sUrl[0] + "list.txt",
Environment.getExternalStorageDirectory() + "/alpha/list.txt")){
setDoing(false);
return "Download failed";//list.txt could not be downloaded. return error message.
}
fileCount++;
beta = new File(Environment.getExternalStorageDirectory() + "/beta/");
File betalist = new File(beta + "/list.txt");
alpha = new File(Environment.getExternalStorageDirectory() + "/alpha/");
File alphalist = new File(alpha + "/list.txt");
//verify that the file is changed.
if (alphalist.lastModified() == betalist.lastModified()// these two are
// never equal.
|| alphalist.length() == betalist.length()) { // better to check
// the length of
// the files.
setDoing(false);
return "Nothing to download.";
}
try {
FileReader inAlpha = new FileReader(alphalist);
BufferedReader br = new BufferedReader(inAlpha);
String s;
// read the name of each file in a loop
while ((s = br.readLine()) != null) {
// if(fileExistsInBeta(s)){
// copyFromBetaToAlpha(s);
// continue;
// }
// download the file.
//Url will truncate the trailing / so keep if statement as is.
if (!download(sUrl[0] + s,
Environment.getExternalStorageDirectory() + "/alpha/"
+ s)){
setDoing(false);
return "Failed at " + s;// the given file could not be downloaded. return error.
}
fileCount++;
}
br.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
Log.e("Pankaj", e.getMessage());
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e("Pankaj", e.getMessage());
} catch (Exception e) {
Log.e("Pankaj", e.getMessage());
}
Log.d("Pankaj", "Download Done");
activity.overridePendingTransition(0, 0);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
activity.finish();
Log.d("Pankaj", "MainActivity Killed");
// rename alpha to beta
deleteSubFolders(beta.toString());
beta.delete();
alpha.renameTo(beta);
if (!alpha.exists()) {
alpha.mkdir();
}
File upper = new File(alpha + "/upper/");
if (!upper.exists())
upper.mkdirs();
File lower = new File(alpha + "/lower/");
if (!lower.exists())
lower.mkdirs();
// ConfLoader.getInstance().reload();//to refresh the settings
// restart the activity
activity.overridePendingTransition(0, 0);
activity.startActivity(intent);
Log.d("Pankaj", "MainActivity restarted");
// now reset done status so we can start again.
setDoing(false);
return "Download finished.";// return the status for onPostExecute.
}
private void copyFromBetaToAlpha(String fileName) {
File beta=new File(Environment.getExternalStorageDirectory()+"/beta/"+fileName);
File alpha=new File(Environment.getExternalStorageDirectory()+"/alpha/"+fileName);
try {
FileInputStream fis=new FileInputStream(beta);
FileOutputStream fos=new FileOutputStream(alpha);
byte[] buf=new byte[1024];
int len;
while((len=fis.read(buf))>0){
fos.write(buf, 0, len);
}
fis.close();
fos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(activity, result, Toast.LENGTH_LONG).show();
super.onPostExecute(result);
}
public boolean download(String url, String file) {
boolean successful = true;
try {
URL u = new URL(url);
URLConnection conn = u.openConnection();
conn.connect();
int filelen = conn.getContentLength();
File f = new File(file);
// skip download if lengths are same
// because the file has been downed fully.
if (f.exists() && filelen == f.length()) {
return successful;
}
InputStream is = u.openStream();
DataInputStream dis = new DataInputStream(is);
byte[] buffer = new byte[1024];
int length;
FileOutputStream fos = new FileOutputStream(f);
while ((length = dis.read(buffer)) > 0) {
fos.write(buffer, 0, length);
}
fos.close();
buffer = null;
dis.close();
} catch (MalformedURLException mue) {
Log.e("SYNC getUpdate", "malformed url error", mue);
successful = false;
} catch (IOException ioe) {
Log.e("SYNC getUpdate", "io error", ioe);
successful = false;
} catch (SecurityException se) {
Log.e("SYNC getUpdate", "security error", se);
successful = false;
}
return successful;
}
private void deleteSubFolders(String uri) {
File currentFolder = new File(uri);
File files[] = currentFolder.listFiles();
if (files == null) {
return;
}
for (File f : files) {
if (f.isDirectory()) {
deleteSubFolders(f.toString());
}
// no else, or you'll never get rid of this folder!
f.delete();
}
}
public static int getFilesCount(File file) {
File[] files = file.listFiles();
int count = 0;
for (File f : files)
if (f.isDirectory())
count += getFilesCount(f);
else
count++;
return count;
}
public boolean isDoing() {
return doing;
}
/**
* #param doing
*/
public void setDoing(boolean doing) {
this.doing = doing;
}
private boolean fileExistsInBeta(final String fileName){
boolean exists=false;
File beta=new File(Environment.getExternalStorageDirectory()+"/beta/"+fileName);
if(beta.exists()){
String[] ext=beta.getName().split(".");
String extName=ext[ext.length-1];
exists=(extName!="txt" && extName!="tmr" && extName!="conf");
}
return exists;
}
in the main activity -
public void run() {
if (!downloadFile.isDoing()) {
downloadFile.execute(ConfLoader.getInstance().getListUrl());
downloadFile.setDoing(true);
}
// change the delay so that it covers the time for download and
// doesn't overlap causing multiple downloads jamming the bandwidth.
h.postDelayed(this, 1000);//check after 60 sec.
}
in the onCreate() -
downloadFile = new DownloadFile(this, getIntent());
h = new Handler();
h.postDelayed(this, 1000);
Any help is appreciated. Thanks in advance.
EDIT:
The logcat error is Cannot execute task the task is already running.
Cannot execute task: Task has already been executed(A task can only be executed once).
EDIT:
Is it possible that the error is because I am trying to execute the asynchtask again in run(). Perhaps AsynchTask does not allow re-entry.
Try using this
1. First create a dialogue
#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;
}
}
The download async task
class DownloadFileAsync extends AsyncTask<String, String, String> {
#SuppressWarnings("deprecation")
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialog(DIALOG_DOWNLOAD_PROGRESS);
}
#Override
protected String doInBackground(String... aurl) {
int count;
File root = android.os.Environment.getExternalStorageDirectory();
//
File dir = new File (root.getAbsolutePath()+"/Downl");
if(dir.exists()==false) {
dir.mkdirs();
}
File file = new File(dir, url.substring(url.lastIndexOf("/")+1)); //name of file
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(file);
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]));
}
#SuppressWarnings("deprecation")
#Override
protected void onPostExecute(String unused) {
dismissDialog(DIALOG_DOWNLOAD_PROGRESS);
Toast.makeText(DisplayActivity.this,"Successfully downloaded in phone memory.", Toast.LENGTH_SHORT).show();
}
}
Call the async new DownloadFileAsync().execute(url); //pass ur url

Android AsyncTask send/read data using Socket

I'm working on a test project, something like a basic chat program using wi-fi connection.
I'm creating sockets to connect two different devices, but my problem is that when I send the first message, it's showing in the other device. But if I try to send again, I can see in the logs from the first one, that the message is sent, but it never shows up in the second device.
I've tried to implement the reading of the received data in another thread..or in Async Task, but the problem is still there. Here are both ways of my implementation :
Single Thread :
public void listenForSocket(){
thread = new Thread(new Runnable() {
public void run() {
Log.e("READDATAFROMSOCKET","READDATAFROMSOCKET");
try {
// sets the service running state to true so we can get it's state from other classes and functions.
serverSocket = new ServerSocket(DNSUtils.port);
client = serverSocket.accept();
client.setKeepAlive(true);
InputStream is = client.getInputStream();
Log.d("","is Size : "+is.available());
BufferedReader in = new BufferedReader(new InputStreamReader(is));
int readed = in.read();
Log.d("","readed bytes : "+readed);
String line = "";
while ((line = in.readLine()) != null) {
Log.i("","line : "+line);
changeText(line);
}
//client.close();
//serverSocket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
}
And here is AsyncTask :
class ServerTask extends AsyncTask<Void, Void, Void>{
private String line = "";
#Override
protected Void doInBackground(Void... params) {
try {
Log.e("ASYNCTASK","ASYNCTASK");
// sets the service running state to true so we can get it's state from other classes and functions.
serverSocket = new ServerSocket(DNSUtils.port);
client = serverSocket.accept();
client.setKeepAlive(true);
InputStream is = client.getInputStream();
Log.d("","is Size : "+is.available());
BufferedReader in = new BufferedReader(new InputStreamReader(is));
int readed = in.read();
Log.d("","readed bytes : "+readed);
while ((line = in.readLine()) != null) {
Log.i("","line : "+line);
}
//client.close();
//serverSocket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
changeText(line);
}
}
changeText(String); -
private void changeText(final String line) {
runOnUiThread(new Runnable() {
#Override
public void run() {
LinearLayout.LayoutParams params = new LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.RIGHT;
TextView sendMsg = new TextView(MainActivity.this);
sendMsg.setText(DNSUtils.clientName+" : "+line);
sendMsg.setTextColor(Color.DKGRAY);
sendMsg.setTextSize(18);
layout.addView(sendMsg, params);
}
});
}
Any ideas how to fix this issue?
And another problem is that when I am reading the received data, the first letter of the sent string never shows. It always starts from the second letter.
Thanks in advance.
If i were you i will try to implement serverSocket = new ServerSocket(DNSUtils.port); only once with new; not in every thread.

Categories

Resources