Изображение существует, а не нулевое, но я получаю на нем исключение NullPointerException

Краткое введение

Приложение, над которым я сейчас работаю, берет изображение из JSON, если оно правильное, оно использует его и сохраняет как загружаемое изображение при следующем использовании.

Проблема

Внезапно приложение начало падать при загрузке, и при дальнейшей проверке проверка file.isFile && file.canRead(), которую я поставил, возвращает положительный результат, но все еще падает на BitmapFactory.decodeStream. Количество байтов файла составляет 8 КБ по сравнению с другими устройствами, которые я использовал, где то же самое изображение фактически имеет 43 КБ.

Изображение json является частью гораздо большего сообщения json (около 500 КБ), и оно не находится в начале или в конце. При последнем использовании до того, как это произошло, не было проблем с загрузкой или признаков того, что загрузка могла быть остановлена ​​на полпути. Несмотря на это, размер изображения по-прежнему составляет 8 КБ, поэтому я думаю, что он должен просто создать что-то с той частью, которая у него есть, а не выбрасывать исключение NullPointerException.

Я использую Android Studio 3.0 Beta 4, а код написан на Kotlin. Должно быть, я запускал его на этом устройстве 100 раз, и даже после того, как это произошло, он отлично работает на других тестовых устройствах, плюс приложение iOS, которое получает точно такой же json при запуске.

Что я ищу

Совет о том, как решить проблему, или информация о том, является ли это известной ошибкой в ​​​​Android или Kotlin. Я, вероятно, могу переустановить приложение на устройстве, и все снова будет в порядке, но я бы не хотел, чтобы это произошло после выпуска приложения, если я могу предотвратить это.

LaterEdit: по предложению Ксавьера я скопировал файл на рабочий стол, и он определенно искажен, когда он загружается, он фактически показывает серьезно искаженное изображение вещей, работающих на Mac. Я пытался загрузить его, но он просто отображается как пустое белое изображение. В нем все еще 8 КБ, поэтому он содержит некоторые данные. Как это возможно и можно ли это предотвратить?

Код

Загружая приложение, я проверяю, существует ли изображение, и загружаю его в изображение.

try {
     if (DesignSupport().imageExists("logo", this)) {
         if (DesignSupport().loadImage("logo", this) != null) {
             imageView.setImageBitmap(DesignSupport().loadImage("logo", this))
         }
     }
 } catch (error: Error) {
     Log.i(tag, error.stackTrace.toString())
 }

Проверить, существует ли изображение

fun imageExists(string: String, context: Context) : Boolean {
        val path = android.os.Environment.getExternalStorageDirectory().toString() + "/" + context.applicationInfo.name + "/" + string + ".png"
        val file = File(path)
        return (file.isFile && file.canRead())
    }

Загрузите изображение

    fun loadImage(string: String, context: Context) : Bitmap {
            val path = android.os.Environment.getExternalStorageDirectory().toString() + "/" + context.applicationInfo.name + "/" + string + ".png"
            val fis = FileInputStream(path)
// it crashes at the next line, but when I print fis.available() it returns 8200
            return BitmapFactory.decodeStream(fis)
        }

Журнал сбоев

 java.lang.RuntimeException: Unable to start activity ComponentInfo{.GeneralAccessScreens.startupScreen}: java.lang.IllegalStateException: BitmapFactory.decodeStream(fis) must not be null
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2412)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2470)
at android.app.ActivityThread.access$900(ActivityThread.java:174)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1307)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5593)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IllegalStateException: BitmapFactory.decodeStream(fis) must not be null
at SupportMethods.DesignSupport.loadImage(DesignSupport.kt:45)
at .GeneralAccessScreens.startupScreen.onCreate(startupScreen.kt:34)
at android.app.Activity.performCreate(Activity.java:5458)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1093)

Импорт отчетов

import android.app.Activity
import android.content.Context
import android.content.res.Resources
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.util.Base64
import android.util.Log
import android.view.inputmethod.InputMethodManager
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream

person Alex Ioja-Yang    schedule 04.09.2017    source источник


Ответы (2)


Вы уверены, что сбой происходит в том же методе loadImage(), а не в другом? В журнале ошибок написано, что сбой произошел в BitmapFactory.decodeReso…ystem(), R.drawable.logo), который кажется другим.

