Error on my fragment “android.app.Application cann

2019-09-10 06:21发布

问题:

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>

回答1:

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" ...>