How to use Asynctask on Android?

Asked

Viewed 3,330 times

0

I’m trying to get my application to download an XML (RSS Feed) and read your tags to display it on the home screen. But the application closes after downloading before trying to start the method onPostExecute asynctask getFeed (Download XML) and Asynctask lerXML (Reading of the Tags). And if I just try to check the application version, I use Asynctask to download the file and read its contents, check the version and ask the user if he wants to perform the application update. Only, if I’ve already executed the Asynctask updateApp, I can’t perform the downloadAPK without the app closing.

Complete code: Pastebin

AsyncTask<Void, Void, String> getFeed = new AsyncTask<Void, Void, String>(){
        @Override
        protected String doInBackground(Void... params) {
            String retorno = "não";
            try {
                // Baixar Feed
                URL url = new URL("http://www.ipoema.tumblr.com/rss");
                File file = new File(PATH + "iPoema.xml");
                file.delete();
                URLConnection ucon = url.openConnection();
                InputStream is = ucon.getInputStream();
                BufferedInputStream bis = new BufferedInputStream(is);
                ByteArrayBuffer baf = new ByteArrayBuffer(50);
                lenghtOfFile = ucon.getContentLength();
                int current = 0;
                while ((current = bis.read()) != -1) {
                    baf.append((byte) current);
                    progress = current;
                }
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(baf.toByteArray());
                fos.close();
                retorno = "sim";
            } catch (IOException e) {
                showMessage(e.getClass().getName(), "Erro ao tentar realizar o download do arquivo.");
            }
            return retorno;
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            if (s.equals("sim")) {
                try {
                    lerXML.execute();
                } catch (Exception e) {
                    showMessage(e.getClass().getName(), "Erro ao tentar realizar a leitura do arquivo.");
                }
            }
        }
    };

    AsyncTask<Void, Void, String> lerXML = new AsyncTask<Void, Void, String>(){
        @Override
        protected String doInBackground(Void... params) {
            String state = "erro";
            try {
                // Ler XML
                showMessage("iPoema", "Arquivo lido com sucesso");
                File f = new File(PATH + "iPoema.xml");
                SAXBuilder sb = new SAXBuilder();
                Document d = sb.build(f);
                Element mural = d.getRootElement();
                List<Element> elements = mural.getChildren("channel");
                Iterator<Element> i = elements.iterator();
                int x = 0;
                //for (int x = 0; x <= elements.size(); x++) {
                while (i.hasNext()) {
                    //Element node = (Element) elements.get(x);
                    Element node = (Element) i.next();
                    Element item = node.getChild("item");

                    titulo[x] = item.getChildText("title");
                    texto[x] = item.getChildText("description");
                    autor[x] = item.getChildText("category");
                    x++;
                }
                state = "ok";
            } catch (JDOMException e) {
                showMessage(e.getClass().getName(), "Erro ao tentar realizar a leitura do XML.");
            } catch (IOException e) {
                showMessage(e.getClass().getName(), "Erro ao tentar realizar a leitura do XML.");
            }
            return state;
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            if (s.equals("ok")) {
                try {
                    // Títulos
                    TextView titulo1 = (TextView) findViewById(R.id.titulo1);
                    TextView titulo2 = (TextView) findViewById(R.id.titulo2);
                    TextView titulo3 = (TextView) findViewById(R.id.titulo3);
                    TextView titulo4 = (TextView) findViewById(R.id.titulo4);

                    // Textos
                    TextView texto1 = (TextView) findViewById(R.id.texto1);
                    TextView texto2 = (TextView) findViewById(R.id.texto2);
                    TextView texto3 = (TextView) findViewById(R.id.texto3);
                    TextView texto4 = (TextView) findViewById(R.id.texto4);

                    // SetText
                    titulo1.setText(getTitulo(0));
                    texto1.setText(getTexto(0)+"\n\n#"+getAutor(0)+"\n\n");

                    titulo2.setText(getTitulo(1));
                    texto2.setText(getTexto(1)+"\n\n#"+getAutor(1)+"\n\n");

                    titulo3.setText(getTitulo(2));
                    texto3.setText(getTexto(2)+"\n\n#"+getAutor(2)+"\n\n");

                    titulo4.setText(getTitulo(3));
                    texto4.setText(getTexto(3)+"\n\n#"+getAutor(3)+"\n\n");

                    // Exibe
                    titulo1.setVisibility(TextView.VISIBLE);
                    texto1.setVisibility(TextView.VISIBLE);

                    titulo2.setVisibility(TextView.VISIBLE);
                    texto2.setVisibility(TextView.VISIBLE);

                    titulo3.setVisibility(TextView.VISIBLE);
                    texto3.setVisibility(TextView.VISIBLE);

                    titulo4.setVisibility(TextView.VISIBLE);
                    texto4.setVisibility(TextView.VISIBLE);
                } catch (Exception e) {
                    showMessage(e.getClass().getName(), "Erro ao tentar realizar a leitura do arquivo.");
                }
            }
        }
    };

    AsyncTask<Void, Void, String> atualizaApp = new AsyncTask<Void, Void, String>(){
        @Override
        protected String doInBackground(Void... params) {
            String versao = "0";
            try {
                // Baixar iPoema.txt
                URL url = new URL("http://www.xadees.xpg.com.br/iPoema.txt");
                File file = new File(PATH + "iPoema.txt");
                file.delete();
                URLConnection ucon = url.openConnection();
                InputStream is = ucon.getInputStream();
                BufferedInputStream bis = new BufferedInputStream(is);
                ByteArrayBuffer baf = new ByteArrayBuffer(50);
                lenghtOfFile = ucon.getContentLength();
                int current = 0;
                while ((current = bis.read()) != -1) {
                    baf.append((byte) current);
                    progress = current;
                }
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(baf.toByteArray());
                fos.close();

                // Ler iPoema.txt
                StringBuilder text = new StringBuilder();
                BufferedReader br = new BufferedReader(new FileReader(file));
                String line;
                while ((line = br.readLine()) != null) {
                    text.append(line);
                }
                versao = text.toString();
            } catch (IOException e) {
                showMessage(e.getClass().getName(), "Erro ao tentar realizar o download do arquivo.");
            } catch (Exception e) {
                showMessage(e.getClass().getName(), "Erro ao tentar realizar a leitura do arquivo.");
            }

            return versao;
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            int vAtual = Pi.versionCode;
            int vAPK = Integer.parseInt(s);

            if (vAtual < vAPK) {
                try {
                    // Baixar
                    URL url = new URL("http://www.xadees.xpg.com.br/iPoema%20for%20Android.apk");
                    File file = new File(PATH + "iPoema.apk");
                    file.delete();
                    URLConnection ucon = url.openConnection();
                    InputStream is = ucon.getInputStream();
                    BufferedInputStream bis = new BufferedInputStream(is);
                    ByteArrayBuffer baf = new ByteArrayBuffer(50);
                    lenghtOfFile = ucon.getContentLength();
                    int current = 0;
                    while ((current = bis.read()) != -1) {
                        baf.append((byte) current);
                        progress = current;
                    }
                    FileOutputStream fos = new FileOutputStream(file);
                    fos.write(baf.toByteArray());
                    fos.close();

                    // Instalar
                    Intent intent = new Intent(Intent.ACTION_VIEW);
                    intent.setDataAndType(Uri.fromFile(new File(PATH + "iPoema.apk")), "application/vnd.android.package-archive");
                    //java.lang.Process proc = Runtime.getRuntime().exec(new String[]{"su", "-c", "adb install -r " + PATH + "iPoema.apk"});
                    //proc.waitFor();
                    startActivityForResult(intent,0);
                } catch (IOException e) {
                    showMessage(e.getClass().getName(), "Erro ao tentar realizar o download do pacote.");
                }
            } else {
                showMessage("iPoema", "iPoema já está atualizado.");
            }
        }
    };
  • To update APK, I advise you to use the Google Play Apis. And I don’t know what your method showMessage is doing more if it’s something that involves UI, is where you can be stopping the application, because in the method doInBackground of a AsyncTask you cannot access to UI

  • Your logcat displays some error message?

  • Ahh, showMessage is a method to display a Messagebox. I will remove it and test it. And I do not use logcat, or at least I do not know see.

  • I don’t know if what I’m going to say makes sense, how far do I understand your app closes "alone", or doesn’t even open the second time (or after the update), is that it? If it is me, I suppose that the "Thread" is "locked" (I don’t know how to explain it in a technical way) and therefore can’t recreate the "process", because it is busy, see if this helps: http://answall.com/a/44480/3635

