So I want to save whatever users write in their EditText to be saved for the next time. This exact same code works for java project but with Android project, it doesnt work.
The code is below.
The PrintWriter out = new PrintWriter("hi"); always gives the FileNotFoundException e.
In java project, this code The PrintWriter out = new PrintWriter("hi"); makes a new file with the name "hi" but android project does not produce a new file instead returns the error. It does not save the String from the EditText to be opened when the app opens up again later.
Does anyone have a solution to this problem?
public void onCreate(blablabla)
{blablabla
try {
FileReader reader = new FileReader ("hi");
Scanner in = new Scanner(reader);
String line = in.nextLine();
mEditText.setText(line);
in.close();
} catch (FileNotFoundException e) {
mEditText.setText("");
Toast.makeText(mContext, "null!!", Toast.LENGTH_SHORT).show();
}
#Override
protected void onDestroy()
{
super.onDestroy();
// The activity is about to be destroyed.
try {
PrintWriter out = new PrintWriter("hi");
out.write(mEditText.toString());
out.close();
} catch (FileNotFoundException e) {
Toast.makeText(mContext, "Can't save", Toast.LENGTH_SHORT).show();
}
}
May be Android permission problem. See http://developer.android.com/guide/topics/manifest/manifest-intro.html#perms
Or better to use SharedPreferences?
Related
I implemented a share button in my app. When I want to share, I can select a saved json data from the device and select via which way I want to share it (mail etc.). The problem is, that the data is NOT in the attachements. The problem is likely because I use the internal app storage. Therefore I want to save tje json data into the external storage, what would be better in my case anyway. But I am not really sure how to do that. I am not sure if I should use the Media type of content of the Documents and other files type of content which is provided by android. There is also the Appspecific files type but this looks like it is not applicaple for me, because I need to share the json data wit ha share functin. At the moment my code looks like this:
Save Function, which get's a file name I can choose myself
private void saveState(String name) {
File file = new File(getFilesDir(), name + ".json");
try{
OutputStream out = new FileOutputStream(file);
MyJsonWriter writer = new MyJsonWriter();
writer.writeJsonStream(out, ... //data structure);
out.close();
}catch (Exception e){
Log.e("saveState ERROR", "----------------------------------------------------");
}
}
LoadButtonClick Functin which shows me all files
public void loadStateClick(View view) {
final LinearLayout layout = new LinearLayout(MainActivity.this);
layout.setOrientation(LinearLayout.VERTICAL);
String[] files = MainActivity.this.fileList();
... //more code which is not important here
Load Function
private void loadState(String name) {
File file = new File(getFilesDir(), name);
InputStream in = null;
... //setting my data structure, not important here
try{
in = new FileInputStream(file);
MyJsonReader reader = new MyJsonReader(MainActivity.this);
SaveData savedData = reader.readJsonStream(in);
... // handling data structure, not important here
in.close();
}catch (Exception e){
Log.e("LOAD ERROR", e.toString());
}
}
I am used to opening my files in my apps using the next code:
public void openFile(#NonNull String uri) {
checkNotNull(uri);
File file = new File(uri);
String dataType = null;
if (ContentTypeUtils.isPdf(uri)) dataType = "application/pdf";
else if (ContentTypeUtils.isImage(uri)) dataType = "image/*";
if (file.exists() && dataType != null) {
Intent target = new Intent(Intent.ACTION_VIEW);
target.setDataAndType(Uri.fromFile(file), dataType);
target.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
Intent intent = Intent.createChooser(target, "Open file");
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
Log.e(TAG, "There is a problem when opening the file :(");
}
} else {
Toast.makeText(getContext(), "Invalido", Toast.LENGTH_LONG).show();
}
}
I had always used static files so this was enough, but now I am using the Google Drive SDK for Android. I possess the driveId of the file I want to open but the problem is I cannot find a clean way to open the file contents I obtain by doing this:
Drive.DriveApi.fetchDriveId(mGoogleApiClient, documentFile.getDriveId())
.setResultCallback(driveIdResult -> {
PendingResult<DriveApi.DriveContentsResult> open =
driveIdResult.getDriveId().asDriveFile().open(
mGoogleApiClient,
DriveFile.MODE_READ_ONLY,
null);
open.setResultCallback(result -> {
DriveContents contents = result.getDriveContents();
InputStream inputStream = contents.getInputStream();
// I know I can get the input stream, and use it to write a new file.
});
});
So the only thing that comes to my mind is creating a static route to create a file every time I have to open it, and erasing it every time I have to open a new file.
What I have understood up until now is that the Google Drive API for Android already saves an instance of the file so what I have in mind sounds unnecessary, I would like to know if there is a better way to achieve this. Is there a way I can open the file and do something similar to what I do with the Intent.ACTION_VIEW in a cleaner way?
Thanks in advance.
Well since it seems this will not be answered I will post what I did. All I did was create a temp file where I put my contents to be read. I still don't know if it was the best choice so this question will still be opened for a better answer.
open.setResultCallback(result -> {
DriveContents contents = result.getDriveContents();
InputStream inputStream = contents.getInputStream();
writeTempFile(inputStream);
});
And here the implementation of the `writeTempFile`:
private synchronized File writeTempFile(#NonNull InputStream inputStream) {
checkNotNull(inputStream);
File filePath = new File(mActivity.getFilesDir(), "TempFiles");
if (!filePath.exists()) filePath.mkdirs();
File file = new File(filePath, TEMP_FILE);
try {
OutputStream outputStream = new FileOutputStream(file);
IOUtils.copyLarge(inputStream, outputStream);
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);
} catch (IOException e) {
e.printStackTrace();
}
return file;
}
I have been searching the internet to find a resolution to my answer, have gone through all the documentation, and have looked through multiple forums before posting my own question on this. I need to save information through a file because my function
#Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putInt("PointCount", pointCount);
savedInstanceState.putInt("UpOneCost", upOne);
savedInstanceState.putInt("UpTwoCost", upTwo);
savedInstanceState.putInt("TimerTime", upgradeTime);
super.onSaveInstanceState(savedInstanceState);
Toast.makeText(this, "Saving", Toast.LENGTH_LONG).show();
}
onSaveInstanceState only works at specific intervals at which I'm not entirely clear on. However, I know it doesn't get called when the activity is destroyed. The function above is mySaveInstanceState function and below is my restoreInstanceState function
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Toast.makeText(this, "Restoring", Toast.LENGTH_LONG).show();
if(savedInstanceState != null){
pointCount = savedInstanceState.getInt("PointCount");
upOne = savedInstanceState.getInt("UpOneCost");
upTwo = savedInstanceState.getInt("UpTwoCost");
upgradeTime = savedInstanceState.getInt("TimerTime");
if(upgradeTime < 5500){
startTimer();
}
TextView pointCountText = (TextView)findViewById(R.id.myTextView1);
pointCountText.setText("Points: " + Integer.toString(pointCount));
TextView pointCountText2 = (TextView)findViewById(R.id.upgradeScreenPointText);
pointCountText2.setText("Points: " + Integer.toString(pointCount));
Button upButtonOne = (Button)findViewById(R.id.upButton1);
upButtonOne.setText("Cost: " + Integer.toString(upOne));
Button upButtonTwo = (Button)findViewById(R.id.upButton2);
upButtonTwo.setText("Cost: " + Integer.toString(upTwo));
TextView myTimerValue = (TextView)findViewById(R.id.myTimerValueText);
myTimerValue.setText("Current Time: " + Integer.toString(upgradeTime));
}
}
There is a bit of useless info in there but overall this doesn't run when I hit the back button on the android device, so after a bit of research, i decided I should just save it into a file directory. This is where I created a file in my android project file named "saveFile" It is a text file, and it is in the same directory as my mainActivity.java file in order to remove file scope complications. In an effort to reach this file I came to the conclusion of overriding the onDestroy() function and try
String fileName = "saveFile";
FileOutputStream outputStream;
#Override
protected void onDestroy() {
super.onDestroy();
outputStream.openFileOutput(fileName, Context.MAKE_PRIVATE);
}
At which point I was already stopped because it couldn't find the file. The documentation is not clear on where this file should go directory wise, and as far as creation and then writing it is also very vague. If anyone could give a very clear explanation as to how all of it works I would be very appreciative of it. Thank you =) Note some of the code may contain minor errors since I typed some of it instead of copy paste but the idea is there. The only error I receive in the editor is on the outputStream.openFileOutput() line, which says it can't find the file.
In order to do file operations you should specify complete file path.
Passing only the filename will throw FileNotFoundException.
You can do one of the following;
1. Save the file in app cache.
filePath = appContext.getCacheDir( ).getAbsolutePath( )+"yourFileName";
Save the file in app data directory.
filePath = Environment.getDataDirectory( ).getPath( ) + File.separator + "data" + File.separator + appContext.getPackageName( ) + File.separator+"yourFileName";
Save the file in some folder on SD card.
File sdCard = Environment.getExternalStorageDirectory( );
String filePath = sdCard.getAbsolutePath( ) + File.separator + BASE_FOLDER_ON_SD_CARD + File.separator+"yourFileName";
For the third option you may need to add WRITE_EXTERNAL_STORAGE permission in AndroidManifest.xml of your application.
Also, saving the file should happen in onStop() method of your activity and reading the file content should happen in onResume()
Use the file from stored location.
You can do like this.
private void writeToFile(String data) {
try {
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(context.openFileOutput("config.txt", Context.MODE_PRIVATE));
outputStreamWriter.write(data);
outputStreamWriter.close();
}
catch (IOException e) {
Log.e("Exception", "File write failed: " + e.toString());
}
}
private String readFromFile() {
String ret = "";
try {
InputStream inputStream = openFileInput("config.txt");
if ( inputStream != null ) {
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String receiveString = "";
StringBuilder stringBuilder = new StringBuilder();
while ( (receiveString = bufferedReader.readLine()) != null ) {
stringBuilder.append(receiveString);
}
inputStream.close();
ret = stringBuilder.toString();
}
}
catch (FileNotFoundException e) {
Log.e("login activity", "File not found: " + e.toString());
} catch (IOException e) {
Log.e("login activity", "Can not read file: " + e.toString());
}
return ret;
}
but for each object you have to create separate file with different name.
hope this will help you..
below is way to store data in android:
shared preferences(data will keep until user uninstall the app or clear the app cache in setting application manager)
sqlite(permanent storage)
create a file to store(permanent storage) or if your data doesn't need to store permanently you may just create a singleton class to store your data. the data stored will gone after user close the app.
public void Save(String fileName) {
try {
OutputStreamWriter out = new OutputStreamWriter(openFileOutput(fileName, 0));
out.write(EditText1.getText().toString());
out.close();
Toast.makeText(this, fileName + " saved!", Toast.LENGTH_SHORT).show();
} catch (Throwable t) {
Toast.makeText(this, "Exception: " + t.toString(), Toast.LENGTH_LONG).show();
}
}
I am working on an android app that need to create a text file and write in it. I use the following code:
public void onButtonClick(View view) {
writeInFile("Hello world");
}
public void writeInFile(String string) {
String dir = android.os.Environment.getExternalStorageDirectory().getAbsolutePath();
File file = new File(dir, "MyFile.txt");
try {
FileWriter fw = new FileWriter(file,true);
//fw.append(string);
fw.write(string);
Toast.makeText(this, "You wrote in the file", Toast.LENGTH_SHORT).show();
} catch(Exception e){
e.printStackTrace();
}
}
When I run the app, the file is created, I can see the toast message, but nothing in written in it. I have tried fw.append and fw.write. In my manifest I have yet written the necessary permission to write on external storage. I want to write directly in the external storage of my Samsung Galaxy Tab 4 (Marshmallow), not on the SD card.
First, always close(). You are not closing your FileWriter.
Second, always flush(). You are not flushing your FileWriter.
Third, even if you flush() and close(), due to the way buffered filesystems work, the bytes may not yet be written to disk. You're flushing from the Android app to the OS, but the writes to the disk may be buffered and delayed by the OS. To deal with this, I don't use FileWriter, but FileOutputStream (sometimes wrapped in an OutputStreamWriter), so you can call getFd().sync() on the FileOutputStream after calling flush() and before calling close().
Fourth, you won't be able to see this file and its contents in your desktop OS file manager until it gets indexed by MediaStore. Either test your results using other means (e.g., adb pull), or use MediaScannerConnection and its scanFile() method to tell the MediaStore to index your newly-created file.
The following code demonstrates everything but the MediaScannerConnection bit:
private static class SaveThread extends Thread {
private final String text;
private final File fileToEdit;
SaveThread(String text, File fileToEdit) {
this.text=text;
this.fileToEdit=fileToEdit;
}
#Override
public void run() {
try {
fileToEdit.getParentFile().mkdirs();
FileOutputStream fos=new FileOutputStream(fileToEdit);
Writer w=new BufferedWriter(new OutputStreamWriter(fos));
try {
w.write(text);
w.flush();
fos.getFD().sync();
}
finally {
w.close();
}
}
catch (IOException e) {
Log.e(getClass().getSimpleName(), "Exception writing file", e);
}
}
}
(from this sample project)
I have an android app that is writing a values to a file that the app also creates. I am able to write to the file and then again read from the file. However, as soon as that activity is finished, it seems that the file is now gone, or loses it's values.
I know you can't browse the files through explorer unless you root your phone and/or run the adb server as a specific user.
Here is my code for writing to the file:
public void savePrices(View view) {
FileOutputStream outputStream;
File getFilesDir = this.getFilesDir();
File filePathOne = new File(getFilesDir, filename);
try {
outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
for (int i = 0; i < priceArray.length; i++) {
outputStream.write(String.format("%.2f\n", priceArray[i]).getBytes());
}
Toast.makeText(this, "Prices saved successfully!", Toast.LENGTH_SHORT).show();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
Here is my code that reads the file:
public void loadPrices(View view) {
int i = 0;
final InputStream file;
BufferedReader reader;
try{
file = getAssets().open(filename);
reader = new BufferedReader(new InputStreamReader(file));
String line = reader.readLine();
while(line != null){
line = reader.readLine();
priceArray[i] = Double.parseDouble(line);
i++;
}
} catch(IOException ioe){
ioe.printStackTrace();
hamburgerPriceText.setText(String.format("%.2f", priceArray[0]));
hotDogPriceText.setText(String.format("%.2f", priceArray[1]));
chipsPriceText.setText(String.format("%.2f", priceArray[2]));
beerPriceText.setText(String.format("%.2f", priceArray[3]));
popPriceText.setText(String.format("%.2f", priceArray[4]));
Toast.makeText(this, "Prices loaded successfully!", Toast.LENGTH_SHORT).show();
}catch (NumberFormatException e) {
Log.e("Load File", "Could not parse file data: " + e.toString());
}
}
After I call the save method which sets the values in the array and saves the values to the file, I run a clear method that removes all the values on the activity fields and in the array. So when I run the read method and it populates the fields on the activity, I know the values are coming from reading the file. This is the only way that I know that I'm saving and reading from the file successfully.
My question is how do I make it permanent? If I close the activity that saves the values and then immediately run the read method, all the values are 0.
Is there something that I am missing? How can I write to a file so if the activity is closed, or the app is completely closed, I can still retain the values?
Here is my code that reads the file:
There is nothing in that code that reads a file. It is reading some stuff out of the your app's assets. Also, for some reason, it is only updating the UI if you have an exception.
So when I run the read method and it populates the fields on the activity, I know the values are coming from reading the file.
No, they are coming from your app's assets, and you are only populating the fields if you have an IOException.
My question is how do I make it permanent?
Step #1: Actually read from the file. Since you are using openFileOutput() to write to the file, use openFileInput() to read from the file.
Step #2: Update the UI when you successfully read in the data, not in the catch block for the IOException.