when i try to uninstall my android app and reinstall it again to get the new updated database, the database sometimes does not get updated, i don't know why.
Database gets updated after trying a random number of attempts of install/uninstall,
Can someone help me with this problem.
What I tried is:
when uninstalling, first I force stop the application, then I cleared the data and then uninstalled.
here is the code that is executed in the MainActivity when the app starts.
try {
File dbFile = getDatabasePath("MyDatabase.db");
if (!dbFile.exists()) {
Log.d(TAG, "Datbase does not exist");
this.copy("MY.db",dbFile.getAbsolutePath());
}
}
catch (Exception e) {
Log.e(TAG, "Error in Copying: "+e.toString());
try {
AppLogging(TAG, "Error in copying Database:" + e.toString());
}
catch(Exception l) {
}
}
Copy method
private void copy(String file, String folder) throws IOException {
try {
File CheckDirectory;
CheckDirectory = new File(folder);
String parentPath = CheckDirectory.getParent();
File filedir = new File(parentPath);
if (!filedir.exists()) {
if (!filedir.mkdirs()) {
return;
}
}
InputStream in = this.getApplicationContext().getAssets().open(file);
File newfile = new File(folder);
OutputStream out = new FileOutputStream(newfile);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
catch (Exception e) {
Log.e(TAG, "Error in Copy: "+e.toString());
try {
AppLogging(TAG, "ERROR In Copy Method (Database) " + e.toString());
}
catch(Exception l) {
}
}
}
Related
I am trying to make a file manager app in Android.
I want to provide the user with an option to move their files. So first I am copying the Files then I am deleting the file if there is no error.
This is the code I am using to copy the files
public static boolean copy(File copy, String directory, Context con) {
static FileInputStream inStream = null;
static OutputStream outStream = null;
DocumentFile dir = getDocumentFileIfAllowedToWrite(new File(directory), con);
String mime = "";
DocumentFile copy1 = dir.createFile(mime, copy.getName());
try {
inStream = new FileInputStream(copy);
outStream = con.getContentResolver().openOutputStream(copy1.getUri());
byte[] buffer = new byte[16384];
int bytesRead;
while ((bytesRead = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inStream.close();
outStream.close();
return true;
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
But in one of my devices the files are simply getting deleted without copying.
So my thought is that I will check the length of the file by SourceFile.length() and the length of the DestinationFile.length() if both are same or not. If both are same then I will delete the SourceFile.
Is the most effective way to check it without checking the MD5 of an File? Also what are the chances that the file transfer is incomplete/corrupted and still the length is same?
Hello all I am having a problem when exporting a named file to the device internal storage for my apps Sqlite database name.
I am getting the error
java.io.FileNotFoundException: /storage/emulated/0/Download/:/09/12/2017-JDO.db: open failed: ENOENT (No such file or directory)
when trying to name the file /09/12/2017-JDO.
I am using File.pathSeparator() with the passed in file name but still am not having any luck. I think it has to do with the / in the file name which is the reason why I tried the File.pathSeparator() to begin with since I want that option for naming the file if the user wants to include the date in that format or in combination with the /.
Here are some code snippets of the methods I am using to try and accomplish this and to show what I am trying to do.
/*
This method saves and exports the current database to the device's internal Downloads folder
This is the default named database
*/
public void backUpDatabase() {
/* Open your local db as the input stream */
DBHelper anotherDbHelper = null;
try {
try {
anotherDbHelper = new DBHelper(ExistingTallyActivity.this);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String path = null;
if (anotherDbHelper != null) {
path = String.valueOf(getApplicationContext().getDatabasePath(anotherDbHelper.getDatabaseName()));
}
File dbFile = null;
if (path != null) {
dbFile = new File(path);
}
FileInputStream fis = null;
try {
if (dbFile != null) {
fis = new FileInputStream(dbFile);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
String outFileName = (Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + "/Pipe_Tally");
/* Open the empty db as the output stream */
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(outFileName);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
/* Transfer bytes from the input-file to the output-file */
byte[] buffer = new byte[1024];
int length;
try {
if (fis != null) {
while ((length = fis.read(buffer)) > 0) {
try {
if (outputStream != null) {
outputStream.write(buffer, 0, length);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
/* Close the streams */
try {
if (outputStream != null) {
outputStream.flush();
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if (anotherDbHelper != null) {
anotherDbHelper.close();
}
}
/*
This method renames the database to what the user inputs they want. Note: The original db is
still present and stored in the Downloads folder as well.
*/
public void renameDbFile(String desiredDbName) {
/* Open your local db as the input stream */
DBHelper dbHelperToRename = null;
try {
try {
dbHelperToRename = new DBHelper(ExistingTallyActivity.this);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String pathRenamed = null;
if (dbHelperToRename != null) {
pathRenamed = String.valueOf(getApplicationContext().getDatabasePath(dbHelperToRename.getDatabaseName()));
}
File dbFileRenamed = null;
if (pathRenamed != null) {
dbFileRenamed = new File(pathRenamed);
}
FileInputStream fisRenamed = null;
try {
if (dbFileRenamed != null) {
fisRenamed = new FileInputStream(dbFileRenamed);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
/* Here is where the db is renamed by the user by inserting the passed in string to the method */
String outFileNameRenamed =
(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
.getAbsolutePath() + "/"+desiredDbName+".db");
// Open the empty db as the output stream
OutputStream outputStreamRenamed = null;
try {
outputStreamRenamed = new FileOutputStream(outFileNameRenamed);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
/* Transfer bytes from the input-file to the output-file */
byte[] bufferRenamed = new byte[1024];
int length;
try {
if (fisRenamed != null) {
while ((length = fisRenamed.read(bufferRenamed)) > 0) {
try {
if (outputStreamRenamed != null) {
outputStreamRenamed.write(bufferRenamed, 0, length);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
/* Close the streams */
try {
if (outputStreamRenamed != null) {
outputStreamRenamed.flush();
outputStreamRenamed.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fisRenamed != null) {
fisRenamed.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if (dbHelperToRename != null) {
dbHelperToRename.close();
}
}
/*
This method exports the database into CSV format as well by naming it the passed in string value
for the desired name.
*/
#TargetApi(Build.VERSION_CODES.KITKAT)
public void saveDbAsCsv(String desiredCsvName) {
/* Getting a instance of the DbHelper class right here. */
DBHelper dbhelperCsv = null;
try {
dbhelperCsv = new DBHelper(ExistingTallyActivity.this);
} catch (ClassNotFoundException | NoSuchFieldException e) {
e.printStackTrace();
}
/* Original name of the file dir where the db will be stored in csv format. (Just like SQLite) */
String pathRenamedCsv = null;
if (dbhelperCsv != null) {
pathRenamedCsv = String.valueOf(getApplicationContext().getDatabasePath(dbhelperCsv.getDatabaseName()));
}
/* Creating a File type here with the passed in name from above from the string */
File dbFile = getDatabasePath(pathRenamedCsv);
/*
Appending the desired name to the Downloads Directory here, which is where the new file
will be written
*/
String renamedCsvName = (Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + "/"+desiredCsvName);
File exportDir = new File(String.valueOf(renamedCsvName));
if (!exportDir.exists())
{
exportDir.mkdirs();
}
/*
Critical .csv extension here. Took me a while originally to figure out where to pass this
in at. Was at first passing it into the renamedCsvName up above and it was just returning
a folder with the .csv extension and not the file contained withn.
*/
File file = new File(exportDir, desiredCsvName+".csv");
try
{
/* Passing in the string value of the file to an instance of the CsvWriter class */
CsvWriter csvWriter = new CsvWriter(String.valueOf(file));
SQLiteDatabase db = null;
if (dbhelperCsv != null) {
db = dbhelperCsv.getReadableDatabase();
}
/* Getting a cursor from the database table Tally_File */
Cursor curCSV = null;
if (db != null) {
curCSV = db.rawQuery("SELECT * FROM Tally_File",null);
}
if (curCSV != null) {
csvWriter.writeRecord(curCSV.getColumnNames());
}
if (curCSV != null) {
while(curCSV.moveToNext())
{
/* Exporting all the columns here to write out to the csv file */
String arrStr[] ={curCSV.getString(0),curCSV.getString(1), curCSV.getString(2),
curCSV.getString(3), curCSV.getString(4), curCSV.getString(5),
curCSV.getString(6), curCSV.getString(7), curCSV.getString(8),
curCSV.getString(9), curCSV.getString(10), curCSV.getString(11),
curCSV.getString(12), curCSV.getString(13), curCSV.getString(14), curCSV.getString(15),
curCSV.getString(16)};
/*
Critical here as I was not at first calling the writeRecord that accepted the
String[] array and was calling the toString() method on it and only getting a large
array.
*/
csvWriter.writeRecord(arrStr);
}
}
csvWriter.close();
if (curCSV != null) {
curCSV.close();
}
}
catch(Exception sqlEx)
{
Toast.makeText(this, "Error naming file", Toast.LENGTH_LONG).show();
}
}
Here is where I am calling the methods and passing in the desiredName for naming the file/Db, which is switch case dependent on a menu selection, all within the same activity.
case R.id.menu_save_and_export:
Thread threadMenuSaveAndExport = new Thread();
/*
This method verifies user permissions then calls the backUpDatabase() method to
backup the original db file before the user renames it, if desired.
*/
verifyStoragePermissions(new Runnable() {
#Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
/* Calling this method here to backup the current database*/
backUpDatabase();
}
});
/* Loading the view of activity_database_name with this LayoutInflater*/
View view = LayoutInflater.from(ExistingTallyActivity.this)
.inflate(R.layout.activity_database_name,null);
/*This editText handles the input from the user for their chosen db name*/
mEtCustomDbName = (EditText) view.findViewById(R.id.etCustomDbName);
AlertDialog.Builder alert = new AlertDialog.Builder(ExistingTallyActivity.this);
/* Taken from the strings.xml file. Says Name Database Prior To Export */
alert.setMessage(getResources().getString(R.string.name_your_db));
alert.setView(view);
/* Using the global "Ok" string from strings.xml */
alert.setPositiveButton(getResources().getString(R.string.global_ok_text), new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
/* Passing in the results of the editText to a string here*/
String userDefinedDbName = mEtCustomDbName.getText().toString().trim();
/*
Calling this method to rename the existing db to what the user input
Note: The original db remains in the same folder, as it was previously
backed up from the backUpDatabase() method above. Using the if statement
below to check for a empty string and if it is, the file is not renamed.
Both situations display custom toast message dependent on which executes.
Also implementing the File.separator method to help with File naming
issues on the Android "Unix-like" filesystem
*/
if (userDefinedDbName.length() > 0) {
/* Naming to a .db extension with this method. Works with SQLite */
renameDbFile(File.pathSeparator+userDefinedDbName);
/* Naming to a .csv extension with this method for working with Excel */
saveDbAsCsv(File.pathSeparator+userDefinedDbName);
Toast.makeText(ExistingTallyActivity.this,
/* Using the "Database Saved" string from strings.xml */
getResources().getString(R.string.database_saved),
Toast.LENGTH_LONG).show();
}else {
Toast.makeText(ExistingTallyActivity.this,
/* Using the "Database Not Saved" string from strings.xml */
getResources().getString(R.string.database_not_saved),
Toast.LENGTH_LONG).show();
}
}
});
/* Using the global "Cancel" string from strings.xml */
alert.setNegativeButton(getResources().getString(R.string.global_cancel_text), null);
alert.setCancelable(false);
AlertDialog showAlert = alert.create();
showAlert.show();
threadMenuSaveAndExport.start();
break;
Any advice or help would be greatly appreciated with this as I do want to be able to use the naming with / if desired as an option. Thanks
I'm creating a class to use in Coldfusion to replace the cfftp tag so I can do FTP over SSL. I have a custom tag that interacts with the class, using either FTPClient or FTPSClient. Connecting, logging in, putting a file, changing directories, listing files all work, but I cannot get a file for the life of me. I have tried both the retrieveFile() and retrieveFileStream methods and neither works. Below is my getFile method implemented with retrieveFileStream() and the inputstream is always null, no matter what. The file is there and the permissions are good. I just have no idea at this point. I can connect and get the file through WSFTP without a problem, so I think it's something in my implementation. Any help is appreciated!
public void getFile(String localFileName, String remoteFileName, String transferMode) {
try {
int transferFileType = 0;
existsFile(remoteFileName);
if (getReturnValue() != "YES" || replyCode == 550) {
throw new IOException("File " + remoteFileName + " does not exist");
}
else {
Boolean transferComplete = false;
File downloadFile = new File(localFileName);
OutputStream output = new BufferedOutputStream(new FileOutputStream(downloadFile));
InputStream input;
byte[] bytesArray = new byte[4096];
int bytesRead = -1;
if (!downloadFile.canWrite()) {
setSucceeded(false);
output.close();
throw new IOException("Cannot write to file " + localFileName);
}
if (!isConnected()) {
setSucceeded(false);
output.close();
throw new IOException("Connection closed by server.");
}
if (getSecure()) {
if (transferMode.toUpperCase() == "BINARY") {
ftps.setFileType(ftps.BINARY_FILE_TYPE);
}
else {
ftps.setFileType(ftps.ASCII_FILE_TYPE);
}
ftps.enterLocalPassiveMode();
ftps.setRemoteVerificationEnabled(false);
try {
input = ftps.retrieveFileStream(remoteFileName);
setReplyCode(true);
if (input == null || replyCode == 550) {
setSucceeded(false);
output.close();
throw new IOException("Cannot read file " + remoteFileName);
}
else {
while ((bytesRead = input.read(bytesArray)) != -1) {
output.write(bytesArray, 0, bytesRead);
output.flush();
}
input.close();
output.close();
transferComplete = ftps.completePendingCommand();
setReplyCode(true);
}
}
catch (IOException e) {
processError(e);
}
}
else {
if (transferMode.toUpperCase() == "BINARY") {
ftp.setFileType(ftps.BINARY_FILE_TYPE);
}
else {
ftp.setFileType(ftps.ASCII_FILE_TYPE);
}
ftp.enterLocalPassiveMode();
ftp.setRemoteVerificationEnabled(false);
try {
input = ftp.retrieveFileStream(remoteFileName);
setReplyCode(true);
if (input == null || replyCode == 550) {
setSucceeded(false);
output.close();
throw new IOException("Cannot read file " + remoteFileName);
}
else {
while ((bytesRead = input.read(bytesArray)) != -1) {
output.write(bytesArray, 0, bytesRead);
output.flush();
}
input.close();
output.close();
transferComplete = ftp.completePendingCommand();
setReplyCode(true);
}
}
catch (IOException e) {
processError(e);
}
}
//setReturnValue("Bytes Read: " + Integer.toString(bytesRead));
setSucceeded(transferComplete);
setReplyCode(true);
}
}
catch (IOException e) {
processError(e);
}
}
Here's my open connection method:
public void open (String server_in, int port_in, int timeout_in, String username_in, String password_in, Boolean implicit_in, Boolean secure_in) {
try {
FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
if (secure_in) {
setSecure(true);
ftps = new FTPSClient("SSL", implicit_in); // Create the client object
ftps.configure(conf); // Set the system type
String[] protocolVersions = {"SSLv3"};
ftps.setEnabledProtocols(protocolVersions); // Enable SSLv3 protocol
ftps.setAutodetectUTF8(true); // Enable auto detect
ftps.connect(server_in, port_in); // Connect
setReplyCode(true); // Get server response
ftps.setConnectTimeout(timeout_in);
if (!FTPReply.isPositiveCompletion(replyCode))
{
ftps.disconnect();
throw new Exception("FTP server refused connection.");
}
ftps.login(username_in, password_in);
setReplyCode(true); // Get server response
ftps.execPBSZ(0); // Set protection buffer to 0
ftps.execPROT("P"); // Private protocol
ftps.enterLocalPassiveMode();
}
else {
setSecure(false);
ftp = new FTPClient(); // Create the client object
ftp.configure(conf); // Set the system type
ftp.connect(server_in, port_in);
setReplyCode(true); // Get server response
ftp.setAutodetectUTF8(true); // Enable auto detect
ftp.setConnectTimeout(timeout_in);
if (!FTPReply.isPositiveCompletion(replyCode))
{
ftp.disconnect();
throw new Exception("FTP server refused connection.");
}
ftp.login(username_in, password_in);
setReplyCode(true); // Get server response
ftp.enterLocalPassiveMode();
}
setSucceeded(true);
}
catch (Exception e) {
processError(e);
}
}
Ok, figured it out. If you look at my getFile() method above you'll see that I first check to make sure the file exists with existsFile(remoteFileName). Well, the method I was using to see if a file exists was to to open an InputStream with retrieveFileStream() to it within a try block and throw an error if it failed. I never called completePendingCommand() after the retrieveFileStream() in existsFile(), so trying to open another stream to the file always failed. Phew!
I'm still receiving 1st file my app generated for me.
First , I thought it's because the file exists so I wrote
File file=new File(getCacheDir(), "Competition.xls");
if (file.exists()) {file.delete(); file =new File(getCacheDir(), "Competition.xls");}
But that didn't help me-I still receive first file that was made
I'm new to working with files so I decided to copy entire method here. Sorry for a lot of text.
private void createFileTosend() {
InputStream inputStream = null;
FileOutputStream outputStream = null;
try {
File toSend=null;
try {
toSend = getFile();
} catch (WriteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
inputStream = new FileInputStream(toSend);
outputStream = openFileOutput("Competition.xls",
Context.MODE_WORLD_READABLE | Context.MODE_APPEND);
byte[] buffer = new byte[1024];
int length = 0;
try {
while ((length = inputStream.read(buffer)) > 0){
outputStream.write(buffer, 0, length);
}
} catch (IOException ioe) {
/* ignore */
}
} catch (FileNotFoundException fnfe) {
/* ignore */
} finally {
try {
inputStream.close();
} catch (IOException ioe) {
/* ignore */
}
try {
outputStream.close();
} catch (IOException ioe) {
/* ignore */
}
}
}
public File getFile() throws IOException, WriteException{
File file=new File(getCacheDir(), "Competition.xls");
if (file.exists()) {file.delete(); file =new File(getCacheDir(), "Competition.xls");}
WritableWorkbook workbook = Workbook.createWorkbook(file);
//then goes long block with creating a .xls file which is not important
workbook.write();
workbook.close();
return file;
}
Help on understanding where the problem is
You should never have a structure like :
catch(Exception ex ) {
//ignore (or log only)
}
Exception are there to tell you something went wrong. What you do is called (in french) "eating/hiding exceptions". You are loosing this very important information that something went abnormally.
You should always either throw the exception you catch to your caller, or process it locally. At the very least, and this is a poor practice, you should log it. But doing nothing is just very wrong.
Here, put the whole try catch in a method for instance :
private void createFileTosend() throws IOException {
InputStream inputStream = null;
FileOutputStream outputStream = null;
try {
File toSend = getFile();
inputStream = new FileInputStream(toSend);
outputStream = openFileOutput("Competition.xls",
Context.MODE_WORLD_READABLE | Context.MODE_APPEND);
byte[] buffer = new byte[1024];
int length = 0;
while ((length = inputStream.read(buffer)) > 0){
outputStream.write(buffer, 0, length);
}
} finally {
try {
if( inputStream != null ) {
inputStream.close();
}
} catch (IOException ioe) {
Log.e( ioe );
}
try {
if( outputStream != null ) {
outputStream.close();
}
} catch (IOException ioe) {
Log.e( ioe );
}
}
}
And now, when you call createFileToSend, do that in a try/catch structure and toast a message, or something if you catch an exception.
I am using the following code to ensure that the file contents are written successfully to disk
public void copyFileFromUrl(URL source, File target, int count) throws IOException {
InputStream in = null;
OutputStream out = null;
if (target != null) {
try {
if (!target.exists()) {
target.createNewFile();
if (source == null) {
return;
} else {
in = source.openStream();
}
out = new FileOutputStream(target);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
log.debug("The contents from the URL: " + source + " are successfully written to the file " + target);
//add for successfull
} else {
log.debug("skipping creation of asset");
}
} catch (Exception e) {
if(count < 3){
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
// Attempt to delete it
boolean success = target.delete();
if (!success) {
log.debug("Unable to delete " + target);
} else {
copyFileFromUrl(source, target, ++count);
}
} else {
log.debug(e.getClass().getName());
e.printStackTrace();
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
}
I am calling this code like this
while(iter.hasNext()) {
CourseMaterials cm = iter.next();
String url;
try {
Asset asset = cm.getAsset();
List<AssetVersion> av = asset.getAssetVersions();
} catch (Exception e1) {
log.debug("Bad asset so skipping...");
e1.printStackTrace();
continue;
}
....
try {
URL earl = new URL(visualElementURL);
scormFileWriter.copyFileFromUrl(earl, new File(absoluteFileName), 0);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
Now how i am trying is like, When i come to function copyFileFromUrl(), i unplug the cable, it tries two times, then on third time i plug in the cable. The function returns successfully. As i am in while loop. Now after that when i come to line
Asset asset = cm.getAsset();
I get Connection Reset by peer exception. It skips this asset and then again it starts normally. Why ? Why i am getting connection Reset by peer exception ? If i am getting this exception because of unplug the cable then i should get it for all other assets also, but i am getting this exception only for the next iteration, then it starts working fine, i mean then line Asset asset = cm.getAsset(); throws no exception after throwing first time?
Why this is happening? How can i overcome it?
I am using SQL server 2008 for database.
Thanks
You may try using flush() method before close() method