Can't access written files on windows - android

I wrote a logfile to my sd (internal storage of the Samsung Galaxy Nexus). Actually the file is invisible in windows. How can I let users access them?
this.state = Environment.getExternalStorageState();
Returns "mounted"
This is my Code:
/**
* Creates a new instance of Logger
*
* */
public Logger() {
String path = Environment.getExternalStorageDirectory()
.getAbsolutePath();
this.file = new File(path, "log.txt");
}
/**
* Writes results to log file
*
* **/
public void log(boolean isConnected, int signalStrength) {
try {
this.buf = new BufferedWriter(new FileWriter(this.file, true));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
Calendar time = Calendar.getInstance();
String result = time.getTime().toString() + " "
+ String.valueOf(isConnected) + " "
+ String.valueOf(signalStrength);
this.buf.write(result);
this.buf.flush();
this.buf.close();
} catch (IOException e) { // TODO Auto-generated catch block
e.printStackTrace();
}
}
It won't write anything (even though I receive no exception).
Manifest contains:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Edit:
File path = Environment.getExternalStorageDirectory()
.getAbsoluteFile();
Didn't help.

The file is there, but it has not been picked up by the MediaScanner yet. You can verify by opening a shell like so:
adb shell ls -l /mnt/sdcard/clown.txt
You need to either wait for it to be picked up, reboot, or (preferably), call MediaScannerConnection.scanFile() when you are done writing to the file.

Related

Android: Check if a file is a valid SQLite database