4 answers

2

Looking quickly at your code, I realized that you initialize all the AsyncTasks in a Thread separate.

AsyncTasks are routines that facilitate the use of Threads on Android. They execute a code in background*(new thread)*, in the call doInBackground and are able to make changes in thread ui on call onPostExecute.

This way, your code presents two problems:

-Create a new thread to call a asyncTask, Which is not necessary, and it can cause problems. -Modifications made to the process doInBackground, when they should be carried out only in onPostExecute

Also, keep in mind that Android limits the number of asyncTasks which may run in parallel. Only 1 to android 3.0 onward

  • I realized I can’t run the same Asynctask more than once or then the application closes without displaying anything. And I use a Asynctask to lower the iPoema.txt and read the apk version, which then he calls another Asynctask, because I tried to use on own onPostExecute, but the app would close if I tried to download the file. And even removing showMessage, nothing has changed.

1

What Felipe meant was to create an interface and make your Activity implement this interface, and when creating the Asynctask instance pass the reference of your Activity to it (your Asynctask class must have a reference to the interface object), thus in the onPostExecute method you call the method implemented by your Activity by passing the parameter (if any). That way you’d be making the threads "communicate".

I use it that way and never had a problem.

0

Well, I didn’t quite understand what you did, but one possible solution would be the following code :

Create a class to do what you want and extend Asynctask, since you can only run one at a time.

private class NomeDaClass extends AsyncTask {

    private  int tipoDeFuncao ;

    public NomeDaClasse(int a) {
       this.tipoDeFuncao = a;
    }

    @Override
    protected Object doInBackground(Object... params) {

      if (typeofFunction == 1) {
        atualizaApp();
      } else if (typeofFunction == 2) {
        lerXML();
      } else if (typeofFunction == 3) {
        getFeed();
      }

      return null;
    }

}

Then, in your normal class, you create the functions you want to run in the background and within them you call the constructor of your class you inherit from Asynctask:

public void atualizaApp() {    
    new Connection(1).execute();
}

public void lerXML(parameters) {
    new Connection(2).execute();

}

public void getFeed(parameters) {
    new Connection(3).execute();

}

It’s not the best, but it’s a solution. :)

0

ALWAYS separate "responsibilities" from each action! Create two separate classes for Asynctask.

Remember, Asynktask is a separate thread from the main thread.

In order to receive the return of your Async, you can create an Interface with Onresult(Boolean result) method and implement in the calling Activity, so you can make the new call of your other Asynctask.

  • Please, could you explain it to me better? I was still having doubts about what to do. I’m thinking about following what @Debeka said, but I want to understand what you said to try something.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.