2014-01-06 27 views
7

對於一些上我的工作,對設備與API 19級我得到異常當android的isValidFragment()來自PreferenceActivity被調用?

Caused by: java.lang.RuntimeException: Subclasses of PreferenceActivity must override isValidFragment(String) to verify that the Fragment class is valid! com... has not checked if fragment com...$. is valid. 

然後應用程序,我發現這些應用程序的Android框架protected boolean isValidFragment(String fragmentName)獲取調用,其代碼

if (getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.KITKAT) { 
     throw new RuntimeException(
       "Subclasses of PreferenceActivity must override isValidFragment(String)" 
       + " to verify that the Fragment class is valid! " + this.getClass().getName() 
       + " has not checked if fragment " + fragmentName + " is valid."); 
    } else { 
     return true; 
} 

然後我試圖複製錯誤

我把我的示例應用程序的代碼Preferences Activity Example 和添加的行清單中的。

但奇怪的是,我沒有得到錯誤(isValidFragment()沒有被調用的情況下)。

所以請告訴我如何在示例應用程序中複製該錯誤。

+0

如果我寫了一個應用程序,並在3年​​前出版,爲什麼不能讓Google運行,而是設置此ANR – matheszabi

回答

6

似乎是一個錯誤或4.4安全限制。工作原理是使用低於19的任何東西,仍然與PreferenceActivity兼容,並咬住子彈與舊的目標進行編譯。

我爲PreferenceActivity使用頭文件「模式」(覆蓋public void onBuildHeaders(List<Header> target)),並且我假設OP也是如此,最有可能是事情發生和崩潰的地方。

就我而言,我已經縮小這一例外<uses-sdk android:targetSdkVersion="19" />,以及任何在[14-18]構建目標將編譯,沒有問題的運行。建議(適用於Eclipse):我從來沒有把這些東西直接搞砸,但我假設你是否在另一個項目上編譯你的PreferenceActivity(也許是片段),目標是18或者下(雙關不打算:O) ,然後將該項目作爲用於您針對KitKat(19)的主項目,也許您可​​以在運行時避免崩潰情況,同時仍然使用最新版本中所需的功能(只要這些功能不是在構建18綁定的PreferenceActivity中)。如果這沒有成功,請嘗試使用jar表單(預編譯)中的該項目,而不是將項目用作庫。

UPDATE:還記得CamilleSévigny的回答。如果問題與其他問題有任何關係(50%的可能性),那麼所有針對API 18的應用程序都容易受到碎片注入攻擊(請參閱他的鏈接問題)。

+0

這是個壞主意! - 尤其是當開始偏好活動,你會設置額外 - > Intent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMEN,Fragment.class.getName()); Intent.putExtra(PreferenceActivity.EXTRA_NO_HEADERS,true);那麼你在黑洞:) - 我的投票下來! – ceph3us

+0

所以你剛剛失去了聲望投下我的答案,已經有一個4月3日14更新說明這是一個壞主意。更多的權力給你然後:P – leRobot

+0

我只指出,使用onBuildsHeaders永遠不會被調用,所以你不能在這個方法上設置片段進行驗證 - isValidFragment被調用,而事務被提交交換片段 – ceph3us

20

您的問題的答案在這篇文章中。這是一個重複的問題:

isValidFragment Android API 19

--Updated--

這裏是解決辦法是什麼:

基本上,無論是活動使用您的片段「COM ... $「在上面的錯誤中,您必須使用下面的修復更新它。您應該使用此修補程序更新項目中的所有活動,以便使用片段的任何Acitvity。

的文檔狀態:

protected boolean isValidFragment (String fragmentName) 

Added in API level 19 

Subclasses should override this method and verify that the given fragment is a 
valid type to be attached to this activity. The default implementation returns 
true for apps built for android:targetSdkVersion older than KITKAT. For later 
versions, it will throw an exception. 

您可以通過重寫此方法的活動/ FragmentActivity修正此錯誤:

@Override 
protected boolean isValidFragment (String fragmentName) { 
    return [YOUR_FRAGMENT_NAME_HERE].class.getName().equals(fragmentName); 
} 

如果你是懶惰,只是想,如果這個測試出修復工作,然後將所有片段編碼爲此方法,您可以簡單地返回true而不進行任何檢查:

@Override 
protected boolean isValidFragment (String fragmentName) { 
    return true; 
} 

我在模擬器上測試時遇到了同樣的問題,這就是解決方案。

+0

首先,它不是重複的,因爲在你給出的鏈接中,他無法刪除錯誤,而且我無法在示例應用程序中重現它。另外我的問題是,當它被調用,而不是如何修復它 –

+0

第二件事,你能詳細說明鏈接的文章嗎?將文章鏈接爲答案通常被認爲是不好的答案。而且我也無法在你的鏈接中找到我的問題的答案。 –

+0

@ShirishHerwade我已經更新了我的答案。 –

4

在這裏,你去!

拍這個在那裏,你很好!

收集此PreferenceActivity中找到的所有內部類。 我選擇了把名單在靜態字段變量:

public class whatever extends PreferenceActivity { 

    static final Class<?>[] INNER_CLASSES = 
            whatever.class.getDeclaredClasses(); 

然後,覆蓋的方法,ValidFragment,並確保將要顯示的片段是一個「父」活動是知道的:

/** 
* Google found a 'security vulnerability' and imposed this hack. 
* Have to check this fragment was actually conceived by this activity. 
*/ 
@Override 
protected boolean isValidFragment(String fragmentName) { 

    Boolean knownFrag = false; 

    for (Class<?> cls : INNER_CLASSES) { 

     if (cls.getName().equals(fragmentName)){ 

      knownFrag = true; 

      break; 
     } 
    }   

    return knownFrag; 
} 
+1

這是正確的,如果你有更多的類(即片段) – user1616685

+0

優雅的解決方案,謝謝! – TechnIx

+0

很好的解決方案,無法調試 - >發佈過渡 – John

相關問題