I need to check whether a file (with unknown extension) is a valid SQLite database.
The db file is stored on the sd card. I need to import the database in my app. But if the user creates a file by the same name as of the database with any extension the file is still accepted by the code as it searches only for the name.
Is there a quick way to check for the validity of sqlite db stored on memory card.
I used this code, but it still accepts arbitrary file with same name as db.
String path = Environment.getExternalStorageDirectory().getPath() + "/FOLDER/DB_FILE";
SQLiteDatabase database;
database = SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY);
if (database == null) {
Toast.makeText(getApplicationContext(), "Error: Incorrect/Corrupted File", Toast.LENGTH_SHORT).show();
return;
} else {Proceed with code here}
A SQLite database file contains a header which provides some useful information.
In particular, every SQlite database file has always in it's first 16 bytes the value: SQLite format 3\0000
So you can check if your file contains that value in its first 16 bytes:
public boolean isValidSQLite(String dbPath) {
File file = new File(dbPath);
if (!file.exists() || !file.canRead()) {
return false;
}
try {
FileReader fr = new FileReader(file);
char[] buffer = new char[16];
fr.read(buffer, 0, 16);
String str = String.valueOf(buffer);
fr.close();
return str.equals("SQLite format 3\u0000");
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
Thanks #Drilon Kurti.
But from my own situation I want to add something.
Sometimes, When trying to open Database, if the file even not valid, an empty database may create with the same name in the app memory, as a result many problems occur, and sometimes, that, for the second time it will direct fall through the memory, which is a database by name and even pass the check as a database file, but not the real one. So, In this situation Drilon Kurti's method also pass true. But finally the database will not open or cant find the required columns. In this case I have checked with a min size with the above answer.
But, in real life, in every situation the following code will not fit, it will fit when you know the min size of the db. In example, when we embedded a db with app, or read an external db which's real size we can determine before opening it, and check it with the size :
public boolean isValidSQLite(String dbPath, int minSizeInMb) {
File file = new File(dbPath);
if (!file.exists() || !file.canRead()) {
return false;
}
boolean isReadable = false ;
try {
FileReader fr = new FileReader(file);
char[] buffer = new char[16];
try {
fr.read(buffer, 0, 16);
} catch (IOException e) {
e.printStackTrace();
}
String str = String.valueOf(buffer);
fr.close();
isReadable = str.equals("SQLite format 3\u0000");
} catch (Exception e) {
e.printStackTrace();
}
if (file.length() > (1024 * 1024 * minSizeInMb) && isReadable) {
return true;
}else {
try {
file.delete();
} catch (Exception e) {
e.printStackTrace();
}
return false ;
}
}
And the database memory path should be:
String DB_PATH;
String DB_NAME;
String packageName = mContext.getPackageName();
DB_PATH = String.format("//data//data//%s//databases//", packageName);
DB_NAME = "Your_Database_tafheemul_quran.db";
String path = DB_PATH + DB_NAME;

How to save to File in android programatically

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

Android Studio: Can not write to the Storage of my device, even though it seems to find the path just fine

So, I am trying to make a little GPS Tracker, which works fine so far. I get the data, put it into a .kml file and then I want to save the file to the storage. I can see in my android console that it creates the file just fine. But when I then try to save it to storage, it always throws a file not found exception.
This is the class that should do the exporting and saving:
private void doExport() {
SQLiteDatabase db = null;
Cursor cursor = null;
try {
// Hard code to set altitudeCorectionMeters
this.setAltitudeCorrectionMeters(40);
db = openOrCreateDatabase(GPSLoggerService.DATABASE_NAME,
SQLiteDatabase.OPEN_READWRITE, null);
cursor = db.rawQuery("SELECT * " + " FROM "
+ GPSLoggerService.POINTS_TABLE_NAME
+ " ORDER BY GMTTIMESTAMP ASC", null);
int gmtTimestampColumnIndex = cursor
.getColumnIndexOrThrow("GMTTIMESTAMP");
int latitudeColumnIndex = cursor.getColumnIndexOrThrow("LATITUDE");
int longitudeColumnIndex = cursor
.getColumnIndexOrThrow("LONGITUDE");
int altitudeColumnIndex = cursor.getColumnIndexOrThrow("ALTITUDE");
int accuracyColumnIndex = cursor.getColumnIndexOrThrow("ACCURACY");
if (cursor.moveToFirst()) {
StringBuffer fileBuf = new StringBuffer();
String beginTimestamp = null;
String endTimestamp = null;
String gmtTimestamp = null;
initFileBuf(fileBuf, initValuesMap());
// Write coordinates to file
do {
gmtTimestamp = cursor.getString(gmtTimestampColumnIndex);
if (beginTimestamp == null) {
beginTimestamp = gmtTimestamp;
}
/**
* 2. getData from database (cursor);
*/
double latitude = cursor.getDouble(latitudeColumnIndex);
double longitude = cursor.getDouble(longitudeColumnIndex);
double altitude = cursor.getDouble(altitudeColumnIndex)
+ this.getAltitudeCorrectionMeters();
double accuracy = cursor.getDouble(accuracyColumnIndex);
/**
* End step 2.
*/
/**
* 3. Write data (query from database) to file
*/
fileBuf.append(sevenSigDigits.format(longitude) + ","
+ sevenSigDigits.format(latitude) + "," + altitude
+ "\n");
/**
* End Step 3.
*/
} while (cursor.moveToNext());
endTimestamp = gmtTimestamp;
closeFileBuf(fileBuf, beginTimestamp, endTimestamp);
String fileContents = fileBuf.toString();
Log.d(tag, fileContents);
/**
* Step 4. Write file to /sdcard
*/
File sdDir = new File("/sdcard/GPSLogger");
sdDir.mkdirs();
File file = new File("/sdcard/GPSLogger/" + currentTripName
+ ".kml");
Toast.makeText(getApplicationContext(), file.toString(), Toast.LENGTH_LONG).show();
FileWriter sdWriter = new FileWriter(file, false);
sdWriter.write(fileContents);
sdWriter.close();
/**
* End Step 4.
*/
// R.string.export_completed Predefined in string.xml
Toast.makeText(getBaseContext(), R.string.export_completed,
Toast.LENGTH_LONG).show();
// If cursor.moveToFirst() Fails, no data is available
// database
} else {
Toast.makeText(
getBaseContext(),
"I didn't find any location points in the database, so no KML file was exported.",
Toast.LENGTH_LONG).show();
File sdDir = new File("/sdcard/GPSLogger");
sdDir.mkdirs();
File file = new File("/sdcard/GPSLogger/" + currentTripName
+ ".kml");
Toast.makeText(getApplicationContext(), file.toString(), Toast.LENGTH_LONG).show();
}
} catch (FileNotFoundException fnfe) {
Toast.makeText(
getBaseContext(),
"Error trying access the SD card. Make sure your handset is not connected to a computer and the SD card is properly installed",
Toast.LENGTH_LONG).show();
File sdDir = new File(Environment.getExternalStoragePublicDirectory(Environment.MEDIA_MOUNTED).getPath());
String pathname = sdDir.toString();
Toast.makeText(getApplicationContext(), pathname, Toast.LENGTH_LONG).show();
} catch (Exception e) {
Toast.makeText(getBaseContext(),
"Error trying to export: " + e.getMessage(),
Toast.LENGTH_LONG).show();
} finally {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
close_db(db);
}
}
The path to:
File sdDir = new File("/sdcard/GPSLogger");
is hardcoded, because otherwise the App only finds the emulated storage. Can anyone tell me where I am going wrong? Everything seems to work fine, until it shall save the file to the actual storage...
The Toast message from the exception also seems to show a valid path+name combination. I would be very grateful for help.
I am an idiot!
I forgot to give it permission to write to my storage.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
That fixed it for me.
:)

MediaPlayer - can't find path of sdcard on real device

On my code I use:
mp = new MediaPlayer();
String filePath = Environment.getExternalStorageDirectory().getPath() + "/mymusic/asong.mp3";
try {
mp.setDataSource(filePath);
} catch (IOException e) {
e.printStackTrace();
}
try {
mp.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mp.start();
And on the emulator the song.mp3 is played normally. But when I test it on my real device, it gives an error (-38, 0). That means it can not find the path of the song. I connect the usb cable, go to my Computer, GT-I8260 and paste the folder "mymusic" (that contains asong.mp3) under "Card" folder (where an empty folder named "LOST.DIR" is also placed). But why doesn't it work? Thanks a lot
it's card but at least
Environment.getExternalStorageDirectory() + "/mymusic/asong.mp3";
is enough.
Make sure it exists because you may not have the folder created before.
File f = new File(Environment.getExternalStorageDirectory() + "/mymusic");
if (!f.exists()) { f.mkdirs(); }
also make sure that it's not mounted while writing, since it may happen that it is not accessable at all.
Also revalidate that you have setupted the manifests permission to read/write the external storage

Path to App own directory in External Storage

In a library, I want to return a file that represents App own directory in External Storage, the directory that is returned by this method:
context.getExternalFilesDir(null);
But using this method before API Level 19, needs WRITE_EXTERNAL_STORAGE permission and I do not want to force user to use this permission, specially my method only want to return abstract File and does not want to create directory.
I can use this code:
Environment.getExternalStorageDirectory().getCanonicalPath() + "/Android/data/" + packageName + "/files";
But I think hard coding is not safe.Is there a way to return that directory without forcing user to use WRITE permission?
If you want to avoid the hard coded string, you could try to use reflect.
Class<?> environmentClass = Environment.class;
try {
Field androidDirectoryField = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
androidDirectoryField = environmentClass.getDeclaredField("DIR_ANDROID");
} else {
androidDirectoryField = environmentClass.getDeclaredField("DIRECTORY_ANDROID");
}
androidDirectoryField.setAccessible(true);
final String externalDir = Environment.getExternalStorageDirectory().getAbsolutePath()
+ getFilesDir().getAbsolutePath().replaceFirst("data", androidDirectoryField.get(null).toString());
Log.d(TAG, "external directory " + externalDir);
} catch (NoSuchFieldException | IllegalAccessException | IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Categories

Resources