Нативный шрифт не может быть сделан только для некоторых людей

У меня есть приложение, которое меняет шрифт для некоторых элементов. Это хорошо работает для большинства людей, но, возможно, 0,5% получают исключение при попытке изменить шрифт. Значительная часть трассировки стека такова:

Caused by: java.lang.RuntimeException: native typeface cannot be made
at android.graphics.Typeface.<init>(Typeface.java:147)
at android.graphics.Typeface.createFromAsset(Typeface.java:121)

Как я уже сказал, это работает для большинства людей, поэтому я не думаю, что это проблема с файлом шрифта или моим кодом. Любые предложения о том, как решить эту проблему?

Изменить: Это мой код:

Typeface phoneticFont = Typeface.createFromAsset(getAssets(),
                                                 "fonts/CharisSILR.ttf");
TextView tv;
tv = ((TextView) findViewById(R.id.searchPronunciationTitle));
tv.setTypeface(phoneticFont);

person user936580    schedule 07.10.2012    source источник
comment
Я обновил вопрос с кодом.   -  person user936580    schedule 09.10.2012
comment
куда вы положили свой файл ttf.   -  person Rishabh Agrawal    schedule 09.10.2012
comment
какая версия андроида, из-за которой вы получаете эту ошибку? Я получил его от GT-i9000, 2.3.6   -  person bigstones    schedule 21.10.2012
comment
Я получил это в версиях Android 2.2 и 2.2.2   -  person user936580    schedule 25.10.2012
comment
Вы видели ‹karanbalkar.com/2013/07? /›? это простой способ добавить шрифт roboto в приложение для Android.   -  person Pranav Jagtap    schedule 14.10.2013
comment
Для меня это была проблема верхнего нижнего регистра.   -  person powder366    schedule 27.11.2013
comment
Я проверил и все буквы точно совпадают в коде и в названии файла.   -  person user936580    schedule 28.11.2013
comment
как ты наконец решил эту проблему?   -  person thedarkpassenger    schedule 05.04.2016
comment
К сожалению, я не мог это исправить.   -  person user936580    schedule 08.04.2016
comment
Я добавил свой ответ здесь: ошибка шрифта   -  person Abhilasha Sharma    schedule 21.06.2017
comment
Я думаю, что ваш ответ не относится к моему случаю, потому что, если бы это была ошибка, которую вы предложили, она бы никогда не сработала; но в моем случае это работает большую часть времени.   -  person user936580    schedule 22.06.2017


Ответы (15)


Эта ошибка ОС Android может быть причиной вашей проблемы:

Typeface.createFromAsset приводит к утечке потока активов

Где также обходной путь в этом отчете об ошибке:

Я изменил обходной путь HTH, чтобы метод не предполагал путь или формат шрифта. Полный путь к активу шрифта должен быть отправлен в качестве параметра. Я также завернул вызов createFromAsset() в блок try-catch, чтобы метод get() возвращал значение null, если актив не найден.

public class Typefaces {
    private static final String TAG = "Typefaces";

    private static final Hashtable<String, Typeface> cache = new Hashtable<String, Typeface>();

    public static Typeface get(Context c, String assetPath) {
        synchronized (cache) {
            if (!cache.containsKey(assetPath)) {
                try {
                    Typeface t = Typeface.createFromAsset(c.getAssets(),
                            assetPath);
                    cache.put(assetPath, t);
                } catch (Exception e) {
                    Log.e(TAG, "Could not get typeface '" + assetPath
                            + "' because " + e.getMessage());
                    return null;
                }
            }
            return cache.get(assetPath);
        }
    }
}
person HitOdessit    schedule 26.10.2012
comment
Спасибо. Если я правильно понимаю, в описании этой ошибки сказано, что проблема заключается в утечке памяти, которая спровоцирует ошибки из памяти. Однако это не то, что я вижу: я получаю, что родной шрифт не может быть создан без исключений из памяти. Кроме того, похоже, что это всегда терпит неудачу для пользователя, который терпит неудачу, и мое приложение не использует много ресурсов. - person user936580; 26.10.2012
comment
@user936580 user936580 блок catch при загрузке шрифта позволит избежать взрыва исключения для вашего пользователя. Компромисс здесь — уродливый шрифт вместо сбоя. Я думаю, что это платно :) - person Bolhoso; 19.12.2013
comment
@Hit Как вы используете/вызываете этот метод? Я пытался выяснить. - person Compaq LE2202x; 06.01.2014
comment
Я не помог мне избавиться от Exception, НО он перестает утекать тонны памяти, если я использую Typefaces вместе с androidsvg, где я загружаю несколько шрифтов, используя файл SVGExternalFileResolver. - person Dirk; 01.11.2014

