How do I backup a SQLite Database to a SD Card? I have looked at many examples on here and none of them work for me. I have added the following lines to my manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
and the following to a fragment with a textview to click on and perform the backup:
// Find the Text View that displays the Backup Database Button //
TextView backupDatabaseTextView = (TextView) rootview.findViewById(R.id.backup_database_text_view);
// Set a click listener on the backup database text view //
backupDatabaseTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
exportDB();
}
});
and the following method:
private void exportDB() {
try {
File sd = Environment.getExternalStorageDirectory();
File data = Environment.getDataDirectory();
if (sd.canWrite()) {
String currentDBPath = "//data//" + "com.budgettrackpro.android.budgettrackpro"
+ "//databases//" + "budgettrackpro.db";
String backupDBPath = "BudgetTrackPro";
File currentDB = new File(data, currentDBPath);
File backupDB = new File(sd, backupDBPath);
FileChannel src = new FileInputStream(currentDB).getChannel();
FileChannel dst = new FileOutputStream(backupDB).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
Toast.makeText(getActivity(), "Backup Successful!",
Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
Toast.makeText(getActivity(), "Backup Failed!", Toast.LENGTH_SHORT)
.show();
}
}
When I debug, it finds the sd card but then drops to the bottom of the try catch
I do not know how to interpret that, as I do not know which lines in that code you think represent "finds the sd card". For example, your code has nothing to do with removable storage.
So, here are various issues, in descending order of likelihood of being the source of your current difficulty (though you should fix all of them):
No Runtime Permission Support
You are running on Android 8.1. Since Android 6.0, you need to request certain permissions at runtime, and WRITE_EXTERNAL_STORAGE is among those permissions.
Hardcoded Database Path
String currentDBPath = "//data//" + "com.budgettrackpro.android.budgettrackpro"
+ "//databases//" + "budgettrackpro.db";
Never hardcode paths. Replace that with:
File currentDB = getActivity().getDatabasePath("budgettrackpro.db");
(and get rid of the File currentDB = new File(data, currentDBPath); line, as you will no longer need it)
Not Logging the Exception
While you are developing an app, log all exceptions. Add this line above your Toast.makeText() line in your catch block:
Log.e(getClass().getSimpleName(), "Exception backing up database", e);
Then, use LogCat to examine the stack trace associated with any crashes.
Doing I/O on the Main Application Thread
At best, your UI will be frozen for the duration of the exportDB() call, and your users will think that your app is broken. At worst, you will crash, because either:
The backup is taking too long and tying up the main application thread, or
StrictMode complains about the disk I/O on the main application thread
Please move this work to a background thread.
Not Making the Backup Visible to the User
Even once you create the file, the user will not be able to see that it exists without rebooting or waiting a few hours.
Related
I want to write text to file in Android. I tried writing to sdcard and public part of internal storage. I always got FileNotFound exception. I tried to get path by Environment.getExternalStorageDirectory().getAbsolutePath() and by Environment.getExternalStoragePublicDirectory(Enviroment.DIRECTORY_DCIM).getAbsolutePath()(it does not metter the file is not a picture, I suppose) and both returned: "storage/emulated/0" and "storage/emulated/0/DCMI" respectively. I have also tried direct path "/sdcard/MyFile/output.txt" and "mnt/sdcard/MyFile/output.txt". I have checked on most stackoverflow.com answears in such topic but I got only code similar to mine. (like from here)
Example of my code (I tried more variations):
try {
File dir = Environment.getExternalStorageDirectory();
File dir = new File (sdCard.getAbsolutePath() + "/MyFile");
if (!dir.exists()) {
dir.mkdirs();
}
File file = new File(dir, "output.txt");
if (!file.exists()) {
file.createNewFile();
}
FileOutputStream stream = new FileOutputStream(file);
stream.write(("some text").getBytes());
stream.close();
toast = Toast.makeText(context, "Saving file successful.", Toast.LENGTH_SHORT);
toast.show();
} catch (Exception e) {
toast = Toast.makeText(context, Environment.getExternalStorageDirectory().getAbsolutePath(), Toast.LENGTH_SHORT);
//toast = Toast.makeText(context, e.toString(), Toast.LENGTH_SHORT);
toast.show();
}
You have to set the
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
permission in your AndroidManifest.xml file.
If you run your app on Android 6.0 or higher you have to request this permission at runtime.
Request App Permissions
I am sorry to all you guys to waste your time. The problem was in permission setting. Here is the answear.
According to user reviews, my app dosn't save on their phones (LG4, oneplus phones, android 5.1, Android 6.0)
For Android 6.0 I have solved the problem by using the new permission system.
But how can I be sure that the code actually works 100% on all devices?
Is there any improvment that can be made?
This is the onClick method that is run, when the user clicks the save button
But also ask for permission for Android 6 devices
public void saveQuote(View v) {
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
//check if we have permissoin to WRITE_EXTERNAL_STORAGE
if (PackageManager.PERMISSION_GRANTED == ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
//This method just create a bitmap of my edittext
saveBitmap();
} else {
//if permission is not granted, then we ask for it
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_WRITE_EXTERNAL_STORAGE);
}
}
}
This is the code that makes the saving operation:
private void saveImageToExternalStorage(Bitmap finalBitmap) {
String filename = "#" + pref_fileID.getInt(SAVE_ID, 0) + " Quote.JPEG";
//The directory in the gallery where the bitmaps are saved
File myDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString() + "/QuoteCreator");
//The directory in the gallery where the bitmaps are saved
File myDir = new File(root + "/QuoteCreator");
//creates the directory myDir.
myDir.mkdirs();
File file = new File(myDir, filename);
try {
FileOutputStream out = new FileOutputStream(file);
finalBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
out.flush();
out.close();
Toast.makeText(getApplicationContext(), R.string.savedToast, Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}
/*
Tell the media scanner about the new file so that it is
immediately available to the user.
*/
MediaScannerConnection.scanFile(this, new String[]{file.toString()}, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
}
Replace:
//The directory in the gallery where the bitmaps are saved
File myDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString() + "/QuoteCreator");
//The directory in the gallery where the bitmaps are saved
File myDir = new File(root + "/QuoteCreator");
with:
File root=
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
File myDir=new File(root, "QuoteCreator");
(note: no /, no toString(), no +)
This ensures that File can handle the cases where root has or does not have a trailing /.
Replace:
out.flush();
out.close();
with:
out.flush();
out.getFD().sync();
out.close();
This ensures all bytes are written to disk before proceeding, particularly before having the file be indexed by the MediaStore.
And replace:
e.printStackTrace();
with something that will be useful for you in production. This statement logs something to LogCat. It's not even the preferred way of logging something to LogCat (which is using methods on android.util.Log, like e()). While you can see LogCat on your development machine for your own devices and emulators, you cannot see LogCat on user devices. There may be useful information in these exceptions that you are lacking. Personally, I use ACRA and its "silent exception" option for recording these sorts of exceptions that I am handling in-app but still want to know about. However, there are plenty of crash-reporting services, and presumably some of them offer an equivalent feature.
I am a newbie to android. In my project i am sending data selected from drop down (spinners) via bluetooth.
I have created a database and loaded the values into spinners and sent the selected values via bluetooth. It is working fine .Now the problem is i know the database is created as i am displaying its values for the spinners. Now i want to display the selected spinner data on submit in the form of a table.
I am not able to have a look at my already created database. say for eg. we have php myadmin in case of php to see and manipulate database. Is there something in android as such. I have already tried using Android device Monitor in DDMS and selecting data/data to find the database but it is not showing any databases. What may be the problem? It has to show something like com com.projectname inside data/data but it is not showing the same.
For security purposes you cannot access the database directly on an Android device. But in case you are testing on an emulator you will be able to see the database from File explorer(Eclipse). Steps:
Go to to Window > Show View > Select File Explorer(in case its not there in the list click other at the bottom for more options).
Select File Explorer.
Your database will be there under data folder and your package name.
Pull the database file.
Install SQLite manager add-on in your browser.
Load your database file in it and you'll be able to see your complete database there.
In case your database is on an Android device, copy your database to another location in your SD card using the following code and then manually copy it from there on your PC and load that file in SQLite Manager.
/**
* Export your database file
*/
private void exportDB() {
String SAMPLE_PKG_NAME = "com.example.android";// your package name
String SAMPLE_DB_NAME = "database"; // your database name
String path = Environment.getExternalStorageDirectory() + "/Android";
File sd = new File(path);
if (sd.exists()) {
Log.d("Database", "EXISTS");
}
File data = Environment.getDataDirectory();
FileChannel source = null;
FileChannel destination = null;
String currentDBPath = "/data/" + SAMPLE_PKG_NAME + "/databases/"
+ SAMPLE_DB_NAME;
String backupDBPath = SAMPLE_DB_NAME;
File currentDB = new File(data, currentDBPath);
File backupDB = new File(sd, backupDBPath + ".sqlite");
try {
source = new FileInputStream(currentDB).getChannel();
destination = new FileOutputStream(backupDB).getChannel();
destination.transferFrom(source, 0, source.size());
source.close();
destination.close();
Toast.makeText(this, "DB Exported!", Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
}
}
In the Eclipse look at the File Explorer tab (near the Console tab). Or look at menu Window -> Show View -> Other... -> File Explorer. Emulator should be run. In the File Explorer window go to the folder data/data/[your_package_name]/databases/.
There you can find your database. You can export it to the your computer. At the right top corner of the window there is a button pull a file from device. Select database, click that button and save a database on the computer.
Program sqlite browser can shows a data in the database. You can download it here. It is easy to use.
Can any one suggest me that how can I view a sql database created in my app? I am running it on the Android device in Eclipse
If you are running your project in Emulator then you can view it in /database/database folder of your project's package name.
If you are running your project in real device then you can not view it directly unless your database is stored on external path like on SD card.
Use this function to first save your database to SD card
public static void saveDbFile() {
try {
File sd = Environment.getExternalStorageDirectory();
File data = Environment.getDataDirectory();
if (sd.canWrite()) {
String currentDBPath = "/data/com.RareMediaCompany.BlueDolphinTest/databases/HeliosEmployeeTracker.db";
String backupDBPath = "backUpheliosCurr.db";
File currentDB = new File(data, currentDBPath);
File backupDB = new File(sd, backupDBPath);
if (currentDB.exists()) {
FileChannel src = new FileInputStream(currentDB)
.getChannel();
FileChannel dst = new FileOutputStream(backupDB)
.getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
}
}
Log.i("save db", "db saved on sd card");
} catch (Exception e) {
e.printStackTrace();
}
}
Then open your "Mozilla Firefox Browser" and add a "Add on" to the browser named "Sqlite Manager". Then just import that database to the Manager and you are ready to go
I have a problem with creating a folder and a file on the sdcard.
Here's the code:
File folder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString() + "/folder");
boolean success;
if (!folder.exists()) {
success = folder.mkdirs();
}
File obdt = new File(folder, "file.txt");
try {
success = obdt.createNewFile();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
With this code I expect to create the folderfolder in the Download folder of the sdcard and in this the file file. I want that the user can access the file. So I want to put it in a shared folder.
The success variable is true and when I run the code again the folder already exists and doesnt come in the if-block.
But I can't see the created folder and file on the sdcard in file explorer.
Info:getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString() returns storage/sdcard/Download
I work with a Galaxy Nexus.
Damn! :)
Now I solved my problem...I was misunderstanding the operation of creating files in the file system.
When I spoke of file explorer I meant the file explorer of the operating system and NOT the file explorer in the DDMS :).
I thought when I create a file I will see it in the file explorer of the operating system but when the device is connected to the PC the files can only be seen in the DDMS file explorer.
Sorry I'm new to Android ;)
When the App is running standalone without PC connection and afterwards I connect with the PC I see the created files and folders of course :)
Thanks for help
Any errors from logcat?
Else: try something like Log.I("PATHNAME",folder.absolutePath()); and then look in your logcat to make sure where you are creating the folder where you think it is.
If you haven't done so already, you will need to give your app the correct permission to write to the SD Card by adding the line below to your Manifest:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
If you have already done that see if :
File obdt = new File(/sdcard/folder/file.txt)
try {
success = obdt.createNewFile();
} catch (IOException e1) {
e1.printStackTrace();
}
works.
You cannot see the folder/file in explorer? Maybe it is because the MediaScanner is active, but not adding your files. You can do this in your program or switch the Media Scanner of somewhere in your phone settings.
MediaScanner
Trigger MediaScanner
Try this out.
File dir = new File(Environment.getExternalStorageDirectory()
+ "/XXX/Wallpapers/");
File[] files = dir.listFiles();
if (files == null)
{
int numberOfImages = 0;
BitmapDrawable drawable = (BitmapDrawable) imageView
.getDrawable();
Bitmap bitmap = drawable.getBitmap();
File sdCardDirectory = Environment
.getExternalStorageDirectory();
new File(sdCardDirectory + "/XXX/Wallpapers/").mkdirs();
File image = new File(sdCardDirectory
+ "/XXX/Wallpapers/Sample" + numberOfImages + ".JPG");
boolean success = false;
FileOutputStream outStream;
try {
outStream = new FileOutputStream(image);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
outStream.flush();
outStream.close();
success = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (success) {
Toast.makeText(
getApplicationContext(),
"Image saved successfully in Sdcard/XXX/Wallpapers",
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(),
"Error during image saving", Toast.LENGTH_LONG)
.show();
}
Dont forget to add permission in manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Apparently there is a known bug in MTP.
Issue 195362
All phones using MTP instead of USB Mass storage do not properly show the list of files when that phone is connected to a computer using a USB cable. Android apps running on the device also cannot see these files.
It is actually as old as 2012
I've encountered the same problem: created files and folders don't show immediately after being written to sdcard, despite the file being flushed and closed !!
They don't show on your computer over USB or a file explorer on the phone.
I observed three things:
if the absolute path of the file starts with /storage/emulated/0/ it doesn't mean it'll be on your sdcard - it could be on your main storage instead.
if you wait around 5 minutes, the files do begin to show over USB (i.e. Windows explorer and built-in file explorer)
if you use adb shell ls /sdcard from terminal, then the file does show! you could use adb pull ... to get the file immediately. You could probably use DDMS too.
Code I used was:
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(myArrayList);
try {
File externalDir = getExternalStorageDirectory();
File newFile = new File(externalDir, "myfile.txt");
FileOutputStream os = new FileOutputStream(newFile);
os.write(json.getBytes());
os.flush();
os.close();
Timber.i("saved file to %s",newFile.getAbsoluteFile().toString());
}catch (Exception ex)
{
Toast.makeText(getApplicationContext(), "Save to private external storage failed. Error message is " + ex.getMessage(), Toast.LENGTH_LONG).show();
}
and
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(myArrayList);
try {
File externalDir = getExternalStorageDirectory();
File newFile = new File(externalDir, "myfile.txt");
FileWriter fw = new FileWriter(newFile);
fw.write(json);
fw.flush();
fw.close();
Timber.i("saved file to %s",newFile.getAbsoluteFile().toString());
}catch (Exception ex)
{
Toast.makeText(getApplicationContext(), "Save to private external storage failed. Error message is " + ex.getMessage(), Toast.LENGTH_LONG).show();
}
why is it like this? Seems like another one of those "Android-isms" that you have to suffer through the first time you experience it.