3

So my app has an ActionDialog which contains a blank canvas as the interface with simple cancel and save buttons. What is happening is best demonstrated in a brief illustration

Screen layout before

-(TextView)-(ImageView)-(Button)-

Then when the user presses the button the ActionDialog pops up requesting they sign. Once they sign the captured drawing is saved. Then the drawing is accessed via memory and placed where the original ImageView is with a bitmap. However this is what ends up happening

Screen Layout after

----------nothing--------------

They just disappear and I get an error in my logcat:

05-14 19:06:27.004: E/Error(25274): java.io.FileNotFoundException: /storage/emulated/0signature.png: open failed: EACCES (Permission denied)
05-14 19:06:27.004: E/BitmapFactory(25274): Unable to decode stream: java.io.FileNotFoundException: /storage/emulated/0signature.png: open failed: ENOENT (No such file or directory)

java.io.FileNotFoundException: /storage/emulated/0signature.png: open failed: ENOENT (No such file or directory)

It does not crash my program though. Anyways here is the code for the files

action dialog

public class CaptureSignature extends DialogFragment {
Sign sign;
View view;

public Dialog onCreateDialog(Bundle savedInstanceState) {

    AlertDialog.Builder capSig = new AlertDialog.Builder(getActivity());

    capSig.setView(sign = new Sign(this.getActivity(), null))
            .setMessage(R.string.store_question)
            .setPositiveButton(R.string.save,
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            try {
                                sign.setDrawingCacheEnabled(true);
                                sign.getDrawingCache()
                                        .compress(
                                                Bitmap.CompressFormat.PNG,
                                                10,
                                                new FileOutputStream(
                                                        new File(
                                                                getActivity()
                                                                        .getExternalFilesDir(
                                                                                "img"),
                                                                "signature.png")));
                            } catch (Exception e) {
                                Log.e("Error ", e.toString());
                            }
                            File mysig = new File(getActivity()
                                    .getExternalFilesDir("img"),
                                    "signature.png");
                            ImageView sig = (ImageView) getActivity()
                                    .findViewById(R.id.sig_image);
                            Bitmap bmp = BitmapFactory.decodeFile(mysig
                                    .getAbsolutePath());
                            sig.setImageBitmap(bmp);

                        }
                    })

            .setNegativeButton(R.string.cancel,
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                        }
                    });

    // Create the Dialog object and return it
    return capSig.create();
}
}

So obviously I've messed this up somewhere. If anyone has any insight I would be grateful. Thanks!

I personally think I am either saving this wrong or I'm not correctly declaring Sign, as in I call it but I don't give it a value, so the drawing cache is not actually being accessed.

Edit I have declared this in the Manifest

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

2nd Edit

showing new code and logcat, the error has changed

final edit

Thank you very much Matt Giles and JRowan, this was driving me insane. It works now and the above code is the final version.

11
  • 1
    try this::::: capSig.setView(sign = new Sign(this.getActivity(), null)) Commented May 14, 2013 at 23:02
  • 1
    do you have read_external_storage in your manifest Commented May 14, 2013 at 23:10
  • 1
    read not write, your getting permission denied to read i think Commented May 14, 2013 at 23:11
  • 1
    before sign.getDrawingCache() try to put sign.setDrawingCacheEnabled(true); Commented May 14, 2013 at 23:15
  • 1
    i got it hold on, i think i know what it is Commented May 14, 2013 at 23:24

1 Answer 1

3

The problem is the line:

new File(Environment.getExternalStorageDirectory().getPath() + "signature.png"

The call to getPath() returns a path that doesn't have a trailing '/'. Hence the file path in the error message, /storage/emulated/0signature.png instead of /storage/emulated/0/signature.png.

It would be better to use application-specific storage, instead of putting files in the sdcard root directory. Instead of the new File(...) call you have now, use:

new File(getActivity().getExternalFilesDir("img"), "signature.png")

getExternalFilesDir(name) creates a folder called "name" that's dedicated to your application. This prevents your app from cluttering up the sdcard root directory.

Sign up to request clarification or add additional context in comments.

11 Comments

No, getExternalStorageDirectory() returns the path to the sdcard root. getExternalFilesDir(someName) returns a folder on the sdcard dedicated to your application for storing files. This way the sdcard root isn't cluttered up with files.
Your welcome. You don't have to use "img" or any presets in there, the folder name can be whatever you want, and you can have multiple ones for different types of files.
Does it give the same error if you use getExternalFilesDir(...) instead? Right now it's trying to read a file called 0signature.png in the /storage/emulated folder, and your app doesn't have permission to access that (it shouldn't).
You're right, my code wasn't correct for inside your listener. The method needs to be called on the Activity object. Updated my example.
Glad that worked. Not immediately sure on the new problem, might be worth making another question with more details.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.