Я следовал некоторым решениям, найденным здесь, но безуспешно. Я думал, что это что-то действительно неясное, как это часто делают программисты. Затем где-то я читал, что это может быть связано с путем к шрифту, понял:

Вместо:

Typeface phoneticFont = Typeface.createFromAsset(getAssets(),
                                             "blanch_caps.ttf");   

Я изменил на:

Typeface phoneticFont = Typeface.createFromAsset(getAssets(),
                                             "fonts/blanch_caps.ttf");   

И мой файл находится в assets/fonts/blanch_caps.ttf. Не работает как шарм!

person joao_dv    schedule 20.07.2013
comment
это сработало для меня, большое спасибо! хотя маленький совет: у меня шрифт назывался с большой буквы, типа COOPBL.TTF поэтому пришлось писать в коде тоже с большой буквы.. может кому поможет :) - person ylka; 07.06.2014
comment
Также исправляет это для createFromFile - person 0101100101; 18.05.2016

Эта ошибка возникала, когда шрифт находился в папке активов библиотеки. Когда я скопировал его в активы приложения, которое использовало эту библиотеку, ошибка исчезла.

Кажется, ресурсы невозможно импортировать: папка ресурсов библиотеки Android не копируется

И вот некоторые другие случаи: Проблема при использовании пользовательский шрифт - собственный шрифт не может быть создан

person Lumis    schedule 05.01.2013
comment
Спасибо, но у меня есть шрифт в папке ресурсов приложения. Это работает в большинстве случаев, но у некоторых людей это не работает, я не знаю, почему. - person user936580; 14.01.2013
comment
Хорошо знать. Я поместил try/catch для загрузки каждого пользовательского шрифта, в случае ошибки по умолчанию будет использоваться встроенный шрифт Android, если шрифт ttf не работает на некоторых устройствах. - person Lumis; 14.01.2013
comment
Я думаю, это потому, что вы используете контекст своего приложения для getAssets(), а не для библиотеки... +1 у меня сработало. - person Saeed.re; 21.08.2014

Я много боролся с этим. Я пробовал все возможности, и ничего не помогает. В конце концов, чтобы проблема была в другом. Если вы создаете свой проект с помощью Gradle, не забудьте добавить эти строки в файл build.gradle. Это решило проблему в моем случае.

    sourceSets {
    main {
        assets.srcDirs = ['assets']
    }
}
person Michal    schedule 11.08.2013
comment
Спасибо за ответ. Я использую Eclipse, так что это не моя проблема. - person user936580; 12.08.2013
comment
если мы используем студию Android и gradle — смотрите это. Каталог активов должен находиться непосредственно под main. Это решило мою проблему. Не было никаких проблем с именем шрифта и файлом шрифта. Это особенно важно, так как имя шрифта, которое мы использовали, было в верхнем/нижнем регистре, тогда как имя файла актива должно быть все в нижнем регистре. - person Mr. B; 17.04.2014
comment
В Android Studio (в настоящее время 0.8.1) мне не нужно было добавлять строки в build.gradle, но мне нужно было поместить папку с активами непосредственно в основную (например, src\main\assets) - person Dominic K; 29.06.2014
comment
Решение DMan было идеальным для меня. Мне не нужно было ничего делать в build.gradle - person CodyMace; 15.07.2014
comment
Этот ответ был действителен в то время, когда плагин Gradle для Android был ниже 0,5, и вам нужно было самостоятельно указать папку res. Теперь конечно не надо! - person Michal; 02.08.2014
comment
Не добавляйте этот код, если вы используете Android Studio 8.1 и выше, я удалил эти строки, и это работает! этот код предназначен для более ранних версий Android Studio - person Amin Keshavarzian; 14.10.2014

Вы должны создать папку с ресурсами внутри src -->main в AndroidStudio. Этот способ сработал!

person Madi    schedule 18.11.2014

В моем случае это было основано на имени файла шрифта. По какой-то причине он был назван FontName..ttf

Я не знаю, почему там были двойные точки - я посмотрел исходный шрифт, и они были в моей папке Windows \ Fonts как FontName..ttf. Windows, по-видимому, было все равно, но Android взбесился. Я переименовал файл, и теперь все устраивает.

person Tab    schedule 29.01.2013

В моем случае я обнаружил, что папка assets находится в /main/java/assets, но они должны быть в /main/assets

person Cool    schedule 15.08.2014
comment
Так было в моем случае! Спасибо - person Adrian L; 22.11.2014

Делать в нижнем регистре:

Typeface phoneticFont = Typeface.createFromAsset(getAssets(),
                                             "fonts/charissilr.ttf");

Не забудьте также переименовать файл.

