Having trouble creating a subclass of application to share data with multiple Activities

I just finished a couple of activities in my game and now I was going to start to wire them both up to use real game data, instead of the test data I was using just to make sure each piece worked. Since multiple Activities will need access to this game data, I started researching the best way to pass this data to my Activities.

I know about using putExtra with intents, but my GameData class has quite a bit of data and not just simple key value pairs. Besides quite a few basic data types, it also has large arrays. I didn’t really want to try and pass all that, unless I can pass the entire object, instead of just key/data pairs.

I read the following post and thought it would be the way to go, but so far, I haven’t got it to work.

How to declare global variables in Android?

I created a simple test app to try this method out, but it keeps crashing and my code seems to look the same as in the post above – except I changed the names. Here is the error I am getting. Can someone help me understand what I am doing wrong?

12-23 00:50:49.762: ERROR/AndroidRuntime(608): Caused by: java.lang.ClassCastException: android.app.Application

It crashes on the following statement:

GameData newGameData = ((GameData)getApplicationContext());  

Here is my code:

package mrk.examples.MainActivity;

import android.app.Application;

public class GameData extends Application {
    private int intTest;

    GameData () {
        intTest = 0;
    }

    public int getIntTest(){
        return intTest;
    }

    public void setIntTest(int value){
        intTest = value;
    }
}

// My main activity

package mrk.examples.MainActivity;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends Activity {

    int intLocal;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        GameData newGameData = ((GameData) getApplicationContext());
        newGameData.setIntTest(0);
        intLocal = newGameData.getIntTest();
        Log.d("MainActivity", "IntLocal = " + intLocal);
        newGameData.setIntTest(1);
        Log.d("MainActivity", "IntLocal = " + intLocal
                + " newGameData IntTest: " + newGameData.getIntTest());
        Intent intentNew = new Intent(this, PassData2Activity.class);
        startActivity(intentNew);
    }
}

// My test Activity to see if it can access the data and its previous state from the last activity

package mrk.examples.MainActivity;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class PassData2Activity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        GameData gamedataPass = ((GameData)getApplicationContext());
        Log.d("PassData2Activity", "gamedatapass IntTest =  " +
                                         gamedataPass.getIntTest());           
    }
}

Below is the relevant portion of my manifest:

<application android:icon="@drawable/icon"
             android:label="@string/app_name">    
    <activity android:name=".MainActivity"
              android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>            
    </activity>

    <activity android:name=".PassData2Activity"></activity>

</application> 

<application android:name=".GameData"
         android:icon="@drawable/icon"
         android:label="@string/app_name">        
</application>

Please help me understand why this code is crashing?

Also, if you think this is just the wrong approach to let multiple activities have access to the same data, please give your suggestion. Please keep in mind that I am talking about quite a few variables and some large arrays.

Answer

I’m not sure, but I think you want to combine those tags in the manifest into a single tag, like this. (You may also need to fully spell out the package name of your app, instead of using the initial . as a shortcut.)

<application android:icon="@drawable/icon"
             android:name=".GameData"
             android:label="@string/app_name">    
    <activity android:name=".StaticGameData"
              android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>            
    </activity>

    <activity android:name=".PassData2Activity"></activity>
</application> 

(By the way, I’d avoid using the names GameData for the application, and StaticGameData for the activity; these make me think that StaticGameData would be a subclass of GameData.)