Moving database on Android - java

I am shipping my Android application with an SQLite database (300 KB), and after what I read I need to move it in order to use it. In iOS you move the database from the app to the documents folder because you can't write to the app because it is signed. Is this the reason on Android as well? So back to my question. The following code does not copy the database correctly, it only copies some of it. Why so? Have I done something wrong here.
private final static String DB_NAME = "klb.sqlite";
dbPath = "/data/data/" + context.getPackageName() + "/databases/"; // setting this in constructor
(The lines above is private members, applies to both code examples below)
BufferedInputStream bis = new BufferedInputStream(context.getAssets().open(DB_NAME));
FileOutputStream fos = new FileOutputStream(dbPath + DB_NAME);
while (bis.read() != -1) {
fos.write(bis.read());
}
bis.close();
fos.flush();
fos.close();
However this works: (Sorry for being lazy about re-indenting)
InputStream inputStream = context.getAssets().open("klb.sqlite");
OutputStream outputStream = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, length);
}
inputStream.close();
outputStream.close();

while (bis.read() != -1) {
fos.write(bis.read());
}
Look at that closely. Your calling read twice, but write once. You're effectively skipping every other byte.

Related

android copy mp3 file success but duration not change

i try to copy mp3 file in external storage and limit duration of new file. it work but when it started, although i run to limit time, it still display end time like old file.
private void copy(File in, File out) throws IOException {
FileInputStream is = null;
FileOutputStream os = null;
try {
is = new FileInputStream(in);
os = new FileOutputStream(out);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0 && out.length()<175642) {
os.write(buffer, 0, length);
}
} finally {
assert is != null;
is.close();
assert os != null;
os.close();
}
}
how can i fix it. i really expect your help. have a nice day,everyone!
You simply cut of the rest of the file. This leads to a kind of corrupted file because the data in the header-block (e.g. the length) is no longer correct.
For some information about the mp3 file format:
https://en.wikipedia.org/wiki/MP3
I highly recommend to adjust the header information after shortening the file.

Unzipped DB in Android not readable

I am trying to transfer a SQLite database into an app by downloading it and then unzipping it to the correct location. I was successful in transferring the DB when it was unzipped. The error I get is that it cannot find any of the tables I query. I have also been successful in unzipping and reading normal text files.
The DB has Hebrew and English, but that has not caused problems before. The bilingual DB was copied successfully when it was not zipped and bilingual texts have been successfully unzipped and read. Still, it is a possibility that there is an encoding problem going on. That seems weird to me, because as you can see below in the code, I'm just copying the bytes directly.
-EDIT-
Let's say the prezipped db is called test1.db. I zipped it, put it in the app, unzipped it and called that test2.db. when I ran a diff command on these two, there were no differences. So there must be a technical issue with the way android is reading the file / or maybe encoding issue on android that doesn't exist on pc?
I hate to do a code dump, but i will post both my copyDatabase() function (which works). That is what I used previously running it on an unzipped DB file. I put it here as comparison. Now I'm trying to use unzipDatabase() function (which doesn't work), and use it on a zipped DB file. The latter function was copied from How to unzip files programmatically in Android?
private void copyDatabase() throws IOException{
String DB_NAME = "test.db";
String DB_PATH = "/data/data/org.myapp.myappname/databases/";
//Open your local db as the input stream
InputStream myInput = myContext.getAssets().open(DB_NAME);
// Path to the just created empty db
String outFileName = DB_PATH + DB_NAME;
//Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(outFileName);
//transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer))>0){
myOutput.write(buffer, 0, length);
}
//Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
private boolean unzipDatabase(String path)
{
String DB_NAME = "test.zip";
InputStream is;
ZipInputStream zis;
try
{
String filename;
is = myContext.getAssets().open(DB_NAME);
zis = new ZipInputStream(is);
ZipEntry ze;
byte[] buffer = new byte[1024];
int count;
while ((ze = zis.getNextEntry()) != null)
{
// write to a file
filename = ze.getName();
// Need to create directories if not exists, or
// it will generate an Exception...
if (ze.isDirectory()) {
Log.d("yo",path + filename);
File fmd = new File(path + filename);
fmd.mkdirs();
continue;
}
OutputStream fout = new FileOutputStream(path + filename);
// reading and writing zip
while ((count = zis.read(buffer)) != -1)
{
fout.write(buffer, 0, count);
}
fout.flush();
fout.close();
zis.closeEntry();
}
zis.close();
}
catch(IOException e)
{
e.printStackTrace();
return false;
}
return true;
}
So still don't know why, but the problem is solved if I first delete the old copy of the database (located at DB_PATH + DB_NAME) and then unzip the new one there. I didn't need to do this when copying it directly.
so yay, it was a file overwriting issue...If someone knows why, feel free to comment

