【问题标题】:cannot be cast to android.app.Fragment, using FragmentActivity twice无法强制转换为 android.app.Fragment,使用两次 FragmentActivity
【发布时间】:2014-04-03 00:18:51
【问题描述】:

我目前正在使用 API Facebook,并尝试将其中一个 Scrumptious 应用程序部分添加到我的应用程序中。

美味的部分:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Base64;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import com.facebook.AppEventsLogger;
import com.facebook.Session;
import com.facebook.SessionState;
import com.facebook.UiLifecycleHelper;
import com.google.android.gms.maps.SupportMapFragment;


    public class MainActivity2 extends FragmentActivity {

        private static final String USER_SKIPPED_LOGIN_KEY = "user_skipped_login";

        private static final int SPLASH = 0;
        private static final int SELECTION = 1;
        private static final int SETTINGS = 2;
        private static final int FRAGMENT_COUNT = SETTINGS +1;

        private Fragment[] fragments = new Fragment[FRAGMENT_COUNT];
        private MenuItem settings;
        private boolean isResumed = false;
        private boolean userSkippedLogin = false;
        private UiLifecycleHelper uiHelper;
        private Session.StatusCallback callback = new Session.StatusCallback() {
            @Override
            public void call(Session session, SessionState state, Exception exception) {
                onSessionStateChange(session, state, exception);
            }
        };

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);


            try {
                PackageInfo info = getPackageManager().getPackageInfo(
                        "info.androidhive.tabsswipe", 
                        PackageManager.GET_SIGNATURES);
                for (Signature signature : info.signatures) {
                    MessageDigest md = MessageDigest.getInstance("SHA");
                    md.update(signature.toByteArray());
                    Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));
                    }
            } catch (NameNotFoundException e) {

            } catch (NoSuchAlgorithmException e) {

            }


            if (savedInstanceState != null) {
                userSkippedLogin = savedInstanceState.getBoolean(USER_SKIPPED_LOGIN_KEY);
            }
            uiHelper = new UiLifecycleHelper(this, callback);
            uiHelper.onCreate(savedInstanceState);

            setContentView(R.layout.main);

            FragmentManager fm = getSupportFragmentManager();
            SplashFragment splashFragment = (SplashFragment) fm.findFragmentById(R.id.splashFragment);
            fragments[SPLASH] = splashFragment;
            fragments[SETTINGS] = fm.findFragmentById(R.id.userSettingsFragment);
            SupportMapFragment test = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.mainActivity2);
            fragments[SELECTION] = test;

            FragmentTransaction transaction = fm.beginTransaction();
            for(int i = 0; i < fragments.length; i++) {
                transaction.hide(fragments[i]);
            }
            transaction.commit();

            splashFragment.setSkipLoginCallback(new SplashFragment.SkipLoginCallback() {
                @Override
                public void onSkipLoginPressed() {
                    userSkippedLogin = true;
                    showFragment(SELECTION, false);
                }
            });
        }

        @Override
        public void onResume() {
            super.onResume();
            uiHelper.onResume();
            isResumed = true;

            // Call the 'activateApp' method to log an app event for use in analytics and advertising reporting.  Do so in
            // the onResume methods of the primary Activities that an app may be launched into.
            AppEventsLogger.activateApp(this);
        }

        @Override
        public void onPause() {
            super.onPause();
            uiHelper.onPause();
            isResumed = false;
        }

        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            uiHelper.onActivityResult(requestCode, resultCode, data);
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            uiHelper.onDestroy();
        }

        @Override
        protected void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            uiHelper.onSaveInstanceState(outState);

            outState.putBoolean(USER_SKIPPED_LOGIN_KEY, userSkippedLogin);
        }

        @Override
        protected void onResumeFragments() {
            super.onResumeFragments();
            Session session = Session.getActiveSession();

            if (session != null && session.isOpened()) {
                // if the session is already open, try to show the selection fragment
                showFragment(SELECTION, false);
                userSkippedLogin = false;
            } else if (userSkippedLogin) {
                showFragment(SELECTION, false);
            } else {
                // otherwise present the splash screen and ask the user to login, unless the user explicitly skipped.
                showFragment(SPLASH, false);
            }
        }

        @Override
        public boolean onPrepareOptionsMenu(Menu menu) {
            // only add the menu when the selection fragment is showing
            if (fragments[SELECTION].isVisible()) {
                if (menu.size() == 0) {
                    settings = menu.add(R.string.settings);
                }
                return true;
            } else {
                menu.clear();
                settings = null;
            }
            return false;
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            if (item.equals(settings)) {
                showSettingsFragment();
                return true;
            }
            return false;
        }

        public void showSettingsFragment() {
            showFragment(SETTINGS, true);
        }

        private void onSessionStateChange(Session session, SessionState state, Exception exception) {
            if (isResumed) {
                FragmentManager manager = getSupportFragmentManager();
                int backStackSize = manager.getBackStackEntryCount();
                for (int i = 0; i < backStackSize; i++) {
                    manager.popBackStack();
                }
                // check for the OPENED state instead of session.isOpened() since for the
                // OPENED_TOKEN_UPDATED state, the selection fragment should already be showing.
                if (state.equals(SessionState.OPENED)) {
                    showFragment(SELECTION, false);
                } else if (state.isClosed()) {
                    showFragment(SPLASH, false);
                }
            }
        }

        private void showFragment(int fragmentIndex, boolean addToBackStack) {
            FragmentManager fm = getSupportFragmentManager();
            FragmentTransaction transaction = fm.beginTransaction();
            for (int i = 0; i < fragments.length; i++) {
                if (i == fragmentIndex) {
                    transaction.show(fragments[i]);
                } else {
                    transaction.hide(fragments[i]);
                }
            }
            if (addToBackStack) {
                transaction.addToBackStack(null);
            }
            transaction.commit();
        }
    }

