How to save to File in android programatically - android

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();
}
}

Related

How to dynamically load a native shared libraries (.so) for NativeActivity on Android N?

I want to load custom .so dynamic for the NaticityActivity, but get error when NativeActivity.onCreate() call classLoader.findLibrary("UE4");
this is party of NativeActivity.onCreate()
BaseDexClassLoader classLoader = (BaseDexClassLoader) getClassLoader();
String path = classLoader.findLibrary(libname);
if (path == null) {
throw new IllegalArgumentException("Unable to find native library " + libname +
" using classloader: " + classLoader.toString());
}
byte[] nativeSavedState = savedInstanceState != null
? savedInstanceState.getByteArray(KEY_NATIVE_SAVED_STATE) : null;
mNativeHandle = loadNativeCode(path, funcname, Looper.myQueue(),
getAbsolutePath(getFilesDir()), getAbsolutePath(getObbDir()),
getAbsolutePath(getExternalFilesDir(null)),
Build.VERSION.SDK_INT, getAssets(), nativeSavedState,
classLoader, classLoader.getLdLibraryPath());
if (mNativeHandle == 0) {
throw new UnsatisfiedLinkError(
"Unable to load native library \"" + path + "\": " + getDlError());
}
super.onCreate(savedInstanceState);
//Hack classLoader nativeLibraryDirectories, add my .so file path
UnrealHelper.RequestPermission(this);
UnrealHelper.CopyFile(Environment.getExternalStorageDirectory().getPath() + "/libUE4.so", getFilesDir() + "/libUE4.so");
String TestA = System.mapLibraryName("gnustl_shared");
//libUE4.so
String fileName = System.mapLibraryName("UE4");
String TmpVal = "";
BaseDexClassLoader classLoader = (BaseDexClassLoader) getClassLoader();
try
{
Field pathListField = classLoader.getClass().getSuperclass().getDeclaredField("pathList");
pathListField.setAccessible(true);
Object pathListVal = pathListField.get(classLoader);
Field nativeLibPathField = pathListVal.getClass().getDeclaredField("nativeLibraryDirectories");
nativeLibPathField.setAccessible(true);
Object nativeLibPathVal = nativeLibPathField.get(pathListVal);
ArrayList nativeLibraryDirectories = (ArrayList)nativeLibPathVal;
//add my .so path to classLoader
nativeLibraryDirectories.add(getFilesDir());
//nativeLibPathField.set(pathListVal, nativeLibraryDirectories);
//pathListField.set(classLoader, pathListVal);
//ref: https://android.googlesource.com/platform/libcore-snapshot/+/ics-mr1/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
//ref: https://android.googlesource.com/platform/libcore-snapshot/+/ics-mr1/dalvik/src/main/java/dalvik/system/DexPathList.java
for (Object directory : nativeLibraryDirectories) {
File file = new File((File)directory, fileName);
if (file.exists() && file.isFile() && file.canRead()) {
//is valid
TmpVal = file.getPath();
}
}
}
catch(Exception Exp)
{
String ErrorMsg = Exp.toString();
System.out.print(ErrorMsg);
}
//test the path added, but got null
String path = classLoader.findLibrary("UE4");
You have to package your shared libraries inside your apk so that System.loadLibrary("your-lib-name") can find it. Note that System.loadLibrary will only accept library name, NOT the full path.
For System.load(), I have tried below steps, it works well. You can try on your project to see how it goes.
Step 1:
Ensure that your app permission for external storage is configured inside your manifest.xml, see below:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
And ensure you have granted those permissions.
Step 2:
Assume your downloaded .so file is at /Download/ of your external SD card, i.e. /Download/libnative-lib.so. Below code snippet will copy the libnative-lib.so to /data/data/<your-app-id>/files/libnative-lib2.so and the load this libnative-lib2.so will succeed.
String path_sd_card = Environment.getExternalStorageDirectory().getAbsolutePath();
FileOutputStream outputStream;
FileInputStream inputStream;
// 1. This path works.
//System.load("/data/data/com.arophix.jniexample/files/libnative-lib.so");
String filesDir = getFilesDir().getAbsolutePath();
try {
inputStream = new FileInputStream(new File(path_sd_card + "/Download/libnative-lib.so"));
outputStream = new FileOutputStream(new File(filesDir + "/libnative-lib2.so"));//openFileOutput("libnative-lib2.so", Context.MODE_PRIVATE);
FileChannel inChannel = inputStream.getChannel();
FileChannel outChannel = outputStream.getChannel();
inChannel.transferTo(0, inChannel.size(), outChannel);
inputStream.close();
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// This path works
System.load(filesDir + "/libnative-lib2.so");
Note: Verified on Android Emulator Nexus 6P API 23.
The SO library can be dynamically loaded on Android via System.load()
The following code successfully loads the OpenCV library and calls the SO library function to get the version number
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Copy "libopencv_java3.so" to App directory and return the full path of the SO file
String pathOpenCV = FileUtil.loadAssetFile(this, "libopencv_java3.so");
try {
System.load(pathOpenCV);
} catch (Exception e) {
android.util.Log.e("System.Load", e.toString());
}
//All version number returns correctly
int vMajor = Core.getVersionMajor_0();
int vMinor = Core.getVersionMinor_0();
int vRev = Core.getVersionRevision_0();
}
See result:
You may need to check your app permissions.

