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)
Related
i am using afilechooser for this purpose . and this is by default programmed to choose the items inside the folder and get you the path that is selected by the user.
but i want to use this as folder chooser where the user choose a location from internal memory of android device and then the app will save the file at that location.
so how do i do it.
the code i am using for this purpose is-
private void showChooser() {
// Use the GET_CONTENT intent from the utility class
Intent target = FileUtils.createGetContentIntent();
// Create the chooser Intent
Intent intent = Intent.createChooser(
target, getString(R.string.chooser_title));
try {
startActivityForResult(intent, REQUEST_CODE);
} catch (ActivityNotFoundException e) {
// The reason for the existence of aFileChooser
}
}
and i suspect the code can be changed to choose the folder instead of files. any suggestion can be helpful . please suggest if any other way to achieve what is want .
thank you
Looking at the github project in the url you posted, it doesn't look like this can be achieved. My claim is based on the following piece of code inside com.ipaulpro.afilechooser.FileChooserActivity class:
#Override
public void onFileSelected(File file) {
if (file != null) {
if (file.isDirectory()) {
replaceFragment(file);
} else {
finishWithResult(file);
}
} else {
Toast.makeText(FileChooserActivity.this, R.string.error_selecting_file,
Toast.LENGTH_SHORT).show();
}
}
just look at the if(file.isDirectory()) statement.
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" />
Hi I am fairly an amateur at android so I might not be realizing something obvious.
I have a method that populates a global File Array variable with a list of flies in a specific directory. Problem is everything works fine if the directory has been made before by using my app to save a file there however when the user hasn't done that an error message is suppose to pop up saying they haven't saved a file yet.
I do a check if the directory exist but the app crashes when the directory has not been created.
This is what my code looks like any assistance would be appreciated
private void getTemplates()
{
//Gets file directory for saved templates
File finalMarkTemplateDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Final Mark Templates");
//Checks if path exists in other word if any templates have been saved before
if(finalMarkTemplateDir.exists())
{
templatePaths = finalMarkTemplateDir.listFiles();
}
else
{
Toast.makeText(this, "No previous templates have been saved.", Toast.LENGTH_LONG).show();
setResult(RESULT_CANCELED);
finish();
}
}
I am too an amateur, you have not created a file in your code, calling a new file() method does not create a file. Pls check that out
try {
finalMarkTemplateDir.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I managed to solve my problem when I call the setResult and finish methods I did not realize the flow of the program is returned to my onCreate method which meant the rest of my method calls in onCreate was still being called and they require the templatePaths array.
So basically I thought finish would stop the processing and move back to the calling class(using startActivityForResult). Instead I now call finish from my onCreate and use a boolean to determine if I could successfully access the directory.
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//setContentView(R.layout.dialog_load_template);
boolean fileLoadStatus = getTemplates();
if(fileLoadStatus)
{
populateTemplateList(templatePaths);
}
else
{
setResult(RESULT_CANCELED);
finish();
}
}
private boolean getTemplates()
{
boolean fileLoadStatus = false;
//Gets file directory for saved templates
File finalMarkTemplateDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Final Mark Templates");
//Checks if path exists in other word if any templates have been saved before
if(finalMarkTemplateDir.isDirectory())
{
templatePaths = finalMarkTemplateDir.listFiles();
fileLoadStatus = true;
}
else
{
Toast.makeText(this, "No previous templates have been saved.", Toast.LENGTH_LONG).show();
}
return fileLoadStatus;
}
New to Android... I understand Dialogs are asynchronous. But I really can't get my head around the flow for confirming an action. Can someone please explain the flow?
I want to save a file on the sdcard. The Activity prompts the used for the filename. Then it checks to see if the file exists. If it exists, it needs to prompt the user to confirm if they want to overwrite it. Then it proceeds to erase and write the file.
I know you can't hold execution waiting for the response. How then would this common flow work in Android?
Thanks
I am not 100% it is what you are looking for, but here is a link to the Android documentation explaining how we should display Confirmation and Acknowledgement popups using the "Android standard way":
http://developer.android.com/design/patterns/confirming-acknowledging.html
I do not know the exact flow, I suppose it would depend on how the application was written. I would check for the file if it existed call the dialog windows then if the Ok/Yes/Confirm is pressed overwrite the file.
Dialogs | Android Developers - Has an excellent code example
public class FireMissilesDialogFragment extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage(R.string.dialog_fire_missiles)
.setPositiveButton(R.string.fire, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// FIRE ZE MISSILES! AKA Overwrite your file.
}
})
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog AKA do nothing
}
});
// Create the AlertDialog object and return it
return builder.create();
}
}
I know it's slightly silly example but basically check for the file (if exist) > Call Dialog (if yes)> Overwrite.
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.