안드로이드 웹뷰로 파일 업로드를 구현할 경우가 있다.
웹뷰에서 "파일선택" 버튼을 누르면 안드로이드 카메라나 갤러리가 뜨도록 하는 것인데..
이 때 카메라 or 갤러리 선택버튼이 떴을 때 안드로이드 Back버튼을 누르면 동작이 취소되면서
그다음부터는 아무리 "파일선택" 버튼을 눌러도 아무런 동작을 안할 경우가 있다.
원인은 아래와 같다.
안드로이드 카메라나 갤러리 선택창일 떴을 때, 취소버튼을 누르면
onActivityResult() 메쏘드가 콜백을 받을 때 resultCode의 값이 RESULT_OK가 아니게 된다.
이렇게 RESULT_OK가 아닐 때에 대한 처리를 하지 않으면
위와 같이 카메라 or 갤러리에서의 취소버튼 후 "파일첨부" 버튼을 아무리 눌러도
mFilePathCallback이 초기화가 되어있지 않기 때문에
앱을 재실행 하지 않는 한 "파일첨부"기능이 먹통이 되는 것이다.
결론은
onActivityResult 에서 RESULT_OK와 그 외에 대한 처리를 잘 해 주어야 한다는 것!
나만 몰랐나? - _-;;
소스는 아래를 참고(빨간색)
Stackoverflow에서 해답을 찾았는데
Stackoverflow는 시간이 지나면 글이 없어져버리더라고 - _-;;
그래서 코드까지 첨부하니 참고하기 바란다.
빨간색으로 표시한 것이 문제의 코드 및 솔루션이다.
Cancel a file upload in a Webview
I implemented this solution for a file uploader in a webview. When I click on the "select file" button in the HTML, the first time it launches the "Select Source" option (like camera, gallery, documents, etc) and everything goes right. If I do it again (after doing it good), it works normally. But if I cancel this operation, pressing the Android's back button, I can't upload a file again until I restart the app. This was tested with many html file uploader forms and always I have the same problem.
This is my implementation:
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
if (resultCode == RESULT_OK) {
// This is for Android 4.4.4- (JellyBean & KitKat)
if (requestCode == FILECHOOSER_RESULTCODE) {
if (null == mUploadMessage) {
super.onActivityResult(requestCode, resultCode, intent);
return;
}
final boolean isCamera;
if (intent == null) {
isCamera = true;
} else {
final String action = intent.getAction();
if (action == null) {
isCamera = false;
} else {
isCamera = action.equals(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
}
}
Uri selectedImageUri;
if (isCamera) {
selectedImageUri = mOutputFileUri;
mUploadMessage.onReceiveValue(selectedImageUri);
mUploadMessage = null;
return;
} else {
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), intent.getData());
selectedImageUri = intent == null ? null : ImageUtility.savePicture(this, bitmap, 1400);
mUploadMessage.onReceiveValue(selectedImageUri);
mUploadMessage = null;
return;
} catch (IOException e) {
e.printStackTrace();
}
}
// And this is for Android 5.0+ (Lollipop)
} else if (requestCode == INPUT_FILE_REQUEST_CODE) {
Uri[] results = null;
// Check that the response is a good one
if (resultCode == Activity.RESULT_OK) {
if (intent == null) {
// If there is not data, then we may have taken a photo
if (mCameraPhotoPath != null) {
results = new Uri[]{Uri.parse(mCameraPhotoPath)};
}
} else {
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), intent.getData());
} catch (IOException e) {
e.printStackTrace();
}
Uri dataUri = ImageUtility.savePicture(this, bitmap, 1400);
if (dataUri != null) {
results = new Uri[]{dataUri};
}
}
}
mFilePathCallback.onReceiveValue(results);
mFilePathCallback = null;
return;
}
} else {
super.onActivityResult(requestCode, resultCode, intent);
return;
}
}
2 Answers
I found the solution. In the onActivityResult()
method is necessary give a null object to the uri callback, when the resultCode
is not RESULT_OK
@Override
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
if (resultCode == RESULT_OK) {
// This is for Android 4.4.4- (JellyBean & KitKat)
if (requestCode == FILECHOOSER_RESULTCODE) {
if (null == mUploadMessage) {
super.onActivityResult(requestCode, resultCode, intent);
return;
}
final boolean isCamera;
if (intent == null) {
isCamera = true;
} else {
final String action = intent.getAction();
if (action == null) {
isCamera = false;
} else {
isCamera = action.equals(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
}
}
Uri selectedImageUri;
if (isCamera) {
selectedImageUri = mOutputFileUri;
mUploadMessage.onReceiveValue(selectedImageUri);
mUploadMessage = null;
return;
} else {
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), intent.getData());
selectedImageUri = intent == null ? null : ImageUtility.savePicture(this, bitmap, 1400);
mUploadMessage.onReceiveValue(selectedImageUri);
mUploadMessage = null;
return;
} catch (IOException e) {
e.printStackTrace();
}
}
// And this is for Android 5.0+ (Lollipop)
} else if (requestCode == INPUT_FILE_REQUEST_CODE) {
Uri[] results = null;
// Check that the response is a good one
if (resultCode == Activity.RESULT_OK) {
if (intent == null) {
// If there is not data, then we may have taken a photo
if (mCameraPhotoPath != null) {
results = new Uri[]{Uri.parse(mCameraPhotoPath)};
}
} else {
Bitmap bitmap = null;
try {
bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), intent.getData());
} catch (IOException e) {
e.printStackTrace();
}
Uri dataUri = ImageUtility.savePicture(this, bitmap, 1400);
if (dataUri != null) {
results = new Uri[]{dataUri};
}
}
}
mFilePathCallback.onReceiveValue(results);
mFilePathCallback = null;
return;
}
} else {
//for Android 5.0+
if (mFilePathCallback != null) {
mFilePathCallback.onReceiveValue(null);
mFilePathCallback = null;
}
//for Android 4.4.4-
if (mUploadMessage != null) {
mUploadMessage.onReceiveValue(null);
mUploadMessage = null;
}
return;
}
}