Why the txt file did not create in Android?

I am developing in Android , I found a sample code and it read and write the data to the txt file like the following code:
The following function is for writing data to text file:
private static final String MESH_DATA_FILE_NAME = "TEST.txt";
public void save(Activity activity) {
try {
int i;
Context context = activity;
FileOutputStream fos = activity.openFileOutput(MESH_DATA_FILE_NAME, context.MODE_PRIVATE);
String str;
for (i = 0; i < 10; i++) {
str += "##" + i;
}
fos.write(str.getBytes());
fos.write('\n');
fos.close();
} catch (Exception e) {
Log.e(TAG, "saveMeshInfo exception: " + e);
}
}
The following code for reading data from text file:
public void read(Activity activity) {
try {
FileInputStream fin = activity.openFileInput(MESH_DATA_FILE_NAME);
BufferedReader br = new BufferedReader(new InputStreamReader(fin));
Log.i(TAG, "From file [" + MESH_DATA_FILE_NAME + "]...");
// Read the information
String text = br.readLine();
String[] strs = text.split("##", 4 + FloodMesh.IV_LEN + FloodMesh.KEY_LEN);
fin.close();
} catch (Exception e) {
}
}
It can see the data from the log when it call read function , so the TEST.txt should be exists.
But I didn't found the TEST.txt via file manager app on my android phone.
Why I didn't found the TEST.txt file on my android phone ?
If the TEST.txt not exists , why the read function can read the data ?
How to find the TEST.txt file ?
You've created file in you app directory (/data/data/your.package) and you don't have access there via file manager. The file exists that is why you can read it via method but you won't see it. Test your code on emulator - than you will be able to see the file
If you want to test it better and you don't want to use emulator you can save file on sdcard, you have access there via file manager and you will be able to see it
your file will be in /data/data/<your package name>/files/ - either you have root and an explorer to see this or you use the run-as command on adb to explore the file
With the right permission you can also write the file to sd-card - then accessing it is easier - depends on your needs
You didn't found the TEST.txt because it's in private mode, you need to write MODE_APPEND,You should check http://developer.android.com/reference/android/content/Context.html.
activity.openFileOutput() This method opens a private file associated with this Context's application package for writing. see doc

"Permission denied for the attachment" (on Gmail 5.0) trying to attach file to email intent