person Pedro HCDO    schedule 05.12.2013

Изменить этот

Typeface phoneticFont = Typeface.createFromAsset(getAssets(),
                                             "fonts/CharisSILR.ttf");

to

Typeface phoneticFont = Typeface.createFromAsset(getAssets(),
                                             "CharisSILR.ttf");
person Kadir altınok    schedule 13.02.2016
comment
С этим он не работает, потому что он у меня есть в каталоге шрифтов. Я пытался поместить его в корневой каталог, но все равно не получается. - person user936580; 14.02.2016

Я просто столкнулся с этой проблемой, когда использовал MagicTextView от qwerjk. Я попытался поместить класс MTV в библиотеку и использовать его в своем основном проекте. Вот как я заставил это работать:

  1. В основной папке ресурсов проекта создайте подпапку с именем fonts.
  2. Скопируйте файл ttf в папку assets/fonts. Мое имя файла было в верблюжьем регистре (например, ReservoirGrunge.ttf), поэтому заглавные буквы или их отсутствие, похоже, не имеют значения.
  3. В своем основном проекте я раздул представление MTV из xml. Убедитесь, что MagicTextView указывает на правильный путь к библиотеке. Например, моя библиотека классов MTV называлась com.library.library_magictextview.MagicTextView, поэтому XML-файл моего основного представления должен был выглядеть так:

        <com.library.library_magictextview.MagicTextView
        android:textSize=           "50dp"
        android:textColor=          "#ffffffff"
        android:layout_width=       "fill_parent"
        android:layout_height=      "wrap_content"
    
        android:textStyle=          "bold"
        android:padding=            "20dp"
        android:gravity=            "center"
    
        r:strokeColor=          "#FFff0000"
        r:strokeJoinStyle=      "miter"
        r:strokeWidth=          "5"
        r:typeface=         "ReservoirGrunge"
        android:text=               "BobDillon" />
    
person Chris Sprague    schedule 11.05.2014

В нашей ситуации мы использовали решение Hit с кешем. Проблема, которую мы представили, заключалась в том, что мы тестировали файлы OTF И файлы TTF в одном и том же блоке try ;) Что, очевидно, потерпит неудачу с первой попытки для OTF, если вы хотите получить TTF, но я подумал, что это стоит опубликовать. ПРОСТО на случай, если кто-то проскользнул мимо внимания, пока они могут пробовать одно и то же решение.

protected static Typeface getTypeface(Context p_context, String p_fontName){
    Typeface tf = null;
    try {
        tf = Typeface.createFromAsset(p_context.getAssets(), "fonts/" + p_fontName + ".otf");
    }catch(Exception e) {}

    if( tf != null ) return tf;

    try {
        tf = Typeface.createFromAsset(p_context.getAssets(), "fonts/" + p_fontName + ".ttf");
    }catch(Exception e) {}

    return tf;
}
person neoRiley    schedule 06.10.2014

В моем случае я просто удалил папку ресурсов (которую я создал вручную) и просто создал новую с помощью мастера. По-видимому, она не читалась как папка с ресурсами, а читалась как обычная папка, поэтому getAssets() не работал и выдавал мне ошибку.

person omarwaleed    schedule 28.10.2014

в студии Android: у меня сработало помещение файла ttf прямо в папку ресурсов без подпапки шрифтов, он не работал с подпапкой ((getAssets(),"fonts/oldengl.ttf") не работал, когда у меня был ttf в src/main/assets/fonts). это работает: src/main/assets/oldengl.ttf Typeface customfont=Typeface.createFromAsset(getAssets(),"oldengl.ttf");

person Stas Krantsov    schedule 27.08.2015

Я столкнулся с этой проблемой, когда импортировал модуль, который должен был поддерживать как проекты в стиле eclipse, так и проект в стиле студии Android.

Я решил свою проблему, удалив активы из исходного набора как

defaultConfig {
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName '1.0'

        sourceSets {
            main {
                java.srcDirs = ['src']
                res.srcDirs = ['res']
                //assets.srcDirs = ['assets']//commented this out because modlue was not having this directory
                manifest.srcFile 'AndroidManifest.xml'
            }
        }
    }

Или преобразование проекта в стиль студии Android также может решить проблему, я думаю.

person Sanjeet A    schedule 19.04.2016

В моем случае,

Я просто использую предыдущий код.. Поэтому я забыл файл шрифта в папке с ресурсами..

Но я не могу понять в течение 2 часов..

Возможные случаи этой ошибки,

  1. Отсутствует файл шрифта
  2. Неверное имя шрифта или неправильное расширение шрифта

например: fonts/roboto.ttf вместо fonts/roboto.otf

person Ranjith Kumar    schedule 31.10.2016