0

I am trying to upload a file to dropbox via AsyncTask and I am gett the window leaked error:

05-16 16:05:53.523: E/WindowManager(4528): Activity com.example.wecharades.ShowVideo has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@2be59ea8 that was originally added here

I looked here and understand it is because my activity is exited and the progressdialog is still there. I can't understand why my activity gets exited. it is just a screen with a button to press to upload the file. I am using almost an identical code to download a file from dropbox and it works perfect.

Any suggestions? thanks in advance!

public class UploadFile extends AsyncTask<Void, Long, Boolean> {

    DropboxAPI<AndroidAuthSession> dDBApi;
    Context dContext;
    protected final  ProgressDialog uDialog;
    private long dFileLen;
    private String SAVE_PATH;
    private String mErrorMsg;

    public UploadFile(Context context,DropboxAPI<AndroidAuthSession> mDBApi, String path) {
        dDBApi=mDBApi;
        dContext=context;
        SAVE_PATH = path;
        uDialog = new ProgressDialog(context);
        uDialog.setMax(100);
        uDialog.setMessage("Uploading Video Charade");
        uDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        uDialog.show();
    }

    @Override
    protected Boolean doInBackground(Void... params) {
        FileInputStream inputStream = null;
        try {
            File file = new File(ShowVideo.path);
            inputStream = new FileInputStream(file);
            Entry newEntry = dDBApi.putFileOverwrite("/GAMES/GAME_BETWEEN_USER_A_USER_B/" + "PresentVideo.mp4", inputStream, file.length(), new ProgressListener() {
                @Override
                public long progressInterval() {
                    // Update the progress bar every half-second
                    return 500;
                }
                @Override
                public void onProgress(long bytes, long total) {
                    dFileLen = total;
                    publishProgress(bytes);
                }
            });

        } 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) {
            // 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) {
        }
        catch (Exception e) {
            System.out.println("Something went wrong: " + e);
        } 
        finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } 
                catch (IOException e) {
                    Log.d("TAG", "IOException" + e.getMessage());
                }
            }
            Log.d("ErrorMsg", mErrorMsg);
        }
        return null;
    }
    @Override
    protected void onProgressUpdate(Long... progress) {
        int percent = (int)(100.0*(double)progress[0]/dFileLen + 0.5);
        uDialog.setProgress(percent);
    }
    @Override
    protected void onPostExecute(Boolean result) {
        uDialog.dismiss();          
        super.onPostExecute(result);

        Log.d("TAG","UDialog Should be dismissed");
    }

}

Here is my Activity class from where i call the UploadFile: The methods buidSession and clearKeys are not yet used.

public class ShowVideo extends Activity implements OnClickListener {
    /** Dropbox Key and AccessType Information*/
    final static private String APP_KEY = "XXXXXXXXXXXX";
    final static private String APP_SECRET = "XXXXXXXXXXXX";
    final static private AccessType ACCESS_TYPE = AccessType.APP_FOLDER;
    final static private String ACCOUNT_PREFS_NAME = "prefs";
    final static private String ACCESS_KEY_NAME = "ACCESS_KEY";
    final static private String ACCESS_SECRET_NAME = "ACCESS_SECRET";
    /**--------------------------------------------------------------*/
    private DropboxAPI<AndroidAuthSession> mDBApi;

