我正在尝试通过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();
}
}
答案 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()
的值,以便获得相同的功能。