导致问题的类“是”:

public class MainActivity extends FragmentActivity implements
        ActionBar.TabListener {

这里是 XML:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">

    <fragment 
              class="info.androidhive.tabsswipe.MainActivity"
              android:id="@+id/mainActivity2"
              android:layout_width="match_parent"
              android:layout_height="match_parent" />
    <fragment android:name="info.androidhive.tabsswipe.SplashFragment"
              android:id="@+id/splashFragment"
              android:layout_width="match_parent"
              android:layout_height="match_parent" />
    <fragment android:name="com.facebook.widget.UserSettingsFragment"
              android:id="@+id/userSettingsFragment"
              android:layout_width="match_parent"
              android:layout_height="match_parent" />
</LinearLayout>

我尝试过使用“class=”、“android:name=”和“tag=”。

我正在使用这两个类扩展 android.support.v4.app.FragmentActivity。

这是日志!

04-02 20:16:33.880: D/KeyHash:(8899): ooZ4+XVqPy+UAL2Sk1NrWojLcIU=
04-02 20:16:33.997: D/AndroidRuntime(8899): Shutting down VM
04-02 20:16:33.997: W/dalvikvm(8899): threadid=1: thread exiting with uncaught exception (group=0x41aaf930)
04-02 20:16:34.028: E/AndroidRuntime(8899): FATAL EXCEPTION: main
04-02 20:16:34.028: E/AndroidRuntime(8899): java.lang.RuntimeException: Unable to start activity ComponentInfo{info.androidhive.tabsswipe/info.androidhive.tabsswipe.MainActivity2}: android.view.InflateException: Binary XML file line #24: Error inflating class fragment
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.app.ActivityThread.access$600(ActivityThread.java:141)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.os.Handler.dispatchMessage(Handler.java:99)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.os.Looper.loop(Looper.java:137)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.app.ActivityThread.main(ActivityThread.java:5039)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at java.lang.reflect.Method.invokeNative(Native Method)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at java.lang.reflect.Method.invoke(Method.java:511)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at dalvik.system.NativeStart.main(Native Method)
04-02 20:16:34.028: E/AndroidRuntime(8899): Caused by: android.view.InflateException: Binary XML file line #24: Error inflating class fragment
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:270)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.app.Activity.setContentView(Activity.java:1881)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at info.androidhive.tabsswipe.MainActivity2.onCreate(MainActivity2.java:91)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.app.Activity.performCreate(Activity.java:5104)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
04-02 20:16:34.028: E/AndroidRuntime(8899):     ... 11 more
04-02 20:16:34.028: E/AndroidRuntime(8899): Caused by: java.lang.ClassCastException: info.androidhive.tabsswipe.MainActivity cannot be cast to android.app.Fragment
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.app.Fragment.instantiate(Fragment.java:585)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.app.Fragment.instantiate(Fragment.java:560)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.app.Activity.onCreateView(Activity.java:4709)
04-02 20:16:34.028: E/AndroidRuntime(8899):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:680)
04-02 20:16:34.028: E/AndroidRuntime(8899):     ... 21 more
04-02 20:16:34.052: D/dalvikvm(8899): GC_CONCURRENT freed 194K, 3% free 9117K/9340K, paused 3ms+2ms, total 30ms

