问题
I have a form in my site that allows the user to upload a photo. My android app uses WebView to allow users access the site. On click of the upload button the app allows the user to choose between an image already existing in the gallery or take a new photo and upload that image. The code I have used for this is
showAttachmentDialog is called by the openFileChooser
private void showAttachmentDialog(ValueCallback<Uri> uploadMsg) {
this.mUploadMessage = uploadMsg;
File imageStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyApp");
// Create the storage directory if it does not exist
if (! imageStorageDir.exists()){
imageStorageDir.mkdirs();
}
File file = new File(imageStorageDir + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg");
this.imageUri= Uri.fromFile(file);
final List<Intent> cameraIntents = new ArrayList<Intent>();
final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
final PackageManager packageManager = getPackageManager();
final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);
for(ResolveInfo res : listCam) {
final String packageName = res.activityInfo.packageName;
final Intent intent = new Intent(captureIntent);
intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
intent.setPackage(packageName);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
cameraIntents.add(intent);
}
// mUploadMessage = uploadMsg;
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
Intent chooserIntent = Intent.createChooser(intent,"Image Chooser");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{}));
this.startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
}
My onActivityResult
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == FILECHOOSER_RESULTCODE) {
if (null == this.mUploadMessage) {
return;
}
Uri result;
if (resultCode != RESULT_OK) {
result = null;
} else {
result = intent == null ? this.imageUri : intent.getData(); // retrieve from the private variable if the intent is null
}
this.mUploadMessage.onReceiveValue(result);
this.mUploadMessage = null;
}
}
I would like to be able to change the size of the image before I upload it and I want this to be done on the phone , not in the webpage. I also want to delete the resized image from the phone when this is done and keep the prototype. Could you suggest me a way to do this? I show several cases in SO where it is suggested to create a bitmap and resize it in the desired size with createScaledBitmap but I am not sure which is the best way to do this in my case. Where should this take place? In my onActivityResult? Thanks in advance!
--------------------EDIT----------------------
private File imageStorageDir,file;
I declared these in my main Activity and added the following snippet in my onActivityResult
String newPath=file.getAbsolutePath();
Bitmap bMap= BitmapFactory.decodeFile(newPath);
Bitmap out = Bitmap.createScaledBitmap(bMap, 150, 150, false);
File resizedFile = new File(imageStorageDir, "resized.png");
OutputStream fOut=null;
try {
fOut = new BufferedOutputStream(new FileOutputStream(resizedFile));
out.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
bMap.recycle();
out.recycle();
} catch (Exception e) { // TODO
}
Now the image is being resized and uploaded when taking a photo with the camera but when I am using the gallery I get a NullPointerException
05-23 10:12:50.354: E/BitmapFactory(1376): Unable to decode stream: java.io.FileNotFoundException: /storage/sdcard/Pictures/MyApp/IMG_1400854361171.jpg: open failed: ENOENT (No such file or directory)
05-23 10:12:50.364: D/AndroidRuntime(1376): Shutting down VM
05-23 10:12:50.414: W/dalvikvm(1376): threadid=1: thread exiting with uncaught exception (group=0x41465700)
05-23 10:12:50.494: E/AndroidRuntime(1376): FATAL EXCEPTION: main
05-23 10:12:50.494: E/AndroidRuntime(1376): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { dat=content://media/external/images/media/76 }} to activity {com.example.sinatra19/com.example.sinatra19.Sinatra22Activity}: java.lang.NullPointerException
05-23 10:12:50.494: E/AndroidRuntime(1376): at android.app.ActivityThread.deliverResults(ActivityThread.java:3367)
05-23 10:12:50.494: E/AndroidRuntime(1376): at android.app.ActivityThread.handleSendResult(ActivityThread.java:3410)
05-23 10:12:50.494: E/AndroidRuntime(1376): at android.app.ActivityThread.access$1100(ActivityThread.java:141)
05-23 10:12:50.494: E/AndroidRuntime(1376): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1304)
05-23 10:12:50.494: E/AndroidRuntime(1376): at android.os.Handler.dispatchMessage(Handler.java:99)
05-23 10:12:50.494: E/AndroidRuntime(1376): at android.os.Looper.loop(Looper.java:137)
05-23 10:12:50.494: E/AndroidRuntime(1376): at android.app.ActivityThread.main(ActivityThread.java:5103)
05-23 10:12:50.494: E/AndroidRuntime(1376): at java.lang.reflect.Method.invokeNative(Native Method)
05-23 10:12:50.494: E/AndroidRuntime(1376): at java.lang.reflect.Method.invoke(Method.java:525)
05-23 10:12:50.494: E/AndroidRuntime(1376): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
05-23 10:12:50.494: E/AndroidRuntime(1376): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
05-23 10:12:50.494: E/AndroidRuntime(1376): at dalvik.system.NativeStart.main(Native Method)
05-23 10:12:50.494: E/AndroidRuntime(1376): Caused by: java.lang.NullPointerException
05-23 10:12:50.494: E/AndroidRuntime(1376): at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:482)
05-23 10:12:50.494: E/AndroidRuntime(1376): at com.example.sinatra19.Sinatra22Activity.onActivityResult(Sinatra22Activity.java:158)
05-23 10:12:50.494: E/AndroidRuntime(1376): at android.app.Activity.dispatchActivityResult(Activity.java:5322)
05-23 10:12:50.494: E/AndroidRuntime(1376): at android.app.ActivityThread.deliverResults(ActivityThread.java:3363)
05-23 10:12:50.494: E/AndroidRuntime(1376): ... 11 more
-----------------------EDIT2------------------------
This snipet
String newPath=getRealPathFromURI(getApplicationContext(), result);
Bitmap bMap= BitmapFactory.decodeFile(newPath);
Bitmap out = Bitmap.createScaledBitmap(bMap, 150, 150, false);
File resizedFile = new File(imageStorageDir, "resize.png");
OutputStream fOut=null;
try {
fOut = new BufferedOutputStream(new FileOutputStream(resizedFile));
out.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
bMap.recycle();
out.recycle();
} catch (Exception e) { // TODO
}
this.mUploadMessage.onReceiveValue(Uri.fromFile(resizedFile));
this.mUploadMessage = null;
calling
public String getRealPathFromURI(Context context, Uri contentUri) {
Cursor cursor = null;
try {
String[] proj = { MediaStore.Images.Media.DATA };
cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
works when the user chooses photo from gallery and crashes when taking photo from camera. I need the way to combine them
回答1:
Well all it needed was an if statement to check what method the user chose. file is created in the showAttachmentDialog and so the private imageUri allways has the Uri of that file. When the user chooses the camera option result also has that values whereas when he chooses gallery result has the Uri of the image chosen from the galery
if(result==this.imageUri){
newPath=file.getAbsolutePath();}
else{
newPath=getRealPathFromURI(getApplicationContext(), result);}
The final code is
@Override
//Receives the results of startActivityFromResult
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
String newPath;
if (requestCode == FILECHOOSER_RESULTCODE) {
if (null == this.mUploadMessage) {
return;
}
Uri result;
if (resultCode != RESULT_OK) {
result = null;
} else {
result = intent == null ? this.imageUri : intent.getData(); // retrieve from the private variable if the intent is null
Log.e("result",result.toString() );
Log.e("intent",this.imageUri.toString() );
}
if(result==this.imageUri){
newPath=file.getAbsolutePath();}
else{
newPath=getRealPathFromURI(getApplicationContext(), result);}
Bitmap bMap= BitmapFactory.decodeFile(newPath);
Bitmap out = Bitmap.createScaledBitmap(bMap, 150, 150, false);
File resizedFile = new File(imageStorageDir, "resize.png");
OutputStream fOut=null;
try {
fOut = new BufferedOutputStream(new FileOutputStream(resizedFile));
out.compress(Bitmap.CompressFormat.PNG, 100, fOut);
fOut.flush();
fOut.close();
bMap.recycle();
out.recycle();
} catch (Exception e) { // TODO
}
this.mUploadMessage.onReceiveValue(Uri.fromFile(resizedFile));
this.mUploadMessage = null;
//resizedFile.delete();
}
}
public String getRealPathFromURI(Context context, Uri contentUri) {
Cursor cursor = null;
try {
String[] proj = { MediaStore.Images.Media.DATA };
cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
来源:https://stackoverflow.com/questions/23813604/resize-image-taken-from-gallery-or-camera-before-being-uploaded