I am currently on the beginner level when it comes to Android & I am currently scratching my head over an issue that I am currently facing.
I am creating an Android app to check if "cache.json" exists in the internal storage:
If it does not exist then first create it & write a string fetched from HTTP API to the file (replaced with fixed string in code below).
Regardless, read the file after writing is done (if necessary) & do appropriate stuff.
This is the code snippet:
public class ShowClasses extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
filename = "cache.json";
file = new File(getApplicationContext().getFilesDir(), filename);
if (file.exists()) {
System.out.println("EXISTS");
} else {
System.out.println("DOES NOT EXIST");
writeFile();
}
readFile();
}
public void writeFile() {
new JsonTask().execute(email);
}
public void readFile() {
FileInputStream fin = null;
try {
fin = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
int c;
result = "";
try {
while( (c = fin.read()) != -1){
result = result + Character.toString((char)c);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
fin.close();
} catch (IOException e) {
e.printStackTrace();
}
return;
}
private class JsonTask extends AsyncTask<String, Void, String> {
protected void onPreExecute() {
result = ""; // Clear result
super.onPreExecute();
pd.setMessage("Please wait");
pd.setCancelable(false);
pd.show();
}
protected String doInBackground(String... params) {
return "THIS STRING IS GOING TO BE RETURNED " + params[0];
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
FileOutputStream fileout = null;
try {
fileout = new FileOutputStream(file);
fileout.write(result.getBytes());
//display file saved message
msg("File saved successfully!");
} catch (Exception e) {
e.printStackTrace();
}
try {
fileout.close();
} catch (IOException e) {
e.printStackTrace();
}
if (pd.isShowing()){
pd.dismiss();
}
}
}
}
I have tried to remove un-necessary part of the code so that it is smaller in length.
The actual issue I am facing is when writeFile() & readFile() both are called. I get a FileNotFoundException in readFile() when I open the stream even though the file should be created since writeFile() is called before readFile().
If I writeFile on one execution & then call readFile() on the other, it simply works as it should be.
This is the error that I am facing.
System.err: java.io.FileNotFoundException: /data/user/0/host.timetable.timetablenotifier/files/cache.json (No such file or directory)
System.err: at java.io.FileInputStream.open(Native Method)
Any help would be really appreciated.
Thanks
writeFile() is asynchronous. When that method returns, nothing has happened with respect to this file. At most, onPreExecute() of your JsonTask might be called. So, when you call readFile(), the file will not exist yet.
Beyond that:
You have an AsyncTask that you use in writeFile(), but you do your disk I/O in onPostExecute(), and that method is called on the main application thread.
You are doing disk I/O on the main application thread in readFile().
You catch exceptions, log them, but then continue executing your code, when most of those exceptions mean that the later statements are going to fail as well.
Reading in data one int at a time has not been a recommended approach for getting close to 20 years, for performance reasons.
You will have multiple issues related to configuration changes, such as screen rotations, as neither your AsyncTask nor your ProgressDialog account for configuration changes
Also:
getApplicationContext().getFilesDir() could be replaced by getFilesDir() in onCreate()
You do not need createNewFile()
AsyncTask runs in a background thread so the other code in the main thread doesn't wait for the execution to complete. In simpler terms, your readFile() method is executed before writeFile() completes and hence there is a FileNotFoundException. What would work for you is if you put the readFile() method at the end of the onPostExecute() method inside your Asynctask
Related
Hey I am trying to upload an image to my ftp server but from some reason the connection isn't working and I can figure out why..
here is the connection code:
public void uploadingFilestoFtp() throws IOException {
FTPClient ftpclient = new FTPClient();
FileInputStream fis = null;
boolean result;
try {
ftpclient.connect(host);
result = ftpclient.login(username, password);
if (result == true) {
System.out.println("Logged in Successfully !");
} else {
System.out.println("Login Fail!");
return;
}
ftpclient.setFileType(FTP.BINARY_FILE_TYPE);
ftpclient.changeWorkingDirectory("/");
File file = new File(imagePath);
fis = new FileInputStream(file);
// Upload file to the ftp serverresult = ftpclient.storeFile(testName, fis);
if (result == true) {
System.out.println("File is uploaded successfully");
} else {
System.out.println("File uploading failed");
}
ftpclient.logout();
} catch (FTPConnectionClosedException e) {
e.printStackTrace();
} finally {
try {
ftpclient.disconnect();
} catch (FTPConnectionClosedException e) {
System.out.println(e);
}
}
}
I am using exactly the details of the ftp server but it doesn't seems to work
How can I get this mehod to work?
android.os.NetworkOnMainThreadException
You are trying to make a network request from the UI thread. Android doesn't allow any network request from main(UI) thread. You need to create a class extending AsyncTask.
public class UploadFileTask extends AsyncTask <Void, Void, Void > {
public void onPreExecute() {
}
public void doInBackground(Void...unused) {
uploadingFilestoFtp(); //Call your method here. Put necessary try-catch block.
}
public void onPostExecute(Void unused) {
// do something when upload is done.
}
}
Note that this onPreExecute() and onPostExecute() run on the UI thread. So you can do any stuff before or after the network call. Make the network call in doInBackground() method.
Check this answer How to fix android.os.NetworkOnMainThreadException?
Provided I have an array of image URLs, I am trying to download all these images one-by-one using glide. Presently, I am able to download a single image when I provide its URL. And here is the code:
private void downx()
{
File sd = getExternalCacheDir();
File folder = new File(sd, "/mobio/");
if (!folder.exists()) {
if (!folder.mkdir()) {
Log.e("ERROR", "Cannot create a directory!");
} else {
folder.mkdirs();
}
}
final File[] fileName = {new File(folder, "one.jpg"), new File(folder, "two.jpg"),new File(folder, "three.jpg")};
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params)
{
try
{
theBitmap = Glide.
with(getApplicationContext()).
load(urls[2]).
asBitmap().
into(Target.SIZE_ORIGINAL,Target.SIZE_ORIGINAL).
get();
}
catch (final ExecutionException e)
{
Log.e("TAG", e.getMessage());
}
catch (final InterruptedException e)
{
Log.e("TAG", e.getMessage());
}
return null;
}
#Override
protected void onPostExecute(Void dummy) {
if (null != theBitmap) {
// The full bitmap should be available here
Log.d("TAG", "Image loaded");
Log.e("GLIDE","I am Ready");
try {
FileOutputStream outputStream = new FileOutputStream(String.valueOf(fileName[1]));
theBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
outputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}.execute();
}
Now the problem is: What approach do I adopt if I need to download multiple images, and how do I force my code to adapt to handle multiple downloads?
I have used a class which takes a list of URLs and downloads the Images to a file. Please check this Gist for more. This uses Picasso to download Images but you can edit the download code to use glide as well. Should be a one line change. Hope this helps.
https://gist.github.com/bpr10/a765a015bf1c774816ba58c7ae6413d6
I guess it will be better to use Download Manager as it will handle queuing, network availability etc.
I have a program that needs to load data at launch. The data comes from a serialized object. I have a method loadData(), which is called upon construction of the Data class. Sometimes, (I.e. after a loss of saveData, or on first program launch on a new system), the file can be empty. (The file will exist though, the method ensures that).
When I try to run the program, I recieve an EOFException. So, in the method, I try to catch it, and just print a line to the console explaining what happened and return to the caller of the method. (so, upon return, the program will think loadData() is complete and has returned. However, it still crashes throwing the exception without printing a line to the console or anything. It is like it is totally ignoring the catch I have in place.
CODE:
protected void loadData()
{
// Gets/creates file object.
saveFileObject = new File("savedata.ser");
if(!saveFileObject.exists())
{
try
{
saveFileObject.createNewFile();
}
catch(IOException e)
{
System.out.println("Uh oh...");
e.printStackTrace();
}
}
// Create file input stream
try
{
fileIn = new FileInputStream(saveFileObject);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
// Create object input stream
try
{
inputStream = new ObjectInputStream(fileIn);
}
catch(IOException e)
{
e.printStackTrace();
}
// Try to deserialize
try
{
parts = (ArrayList<Part>)inputStream.readObject();
}
catch(EOFException e)
{
System.out.println("EOFException thrown! Attempting to recover!");
return;
}
catch(ClassNotFoundException e)
{
e.printStackTrace();
}
catch(IOException e)
{
e.printStackTrace();
}
// close input stream
try
{
inputStream.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
Any help please?
Try writing your code like :
protected void loadData() {
// Gets/creates file object.
saveFileObject = new File("savedata.ser");
try {
if (!saveFileObject.exists()) {
saveFileObject.createNewFile();
}
// Create file input stream
fileIn = new FileInputStream(saveFileObject);
// Create object input stream
inputStream = new ObjectInputStream(fileIn);
// Try to deserialize
parts = (ArrayList<Part>) inputStream.readObject();
// close input stream
inputStream.close();
} catch (EOFException e) {
System.out.println("EOFException thrown! Attempting to recover!");
} catch (IOException e) {
System.out.println("Uh oh...");
e.printStackTrace();
}
}
Also note that EOFException is a sub-class of IOException
How about making one try and then making catches respectively like here?
Can someone possibly help me with this?
I want to observe a file to see if it gets modified so that I can update the activity. After several tests, I've determined it's just plain not working.
Am I doing something wrong?
I'm creating a FileObserver with an onEvent method to display a Toast and log data just to see if it's working, however the onEvent is never getting called.
I have tried it both with an existing and a new file, but it doesn't seem to work in either case.
Context context = this;
File fileFolder = context.getFilesDir();
String fileName = "quest";
FileObserver questObserver = new FileObserver(fileFolder.getPath()) { // also tried fileFolder.getName()
#Override
public void onEvent(int event, String path) {
Toast.makeText(getApplicationContext(), "onEvent fired", Toast.LENGTH_LONG).show();
Log.d(TAG, "FileObserver().onEvent");
}
};
questObserver.startWatching();
/* create file */
ObjectOutputStream objectOut = null;
try {
FileOutputStream fileOut = context.openFileOutput(fileName, Context.MODE_PRIVATE);
objectOut = new ObjectOutputStream(fileOut);
objectOut.writeObject(new Quest());
fileOut.getFD().sync();
} catch (IOException e) {
Log.d(TAG, e.getMessage());
} finally {
if (objectOut != null) {
try {
objectOut.close();
} catch (IOException e) {
Log.d(TAG, e.getMessage());
}
}
}
/* read file */
ObjectInputStream objectIn = null;
Quest quest = null;
try {
FileInputStream fileIn = context.openFileInput(fileName);
objectIn = new ObjectInputStream(fileIn);
quest = (Quest) objectIn.readObject();
} catch (FileNotFoundException e) {
// Do nothing
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (objectIn != null) {
try {
objectIn.close();
} catch (IOException e) {
Log.d(TAG, e.getMessage());
}
}
}
Toast.makeText(context, quest.getTitle(), Toast.LENGTH_LONG).show();
questObserver.stopWatching();
Any help would be greatly appreciated.
'public abstract void onEvent (int event, String path)" -
This method is invoked on a special FileObserver thread. It runs
independently of any threads, so take care to use appropriate
synchronization! Consider using post(Runnable) to shift event handling
work to the main thread to avoid concurrency problems.
http://developer.android.com/reference/android/os/FileObserver.html
If you put the toast through a handler.post(new Runnable(){...}), that should work.
Assuming your file doesn't (always) exist you should probably put your observer on the files folder, obtained like so:
Context ctx = ...;
File filesFolder = ctx.getFilesDir();
Note that this will also ensure that the filesFolder directory will be created.
Your observer will now be notified whenever a file is written, deleted or updated using for instance Context#.openFileOutput(..) - and you can filter in your FileObserver for the file name, in your example "quest".
I have a saving method that runs during onPause():
String save = numberValue.getText().toString();
FileInputStream fos;
try {
fos = openFileOutput(FILENAME,Context.MODE_PRIVATE);
fos.write(save.getBytes());
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
Toast.makeText(getBaseContext(), "Save has run", Toast.LENGTH_SHORT).show();
}
and I try to read this file by calling
new Loader().execute(FILENAME);
and my Loader class looks like this:
public class Loader extends AsyncTask<String, Integer, String> {
protected void onPostExecute(String result) {
textview.setText(result);
}
#Override
protected String doInBackground(String... params) {
FileInputStream fis;
String loaded = null;
try {
fis = openFileInput(FILENAME);
byte[] dataArray = new byte[fis.available()];
while (fis.read(dataArray) != -1) {
loaded = new String(dataArray);
}
fis.close();
textview.setText(loaded);
return loaded;
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return loaded;
}
}
And I have no idea as to why the textview does not get set as the bytes from FILENAME. The idea is that the textview is an increasing number, and this number gets saved when the activity is closed and gets restored to the textview when the activity starts up again.
It does start, I know that because after a few minutes, Watch Dog tells me that a background service from this app is consuming about 50% of CPU. I did check /data/data//files and the file that I write to is there with the correct value.
You probably need to call your Loader from onResume() for this to work.
Why not just save the state you need by using the onSavedInstanceState() method? Writing stuff out to the fileSystem on the onPause method is going to making switching out of your application really slow. From the Activity Documentation regarding the onPause method:
Called when the system is about to start resuming a previous activity. This is typically used to commit unsaved changes to persistent data, stop animations and other things that may be consuming CPU, etc. Implementations of this method must be very quick because the next activity will not be resumed until this method returns.
Also, from the android documentation:
In situations where the system needs more memory it may kill paused processes to reclaim resources. Because of this, you should be sure that all of your state is saved by the time you return from this function. In general onSaveInstanceState(Bundle) is used to save per-instance state in the activity and this method is used to store global persistent data (in content providers, files, etc.)
Here's where I got that from.