知道是什么导致了这个问题吗? 提前谢谢你们!

【问题讨论】:

    标签: android fragment android-fragmentactivity


    【解决方案1】:

    ClassCastException 表示您尝试投射两种不同的东西(例如 intString..)。在您的情况下,您尝试在布局中使用 FragmentActivity 类作为片段,但事实并非如此,MainActivityFragmentActivity不是 Fragment
    根据您的 LogCat,这一行:

    java.lang.ClassCastException: info.androidhive.tabsswipe.MainActivity cannot be cast to android.app.Fragment
    

    你的问题在这里:

     <fragment 
         class="info.androidhive.tabsswipe.MainActivity"
         android:id="@+id/mainActivity2"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />  
    

    info.androidhive.tabsswipe.MainActivity 不是Fragment 并且不能在布局中使用。


    更新:
    在 cmets 中,我建议您重新设计您的应用程序。您应该首先创建一个Activity 以显示您的登录FB,然后调用Intent 以显示FragmentActivityTabs 并显示您的面板。
    你也可以试试别的:

    • 创建一个FragmentActivity,其布局包含FrameLayout(例如id 容器),并在您的Tabs 和其他视图中。
    • 在您的 FragmentActivity 中,在第一次创建时,执行 FragmentTransaction 并在您的 FrameLayout(容器)中显示一个显示您的登录 FB 的片段。
    • 然后,当用户登录时,remove 这个片段让用户看到你的Tabs“背景”,并在里面显示你的面板。

    希望这会有所帮助。

    【讨论】:

    • 感谢您的回答!那我该怎么办?
    • 好吧,我真的不知道你想用这个实现什么。但是,你有一些选择:创建另一个片段或将片段托管在 MainActivity 而不是 MainActivity2 中。你想用你的代码来实现吗?
    • Facebook 给出的部分(MainActivity2)将用作应用程序的实际主屏幕。当用户未登录时,它将包含登录屏幕,或者在登录时“重定向”到用户面板。感觉代码是“准备就绪”的部分,但看起来不是!
    • 我认为它已经“准备就绪”,但您想快点。我看到你想要一张在MainActivity2 里面的地图? (我阅读了 SupportMapFragment)将您的 MainActivity layout fragment 视图更改为 SupportMapFragment class fragment,在这里您将看到:truiton.com/2013/05/android-supportmapfragment-example
    • 我的错,我不想要 MainActivity2 类上的任何地图。我只是想通过任何可能的解决方案来修复它......这个类包含选项卡和东西。 mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-21
    • 2012-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多