Reputation: 483
I have on fragment loaded in an activity.
Inside this fragment, i set an event onClick to a button to take a picture. I want to save this picture inside internal storage in a specific folder.
This is my fragment class, i've tried a lot of different solutions but i can't understand why mCurrentPhotoPath is created but not filled by the picture taken (SkImageDecoder::Factory returned null).
This is my fragment class (i removed some part of code)
public class Q3Fragment extends Fragment {
private OnFragmentInteractionListener mListener;
private Spinner field;
private int TAB_ID = 1;
private int Q_ID = 3;
private final static String DEBUG_TAG = "PHOTOMANAGER";
private String mCurrentPhotoPath;
private ImageView imagePreview;
private String filePath = "";
Intent takePictureIntent;
private PhotoManager pm;
public static Q3Fragment newInstance(String type) {
Q3Fragment fragment = new Q3Fragment();
Bundle args = new Bundle();
args.putString("type", type);
fragment.setArguments(args);
return fragment;
}
public Q3Fragment() {}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_q3, container, false);
/////////////
imagePreview = (ImageView) view.findViewById(R.id.q4imgPreview);
takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Button buttonPhoto = (Button) view.findViewById(R.id.q4BtnPhoto);
buttonPhoto.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
}
// Continue only if the File was successfully created
if (photoFile != null) {
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoFile));
startActivityForResult(takePictureIntent, 11);
}
}
});
/////////////
return view;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
public void onFragmentInteraction(Boolean valid,int qId);
}
@Override
public void onActivityResult(int requestCode, int resultCode,
Intent data) {
Log.d("Fragment PHOTOMANAGER","onActivityResult");
// lors du resultat de l'intent (lorsqu'on clique sur save la photo)
try {
handleSmallCameraPhoto();
} catch (IOException e) {
e.printStackTrace();
}
if(data != null) {
getActivity().getContentResolver().delete(data.getData(), null, null);
}
}
// on enregistre la photo
private void handleSmallCameraPhoto() throws IOException {
File f = new File(mCurrentPhotoPath);
Uri contentUri = Uri.fromFile(f);
if(f.exists()){
Log.d(DEBUG_TAG,"FILE EXISTS " + mCurrentPhotoPath);
}
// here the bitmap not containing picture.
Bitmap mBitmap = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), contentUri);
imagePreview.setImageBitmap(mBitmap);
filePath = saveToInternalStorage(mBitmap);
}
// methode pour sauvegarder une photo (min ou full)
private String saveToInternalStorage(Bitmap bitmapImage){
ContextWrapper cw = new ContextWrapper(getActivity().getApplicationContext());
Log.d(DEBUG_TAG,"saveToInternalStorage");
File directory = cw.getDir("imageDir_"+getArguments().getString("type"), Context.MODE_PRIVATE);
String fileName;
fileName = "q" + Q_ID + ".jpg";
// Create imageDir
File mypath = new File(directory, fileName);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.JPEG, 80, fos);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
Log.d(DEBUG_TAG,"FILE SAVED "+mypath.getAbsolutePath());
return mypath.getAbsolutePath();
}
private File createImageFile() throws IOException {
// Create an image file name
String imageFileName = "q" + Q_ID +"photo";
ContextWrapper cw = new ContextWrapper(getActivity().getApplicationContext());
Log.d(DEBUG_TAG,"saveToInternalStorage");
File directory = cw.getDir("imageDir_"+getArguments().getString("type"), Context.MODE_PRIVATE);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
directory /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
Log.d(DEBUG_TAG," createcontainer file "+mCurrentPhotoPath);
return image;
}
}
Thanks in advance for any help..
Upvotes: 1
Views: 832
Reputation: 2225
Let me mention a key concept in Android that's needed to understand why your code does not work as is. The ACTION_IMAGE_CAPTURE
intent launches another app. In this case, a camera app to do a job. The EXTRA_OUTPUT
tells the app called (i.e. the camera app) where to save the taken picture in the filesystem.
The problem is that apps may only access their own private internal storage. Thus, the camera app is not able to save the picture inside the caller's app (i.e. your app) private storage.
Note that you are calling ContextWrapper.getDir
which points to a directory in your app's private storage.
If you want to store the picture in your app's private storage you will have to temporally store the image where it's accessible by both apps and onActivityResult
copy the picture to your app's private storage.
Upvotes: 3