Question

Here's my current situation:
Eclipse
Win7
Samsung SII (for testing)

I am writing an Application that will read from a file stored privately on the device when it starts, and then, i want to write to that same file (overwrite basically) when the application's onDestroy() is called.

I first tried to extend the application with my own class, and then read and write to that file on the constructor and destroy of that class, however, reading or writing within that class seems to not be allowed as my application simply crashes every time as it starts. So i thought about it for a while and resigned myself to doing this at the main menu, since this is the only activity that i do not "destroy" (or ActivityName.this.finish();). but my programmer brain would like to make this happen at the application level, and not the activity level.

So is it possible for me to read from the file in the Application class constructor i created, and write to the file in the onDestroy()? if so, how? My application just constantly crashes/won't even start...

This is the code i use. this effectively reads a file, and stores some strings into global memory (spare me the "no no no"'s please... Global vars are very useful to me), then overwrites the file when onDestroy() is called with the values in Global vars (i know this because it works at the activity level):

CONSTRUCTOR:
super();

    try 
    {
        String origprefs =",0,1-1";

        File f = new File(this.getFilesDir(),FILENAME);

        if(!f.exists())
        {
            FileOutputStream fos2 = new FileOutputStream(f);
            fos2.write(origprefs.getBytes());
            fos2.close();
        }

        FileInputStream fis;
        fis = openFileInput(FILENAME);
        StringBuffer fileContent = new StringBuffer("");

        byte[] buffer = new byte[1024];
        int length;
        while ((length = fis.read(buffer)) != -1) {
            fileContent.append(new String(buffer));
        }
        fis.close();

        origprefs = fileContent.toString();

        //set our globals
        Username = origprefs.split(",")[0];
        Score = origprefs.split(",")[1];
        Stage = origprefs.split(",")[2];

    } 
    catch (IOException e) 
    {
        throw new RuntimeException("Unable to either Read or Write to Match Two file.");
    }

onDestroy:
if(GameRunning)
    {
        try
        {
            FileOutputStream fis;
                fis = openFileOutput(FILENAME, this.MODE_PRIVATE);
                String fileContent = Username + "," + Score + "," + Stage;
                fis.write(fileContent.getBytes());
                fis.close();
        }
        catch(IOException e)
        {
            throw new RuntimeException("Unable to either Read or Write to Match Two file.");
        }
    }

Now, this is the same process, minus a few alterations to get the proper context, inside the MainMenu class. I just can't wrap my head around why this would crash my app when i do it at the application level? thanks a ton for any help!

here's the logcat entries logcat is cryptic i find...

08-08 02:03:58.362: E/AndroidRuntime(10360): FATAL EXCEPTION: main
08-08 02:03:58.362: E/AndroidRuntime(10360): java.lang.RuntimeException: Unable to instantiate application maxovrdrv.FirstApp.MatchTwo: java.lang.NullPointerException
08-08 02:03:58.362: E/AndroidRuntime(10360):    at android.app.LoadedApk.makeApplication(LoadedApk.java:466)
08-08 02:03:58.362: E/AndroidRuntime(10360):    at android.app.ActivityThread.handleBindApplication(ActivityThread.java:3268)
08-08 02:03:58.362: E/AndroidRuntime(10360):    at android.app.ActivityThread.access$2200(ActivityThread.java:117)
08-08 02:03:58.362: E/AndroidRuntime(10360):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:973)
08-08 02:03:58.362: E/AndroidRuntime(10360):    at android.os.Handler.dispatchMessage(Handler.java:99)
08-08 02:03:58.362: E/AndroidRuntime(10360):    at android.os.Looper.loop(Looper.java:130)
08-08 02:03:58.362: E/AndroidRuntime(10360):    at android.app.ActivityThread.main(ActivityThread.java:3691)
08-08 02:03:58.362: E/AndroidRuntime(10360):    at java.lang.reflect.Method.invokeNative(Native Method)
08-08 02:03:58.362: E/AndroidRuntime(10360):    at java.lang.reflect.Method.invoke(Method.java:507)
08-08 02:03:58.362: E/AndroidRuntime(10360):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:907)
08-08 02:03:58.362: E/AndroidRuntime(10360):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:665)
08-08 02:03:58.362: E/AndroidRuntime(10360):    at dalvik.system.NativeStart.main(Native Method)
08-08 02:03:58.362: E/AndroidRuntime(10360): Caused by: java.lang.NullPointerException
08-08 02:03:58.362: E/AndroidRuntime(10360):    at android.content.ContextWrapper.getFilesDir(ContextWrapper.java:178)
08-08 02:03:58.362: E/AndroidRuntime(10360):    at maxovrdrv.FirstApp.MatchTwo.<init>(MatchTwo.java:26)
08-08 02:03:58.362: E/AndroidRuntime(10360):    at java.lang.Class.newInstanceImpl(Native Method)
08-08 02:03:58.362: E/AndroidRuntime(10360):    at java.lang.Class.newInstance(Class.java:1409)
08-08 02:03:58.362: E/AndroidRuntime(10360):    at android.app.Instrumentation.newApplication(Instrumentation.java:957)
08-08 02:03:58.362: E/AndroidRuntime(10360):    at android.app.Instrumentation.newApplication(Instrumentation.java:942)
08-08 02:03:58.362: E/AndroidRuntime(10360):    at android.app.LoadedApk.makeApplication(LoadedApk.java:461)
08-08 02:03:58.362: E/AndroidRuntime(10360):    ... 11 more

Matt

Was it helpful?

Solution

You Should read the docs of onDestroy.. you should use onPause instead. read below for more detail

do not count on this(onDestroy()) method being called as a place for saving data! For example, if an activity is editing data in a content provider, those edits should be committed in either onPause() or onSaveInstanceState(Bundle),

protected void onDestroy ()
Since: API Level 1

Perform any final cleanup before an activity is destroyed. This can happen either because the activity is finishing (someone called finish() on it, or because the system is temporarily destroying this instance of the activity to save space. You can distinguish between these two scenarios with the isFinishing() method.

Note: do not count on this method being called as a place for saving data! For example, if an activity is editing data in a content provider, those edits should be committed in either onPause() or onSaveInstanceState(Bundle), not here. This method is usually implemented to free resources like threads that are associated with an activity, so that a destroyed activity does not leave such things around while the rest of its application is still running. There are situations where the system will simply kill the activity's hosting process without calling this method (or any others) in it, so it should not be used to do things that are intended to remain around after the process goes away. Derived classes must call through to the super class's implementation of this method. If they do not, an exception will be thrown.

reference link :- Android onDestroy

OTHER TIPS

I think you choice of data store is causing you more problems than it is worth. I don't know of many siutations that are relying on the process coming up and dieing to manage data flow.

By your variable names perhaps SharedPreferences is a more appropriate data structure? http://developer.android.com/reference/android/content/SharedPreferences.html

If you persist with a flat file, then I think you should still be managing the data store using a contentprovider.

http://www.vogella.com/articles/AndroidSQLite/article.html

Now the tute does use a sqlite backed content provider. But you can use a flat file anyway.

Anyway, why the app is crashing is a separate problem from the timing of your data flow.

Everything Pork and Ankit said. Additionally, do not perform file I/O on your main (UI) thread! Unless you are persisting a huge amount of information, I think SharedPreferences is the way to go. It's ideal for storing the couple of dozen odd values that you need to recreate the state of your app.

Looking in the docs here, it seems there is no onDestroy method for the Application class, so that appears to make that idea a non-starter right there.

I don't know why you're trying to re-invent the wheel, but I'd abandon it and use the standard practices that everyone else is using... there's a reason they're standard practices. :p

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top