I am trying to save a value as a string on the device's internal memory so that it can be accessed when the app is closed and reopened by clicking another button. When I run the program, I enter values for inputs A and B, and I know it processes them through the calculations because I modified it so that it displays the answer as soon as it is calculated.
But on this version, if I click the save button, and subsequently click the Access button to show the answer and the textview labeled Previous Answer, it simply shows "xx" which is the initial value of the string I'm trying to save. So either it doesnt store the updated version which includes the answer, or the Access button is only able to access the original value of the string.
Button jSave = (Button) findViewById(R.id.iSave);
Button jAccess = (Button) findViewById(R.id.iAccess);
final String saveName="Name";
final String saveValue = "xx";
jSave.setOnClickListener(
new Button.OnClickListener(){
public void onClick(View v){
//Calculations. These are a part of a more complex series of
//calculations between several classes, but I've simplified it
//somewhat for this post.
EditText jInputA = (EditText)findViewById(R.id.iInputA);
double dInputA = Double.parseDouble(jInputA.getText().toString());
EditText jInputB = (EditText)findViewById(R.id.iInputB);
double dInputB = Double.parseDouble(jInputB.getText().toString());
double myAnswer = Double.parseDouble(ProfileCalculations.functionQ(jInputA, jInputB));
//Update the value of saveValue to match that of myAnswer
final String saveValue = "The answer is " myAnswer;
//Save saveValue as a string under file saveName
try{
FileOutputStream jFOS = openFileOutput(saveName, Context.MODE_PRIVATE);
jFOS.write(saveValue.getBytes());
jFOS.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(Profile.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Profile.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
);
jAccess.setOnClickListener(
new Button.OnClickListener() {
public void onClick(View v) {
try {
FileInputStream jFIS = openFileInput(saveName);
jFIS.read(saveValue.getBytes());
jFIS.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(Profile.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Profile.class.getName()).log(Level.SEVERE, null, ex);
}
TextView jPreviousAns = (TextView) findViewById(R.id.iPreviousAns);
jPreviousAns.setText(saveValue + "");
}
}
);
How about shared preferences? Here's an example.
private SharedPreferences defaultPrefs;
defaultPrefs = PreferenceManager.getDefaultSharedPreferences(this);
String url = "http://www.example.com";
SharedPreferences.Editor ed = defaultPrefs.edit();
ed.putString("homepage", url);
ed.commit();
And, later:
String url = defaultPrefs.getString("homepage", "http://www.example.com/some_default_page");
Android provides several options for you to save persistent application data. The solution you choose depends on your specific needs, such as whether the data should be private to your application or accessible to other applications (and the user) and how much space your data requires.
Your data storage options are the following:
Shared Preferences
Store private primitive data in key-value pairs.
Internal Storage
Store private data on the device memory.
External Storage
Store public data on the shared external storage.
SQLite Databases
Store structured data in a private database.
Network Connection
Store data on the web with your own network server.
For your given application of this, I would imagine that Shared Preferences or Internal Storage would be the way to go.
Internal Storage: Using this route, you would have to call openFileOutput() to start a FileOutputStream, and from there use write() to write data to the file, and close() to close the FileOutputStream.
Ex:
String FILENAME = "hello_file";
String string = "hello world!";
//Initiate
FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
//Write to file
fos.write(string.getBytes());
//Close file
fos.close();
Shared Preferences: If you are to use this, then you must call edit() to get a SharedPrefrencesEditor, and then to add values to this, you would simply use putBoolean(), putString(), etc. Once you're finished you commit the data using commit().
Ex:
//Initiate Shared Preferences
SharedPreferences.Editor editor = settings.edit();
//Writes data
editor.putBoolean("silentMode", mSilentMode);
// Commit the edits!
editor.commit();
(Source)
Related
Im trying to add jsonObject to an existing JSON file in "raw" folder.
Every time the button pressed it should add to the JSON file two new variables from the plainText input. I cant figure out how to do that because I cant properly get the path of the "raw" folder.
the code that I wrote without the "adding to JSON" part
public void submit(View view) {
EditText editAmount;
EditText editReason;
Log.d("Smth", "Submit!");
editAmount = (EditText)findViewById(R.id.editAmount);
editReason = (EditText)findViewById(R.id.editReason);
String amount = editAmount.getText().toString();
String date = "18.02.2023";
String reason = editReason.getText().toString();
Log.d("Smth", amount);
Log.d("Smth", reason);
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("amount", amount);
jsonObject.put("reason", reason);
jsonObject.put("date", "18.02.2023");
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
I have tried a lot of other solutions on StackOverFlow, but all of them give me errors.
I hope you will help me with this problem of editing JSON file) Thank you
My Database Adapter Class
public class DatabaseAdapter {
// Declare a DatabaseHelper object reference
DatabaseHelper helper;
// Declare a SQLiteDatabase object reference.
SQLiteDatabase db;
// SQLiteDatabase class has methods to create, delete, execute SQL commands and perform other common database
// management tasks.
// Define an ArrayList of Term object.
ArrayList<Term> termsList = new ArrayList<Term>();
// What is Term?
// You'll create a Term class to contain and model the information and make it more easy to implement.
// Define the constructor for DatabaseAdapter
public DatabaseAdapter(Context context){
// Instantiate helper
helper = new DatabaseHelper(context);
// Call getWritableDatabase() method on helper. This is going to give you an object of SQLiteDatabase. Store that in db.
db = helper.getWritableDatabase();
// Now, this SQLiteDatabase object, db, is going to represent the database you have and you are going to use that object
// to perform the different queries that you want to do, for example, insert, update or delete from database.
}
// Define a method to close the database
public void close() {
helper.close();
}
public int deleteData(long id) {
// Define the whereArgs String array
String whereArgs[] = {""+id};
// Call delete() method on db
return db.delete(DatabaseHelper.TABLE_NAME, DatabaseHelper.KEY_ID + "=?", whereArgs);
// delete() returns the number of rows deleted as an integer.
}
public int updateTermFullForm(long id, String meaning) {
// To update the database, you need to create an object of the class called ContentValues that acts like a map, inside which you can
// put your key-value pairs.
// Here, what is expected is the name of the key that you give here is the name of the column in your table
// and the value you want to put inside the column goes in the second parameter.
ContentValues contentValues = new ContentValues();
contentValues.put(DatabaseHelper.KEY_MEANING, meaning);
// You need to create whereArgs[] array. whereArgs[] is just an array that contains the values that are substituted inside the
// question mark (?) of whereClause at run-time, when you are executing the query.
// whereArgs[] is going to contain the values for against you want to compare.
String whereArgs[] = {""+id};
// Call update() method on db
return db.update(DatabaseHelper.TABLE_NAME, contentValues, DatabaseHelper.KEY_ID + "=?", whereArgs);
// update() returns the number of rows affected as an integer.
// The plain sql statement for this can be:
// UPDATE ct SET full_form="New Value" WHERE _id=2
}
public long insertTerm(String words, String meaning) {
// Define a new ContentValues object
ContentValues contentValues = new ContentValues();
// Add term and fullForm into that
contentValues.put(DatabaseHelper.KEY_WORDS, words);
contentValues.put(DatabaseHelper.KEY_MEANING, meaning);
// Call insert() method on db object and return
return db.insert(DatabaseHelper.TABLE_NAME, null, contentValues);
}
// Next, define a method that returns an ArrayList of specific Term objects where the term starts with the String in parameter.
public ArrayList<Term> getSomeTerms(String termStartsWith){
// Call query() method on db and store the returned cursor.
Cursor cursor = db.query(DatabaseHelper.TABLE_NAME, new String[]{DatabaseHelper.KEY_ID, DatabaseHelper.KEY_WORDS,
DatabaseHelper.KEY_MEANING}, DatabaseHelper.KEY_WORDS + " like '"
+ termStartsWith + "%'",null,null,null,null);
// Here, % is a wildcard character which indicates 0 or any number of characters. So, there can be any number of characters
// after “A”, or "B" or "S" etc.
// The plain sql statement for this can be:
// SELECT * FROM ct WHERE terms LIKE 'A%';
// Use a while loop to traverse the database and populate the ArrayList of Term objects
while (cursor.moveToNext()){
// Get the database column index or position by passing the column name
int index1 = cursor.getColumnIndex(DatabaseHelper.KEY_ID);
// Now, get the value of id for that cell
long id = cursor.getInt(index1);
// Do the same thing to get values from other two columns
int index2 = cursor.getColumnIndex(DatabaseHelper.KEY_WORDS);
String words = cursor.getString(index2);
int index3 = cursor.getColumnIndex(DatabaseHelper.KEY_MEANING);
String meaning = cursor.getString(index3);
// Create a Term object from database values
Term term = new Term(id, words, meaning);
// Add the Term object to termsList
termsList.add(term);
}
// return termList
return termsList;
}
// For managing all the operations related to the database, a helper class has been provided by Android
// and it is called SQLiteOpenHelper.
// It takes care of opening the database if it exists, creating it if it does not exists, and upgrading it as necessary.
// So, inside DatabaseAdapter you'll create a static inner class that extends SQLiteOpenHelper.
private static class DatabaseHelper extends SQLiteOpenHelper{
// Define some private static final String variables to store information related to the database
private static final String DATABASE_NAME ="Test.db";
// Database name must be unique within an app, not across all the apps.
private static final String TABLE_NAME = "words";
// When you do change the structure of the database change the version number from 1 to 2
private static final int DATABASE_VERSION = 7;
static final String KEY_ID = "id";
static final String KEY_WORDS = "words";
static final String KEY_MEANING = "meaning";
private Context context;
// Define the constructor
public DatabaseHelper(Context context){
super(context, DATABASE_NAME, null, DATABASE_VERSION);
// Store the context received from constructor into this class's context variable
this.context = context;
}
// Since, you're not creating or upgrading the database since you're using a pre-created database file
// copied to the right location, you don't need to write any code inside onCreate() or onUpgrade().
#Override
public void onCreate(SQLiteDatabase db) {
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
}
My PreCreate Database Class
public class PreCreateDB {
static String destPath;
static String destPathwithFilename;
// Lets define copyDB() method
public static void copyDB(Context context){
// Defile two String variables containing path upto "database" folder and "CTDB" file respectively
destPath = "/data/data/" + context.getPackageName() + "/databases";
destPathwithFilename = destPath+"/Test.db";
// Create two File objects from those Strings
File fPath = new File(destPath);
File fPathWithName = new File(destPathwithFilename);
// Now, the question is, why we created two separate File objects?
// It's because in some devices databases folder will be automatically created by Android system.
// In some other devices it won't be there by default.
// So, we need to check if it's not present in the device.
if(!fPath.exists()){
// If true, you'll create the databases folder
fPath.mkdirs();
// And then copy the CTDB Database file from assets folder to databases folder.
// You'll define a method named rawCopy that takes an InputStream and an OutputStream.
// This method will copy the file.
try {
rawCopy(context.getAssets().open("Test.db"), new FileOutputStream(destPath+"/Test.db"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void rawCopy(InputStream inputStream, OutputStream outputStream) throws IOException {
// To copy 1k bytes at a time, create a byte array of size 1024
byte[] buffer = new byte[1024];
// Declare an integer variable to store the total number of bytes read from the buffer.
int length;
// If you call read() method on inputStream object and pass buffer as parameter, it will read 1024 bytes at a time.
// It returns -1 if there is no more data because the end of the stream has been reached.
// Using this information you use a while loop to read from the inputStream and write to the outputStream.
// This copies the database file CTDB from assets folder to data/data/[package-name]/databases folder.
while((length = inputStream.read(buffer)) > 0){
outputStream.write(buffer, 0, length);
}
// Close the input and output streams once you're done
inputStream.close();
outputStream.close();
}
public static void resetDB(Context context) {
// Call rawCopy() inside try block
try {
rawCopy(context.getAssets().open("Test.db"), new FileOutputStream(destPathwithFilename));
} catch (IOException e) {
e.printStackTrace();
}
}
}
MY Show Term Class
public class ShowTerm extends AppCompatActivity {
// Declare a DatabaseAdapter object reference
static DatabaseAdapter databaseAdapter;
// Declare a RecyclerView object reference
static RecyclerView rvTerms;
// Declare an Adapter object reference
TermsAdapter termsAdapter;
// Declare a LayoutManager object reference
RecyclerView.LayoutManager layoutManager;
// Define an ArrayList of type Term
static ArrayList<Term> termsList = new ArrayList<>();
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.show_term);
// Get the received String from Intent
String termStartsWith = getIntent().getStringExtra("termStartsWith");
// Instantiate DatabaseAdapter class and pass this for the Context
databaseAdapter = new DatabaseAdapter(this);
// Call getSomeTerms() on databaseAdapter object and store the returned ArrayList in
// termsList
termsList = databaseAdapter.getSomeTerms(termStartsWith);
// Obtain a handle for the RecyclerView
rvTerms = findViewById(R.id.rvTerms);
// You may use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
rvTerms.setHasFixedSize(true);
// Instantiate the linear layout manager
layoutManager = new LinearLayoutManager(this);
// Set the layout with RecyclerView
rvTerms.setLayoutManager(layoutManager);
// Create an instance of TermsAdapter. Pass context, termsList and the
// RecyclerView to the constructor
termsAdapter = new TermsAdapter(this, termsList, rvTerms);
// Finally, attach the adapter with the RecyclerView
rvTerms.setAdapter(termsAdapter);
}
}
My Bengali + Hindi Mix Sqlite Database
MainActivity Ui
This Sqlite query giving blank results for Hindi words but English words are showning Properly
My MainActivity Class
public class MainActivity extends AppCompatActivity {
// Store the text to be shared in a String
String shareBody = "Download CTD App now and know about all the important Computer Terms and their Full Forms: \n" +
"https://play.google.com/store/apps/details?id=com.sandipbhattacharya.computertermsdictionary";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create a class containing static methods to copy the database file
// from assets folder into: data/data/package-name/databases folder, from where the app can access it.
// Lets name it PreCreateDB.
// From MainActivity, call the copyDB method of PreCreateDB and pass "this" for Context
PreCreateDB.copyDB(this);
}
public void show(View view) {
// We have set a text with every button. This text simply contains an alphabet.
// Get the clicked Button's text and store in a String variable
String termStartsWith = ((Button) view).getText().toString().trim();
// Create an Intent to go to another Activity where you can show all the Terms that start with a letter termStartsWith contains
Intent intent = new Intent(this, ShowTerm.class);
// Set termStartsWith with the Intent object as Extra
intent.putExtra("termStartsWith", termStartsWith);
// Start the Activity with the Intent
startActivity(intent);
// Create the ShowTerm class.
}
public void reset(View view) {
// You'll use Android AlertDialog to ask the user about his/her choice to continue or discontinue the reset operation.
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Resetting will delete all your personal data. Proceed?");
builder.setCancelable(true);
builder.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Here, you call a method and pass MainActivity.this as context,
// to replace the database file from assets folder to databases folder.
PreCreateDB.resetDB(MainActivity.this);
}
});
builder.setNegativeButton("No",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
public void addNew(View view) {
// You'll use an Intent to go to AddNew Activity
Intent intent = new Intent(this, AddNew.class);
startActivity(intent);
}
public void rate(View view) {
// Create an Intent that opens a URL in Google Play
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://play.google.com/store/apps/details?id=" + getPackageName()));
// As you configure this intent, pass "com.android.vending" into Intent.setPackage() so that users see your app's details
// in the Google Play Store app instead of a chooser. Make sure your emulator has pre-installed Play Store app.
intent.setPackage("com.android.vending");
// Start the Activity
try {
startActivity(intent);
}catch (ActivityNotFoundException e) {
Toast.makeText(this, "Couldn't launch Play Store", Toast.LENGTH_LONG).show();
}
}
public void shareApp(View view) {
// Create a send Intent
Intent sendIntent = new Intent(Intent.ACTION_SEND);
// Set the Sharing Type
sendIntent.setType("text/plain");
// Pass your sharing content using the putExtra() method of the Intent
sendIntent.putExtra(Intent.EXTRA_SUBJECT, "Share CTD App");
sendIntent.putExtra(Intent.EXTRA_TEXT, shareBody);
// Next, instruct Android system to let the user choose their sharing medium
startActivity(Intent.createChooser(sendIntent, "Share using"));
// This will pass the sendIntent along with a title to be displayed at the top of the chooser.
// When the user chooses an application from the list, your share content will be passed to that application,
// where he/she will be able to edit the content before sending it if they wish to do so.
}
}
Please Help me because im beginner in android development and it is very important for my dictionary app 🙏
Solved the problem, in Sqlite database your table creation rules are also important when using external database.
In my app, I have a database of objects that are generated by the user and then saved to the internal storage using shared prefs when the user leaves the app. Now when the user re-opens the app, that data is retrieved and presented to the user for further editing. I noticed that when I roll out an update to my app and the user installs it, all the data is lost. I tried retrieving it by saving the app's current version code using shared prefs and then comparing it to the current one in order to know when it's an app update and then i call the Read & Write data methods to retrieve the old data but with no luck. Any ideas on how i should approach this issue?
SerializeGLB.java:
public class SerializeGLBData {
/**
* Writes the Global User Box's cardList to the user's internal storage using the Gson
* library so that the user doesn't lose his/her data.
* #param cardList The list to write to the internal storage
* #param context Getting the app's current context
*/
public static void Write(ArrayList<Card> cardList, Context context) {
SharedPreferences appPrefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = appPrefs.edit();
Gson gson = new Gson();
String cardsGLBJson = gson.toJson(cardList);
editor.putString("cardsGLB",cardsGLBJson);
editor.apply();
editor.commit();
Log.d("WriteData","Data written successfully!");
}
/**
* Reads the cards list that gets saved when the app closes
* #param context Get the app's current context
* #return Returns an ArrayList of Card Objects containing the card info
*/
public static ArrayList<Card> ReadCards(Context context) {
SharedPreferences appPrefs = PreferenceManager.getDefaultSharedPreferences(context);
Gson gson = new Gson();
String cardsGLBJson = appPrefs.getString("cardsGLB","");
Type type = new TypeToken<ArrayList<Card>>(){}.getType();
return gson.fromJson(cardsGLBJson,type);
}
}
private void checkForFirstRun() {
final String PREF_VERSION_CODE_KEY = "version_code";
final int DOESNT_EXIST = -1;
// Get current version code
int currentVersionCode = BuildConfig.VERSION_CODE;
// Get saved version code
SharedPreferences prefs = getSharedPreferences(PREFS_NAME,MODE_PRIVATE);
int savedVersionCode = prefs.getInt(PREF_VERSION_CODE_KEY, DOESNT_EXIST);
// Check for first run or upgrade
if(currentVersionCode == savedVersionCode) {
// This is just a normal run
Log.d("RUN_TYPE:" , "Normal Run");
} else if(savedVersionCode == DOESNT_EXIST) { // This is a new install(or the user cleared the shared prefs)
CallWriteDataMethods(this);
Log.d("RUN_TYPE:", "New Install");
// Showing the tutorial page when the app starts for the first time
Intent tutorialIntent = new Intent(this, Tutorial.class);
startActivity(tutorialIntent);
UsernameDialog dialog = new UsernameDialog();
dialog.setCancelable(false);
dialog.show(getFragmentManager(),"USERNAME_DIALOG");
} else if(currentVersionCode > savedVersionCode) { // This is an upgrade
CallWriteDataMethods(this);
Log.d("RUN_TYPE:","Update");
}
// Update the shared prefs with the current version code
prefs.edit().putInt(PREF_VERSION_CODE_KEY,currentVersionCode).apply();
return;
}
public static void CallWriteDataMethods(Context context) {
// Write all the -empty- data from GlobalDataHolder to the internal memory to avoid a first time read error
SerializeGLBData.Write(GlobalDataHolder.cards,context);
// Write all the -empty- data from JPDataHolder to the internal memory to avoid a first time read error
SerializeJPData.Write(JPDataHolder.cards,context);
}
/**
* Calls every available Read method to retrieve all available data from the GLB database
*/
public static void callReadDataMethodsGLB(Context context) {
GlobalDataHolder.cards = SerializeGLBData.ReadCards(context);
Log.i("Read Methods[GLB]", "ReadMethods called!");
}
/**
* Calls every available Read method to retrieve all available data from the JP database
*/
public static void callReadDataMethodsJP(Context context) {
JPDataHolder.cards = SerializeJPData.ReadCards(context);
Log.i("Read Methods[JP]", "ReadMethods called!");
}
How does your SerializeGLBData.Write function works? Because by reading your code, when you are in the case of an upgrade, you are only calling the CallWriteDataMethods directly, and according to your comment in it:
// Write all the -empty- data from GlobalDataHolder to the internal memory to avoid a first time read error
You are writing the memory with empty data. Are your writing functions checking if data exists before putting empty data in it?
So something like
if(!prefs.contains("your_data_key")) {
// your code to add data
}
I have two different app,i have user database in backend,if any user loged in one app,he can also login in the another app without pressing login,just like facebook,how can i implement SSO in app?
You can do that using Content Provider also you can do the same using Shared preferences
Using Shared preferences here is the example:
Call this method when user logged in one app.
public void writeSSOInfo(){
SharedPreferences prefs = getSharedPreferences("CheckSSO",Context.MODE_WORLD_READABLE);
SharedPreferences.Editor editor = prefs.edit();
if(userLoggedIn){
editor.putBoolean("isLoggedIn", true);
}else{
editor.putBoolean("isLoggedIn", false);
}
editor.commit();
}
After saving in shared memory you can access the same detail in another application using below method.
public void readSSOInfo(){
Context con;
try {
con = createPackageContext("com.app.packagename1", 0);
SharedPreferences pref = con.getSharedPreferences("CheckSSO", Context.MODE_PRIVATE);
dataShared = pref.getBoolean("isLoggedIn", false);
}
catch (Exception e) {
Log.e("Not data shared", e.toString());
}
}
My advice would be after you logged in with any of the apps, I would store a user token with in SharedPreferences between both apps. Then get it at onCreate method of the both apps like this:
String PACKAGE_NAME = "your.package";
String PREFERENCE_NAME = "user-token";
String USER_TOKEN = "";
try {
myContext = createPackageContext(PACKAGE_NAME,Context.MODE_WORLD_WRITEABLE);
SharedPreferences sharedPrefs = myContext.getSharedPreferences(PREFERENCE_NAME, Context.MODE_WORLD_READABLE);
USER_TOKEN = sharedPrefs.getString(PREFERENCE_NAME, "");
}
catch (NameNotFoundException e) {
e.printStackTrace();
}
Then check if USER_TOKEN is empty or not and if it is not I would skip to next screen and keep using same Auth token.
i created a file and when i run the program, the data is been written in to the file but when i run the program again the new data over write on old data.
i need once the program is running and gathers data, these data are writable into the file in cascade next each other without overwriting on previous data in file.
this code running successful but when i run the program again the over writing happens which i don need that, i need to save previous data in side the file and write the new data next it and soon.
public class MainActivity extends Activity {
File file;
String sdCard;
FileOutputStream fos;
OutputStreamWriter myOutWriter;
String FlieName = "Output1.txt";
EditText txtData;
Button btnWriteSDFile;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtData = (EditText) findViewById(R.id.editText1);
btnWriteSDFile = (Button) findViewById(R.id.button1);
btnWriteSDFile.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
try {
file = new File("/sdcard/Output1.txt");
file.createNewFile();
fos = new FileOutputStream(file);
String eol = System.getProperty("line.separator");
myOutWriter =new OutputStreamWriter(fos);
myOutWriter.append(txtData.getText() + eol);// write from editor
myOutWriter.close();
fos.close();
Toast.makeText(v.getContext(),"Done writing SD 'Output.txt'", Toast.LENGTH_SHORT).show();
txtData.setText("");
} catch (Exception e) {
// e.printStackTrace();
Toast.makeText(v.getContext(), e.getMessage(),Toast.LENGTH_SHORT).show();
}
}
});
}
}
First, you are calling createNewFile(). This indicates that you want to create a new file. If you do not want to create a new file, do not call createNewFile(). And, since the documentation for createNewFile() says "This method is not generally useful", you may wish to consider just getting rid of it.
Second, you need to indicate that you want to append to the existing data when you open and use that file. The standard recipe for this:
try {
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("outfilename", true)));
out.println("the text");
out.close();
} catch (IOException e) {
//oh noes!
}
The true in the second parameter to the FileWriter constructor indicates that you want to append instead of overwrite.
Third, do not hardcode paths in Android. /sdcard/Output1.txt has been poor form for years and will not work on some Android devices.
Fourth, do not clutter up the root of external storage. Hence, instead of:
file = new File("/sdcard/Output1.txt");
use:
file = new File(getExtenalFilesDir(null), "Output1.txt");
to put the file in a subdirectory unique for your own app.
Try using java.nio.Files along with java.nio.file.StandardOpenOption
try(BufferedWriter bufWriter =
Files.newBufferedWriter(Paths.get("/sdcard/Output1.txt"),
Charset.forName("UTF8"),
StandardOpenOption.WRITE,
StandardOpenOption.APPEND,
StandardOpenOption.CREATE);
PrintWriter printWriter = new PrintWriter(bufWriter, true);)
{
printWriter.println("Text to be appended.");
}catch(Exception e){
//Oh no!
}
This uses a try-with-resources statement to create a BufferedWriter using Files, which accepts StandardOpenOption parameters, and an auto-flushing PrintWriter from the resultant BufferedWriter. PrintWriter's println() method, can then be called to write to the file.
The StandardOpenOption parameters used in this code: opens the file for writing, only appends to the file, and creates the file if it does not exist.
Paths.get("path here") can be replaced with new File("path here").toPath().
And Charset.forName("charset name") can be modified to accommodate the desired Charset.