Downloading a file from the internet

I am trying to download an MP3 file from the internet to an SD card in Android.
I know the desktop Java equivalent, but because I want to take advantage of some interesting looking Android based SDKs so I decided to try my hand at writing a mobile app.
Was a lot to learn, and I feel like I skipped a lot of steps.
I did something like this in Java:
File outputSong = new File("outputFolder/testSong.mp3");
is1 = new URL(currentSong).openStream();
ReadableByteChannel rbc = Channels.newChannel(is1);
FileOutputStream fos = new FileOutputStream(outputSong);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
But Android didn't like that. I looked here, the developer.android website, and some internet tutorials on how to deal with files. I tried doing this:
String currentSong = "http://nyan.90g.org/e/1/50/9f755b639fa518e7f5580b648c7b2f60.mp3";
String currentArtwork = "http://moefou.90g.org/wiki_cover/000/00/29/000002938.jpg";
String fileName = "";
URLConnection conn = new URL(currentArtwork).openConnection();
conn.setUseCaches(false);
int lastSlash = conn.getURL().toString().lastIndexOf('/');
if (lastSlash>=0)
fileName = conn.getURL().toString().substring(lastSlash+1);
if (fileName.equals(""))
fileName = conn.getURL().hashCode() + ".jpg";
BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
File outputArtwork = new File(Environment.getExternalStorageDirectory() + "/" + fileName);
FileOutputStream fos = new FileOutputStream(outputArtwork);
BufferedOutputStream bos = new BufferedOutputStream(fos);
byte[] data = new byte[8192];
int bytesRead = 0;
while((bytesRead = bis.read(data, 0, data.length)) >= 0) {
bos.write(data, 0, bytesRead);
}
bos.close();
bis.close();
I got it to work ONCE, and now I've been unsuccessful in trying to repeat the action. I got the manifest permissions in. I would be grateful if anybody could show me how they would go about this.
While I'm at it, everyone says to use logcat. Is that like printing to the console? That would be helpful.

making zip process more optimized one

I have developed a method to zip a file that will take file path and filename as a parameter and will zip a file as shown below could you please advise how can I modify this method to be more efficient and more fast as I am a big fan of optimization..
public File generateZipForAFile(String folderPath, String reportFileName)
throws FileNotFoundException, IOException {
File inputFile = new File(folderPath + reportFileName);
FileInputStream in = new FileInputStream(inputFile);
File outputZipFile = new File(folderPath, reportFileName + ".zip");
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outputZipFile));
// Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(reportFileName ));
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.closeEntry();
out.close();
in.close();
return outputZipFile;
}
There is not much you can do in your code. Furthermore, most of the time is spent while actually doing the zip.
So even if you reduce the time spent in your part to 0 the overall gain will be very small.

SQLite Database from Internet

I have a rather large database that ships with my app. I'm having a lot of trouble getting it to properly create itself on the local device, so I figure with the issues and it being so large, it might make more sense to host it on a server and work with it from there.
The database is 40 MB or less. What is the best way to manage this with it hosted somewhere?
The problem is with Database file size. You can make a Zip of your Database file and then copy it to your local path from Assets.
Here is the link: Copy Db File From Assets
Now, in that code replace the copyDataBase() function with the below one.
private void copyDataBase() throws IOException {
try {
InputStream mInputStream = mContext.getAssets().open(DB_NAME_ZIP);
String outFileName = DB_PATH + DB_NAME_ZIP;
OutputStream mOutputStream = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while ((length = mInputStream.read(buffer)) > 0) {
mOutputStream.write(buffer, 0, length);
}
ZipFile mZipFile = new ZipFile(DB_PATH + DB_NAME_ZIP);
InputStream nInputStream = mZipFile.getInputStream(mZipFile.getEntry(DB_NAME));
OutputStream nOutputStream = new FileOutputStream(DB_PATH + DB_NAME);
while ((length = nInputStream.read(buffer)) > 0) {
nOutputStream.write(buffer, 0, length);
}
nOutputStream.flush();
nOutputStream.close();
nInputStream.close();
// Close the streams
mOutputStream.flush();
mOutputStream.close();
mInputStream.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
//Delete Zip file to minimize memory usage
final String mPath = DB_PATH + DB_NAME_ZIP;
final File file = new File(mPath);
if (file.exists())
file.delete();
}
}
Here DB_NAME_ZIP is the Database Zip file what you put in Assets folder like Android.zip but it actually contains Android.sqlite or Android.db.
I hope this one can help you.

Categories