Android copy local app database file to Internal device memory folder - android

I want to achieve that after I click the BACKUP button, the mydb.db file from my app database folder will be copied to device internal memory, where a New folder should be created and the file put inside it.
My code what I tried:
backupbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try {
File data = Environment.getDataDirectory();
File extdata = Environment.getExternalStorageDirectory();
String backupDBPath = "/Newfolder/mydb.db";
File ddir = new File(Environment.getExternalStorageDirectory()
+ "/Newfolder/");
DirectoryExist(ddir);
String currentDBPath ="/data/mypackage/databases/mydb.db";
File currentDB = new File(data, currentDBPath);
File backupDB = new File(extdata, 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();
Toast.makeText(getApplicationContext(), "Backup is successful ", Toast.LENGTH_SHORT).show();
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
private void DirectoryExist(File destination) {
if (!destination.isDirectory()) {
if (destination.mkdirs()) {
Log.d("Carpeta creada", "....");
} else {
Log.d("Carpeta no creada", "....");
}
}
}
However I have this error: java.io.FileNotFoundException: /storage/emulated/0/Newfolder/mydb.db (No such file or directory)
UPDATE: After investigation I found out, it is a storage permission issue.
If I set permissions manually in app settings, it is working. But when I try to set permissions in the app, it still says, permission denied:
if(!checkPermissionForReadExtertalStorage())
{
try {
requestPermissionForReadExtertalStorage();
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean checkPermissionForReadExtertalStorage() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int result = this.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
return result == PackageManager.PERMISSION_GRANTED;
}
return false;
}
public void requestPermissionForReadExtertalStorage() throws Exception {
try {
ActivityCompat.requestPermissions((Activity) this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
READ_STORAGE_PERMISSION_REQUEST_CODE);
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
The popup with permissions comes up, but still, seems it doesn't allows permissions.
In manifest I have:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
However the WRITE_EXTERNAL_STORAGE is not used anymore for android 10+, so not sure if I need to keep it there.
And I have also <application android:requestLegacyExternalStorage="true"
But as I read: Starting in Android 11, apps that use the scoped storage model can access only their own app-specific cache files.
So it seems, there is no option to create any folder in local storage to backup files anymore except the app folder. One option seems to be via MediaStore API, but using this for backup one small db file seems to be an overkill.

Related

How do I backup a SQLite Database to a SD Card?

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.

Android - Avoid saving to storage/emulated/0

I'm trying to save an image on the public storage directory using the below code. However, when this is saving to storage/emulated/0 and not to the public Pictures folder. I have used basically this exact code in another app and it's worked fine. Does anyone know why .getExternalStoragePublic directory is not returning the accessible /Pictures/ and instead returning storage/emulated/0 ?
I have "uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" in my Manifest file
File backupFile;
File appFolder;
String path= Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath() + "/CustomFolder";
appFolder = new File(path);
if (!appFolder.exists())
appFolder.mkdir();
String fileName = "picture.jpg"
backupFile = new File(appFolder, fileName);
FileOutputStream output = null;
try {
output = new FileOutputStream(backupFile);
output.write(bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
mImage.close();
if (null != output) {
try {
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Nevermind, I figured it out. It turns out just having "uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" in the Manifest file is insufficient, and I had to put the following code before it to make it work:
int CAMERA_PERMISSION_REQUEST_CODE = 2;
int result = ContextCompat.checkSelfPermission(getActivity().getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (result != PackageManager.PERMISSION_GRANTED){
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)){
Toast.makeText(getActivity().getApplicationContext(), "External Storage permission needed. Please allow in App Settings for additional functionality.", Toast.LENGTH_LONG).show();
} else {
ActivityCompat.requestPermissions(getActivity(),new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},CAMERA_PERMISSION_REQUEST_CODE);
}
}

Can't write to /mnt/sdcard

This one has me stumped (Android 4.3)
I have the right permission:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
... I'm explicitly creating a path to /storage/sdcard0/path/to/data.csv and the FileOutputStream doesn't throw any exceptions.
I tried reading the path via Environment.getExternalStorageDirectory() but that has some "emulated" path.
In either case, I can't see the files on the filesystem ...
What's more confusing is that MEDIA_MOUNTED_READ_ONLYis mounted_ro ... but this isn't the case .
It looks like another app us using /mnt/extSdCard... I tried hard coding that in my app but that doesn't work either. Even the directory is missing. This is very confusing.
I'm calling mkdirs() on this of course and the FileOutputStream is created....
What am I doing wrong?
Try the following code, and see where it fails?
try {
File mPath = new File(android.os.Environment.getExternalStorageDirectory(),"path/to");
if (!mPath.exists()) {
if(!mPath.mkdirs()) {
Log.e(getClass().getName(), "Can't Create Folder: "+mPath.getName());
}
}
File mLogFile = new File(mPath, "data.csv");
FileWriter mFileWriter = null;
if(mPath.canWrite()) {
mFileWriter = new FileWriter(mLogFile, true);
mBufferedWriter = new BufferedWriter(mFileWriter);
}
else {
Log.e(getClass().getName(), "Can't write under Folder: "+mPath.getName());
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}

Writing file to SD_Card

///edited
I try to run the program on the main thread and it can read and save.
I think is problem of the asynctask!!
///
First I already add the user permission to the android manifest
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
I try to read a raw image data from mnt/sdcard/Bluetooth and process it and then write to the internal sdcard and the write path is mnt/sdcard/Bluetooth.
The program can run in my android emulator and save File.
However,when run it real phone, it seems that the phone can only read my file,but not save file.
public class MainActivity extends Activity {
String filenameIn ="ardrone.raw";
File file = new File(Environment.getExternalStorageDirectory()+"/Bluetooth/", filenameIn);
String filename ="convertA.jpg";
File outputfile = new File(Environment.getExternalStorageDirectory() +"/Bluetooth/",filename);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myImageView = (ImageView)findViewById(R.id.imageView);
Toast.makeText(this, "search raw file", Toast.LENGTH_LONG).show();
new imageProcess().execute();
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,Uri.parse("file://" + Environment.getExternalStorageDirectory())));
Bitmap myBitmap = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory()
.getAbsolutePath()+"/Bluetooth/convertA.jpg");
myImageView.setImageBitmap(myBitmap);
if (file.exists()){
Toast.makeText(this, "InFile:)", Toast.LENGTH_LONG).show();
}
else{
Toast.makeText(this, "InFile:(((((", Toast.LENGTH_LONG).show();
}
if (outputfile.exists()){
Toast.makeText(this, "outputfile:)", Toast.LENGTH_LONG).show();
}
else{
Toast.makeText(this, "outputfile:(((((", Toast.LENGTH_LONG).show();
}
}
public class imageProcess extends AsyncTask<String, Integer, Boolean>{
Boolean check_point= false;
#Override
protected Boolean doInBackground(String... arg0) {
try {
receiveVideoRawData();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
public void receiveVideoRawData() throws IOException{
byte[] buf_rcv = new byte[153600];
ByteArrayOutputStream ous = new ByteArrayOutputStream();
InputStream ios = new FileInputStream(file);
int read = 0;
while ( (read = ios.read(buf_rcv)) != -1 ) {
ous.write(buf_rcv, 0, read);
}
ous.close();
ios.close();
ReadRawFileImage readMyRawData=new ReadRawFileImage();
image = readMyRawData.readUINT_RGBImage(buf_rcv);
//transfer data
OutputStream _outStream = new FileOutputStream(outputfile);
Bitmap pBitmap = image ;
pBitmap.compress(Bitmap.CompressFormat.JPEG, 90, _outStream);
_outStream.flush();
_outStream.close();
}
}
The first thing is to check if your path exists; on different phones the sd card may be mounted at different locations. On my Linux,
$ ~/android-sdk-linux/platform-tools/adb shell ls -l /mnt/sdcard/
The 2nd thing is to check permissions on the file and the containing directory.
Then, you might examine the logs (they may already contain an error message); then, add debug output to your code and examine the logs with that debug output.
try making your new file writable using file.writable(true). It could also be that your new file doesnt really exist.
Apparently you only need to set the external read permission if you don't have the write permission, this might be overwriting your write privileges?
http://developer.android.com/reference/android/Manifest.permission.html#READ_EXTERNAL_STORAGE
First you should confirm that the real device has SDCARD storage(Some device have not "SDCARD" storage).
Please see below reference to get all storage list
How to list additional external storage folders (mount points)?

android: writing to sdcard fails - why?

i have a problem with my code that is supposed to write some data string to my sdcard. i use a class to do this:
public class CVS {
private String path;
private String filename;
private File dir;
private File file;
private FileWriter fw;
public CVS() {
path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/traffic/";
filename = "data.cvs";
file = new File(path, filename);
createDir();
}
private void createDir() {
dir = new File(path);
if(!dir.exists()) {
if(file.mkdirs() == false) {
Log.d(Config.LOGTAG, "UHOH!!!!!!!!!!!!!!!!!!!!!!!!");
}
}
else Log.d(Config.LOGTAG, "dir exists");
}
public void writeToFile(String data) {
try {
fw = new FileWriter(file);
fw.append(data); Log.d(Config.LOGTAG, "data saved to file...");
}
catch(Exception e) {
Log.d(Config.LOGTAG, "file: " + e.getMessage());
}
}
}
this results ALWAYS in an exeption being caught in writeToFile(), saying "permission denied". actually, i set permissions to WRITE_EXTERNAL_STORAGE in the manifest. so - what am i doing wrong!?
additional info: real device with sd card mounted. no emulator. android 2.2. if i create the dir myself, the problem wont go away :(
Either:
Your manifest is wrong, or
Your external storage is mounted on your development machine, or
Your manual concatenation of your directory is wrong
Your code is ok but still you can add a check for whether sdcard is inserted or not, if you run this code and sdcard is not inserted then it will throw an exception, good practice is that you should always catch the exeptions.
you can check sdcard by following code...
if (android.os.Environment.getExternalStorageState().equals
(android.os.Environment.MEDIA_MOUNTED))
{
//code or logic if sd card is inserted....
}
else
{
Log.e("Exception","SD Card not found!");
}
All of the answers are needed, but if it's a Samsung device, then you need to append "/external_sd/" to the path - because they decided they needed to dork with our minds and break the API:
"http://developer.samsung.com/forum/board/thread/view.do?boardName=GeneralB&messageId=162934&messageNumber=1381&startId=zzzzz~&searchType=TITLE&searchText=sdcard

Categories

Resources