泄露了一个窗口ProgressDialog Android Dropbox

时间:2013-05-16 14:23:42

标签: android progressdialog dropbox-api

我正在尝试通过AsyncTask将文件上传到Dropbox,我得知窗口泄露错误:

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

我看了here并理解这是因为我的活动已经退出并且progressdialog仍在那里。我无法理解为什么我的活动会退出。它只是一个屏幕,按下按钮上传文件。我使用几乎相同的代码从dropbox下载文件,它完美无缺。

有什么建议吗? 提前谢谢!

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");
    }

}

这是我调用UploadFile的Activity类: 尚未使用buidSession和clearKeys方法。

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();
    }


}

2 个答案:

答案 0 :(得分:0)

试试这个,在你的构造函数中你不会得到这样的上下文:

dContext=context.getApplicationContext();

但尝试传递启动asynctask的活动

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

所以在你的构造函数中你现在只有:

dContext=context;

答案 1 :(得分:0)

super.onPostExexute(result)

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

修改

好的,我认为你应该调用这段代码

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);
        }

在onPostExecute触发器中,因为它在没有等待AsyncTask完成的情况下执行。这意味着您必须传递v.getId()的值,以便获得相同的功能。