I'm programming a little game and I want to save on sd-card the scores and the the volume (enabled or disabled)
the code of my two functions is:
public static void load(FileIO files) {
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(
files.readFile(".save")));
soundEnabled = Boolean.parseBoolean(in.readLine());
for (int i = 0; i < 5; i++) {
highscores[i] = Integer.parseInt(in.readLine());
}
} catch (IOException e) {
// :( It's ok we have defaults
} catch (NumberFormatException e) {
// :/ It's ok, defaults save our day
} finally {
try {
if (in != null)
in.close();
} catch (IOException e) {
}
}
}
//-----------------------
public static void save(FileIO files) {
BufferedWriter out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(
files.writeFile(".save")));
out.write(Boolean.toString(soundEnabled));
for (int i = 0; i < 5; i++) {
out.write(Integer.toString(highscores[i]));
}
} catch (IOException e) {
} finally {
try {
if (out != null)
out.close();
} catch (IOException e) {
}
}
}
while the program is running this code is ok but if I restart my device the scores are lost..
do you know why?
thanks!!
ps: the FileIO class is:
public class AndroidFileIO implements FileIO {
Context context;
AssetManager assets;
String externalStoragePath;
public AndroidFileIO(Context context) {
this.context = context;
this.assets = context.getAssets();
this.externalStoragePath = Environment.getExternalStorageDirectory()
.getAbsolutePath() + File.separator;
}
public InputStream readAsset(String fileName) throws IOException {
return assets.open(fileName);
}
public InputStream readFile(String fileName) throws IOException {
return new FileInputStream(externalStoragePath + fileName);
}
public OutputStream writeFile(String fileName) throws IOException {
return new FileOutputStream(externalStoragePath + fileName);
}
public SharedPreferences getPreferences() {
return PreferenceManager.getDefaultSharedPreferences(context);
}
}
There are two problems here. First, out.write does not insert a newline at the end of each call, you have to do that manually. So what is happening is when you do the readline in the cal to parse the Boolean you are actually consuming ALL the data in the file. Second, you need to flush and close the file before leaving that function to be sure you do not leave any data in the buffers.
Here is save rewritten that should work:
public static void save(FileIO files) {
BufferedWriter out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(
files.writeFile(".mrnom")));
out.write(Boolean.toString(soundEnabled));
out.write("\n");
for (int i = 0; i < 5; i++) {
out.write(Integer.toString(highscores[i]));
out.write("\n");
}
out.flush();
out.close();
} catch (IOException e) {
} finally {
try {
if (out != null)
out.close();
} catch (IOException e) {
}
}
}
I'm proggraming for first time but iv solved this using shared prefs. That way you avoid losing data when updating the app.
Related
I am using the com.googlecode.mp4parser library to merge audio files. I have an external audio mp3 file which I store in raw resources. This file fails to merge due to following exception, Below is my code :
Reading a file from raw folder :
InputStream is = context.getResources().openRawResource(R.raw.my_mp3_file);
OutputStream output = null;
try {
File file = new File(context.getFilesDir(), "silence.mp3");
if(!file.exists()) {
file.createNewFile();
}
output = new FileOutputStream(file);
byte[] buffer = new byte[4 * 1024]; // or other buffer size
int read;
while ((read = is.read(buffer)) != -1) {
output.write(buffer, 0, read);
}
output.flush();
output.close();
fileReference= file;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace(); // handle exception, define IOException and others
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Code that reads movie ( Which is failing ) :
if(fileReference.exists()) {
Movie m = new MovieCreator().build(fileReference.getAbsolutePath());
}
While getting this Movie m my code fails throwing the exception :
java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List com.coremedia.iso.boxes.MovieBox.getBoxes(java.lang.Class)' on a null object reference
It works for some mp3 files fails for raw resource files ? What's wrong here ?
Here are my conclusion and solution after a lot of research
MP4Parser for merging audio and video only use .m4a extension
String root = Environment.getExternalStorageDirectory().toString();
String audio = root + "/" + "tests.m4a";
String video = root + "/" + "output.mp4";
String output = root + "/" + "aud_vid.mp4";
mux(video, audio, output);
and here is the method
public boolean mux(String videoFile, String audioFile, String outputFile) {
Movie video;
try {
video = new MovieCreator().build(videoFile);
} catch (RuntimeException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
}
Movie audio;
try {
audio = new MovieCreator().build(audioFile);
} catch (IOException e) {
e.printStackTrace();
return false;
} catch (NullPointerException e) {
e.printStackTrace();
return false;
}
Track audioTrack = audio.getTracks().get(0);
video.addTrack(audioTrack);
Container out = new DefaultMp4Builder().build(video);
FileOutputStream fos;
try {
fos = new FileOutputStream(outputFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
}
BufferedWritableFileByteChannel byteBufferByteChannel = new BufferedWritableFileByteChannel(fos);
try {
out.writeContainer(byteBufferByteChannel);
byteBufferByteChannel.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
private static class BufferedWritableFileByteChannel implements WritableByteChannel {
private static final int BUFFER_CAPACITY = 1000000;
private boolean isOpen = true;
private final OutputStream outputStream;
private final ByteBuffer byteBuffer;
private final byte[] rawBuffer = new byte[BUFFER_CAPACITY];
private BufferedWritableFileByteChannel(OutputStream outputStream) {
this.outputStream = outputStream;
this.byteBuffer = ByteBuffer.wrap(rawBuffer);
}
#Override
public int write(ByteBuffer inputBuffer) throws IOException {
int inputBytes = inputBuffer.remaining();
if (inputBytes > byteBuffer.remaining()) {
dumpToFile();
byteBuffer.clear();
if (inputBytes > byteBuffer.remaining()) {
throw new BufferOverflowException();
}
}
byteBuffer.put(inputBuffer);
return inputBytes;
}
#Override
public boolean isOpen() {
return isOpen;
}
#Override
public void close() throws IOException {
dumpToFile();
isOpen = false;
}
private void dumpToFile() {
try {
outputStream.write(rawBuffer, 0, byteBuffer.position());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Seem like this issue happens because Google devs have forgotten to handle that NullPointerException case. After several hours diving into the code base, I finally found the solution and It works very fine, you can try this:
Movie movie;
try{
movie = MovieCreator.build(videoPath);
}catch(NullPointerException e){
Log.d("AsyncTask", "Catch null getMovieBoxes");
FileDataSourceImpl fileDataSource = new FileDataSourceImpl(new File(videoPath));
IsoFile isoFile = new IsoFile(fileDataSource);
List<TrackBox> trackBoxes = isoFile.getBoxes(TrackBox.class);
for (TrackBox trackBox : trackBoxes) {
SchemeTypeBox schm = Path.getPath(trackBox, "mdia[0]/minf[0]/stbl[0]/stsd[0]/enc.[0]/sinf[0]/schm[0]");
if (schm != null && (schm.getSchemeType().equals("cenc") || schm.getSchemeType().equals("cbc1"))) {
movie.addTrack(new CencMp4TrackImplImpl(fileDataSource.toString() + "[" + trackBox.getTrackHeaderBox().getTrackId() + "]", trackBox));
} else {
movie.addTrack(new Mp4TrackImpl(fileDataSource.toString() + "[" + trackBox.getTrackHeaderBox().getTrackId() + "]" , trackBox));
}
}
}
I have succesfully saved int values to sd but cant read. It always gives numberformat information. I made all logics, but cant find why it gives error.
Here is my code ;
this my constant
private final static String EXTERNAL_FILES_DIR = "ARDROID";
private final static String FILE_NAME = "turkcell.txt";
private boolean isThereAnySavedFile = false;
when this method called, it tries to open file, if file does not exist, create the file
public void anySavedDataInSD() {
String textFromSD = String.valueOf(read());
if (isThereAnySavedFile) {
int numberOfSendedSMS = Integer.parseInt(textFromSD.toString());
numberOfSendedSMS++;
writeToSD(String.valueOf(numberOfSendedSMS));
} else {
int first=60;
String g = String.valueOf(first);
writeToSD(g);
}
}
this method for writing
private void write(File file, String msg) {
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(file);
outputStream.write(msg.getBytes());
Logger.info("oldu bu kez");
} catch (IOException e) {
Logger.info("oldu bu kez2" + e);
} finally {
Logger.info("oldu bu kez3");
try {
if (outputStream != null)
outputStream.close();
} catch (IOException exception) {
}
}
}
this methof for reading
public StringBuilder read() {
StringBuilder textBuilder = new StringBuilder();
BufferedReader reader = null;
try {
File externalFilesDir = getExternalFilesDir(EXTERNAL_FILES_DIR);
File file = new File(externalFilesDir, FILE_NAME);
Logger.info("oldu2");
reader = new BufferedReader(new FileReader(file));
String line;
while ((line = reader.readLine()) != null) {
textBuilder.append(line);
textBuilder.append("\n");
}
isThereAnySavedFile = true;
} catch (FileNotFoundException e) {
Logger.info("oldu3");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return textBuilder;
}
I'm using this code to save data to file and read data from the file:
public static void save(FileIO files) {
BufferedWriter out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(
files.writeFile(".save")));
for (int i = 0; i < 20; i++) {
out.write(Integer.toString(scores[i]));
out.write("\n");
}
} catch (IOException e) {
} finally {
try {
if (out != null)
out.close();
} catch (IOException e) {
}
}
}
public static void load(FileIO files) {
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(
files.readFile(".save")));
for (int i = 0; i < 20; i++) {
scores[i] = Integer.parseInt(in.readLine());
}
} catch (IOException e) {
} catch (NumberFormatException e) {
} finally {
try {
if (in != null)
in.close();
} catch (IOException e) {
}
}
}
FileIO.java
package com.avoidblocks.avoidblocks.framework;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.content.SharedPreferences;
public interface FileIO {
public InputStream readFile(String file) throws IOException;
public OutputStream writeFile(String file) throws IOException;
public InputStream readAsset(String file) throws IOException;
public SharedPreferences getSharedPref();
}
I'm calling save(FileIO files) and load(FileIO files) multiple times in an app and it works fine while I'm in an app, but when I exit the app and start the app again, all data is gone.
Does anyone know how to create that data remains saved even when I exit the app, so that I could restore the data when I start the app again?
Also, is this the right way to save data if I want that saved data is only visible to my app and that after uninstall, all saved data is erased?
EDIT-EDIT-EDIT:
ok its your FileIO files variable that looks like it is wrong,
what are you using to get that variable?
should be
context.openFileOutput(".save", Context.MODE_PRIVATE)
for save and
context.openFileInput(".save")
for load
and it should be FileOutputStream for save and FileInputStream for read instead of FileIO.
and when adding it to the stream just pass that in.
so in your code you should create the BufferedWriter like this:
out = new BufferedWriter(new OutputStreamWriter(
context.openFileOutput(".save", Context.MODE_PRIVATE)));
and create BufferedReader like this:
in = new BufferedReader(new InputStreamReader(
context.openFileInput(".save")));
==================EDIT: my testing code=================
Ok, I created an activity and made the following two methods and declared an array of ints:
public static int scores[] = {11,12,13,14,15};
public static void save(Context context) {
BufferedWriter out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(
context.openFileOutput(".saveingTest", Context.MODE_PRIVATE)));
for (int i = 0; i < scores.length; i++) {
out.write(Integer.toString(scores[i]));
out.write("\n");
}
} catch (IOException e) {
} finally {
try {
if (out != null)
out.close();
} catch (IOException e) {
}
}
}
public static void load(Context context) {
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(
context.openFileInput(".saveingTest")));
for (int i = 0; i < scores.length; i++) {
Log.d("testingApp", "test: " + Integer.parseInt(in.readLine()));
// scores[i] = Integer.parseInt(in.readLine());
}
} catch (IOException e) {
} catch (NumberFormatException e) {
} finally {
try {
if (in != null)
in.close();
} catch (IOException e) {
}
}
}
in my onCreate I have the following two lines of code:
save(this);
load(this);
to test I did the following:
commented out load in onCreate, ran the app, than I removed the comment on load and commented out save in onCreate and i changed the numbers in the scores variable(this is unnecessary but i did it anyway) and ran the app, the result was the int values in scores from the first time the app was run, inside the android log viewer window on eclipse. you can also have buttons that trigger save and load instead if you don't want to comment and run.
try it yourself, it should work, and make sure you are doing the same thing in your actual android app, if it still dose not work you are doing something else wrong and its not an issue with saving the file.
(I'm deeply sorry for my poor english)
For a school project, i have to realize an Android Application. It uses an intern SQLite Database which is a copy from a website MySQL database. (The android application is a search engine for an Electrical Engineering database)
Since it has to be independant from the website (offline), i have to create an update option.
For this purpose, i've made a special DownloadHelper class :
#SuppressLint("SdCardPath")
public final class DownloadHelper extends AsyncTask<Void,Void,Void>
{
Context context;
File cheminBdd = new File("/data/data/com.example.btc_pe/databases/basesqlite.db");
public DownloadHelper(Context ctxt)
{ this.context = ctxt; }
#Override
protected Void doInBackground(Void... params)
{
// TODO Auto-generated method stub
try
{
downloadDatabase(cheminBdd);
//copyServerDatabase(this.context);
}
catch (Exception ex)
{
Log.e("BTC","Failed to download database !",ex);
}
return null;
}
private static void downloadDatabase(File destFile) throws IOException
{
URLConnection ucon;
InputStream is = null;
OutputStream os = null;
try
{
Log.d("BTC","start DL");
URL url = new URL("adresse" + "basesqlite.db");
ucon = url.openConnection();
Log.d("BTC","Connection open");
is = ucon.getInputStream();
Log.d("BTC","Stream In got");
os = new FileOutputStream(destFile);
Log.d("BTC","Debut copy()");
copy(is,os);
Log.d("BTC","end DL");
}
finally
{
if (os != null) try { os.close(); } catch (Exception ex) { Log.e("BTC","Failed to gracefully close output stream",ex); }
if (is != null) try { is.close(); } catch (Exception ex) { Log.e("BTC","Failed to gracefully close input stream",ex); }
}
}
public static int copy(InputStream input, OutputStream output) throws IOException
{
byte[] buffer = new byte[8192];
int count = 0;
int n = 0;
while (-1 != (n = input.read(buffer)))
{
output.write(buffer, 0, n);
count += n;
}
output.flush();
return count;
}
#SuppressLint("SdCardPath")
private void copyServerDatabase(Context context)
{
BtcDb db = new BtcDb(context,"clean.db",null,0);
// by calling this line an empty database will be created into the default system path
// of this app - we will then overwrite this with the database from the server
db.getReadableDatabase();
db.close();
OutputStream os = null;
InputStream is = null;
try {
// Log.d("BTC", "Copying DB from server version into app");
is = context.openFileInput("basesqlite.db");
os = new FileOutputStream("/data/data/com.example.btc_pe/databases/");
copyFile(os, is);
}
catch (Exception e)
{
Log.e("BTC", "Server Database was not found - did it download correctly?", e);
}
finally
{
try
{
//Close the streams
if(os != null)
{
os.close();
}
if(is != null)
{
is.close();
}
}
catch (IOException e)
{
Log.e("BTC", "failed to close databases");
}
}
Log.d("BTC", "Done Copying DB from server");
}
private static void copyFile(OutputStream os, InputStream is) throws IOException
{
byte[] buffer = new byte[1024];
int length;
while((length = is.read(buffer))>0)
{
os.write(buffer, 0, length);
}
os.flush();
}
}
I call the update by an Actionbar button, using DownloadHelper.execute() method from an instanciated object.
Then i get an exception after passed the "is = ucon.getInputStream();", i get this LogCat :
http://www.dump-it.fr/btcpng/7865ef3fef44de25fd62f01dad23d02d.png.html
Of course, i checked this file on the server, my URL, my Android Devices. Nothing to do.
If somebody could give me a hand, i'm getting lost :/
Since Google analytics can raise many privacy concerns, I implemented an events logger.
My first idea is to track user's generated events into a logfile and then send them back to the server that will perform the analysis of data for the System Administrator and Application Engineers.
For the moment the idea is to instantiate the Logger into an Application or a Service class and use those elements onCreate and onDestroy to safely handle the LogFile.
The solution is quite simple:
Open file
Append to it every time an event is generated
Once the a MAX_NUM_LINES is reached, send the log to the server (possibly I'll zip the text file I am generating)
I wonder if there's anything already baked there in the wild I am unaware of that you might know (something like ACRA).
Every contribution will be appreciated.
Here my implementation.
However any better version is much appreciated.
The TSG objet is just a static class that I use as time manager.
Use the code and improve it as long as you repost / edit the modifications.
public class Logger {
private BufferedWriter logFile;
private String nameFile;
public int fileLines;
private File fTemp;
private timeStampGenerator TSG;
private int LOG_LINES_LIMIT = 100;
private Object mutex;
public enum EventType {
BUTTON_PRESSED,
PAGE_VIEWED,
LOADED_ACTIVITY,
GENERIC_EVENT
}
public Logger (String fileName) throws IOException {
nameFile = fileName;
createLogFile();
fileLines = countLines();
TSG = new timeStampGenerator();
// This is our mutex to access to the file
mutex = new Object();
}
public void createLogFile() throws IOException{
fTemp = new File (nameFile);
if (!fTemp.exists()) {
fTemp.createNewFile();
}
logFile = new BufferedWriter(new FileWriter(nameFile, true));
}
public void LogEvent(EventType event, String comment, String value) {
String line = "";
line += TSG.getTimestampMillis();
line += ",";
line += event.name();
line += ",";
if (comment != "") {
line += comment.replaceAll(",", ";");
} else {
line += " ";
}
line += ",";
if (value != "") {
line += value.replaceAll(",", ";");
} else {
line += " ";
}
line += "\n";
synchronized (mutex) {
try {
logFile.append(line);
} catch (IOException e) {
// Do wathever you want here
}
fileLines++;
}
}
public int countLines() //throws IOException
{
InputStream is;
try {
is = new BufferedInputStream(new FileInputStream(nameFile));
} catch (FileNotFoundException e1) {
//let's consider it an empty file
return 0;
}
int count = 0;
boolean empty = true;
try {
int readChars = 0;
byte[] c = new byte[1024];
while ((readChars = is.read(c)) != -1) {
empty = false;
for (int i = 0; i < readChars; ++i) {
if (c[i] == '\n')
++count;
}
}
} catch(IOException e) {
// Do wathever you want here
}
try {
is.close();
} catch (IOException e) {
// Do wathever you want here
}
return (count == 0 && !empty) ? 1 : count;
}
public boolean isLimitReached() {
return (fileLines >= LOG_LINES_LIMIT);
}
public void close () {
flush();
try {
logFile.close();
} catch (IOException e) {
// Do wathever you want here
}
}
/**
* clear the content of the file
*/
public void clearFile() {
synchronized (mutex) {
if ( fTemp.delete() ) {
try {
createLogFile();
} catch (IOException e1) {
// Do wathever you want here
}
}
}
}
/**
* Get the full content of the file
* #return the content
*/
public String getContent() {
StringBuffer fileData = new StringBuffer();
synchronized (mutex) {
try {
BufferedReader reader = new BufferedReader(new FileReader( nameFile ));
char[] buf = new char[1024];
int numRead = 0;
while ((numRead = reader.read(buf)) != -1) {
String readData = String.valueOf(buf, 0, numRead);
fileData.append(readData);
}
reader.close();
} catch (IOException e) {
// Do wathever you want here
}
}
return fileData.toString();
}
public void flush() {
try {
logFile.flush();
} catch (IOException e) {
// Do wathever you want here
}
}
}