0

Just following this question: Using Google Analytics To Track Fragments I have an app which implements a Navigation Drawer, so they're Fragments but Google Analytics don't work on this line:

final Tracker tracker = ((App) getActivity().getApplication()).getTracker();

The Fragment:

public class Accueil extends android.support.v4.app.Fragment {

@Override
public void onResume() {

    super.onResume();

    final Tracker tracker = ((App) getActivity().getApplication()).getTracker();
    if(tracker != null){

        tracker.setScreenName(getClass().getSimpleName());
        tracker.send(new HitBuilders.ScreenViewBuilder().build());
    }
}
    }

App:

public class App extends Application {
private static final String TAG = "App";
public synchronized Tracker getTracker() {

    try {
        final GoogleAnalytics googleAnalytics = GoogleAnalytics.getInstance(this);
        return googleAnalytics.newTracker(R.xml.app_tracker);

    }catch(final Exception e){
        Log.e(TAG, "Failed to initialize Google Analytics V4");
    }

    return null;
}
}

And I have MainActivity for the Navigation Drawer:

public class MainActivity extends AppCompatActivity implements FragmentDrawer.FragmentDrawerListener {
...
}

LOGCAT:

07-09 08:23:06.688    1125-1125/(package) E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.RuntimeException: Unable to resume activity {(package)/(package).MainActivity}: java.lang.ClassCastException: android.app.Application cannot be cast to (package).App
            at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2443)
            at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2471)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1985)
            at android.app.ActivityThread.access$600(ActivityThread.java:122)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1146)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4340)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.ClassCastException: android.app.Application cannot be cast to (package).App
            at (package).Accueil.onResume(Accueil.java:53)
            at android.support.v4.app.Fragment.performResume(Fragment.java:1832)
            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:995)
            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1138)
            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1120)
            at android.support.v4.app.FragmentManagerImpl.dispatchResume(FragmentManager.java:1939)
            at android.support.v4.app.FragmentActivity.onResumeFragments(FragmentActivity.java:447)
            at android.support.v4.app.FragmentActivity.onPostResume(FragmentActivity.java:436)
            at android.support.v7.app.AppCompatActivity.onPostResume(AppCompatActivity.java:138)
            at android.app.Activity.performResume(Activity.java:4552)
            at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2433)
            at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2471)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1985)
            at android.app.ActivityThread.access$600(ActivityThread.java:122)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1146)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4340)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
            at dalvik.system.NativeStart.main(Native Method)

Error when I put App class in my AndroidManifest:

on: android:label="@string/app_name" ERROR = (package).App is not assignable to 'Android.app.activity':

<activity
    android:name=".App"
    android:label="@string/app_name"
    android:screenOrientation="portrait">
    <intent-filter>
        <action android:name="android.intent.action.APP" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>
Community
  • 1
  • 1
  • 1
    did you declare your application's subclass in the manifest ? – Blackbelt Jul 09 '15 at 08:38
  • As Blackbelt said, the exceptions says that your used Application context is still the base impl. of the SDK and not yours. Your own Application Context is only loaded when defined in Manifest Application Tag. – Rene M. Jul 09 '15 at 08:39
  • @Blackbelt Talking about App class ? I already tryed to put it in my mManifest but I get an error, look at my edit please –  Jul 09 '15 at 08:45
  • @ReneM. Talking about App class ? I already tryed to put it in my mManifest but I get an error, look at my edit please –  Jul 09 '15 at 08:45
  • 1
    instead of using `.App` use the fully qualified package to `App` – Blackbelt Jul 09 '15 at 08:48
  • @Blackbelt same error "is not assignable to..." –  Jul 09 '15 at 08:51
  • 1
    But you are in the wrong tag. It goes on the application tag not in the Activity's one – Blackbelt Jul 09 '15 at 08:52
  • Please provide full packname + manifest including described activity and the rest around it + gradle build file for app module – Rene M. Jul 09 '15 at 08:52
  • @Blackbelt I did not totally understand the system of the Manifest but now it's clearer thanks guy :) –  Jul 09 '15 at 09:06

1 Answers1

0

Here minimum manifest defining package, application context and a main acitivty:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="my.app.package.name">

    <application
        android:name=".MyCustomApplicationContext"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">

        <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>
    </application>

</manifest>

Important properties are:

  1. Manifest tag (root node) attribute package defines the apps package which is then prefix for all classpathes starting with .
  2. Application tag attribute android:name defines the Application Context class to overload the SDK Application Class
  3. Activity Tag attribute android:name Name of activity class

Regarding comment how about using more then one Application Class. First this is not possible an Android app can only have one Context. But you can chain Implementations to seperate functionality. Here an example of a chained application context:

Base Impl. of a custom Application context introducing some useful methods:

public class UtilApp extends Application {
    ...
    some useful methods
    ...
}

Chained Application context by extending first Impl. of Context. This one now includes Application and all Usefull Methods out of UtilApp, too.

public class MyApp extends UtilApp {
    ...
    some useful methods
    ...
}

Use the highest impl. in the chain as your Context.

<application
        android:name=".MyApp" ...>
Rene M.
  • 2,660
  • 15
  • 24
  • I see thanks, and if I have two classes extend Application how we will do ? –  Jul 09 '15 at 09:06
  • 1
    Then you have to chain them, because an Android App can only have one Application Context! – Rene M. Jul 09 '15 at 09:07