Android getIdentifier返回0x1?

时间:2016-01-07 17:56:50

标签: android android-resources

在运行我的应用程序的一小部分设备上,用户在通过首选项更改图像时会崩溃。完整堆栈跟踪:

java.lang.RuntimeException: Unable to resume activity {com.printandpixel.lolhistory/com.printandpixel.lolhistory.activities.MainActivity}: android.content.res.Resources$NotFoundException: Resource ID #0x1
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3346)
    at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3377)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2728)
    at android.app.ActivityThread.access$900(ActivityThread.java:172)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1422)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:145)
    at android.app.ActivityThread.main(ActivityThread.java:5832)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
Caused by: android.content.res.Resources$NotFoundException: Resource ID #0x1
    at android.content.res.Resources.getValue(Resources.java:2329)
    at android.content.res.Resources.getDrawable(Resources.java:1846)
    at android.content.res.Resources.getDrawable(Resources.java:1814)
    at com.printandpixel.lolhistory.util.GeneralUtils.getDrawableFromName(GeneralUtils.java:226)
    at com.printandpixel.lolhistory.util.GeneralUtils.getHomepageHeader(GeneralUtils.java:277)
    at com.printandpixel.lolhistory.activities.MainActivity.onResume(MainActivity.java:252)
    at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1255)
    at android.app.Activity.performResume(Activity.java:6338)
    at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3335)
    ... 11 more

此处引用的函数getDrawableFromName中的行如下:

return context.getResources().getDrawable(resourceId);

此方法的完整实现如下:

public static Drawable getDrawableFromName(String name, Context context) {
    int resourceId = context.getResources().getIdentifier(name, "drawable", context.getPackageName());
    if (resourceId > 0) {
        return context.getResources().getDrawable(resourceId);
    } else {
        Tracker t = ((LoLHistory) ((Activity) context).getApplication()).getTracker(LoLHistory.TrackerName.APP_TRACKER);
        t.send(new HitBuilders.EventBuilder().setCategory("EVENT").setAction("DrawableNotFound").setLabel(name).build());
        return null;
    }
}

据我所知,目前为止仅在Android 5上发生,而不是在所有Android 5设备上发生。据我所知,文档指定getIdentifier应该返回0如果没有找到drawable但在这种情况下它返回0x1?我的应用程序中有数百个不同的图像,所有用户报告都将0x1作为无效ID。

假设resourcesIds为1都无效是否安全?

编辑:根据@ρяσѕρєяK建议,要处理弃用getDrawable(id),并在意外找不到资源时优雅地失败,我已编辑我的函数如下:

public static Drawable getDrawableFromName(String name, Context context) {
    int resourceId = context.getResources().getIdentifier(name, "drawable", context.getPackageName());
    Drawable drawable = null;
    try {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            drawable = context.getResources().getDrawable(resourceId, context.getTheme());
        } else {
            drawable = context.getResources().getDrawable(resourceId);
        }
    } catch (Resources.NotFoundException e) {
        Tracker t = ((LoLHistory) ((Activity) context).getApplication()).getTracker(LoLHistory.TrackerName.APP_TRACKER);
        t.send(new HitBuilders.EventBuilder().setCategory("EVENT").setAction("DrawableNotFound").setLabel(name).build());
    }
    return drawable;
}

1 个答案:

答案 0 :(得分:0)

问题最终不是由getDrawableFromName功能引起的。它实际上完全不相关:(。我在我的应用程序中有另一个函数来获取特定的默认偏好值,如下所示:

public static Drawable getHomepageHeader(Context context) {
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
    String headerImageName = prefs.getString(context.getString(R.string.pref_champion_header_name), "darius_600");
    Drawable drawable = getDrawableFromName(headerImageName, context);
    if (drawable == null) {
        drawable = new ColorDrawable(ContextCompat.getColor(context, R.color.green));
    }
    return drawable;
}

此偏好设置在PreferenceActivity中,其中包含以下ListPreference

<ListPreference
    android:key="pref_champion_header"
    android:entries="@array/headers"
    android:entryValues="@array/header_values"
    android:summary="Champion splash to appear at the top of the homepage"
    android:title="Homepage champion"
    android:defaultValue="1"/>

引用以下两个数组:

<string-array name="headers" translatable="false">
    <item>Darius</item>
    <item>Garen</item>
    <item>Malphite</item>
    <item>Gnar</item>
    <item>Buccaneer Tristana</item>
</string-array>
<string-array name="header_values" translatable="false">
    <item>darius_600</item>
    <item>garen_600</item>
    <item>malphite_600</item>
    <item>gnar_600</item>
    <item>buccaneer_tristana_600</item>
</string-array>

无论出于何种原因,某些设备defaultValue="1"已解析为header_values的第一个条目,而其他设备已解决为"1",导致"1"传递给我的自定义getDrawableFromName方法。要解决此问题,我只需将defaultValue更改为显式等于header_values数组的第一个值"darius_600"