Кроме того, вы пытались сначала сделать Rebuild? Я видел много проблем в бета-версиях AS 3.0, которые решаются таким образом.

Из документации, даже если fis равен нулю, он не должен падать с этой ошибкой, просто верните null (выделено мной).

Декодируйте входной поток в растровое изображение. Если входной поток имеет значение null или не может быть использован для декодирования растрового изображения, функция возвращает значение null. Положение потока будет таким, каким оно было после считывания закодированных данных.

Просто чтобы отбросить вещи, можете ли вы добавить оператор import для BitmapFactory? Должно быть import android.graphics.BitmapFactory.

person Xavier Rubio Jansana    schedule 04.09.2017
comment
Спасибо, я только что понял, что журнал был из предыдущего сбоя, когда пробовал разные решения, поэтому не чистый, я обновил журнал сбоев. - person Alex Ioja-Yang; 04.09.2017
comment
@ AlexIoja-Yang Я все еще вижу тот же журнал сбоев. - person Xavier Rubio Jansana; 04.09.2017
comment
И восстановление ничего не дает, я пытался запустить его на другом устройстве, и у него нет проблем, затем снова подключите это одно и то же. Я предполагаю, что в какой-то момент он должен был повредить данные, но он все равно должен загружать странное изображение. - person Alex Ioja-Yang; 04.09.2017
comment
java.lang.IllegalStateException: BitmapFactory.decodeStream(fis) не должен быть нулевым, это разница в верхней строке вместо BitmapFactory.decodeResource(Resources.getSystem(), R.drawable.logo). Это было в качестве альтернативы, если размер был меньше x кб, но потом я понял, что не должен просто пытаться избежать проблемы, устанавливая произвольный предел. - person Alex Ioja-Yang; 04.09.2017
comment
Обновил мой ответ, пожалуйста, посмотрите. - person Xavier Rubio Jansana; 04.09.2017
comment
но fis не равен нулю, fis.available() возвращает 8200, что, как я предполагаю, должно быть количеством символов. Также я добавил оператор импорта, но это класс из нескольких методов, поэтому не все из них относятся к этим двум методам, показанным здесь. - person Alex Ioja-Yang; 04.09.2017
comment
@ AlexIoja-Yang Я думаю, то, что вы говорите, выглядит более правдоподобным объяснением. Это или какое-то повреждение файла. Я попытался войти в метод, но он родной, так что не повезло. Я бы попробовал скачать файл себе на комп и проверить там. - person Xavier Rubio Jansana; 04.09.2017
comment
Я напечатал fit.read().toString(), и он показывает 137. Я не знаком с Android, я надеялся, что это будет содержимое файла. - person Alex Ioja-Yang; 04.09.2017
comment
fit.read() прочитает первый первый байт файла и .toString() преобразует его в печатную строку. 137 — это первый байт заголовка PNG-файла: libpng.org/pub /png/spec/1.2/PNG-Structure.html Итак, по крайней мере, начало файла, вероятно, правильное. Надеюсь это поможет! - person Xavier Rubio Jansana; 04.09.2017

Конкретное исключение возникает, потому что BitmapFactory.decodeStream(fis) возвращает null, в то время как функция указана для возврата объекта, не допускающего значение NULL. Либо сделайте возвращаемое значение обнуляемым, либо определите подходящую замену, если оно возвращает null.

В фоновом режиме Kotlin генерирует следующий код «java»:

Bitmap tmp = BitmapFactory.decodeStream(fis);
Intrinsics.checkExpressionValueIsNotNull(tmp, "BitmapFactory.decodeStream(fis)");
return tmp;

Источником исключения является вызов Intrinsics.checkExpressionValueIsNotNull.

person Kiskae    schedule 04.09.2017
comment
Но в том-то и проблема, что оно не равно нулю, и оно проходит любую проверку, которую я сделал на предмет того, будет ли оно нулевым. Сбой происходит при декодировании, хотя поток не нулевой. - person Alex Ioja-Yang; 05.09.2017
comment
Сбой происходит после декодирования, это конкретное исключение генерируется при проверке возвращаемого значения функции, в данном случае BitmapFactory.decodeStream. - person Kiskae; 05.09.2017