    UploadFile upload;
    static String path = "";
    public static String fileName;
    private VideoView ww;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); //Forces landscape orientation which is what the camera uses.
        setContentView(R.layout.showvideo);
        Button yesButton = (Button) findViewById(R.id.yesButton);
        Button noButton  = (Button) findViewById(R.id.NoButton);
        yesButton.setOnClickListener(this);
        noButton.setOnClickListener(this);

        ww = (VideoView) findViewById(R.id.satisfiedVideoView);
        path = getRealPathFromURI(CaptureVideo.uriVideo);
        fileName = getFileNameFromUrl(path);

        AppKeyPair appKeys = new AppKeyPair(APP_KEY, APP_SECRET);
        AndroidAuthSession session = new AndroidAuthSession(appKeys, ACCESS_TYPE);
        mDBApi = new DropboxAPI<AndroidAuthSession>(session);

        if(!mDBApi.getSession().isLinked())
            mDBApi.getSession().startAuthentication(ShowVideo.this);

    }
    private void playVideo(){
        ww.setVideoURI(CaptureVideo.uriVideo);
        ww.setMediaController(new MediaController(this));
        ww.start();
        ww.requestFocus();
    }
    public static String getFileNameFromUrl(String path) {
        String[] pathArray = path.split("/");
        return pathArray[pathArray.length - 1];
    }
    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.yesButton){
            UploadFile upload = new UploadFile(ShowVideo.this,mDBApi,path);
            upload.execute();
            //if(upload.getStatus() == upload.){
                //Intent intentHome = new Intent(ShowVideo.this, StartScreen.class);
                //startActivity(intentHome);
            //}
        }
        if(v.getId() == R.id.NoButton){
            File file = new File(path);
            boolean deleted = false;
            deleted = file.delete();
            Log.d("TAG", Boolean.toString(deleted));
            Intent intent = new Intent(ShowVideo.this, CaptureVideo.class);
            startActivity(intent);
        }

    }
    public String getRealPathFromURI(Uri contentUri) {
        String[] proj = { MediaStore.Images.Media.DATA };
        Cursor cursor = managedQuery(contentUri, proj, null, null, null);
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    }

    /**DROPBOX-METHOD------------------------------------------*/
    @Override
    protected void onResume() {
        super.onResume();
        AndroidAuthSession session = mDBApi.getSession();

        // The next part must be inserted in the onResume() method of the
        // activity from which session.startAuthentication() was called, so
        // that Dropbox authentication completes properly.
        if (session.authenticationSuccessful()) {
            try {
                // Mandatory call to complete the auth
                session.finishAuthentication();

                // Store it locally in our app for later use
                TokenPair tokens = session.getAccessTokenPair();
                storeKeys(tokens.key, tokens.secret);
                //setLoggedIn(true);
            } catch (IllegalStateException e) {
                showToast("Couldn't authenticate with Dropbox:" + e.getLocalizedMessage());
                Log.i("TAG", "Error authenticating", e);
            }
        }
    }
    /**
     * Shows keeping the access keys returned from Trusted Authenticator in a local
     * store, rather than storing user name & password, and re-authenticating each
     * time (which is not to be done, ever).
     *
     * @return Array of [access_key, access_secret], or null if none stored
     */
    private String[] getKeys() {
        SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
        String key = prefs.getString(ACCESS_KEY_NAME, null);
        String secret = prefs.getString(ACCESS_SECRET_NAME, null);
        if (key != null && secret != null) {
            String[] ret = new String[2];
            ret[0] = key;
            ret[1] = secret;
            return ret;
        } else {
            return null;
        }
    }

    /**
     * Shows keeping the access keys returned from Trusted Authenticator in a local
     * store, rather than storing user name & password, and re-authenticating each
     * time (which is not to be done, ever).
     */
    private void storeKeys(String key, String secret) {
        // Save the access key for later
        SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
        Editor edit = prefs.edit();
        edit.putString(ACCESS_KEY_NAME, key);
        edit.putString(ACCESS_SECRET_NAME, secret);
        edit.commit();
    }

    private void clearKeys() {
        SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
        Editor edit = prefs.edit();
        edit.clear();
        edit.commit();
    }

    private AndroidAuthSession buildSession() {
        AppKeyPair appKeyPair = new AppKeyPair(APP_KEY, APP_SECRET);
        AndroidAuthSession session;

        String[] stored = getKeys();
        if (stored != null) {
            AccessTokenPair accessToken = new AccessTokenPair(stored[0], stored[1]);
            session = new AndroidAuthSession(appKeyPair, ACCESS_TYPE, accessToken);
        } else {
            session = new AndroidAuthSession(appKeyPair, ACCESS_TYPE);
        }

        return session;
    }
    private void showToast(String msg) {
        Toast error = Toast.makeText(this, msg, Toast.LENGTH_LONG);
        error.show();
    }


}
Community
  • 1
  • 1
Brindarmor
  • 67
  • 2
  • 9

2 Answers2

0

Try this, in your constructor you dont get the context like this:

dContext=context.getApplicationContext();

but try passing the activity from which you start your asynctask

UploadFile upFile = new UploadFile( ActivityName.this, mDBApi, path);

so in your constructor you have now only:

dContext=context;
Andres L
  • 683
  • 9
  • 20
0

call super.onPostExexute(result) after uDialog.dismiss();

@Override
    protected void onPostExecute(Boolean result) {
        uDialog.dismiss();            
        Log.d("TAG","UDialog Should be dismissed");
        super.onPostExecute(result);            
    }

EDIT:

ok, I think you should call this code

if(v.getId() == R.id.NoButton){
            File file = new File(path);
            boolean deleted = false;
            deleted = file.delete();
            Log.d("TAG", Boolean.toString(deleted));
            Intent intent = new Intent(ShowVideo.this, CaptureVideo.class);
            startActivity(intent);
        }

in the onPostExecute trigger, because it's executed without waiting the AsyncTask to finish. This means you will have to pass the value of the v.getId() so you can achive the same functionality.

mihail
  • 2,173
  • 19
  • 31
  • but this refers to the other option, a button if the user wants to re-record the video. Why should i put it in onPostExecute? – Brindarmor May 16 '13 at 15:40
  • ahh, sorry, I didn't notice that there are different ids. Ignore the edit. Anyway, there is something that finishes your activity (Context) from which you are calling the Dialog. – mihail May 17 '13 at 07:25