This question has been posted before, but there was no clear or accepted answer and all of the solutions provided that were supposed to "work" didn't for me. See here: Gmail 5.0 app fails with "Permission denied for the attachment" when it receives ACTION_SEND intent
I have an app which builds up data in a text file and needs to send the text file along in an email, automatically attaching it. I have tried many ways to get this to attach, and it apparently works for Gmail 4.9 and below but 5.0 has some new permission features disabling it from doing what I wish.
Intent i = new Intent(Intent.ACTION_SEND);
String to = emailRecipient.getText().toString();
i.setType("message/rfc822");
i.putExtra(Intent.EXTRA_EMAIL, new String[] { to });
i.putExtra(Intent.EXTRA_SUBJECT, "Pebble Accelerometer Data");
i.putExtra(Intent.EXTRA_TEXT, "Attached are files containing accelerometer data captured by SmokeBeat Pebble app.");
String[] dataPieces = fileManager.getListOfData(getApplicationContext());
for(int i2 = 0; i2 < dataPieces.length; i2++){
i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(getApplicationContext().getFilesDir() + File.separator + dataPieces[i2])));
}
i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(getApplicationContext().getFilesDir() + File.separator + fileManager.getCurrentFileName(getApplicationContext()))));
Log.e("file loc", getApplicationContext().getFilesDir() + File.separator + fileManager.getCurrentFileName(getApplicationContext()));
try {
startActivity(Intent.createChooser(i, "Send Email"));
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(Main.this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
}
The datapieces might be empty yes but the current file line below the for loop is always reliable and always attaches something.
I have tried changing
Uri.fromFile()
to
Uri.parse()
When I do that, it attaches, but Gmail then crashes and when I check the logcat it's because of a null pointer. This is most likely because Gmail has no access to the file and therefore results as null.
I've also tried using
getCacheDir()
instead of
getFilesDir()
and it has the same outcome.
What am I doing wrong here, and how should I go about fixing it? Some example code would be really, really handy because I am new to Android development and explaining what I need to do without some sort of push off probably won't end up helping.
Thanks a lot.
Alright guys. Took a break and came back, figured it out.
Here's how it works, you need to have write/read permissions to external storage, so add these permissions to your manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Then, your file has to be copied from your app's internal storage directory into the app's external directory. I recommend you use internal storage, and that's what I'm doing here so you can figure out SD cards yourself.
Here is the block of code that does the magic. Logs are included but you can remove them by all means.
public void writeToExternal(Context context, String filename){
try {
File file = new File(context.getExternalFilesDir(null), filename); //Get file location from external source
InputStream is = new FileInputStream(context.getFilesDir() + File.separator + filename); //get file location from internal
OutputStream os = new FileOutputStream(file); //Open your OutputStream and pass in the file you want to write to
byte[] toWrite = new byte[is.available()]; //Init a byte array for handing data transfer
Log.i("Available ", is.available() + "");
int result = is.read(toWrite); //Read the data from the byte array
Log.i("Result", result + "");
os.write(toWrite); //Write it to the output stream
is.close(); //Close it
os.close(); //Close it
Log.i("Copying to", "" + context.getExternalFilesDir(null) + File.separator + filename);
Log.i("Copying from", context.getFilesDir() + File.separator + filename + "");
} catch (Exception e) {
Toast.makeText(context, "File write failed: " + e.getLocalizedMessage(), Toast.LENGTH_LONG).show(); //if there's an error, make a piece of toast and serve it up
}
}
Encountered the same attachment denied. Permissions in manifest did not have any effect, rather do not have an effect any more since API 23. Finally solved it as follows.
1st need to check and grant permissions on run-time, I did it in my main activity:
public static final int MY_PERMISSIONS_REQUEST_READ_STORAGE=10001;
private void checkPermission(){
if (this.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (this.shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) {
// Show an explanation to the user asynchronously
} else {
// No explanation needed, we can request the permission.
this.requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
MY_PERMISSIONS_REQUEST_READ_STORAGE);
}
}
}
Now when sending, create a file in PUBLIC directory (tried saving to my app folder - same denial problem)
public File createFile(){
String htmlStr="<!DOCTYPE html>\n<html>\n<body>\n<p>my html file</p></body></html>";
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "aimexplorersummary.html");
try {
FileWriter writer = new FileWriter(file ,false);
writer.write(htmlStr);
}
writer.flush();
writer.close();
} catch (IOException e) {
e.printStackTrace();
return null;
}
return file;
}
Now compose sending intent and putExtra with uri to your file which is in public storage that user must grant permissions to and that causes no problem now
public void send(){
Intent intentSend = new Intent(android.content.Intent.ACTION_SEND);
intentSend.setType("text/html");
File file = createFile();
if(file!=null){
intentSend.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
}
startActivity(Intent.createChooser(intentSend, "Send using:"));
}

Saving a text from EditText into the Android internal Storage

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?

Android file.exists() not working

Hallo,
Here's some code which writes a data class to a file, then checks to see that the file exists. I can see that the file exists on the emulator, but file.exists() and therefore saveStateAvailable() returns false.
private void saveStateFile() {
/*DEBUG*/Log.d(this.getClass().getName(), "saveStateFile: Started");
mGameData = getGameData();
try {
FileOutputStream fileoutputstream = openFileOutput(mGameData.pilotName + STATE_FILE_EXTENSION, Context.MODE_WORLD_WRITEABLE);
ObjectOutputStream objectoutputstream;
objectoutputstream = new ObjectOutputStream(fileoutputstream);
objectoutputstream.writeObject(mGameData);
objectoutputstream.close();
fileoutputstream.close();
/*DEBUG*/Log.i(this.getClass().getName(), "saveStateFile: State saved to "+mGameData.pilotName + STATE_FILE_EXTENSION);
} catch (IOException e) {
/*DEBUG*/Log.e(this.getClass().getName(), "saveStateFile: Error writing data state file, "+mGameData.pilotName + STATE_FILE_EXTENSION);
e.printStackTrace();
}
/*DEBUG*/Log.d(this.getClass().getName(), "saveStateFile: Finished stateFileAvailable="+stateFileAvailable());
}
private boolean stateFileAvailable() {
File file = new File(mGameData.pilotName + STATE_FILE_EXTENSION);
/*DEBUG*/Log.d(this.getClass().getName(), "stateFileAvailable: Called ("+mGameData.pilotName + STATE_FILE_EXTENSION+" exists = "+file.exists()+")");
return file.exists();
}
Any ideas?
-Frink
You need to use Context#getFileStreamPath(String) where the String is the filename of the File object you are trying to access. Then you can call File#exists on that object. So:
File file = getFileStreamPath(mGameData.pilotName + STATE_FILE_EXTENSION);
Gives you access to the File object that points to the correct place in your private app storage area.
What your code is going atm is accessing the file /<your file name> which is on the root path. You file obviously does not exist there.

Categories

Resources