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.
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.
Related
Ok, so have 2 Activities in my app, that will do some stuff.
In the mainActivity before I start the second Intent, I want to create the necessary folders for my app to work correctly.
So, my code so far looks like this:
In the main activity I use this code to create my folder on the SD card, before starting the new intent :
// on click of a button
createWholePath(spinner1.getSelectedItem().toString(),"test");
// and the function
public static boolean createWholePath(String mainfolder, String subfolder){
boolean ret= true;
File wallpaperDirectory = new File(Environment.getExternalStorageDirectory()+"/"+mainfolder+"/"+subfolder);
wallpaperDirectory.mkdirs();
return ret;
}
In AndroidManifest I added the permission like:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Now I expect to see a folder created (on the device's SD card) after I click the button
But it does not happen...
What could be wrong?
Why doesn't the folder appear?
I use for debugging a real device *(Samsung Galaxy Note 2)
Thank you
UPDATE
So my problem was part of a bigger project and something went wrong somewhere else apparently. I decided to make a new empty project just to test my code and yes, it works fine outside my original project. I will investigate further. I will award the answer to the guy that tested my code and said that it works
Thank you all.
Are you sure it isn't working? Your code is working for me (after I replaced the spinner value with a constant string). Perhaps the directory is being created, just not where you're expecting it. You can see where the directory will be created using a line like:
Log.v(TAG, "wallpaperDirectory=" + wallpaperDirectory.getAbsolutePath());
try this it could be your method is not called on spinner item selection
spinner1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view,
int pos, long id) {
try{
Object item = parent.getItemAtPosition(pos);
createWholePath(item.toString(),"test");
}catch(Exception e){}
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
File wallpaperDirectory = new File(Environment.getExternalStorageDirectory(),mainfolder+"/"+subfolder);
if (!wallpaperDirectory.exists()) {
wallpaperDirectory.mkdirs();
}
and put these permission to manifiest :-
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
I'm attempting to use some code to load a basic changelog from a text file into an alert dialog. The only issue is that I am having trouble getting my code to find the location of my changelog file. The file "changelog" is located in app/src/main/. Here is a sample of my code.
private void displayChangelogDialog() {
Context context = this;
try {
new AlertDialog.Builder(this)
.setTitle("Changelog")
.setMessage(readFile(getApplicationContext().getFilesDir().getAbsolutePath() + "/app/src/main/changelog"))
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
})
.show();
} catch (IOException e) {
Toast.makeText(MainActivity.this, "Error", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
I am not very familiar with getFilesDir() or getAbsolutePath(), so I'd imagine this would be a good learning experience if anyone can help me figure out what I'm doing wrong. I'm sure the problem resides in the path I have entered, but I am a bit stumped at the moment. Thanks in advance.
getFilesDir documentation:
Returns the absolute path to the directory on the filesystem where files created with openFileOutput(String, int) are stored.
Typically, openFileOutput access to /data/data, which is completly different from your application install path.
If you want to access a file, put it in the assets folder the check the assets related functions (see AssetManaget)
I have some code that build a dialog box and makes a listener for it. The dialog box displays fine, but the code inside the listener doesn't seem to run, and I don't know why.
private void showBackgrounDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(MeacruxActivity.this);
builder.setTitle(R.string.background_dialog_title).setCancelable(true)
.setItems(R.array.background_options,
new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialog, int selection) {
Log.d(logID, "the selection is: " + selection);
if(backgrounds.length==selection){
notImplementedYet.show();
return;
}
setBckground(backgrounds[selection]);
}
});
currentDialog = builder.create();
currentDialog.show();
}
private void setBackground(String bgName) {
Log.d(logID, bgName);
}
The dialog shows up properly with all the options and everything, but when I click on one nothing come sup in the log.... Why is that?
Edit: I did some more testing and I can confirm that the code inside of the onClick function is being run, its just that the log isnt showing up...
I'm assuming you are looking in eclipse or studio
In DDMS view, make sure the device is selected.
In Logcat view, make sure there's not a filter applied.
On terminal, type adb logcat... does it show up there?
I have an application that uses data stored on the SD card, but my problem, I want to display a dialog box with error message before the application terminates. I tried to create a dialog box not in activity but in a simple class. the code that i use is unkown. for the first part and the second every thing is ok. when the SD card is installed and when i use a nexus google Tablet. I would like to have a message that their is no SDCard before that application crashed, or to start an other Activity used to tell the user that application need an Sdcard. the code that i use is given below. My application print the Log the crash when their is no SDcard.
public File getRootDirectory()
{
if (this.rootDirectory == null)
{
File sdCardRoot = MainApplication.getInstance().getSDCardRootDirectory();
if (sdCardRoot != null)
{
this.rootDirectory = sdCardRoot;
}
else if(Build.BRAND.equals("google"))
{
this.rootDirectory = Environment.getExternalStoragePublicDirectory(MainApplication.Appli_DIRECTORY);
} else {
Log.d(CLASS_TAG, " their is no carte Sd ");
/**
* I am trying to start a Fail Activity
*/
//Intent intent = new Intent(context, FailActivity.class)
//.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//context.startActivity(intent);
}
Log.i(CLASS_TAG, "Root directory set to :" + this.rootDirectory.getAbsolutePath());
}
return this.rootDirectory;
}
Try this
boolean isSDPresent = android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
if(!isSDPresent)
{
// yes SD-card is present
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage("Sorry,SD Card not Found")
.setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
}
});
builder.setCancelable(false);
// Create the AlertDialog object and return it
builder.create();
builder.show();
}
Probably you must create the alertbox in the UI Thread.
I'm trying to simply delete an image from a simple app. I have it so that when you click on the image, it'll bring up an a dialog with the option to delete it. I thought this would just be something simple, but everything I have been trying doesn't seem to be doing anything. Below is my code. Any ideas would be greatly appreciated.
delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
int id = viewIt.getId();
File file = new File("file://" + arrPath[id]+".jpg");
file.delete();
}
});
Have you added permission in manifest file ?
Any app that declares the WRITE_EXTERNAL_STORAGE permission is implicitly granted READ_EXTERNAL_STORAGE permission.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Get the path of the file required and delete the file
File file= new File(android.os.Environment.getExternalStorageDirectory()+ "/myfolder/myimage.jpg");
if(file.exists())
{
file.delete();
}