2016-11-29 2 views
1

Utilisez une intention avec Intent.ACTION_GET_CONTENT pour choisir un fichier XML. Dans onActivityResult(), je lance une asynctask pour lire ce fichier XML dans une base de données. Je souhaite que la tâche asynchrone affiche une barre de progression pour s'assurer qu'elle se termine avant que l'application ne procède en raison de la gestion des erreurs et des modifications d'interface utilisateur attendues.Lancement d'une asynctask dans onActivityResult()

La boîte de dialogue de sélection créée par l'intention est affichée tant que la tâche asynchrone est exécutée, c'est-à-dire que l'application est toujours dans le bloc onActivityResult() et qu'aucun dialogue de progression n'est affiché. Le onPostExecute() est appelé AFTER onActivityResult() se termine.

J'ai aussi essayé d'utiliser .get() le faire la finition AsyncTask avant que le app, mais pas de chance ...

Je pense que cela se résume à une mauvaise logique de ma part ...

Tout se passe dans une activité sauf que importDB est une classe à part.

Le but est startet cette façon ...

intent = new Intent(Intent.ACTION_GET_CONTENT); 
intent.addCategory(Intent.CATEGORY_OPENABLE); 
intent.setType("text/xml"); 
startActivityForResult(Intent.createChooser(intent, "Select XML"), RC_IMPORT_FILE); 

... et le onActivityResult() ressemble à ceci ...

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
    super.onActivityResult(requestCode, resultCode, data); 
    switch (resultCode) { 
     case Activity.RESULT_OK: 
      switch (requestCode) { 
       case RC_IMPORT_FILE: 
        Uri uri = data.getData(); 
        if (data != null) { 
         importDB(new File(uri.toString()), uri, false); 
        }; 
       break; 
     ... more switch statements... 
    } 
} 

... et importDB ressemble à ceci. ..

private void importDB(File file, Uri uri, boolean xmlRaw, Context context) { 
    int error = 0; 

    ImportDataBase importDataBase = new ImportDataBase(); 
    importDataBase.setContext(this); 
    importDataBase.setUri(uri); 
    importDataBase.xmlRaw(xmlRaw); 
    try { 
     importDataBase.execute("ImportDB").get(); 
    } catch (ExecutionException ee) { 
     logException(TAG, "importDB", ee); 
     error = 1; 
    } catch (InterruptedException ie) { 
     logException(TAG, "importDB", ie); 
     error = 2; 
    } 
} 

... et la tâche async (ImportDatabase) ressemble à ceci ...

import android.app.ProgressDialog; 
import android.content.Context; 
import android.net.Uri; 
import android.os.AsyncTask; 
import android.widget.Toast; 
import java.io.InputStream; 

public class ImportDataBase extends AsyncTask<String, Integer, String> { 

private static final String TAG = "ImportDataBase"; 

private Context context; 
private ProgressDialog progressDialog; 

private Uri uri = null; 
private InputStream xmlStream = null; 

private XMLParser xmlParser; 
private boolean xmlRaw = true; 
private int errorCode = 0; 

public void xmlRaw(boolean xmlRaw) { 
    this.xmlRaw = xmlRaw; 
} 

public void setUri(Uri uri) { this.uri = uri; } 
public void setInputStream(InputStream inputStream) { this.xmlStream = inputStream; } 
public void setContext(Context context) { 
    this.context = context; 
} 

@Override 
protected void onPreExecute() { 
    super.onPreExecute(); 
    progressDialog = this.context; 
    progressDialog.setCancelable(false); 
    progressDialog.setMessage("Please wait..."); 
    progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 
    progressDialog.show(); 
    xmlParser = new XMLParser(); 
    xmlParser.xmlRaw(xmlRaw); 
} 

@Override 
protected String doInBackground(String... params) { 
    String result = "0"; 
    int error = 0; 
    InputStream inputStream = null; 
    try { 
     if (uri != null) inputStream = context.getContentResolver().openInputStream(uri); 
      else inputStream = this.xmlStream; 
    } catch (Exception e) { 
     result = "1000"; 
    } 

    if (error == 0) { 
     try { 
      xmlParser.readXML(inputStream); 
     } catch (NullPointerException npe) { 
       result ="10"; 
     } catch (Exception e) { 
       result ="10"; 
     } 

    } else result = "31"; 

    switch (xmlParser.getError()) { 
     case 1 : result = "10"; break; // XML Parser error 
     case 2 : result = "15"; break; // URLERROR; 
     case 3 : result = "30"; break; // IOFileError 
     case 4 : result = "31"; break; // FileError; 
     case 5 : result = "32"; break; // FileDoesNotExists; 
     default : result = "0"; 
    } 

    try { 
     inputStream.close(); 
    } catch (Exception e) { 
    } 
    return result; 
} 

@Override 
protected void onPostExecute(String string) { 
    super.onPostExecute(string); 
    String error = ""; 
    if (Integer.valueOf(string) > 0) { 
     switch (Integer.valueOf(string)) { 
      case 1: 
       error = "You need to update the app to the newest version!"; 
       errorCode =1; 
      break; 
      case 10 : 
       error = "XML parser error! Wrong file?"; 
       errorCode =10; 
      break; 
      case 15 : 
       error = "Wrong URL!"; 
       errorCode =15; 
      break; 
      case 30 : 
       error = "File read/Write error!"; 
       errorCode =30; 
       break; 
      case 31 : 
       error = "File error"; 
       errorCode =31; 
       break; 
      case 32 : 
       error = "File does not exsits!"; 
       errorCode =32; 
       break; 
      case 99 : 
       error = "Unknwon XML parser error!"; 
       errorCode =99; 
       break; 
      case 100: 
       error = "Database error! Retry or reinstall app!"; 
       errorCode =100; 
      break; 
      case 1000: 
       error = "Unknown error!"; 
       errorCode =1000; 
      break; 
      default: 
       error = "Unknwon error!"; 
     } 
     Toast.makeText(context, error, Toast.LENGTH_SHORT).show(); 
    } 
    if (progressDialog.isShowing()) progressDialog.dismiss(); 
} 

public int getError() { 
    return this.errorCode; 
} 

@Override 
protected void onCancelled() { 
    super.onCancelled(); 
} 
} 

Des suggestions sur la façon dont je peux faire attendre l'application pour terminer l'application asynctask? Est-il possible de fermer la boîte de dialogue onActivityResult() avant d'appeler importDB() et d'afficher une barre de progression?

Répondre

0

Fondamentalement, vous devriez jamais bloquer quoi que ce soit. J'utiliser un AsyncTask avec l'affichage d'un ProgressDialog lors du démarrage et le cacher à la fin:

private ProgressDialog progressDialog; 

@Override 
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
    // blahblah 
        if (data != null) { 
         new ImportTask(new File(uri.toString()), uri).execute(); 
        } 
    // blahblah 
} 

class ImportTask extends AsyncTask<Void, Void, Void> { 
    private File file; 
    private Uri uri; 

    ImportTask(File file, Uri uri){ 
    this.file = file; 
    this.uri = uri; 
    } 

    @Override 
    protected void onPreExecute() { 
    progressDialog.show(); 
    } 

    @Override 
    protected Void doInBackground(Void... voids) { 
    importDB(file, uri, false); 
    return null; 
    } 

    @Override 
    protected void onPostExecute(Void res) { 
    progressDialog.hide(); 
    }  
} 

De cette façon, vous pouvez décider de faire d'autres choses en parallèle pendant la importDB() est en cours d'exécution.

+0

Peut-être que j'étais un peu peu clair. J'ai essayé d'afficher une barre de progression, mais puisque la fenêtre de dialogue de fichier que l'intention créée est ouverte jusqu'à ce que l'asynctask atteigne onPostExecute(), la barre de progression n'est jamais montrée pendant onPreExecute et doInBackground(). La chose amusante est que progressbar.isShowing() renvoie vrai ... – user1086500

+0

ne sais pas ce que vous voulez dire. habituellement l'activité ouverte avec 'startActivityForResult()' est fermée juste avant que le 'onActivityResult' soit exécuté – injecteer

+0

J'ai essayé ceci dans un émulateur API 23 et mon téléphone samsung s6 avec android 6. J'ai mis un Thread.sleep à l'intérieur doInBackground() dans l'asynctask appelée onActivityResult() et la boîte de dialogue avec les fichiers à choisir est affichée pendant cette mise en veille. Il semble que l'activité/l'intention soit fermée après la fin de la procédure onAcitivtyResult() ... – user1086500