Глайд показывает только некоторые (случайные) изображения из Google Drive.

Вопрос или проблема

У меня есть приложение для экзаменов, где есть категория с идентификацией изображений, ничего особенного. Чтобы предотвратить увеличение размера приложения, я решил хранить изображения в Google Drive (это показалось мне лучшим решением, потому что я могу создать изображения на своем ПК, а затем немедленно и, что более важно, автоматически загрузить их на Drive). НО моя функция отображает только некоторые изображения, и всегда случайные. Представьте, у вас есть 10 вопросов викторины – первое изображение загружается, 2-е и 3-е нет, но 4-е да, и так далее. Всегда случайным образом. В следующий раз 1-е не загружается, но 2-е да, 3-е нет…

Код функции:

private void loadImage(String id, ImageView mainImage){
    Glide.with(this)
            .asBitmap()
            .load(BASE_URL + id)
            .fitCenter()
            .diskCacheStrategy(DiskCacheStrategy.NONE)
            .dontAnimate()
            .listener(new RequestListener<Bitmap>() {
                @Override
                public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) {
                    assert e != null;
                    for (Throwable t : e.getRootCauses()) {
                        Log.e("TAG", "Caused by", t);
                    }
                    e.logRootCauses("TAG");
                    return false;
                }

                @Override
                public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) {
                    Toast.makeText(getApplicationContext(), "Image ready!", Toast.LENGTH_LONG).show();
                    return false;
                }
            })
            .into(mainImage);
}

BASE_URL является стандартным “https://docs.google.com/uc?id=”, а id извлекается как вопрос из массива

Ошибка Logcat:

E  Caused by com.bumptech.glide.load.HttpException: Failed to connect or obtain data, status code: -1
    at com.bumptech.glide.load.data.HttpUrlFetcher.loadDataWithRedirects(HttpUrlFetcher.java:98)
    at com.bumptech.glide.load.data.HttpUrlFetcher.loadDataWithRedirects(HttpUrlFetcher.java:122)
    at com.bumptech.glide.load.data.HttpUrlFetcher.loadData(HttpUrlFetcher.java:58)
    at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.loadData(MultiModelLoader.java:100)
    at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:95)
    at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:88)
    at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:311)
    at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:277)
    at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:235)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:421)
    at java.lang.Thread.run(Thread.java:923)
    at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultPriorityThreadFactory$1.run(GlideExecutor.java:380)
Caused by: java.net.SocketTimeoutException: timeout
    at com.android.okhttp.okio.Okio$3.newTimeoutException(Okio.java:214)
    at com.android.okhttp.okio.AsyncTimeout.exit(AsyncTimeout.java:263)
    at com.android.okhttp.okio.AsyncTimeout$2.read(AsyncTimeout.java:217)
    at com.android.okhttp.okio.RealBufferedSource.indexOf(RealBufferedSource.java:307)
    at com.android.okhttp.okio.RealBufferedSource.indexOf(RealBufferedSource.java:301)
    at com.android.okhttp.okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:197)
    at com.android.okhttp.internal.http.Http1xStream.readResponse(Http1xStream.java:188)
    at com.android.okhttp.internal.http.Http1xStream.readResponseHeaders(Http1xStream.java:129)
    at com.android.okhttp.internal.http.HttpEngine.readNetworkResponse(HttpEngine.java:750)
    at com.android.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:622)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:475)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:411)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:248)
    at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getInputStream(DelegatingHttpsURLConnection.java:211)
    at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:30)
    at com.bumptech.glide.load.data.HttpUrlFetcher.loadDataWithRedirects(HttpUrlFetcher.java:95)
    at com.bumptech.glide.load.data.HttpUrlFetcher.loadDataWithRedirects(HttpUrlFetcher.java:122) 
    at com.bumptech.glide.load.data.HttpUrlFetcher.loadData(HttpUrlFetcher.java:58) 
    at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.loadData(MultiModelLoader.java:100) 
    at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:95) 
    at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:88) 
    at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:311) 
    at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:277) 
    at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:235) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
    at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:421) 
    at java.lang.Thread.run(Thread.java:923) 
    at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultPriorityThreadFactory$1.run(GlideExecutor.java:380) 
Caused by: java.net.SocketTimeoutException: Read timed out
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:119)
    at java.net.SocketInputStream.read(SocketInputStream.java:176)
    at java.net.SocketInputStream.read(SocketInputStream.java:144)
    at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.readFromSocket(ConscryptEngineSocket.java:936)
    at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.processDataFromSocket(ConscryptEngineSocket.java:900)
    at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.readUntilDataAvailable(ConscryptEngineSocket.java:815)
    at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.read(ConscryptEngineSocket.java:788)
    at com.android.okhttp.okio.Okio$2.read(Okio.java:138)
    at com.android.okhttp.okio.AsyncTimeout$2.read(AsyncTimeout.java:213)
    at com.android.okhttp.okio.RealBufferedSource.indexOf(RealBufferedSource.java:307) 
    at com.android.okhttp.okio.RealBufferedSource.indexOf(RealBufferedSource.java:301) 
    at com.android.okhttp.okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:197) 
    at com.android.okhttp.internal.http.Http1xStream.readResponse(Http1xStream.java:188) 
    at com.android.okhttp.internal.http.Http1xStream.readResponseHeaders(Http1xStream.java:129)
    at com.android.okhttp.internal.http.HttpEngine.readNetworkResponse(HttpEngine.java:750)
    at com.android.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:622)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:475)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:411)
    at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:248)
    at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getInputStream(DelegatingHttpsURLConnection.java:211)
    at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:30)
    at com.bumptech.glide.load.data.HttpUrlFetcher.loadDataWithRedirects(HttpUrlFetcher.java:95) 
    at com.bumptech.glide.load.data.HttpUrlFetcher.loadDataWithRedirects(HttpUrlFetcher.java:122) 
    at com.bumptech.glide.load.data.HttpUrlFetcher.loadData(HttpUrlFetcher.java:58) 
    at com.bumptech.glide.load.model.MultiModelLoader$MultiFetcher.loadData(MultiModelLoader.java:100) 
    at com.bumptech.glide.load.engine.SourceGenerator.startNextLoad(SourceGenerator.java:95) 
    at com.bumptech.glide.load.engine.SourceGenerator.startNext(SourceGenerator.java:88) 
    at com.bumptech.glide.load.engine.DecodeJob.runGenerators(DecodeJob.java:311) 
    at com.bumptech.glide.load.engine.DecodeJob.runWrapped(DecodeJob.java:277) 
    at com.bumptech.glide.load.engine.DecodeJob.run(DecodeJob.java:235) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
    at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultThreadFactory$1.run(GlideExecutor.java:421) 
    at java.lang.Thread.run(Thread.java:923) 
    at com.bumptech.glide.load.engine.executor.GlideExecutor$DefaultPriorityThreadFactory$1.run(GlideExecutor.java:380) 

Я имею в виду код состояния -1? Я привык к исключениям Http 400-500, но -1? Я пытался разобраться в ошибке, но это слишком сложно для меня, я не так уж опытен в https и подобном.

Спасибо за любую помощь!

Ответ или решение

Проблема, с которой вы столкнулись при использовании библиотеки Glide для загрузки изображений из Google Drive, может быть связана с несколькими возможными причинами. При анализе ошибки и поведения вашего приложения полезно рассмотреть как технические детали, так и основные принципы работы с API и загрузкой изображений.

Причины проблемы

  1. Неправильные URLs для изображений:
    Использование BASE_URL = "https://docs.google.com/uc?id=" требует, чтобы идентификатор изображения (id) был корректным и доступным. Убедитесь, что все ваши изображения имеют правильные ссылки и что эти изображения открыты для общего доступа. Если изображение недоступно по ссылке, Glide не сможет его загрузить.

  2. Настройки доступа к файлам Google Drive:
    Убедитесь, что у всех изображений, которые вы пытаетесь загрузить, установлены правильные разрешения. Если изображения находятся в личной папке или имеют ограничения доступа, попробуйте установить доступ для всех, использующих ссылку. Это можно сделать в настройках общего доступа файла в Google Drive.

  3. Стратегия кеширования:
    В вашем коде используется стратегия кеширования DiskCacheStrategy.NONE, что означает, что Glide не будет кешировать загруженные изображения. Это может привести к увеличению числа запросов к Google Drive и в конечном итоге быть причиной ошибок при загрузке изображений. Рассмотрите возможность использования другой стратегии кеширования (например, DiskCacheStrategy.AUTOMATIC), чтобы уменьшить количество запросов.

  4. Проблемы с сетью и таймауты:
    Ошибка SocketTimeoutException свидетельствует о том, что приложение не смогло получить ответ от сервера в установленный период времени. Проверьте своё интернет-соединение и настройте таймауты в Glide. Вы можете задать свои значения таймаутов, используя настройки OkHttpClient.

Рекомендации по исправлению

  • Проверка доступа к файлам:
    Убедитесь, что все необходимые изображения общедоступны по ссылке. Для этого проверьте настройки доступа в Google Drive.

  • Логи и обработка ошибок:
    Добавьте дополнительные логи в ваше приложение, чтобы лучше понять, какие именно идентификаторы не загружаются. Попробуйте реализовать показ ошибок более наглядно для пользователей (например, при загрузке ошибок показывать уведомление).

  • Эффективная обработка изображений с Glide:
    Рассмотрите следующие улучшения в вашем коде:

    private void loadImage(String id, ImageView mainImage) {
      Glide.with(this)
              .asBitmap()
              .load(BASE_URL + id)
              .fitCenter()
              .diskCacheStrategy(DiskCacheStrategy.AUTOMATIC) // Поменяйте на AUTOMATIC или ALL
              .timeout(10000) // Установите таймаут в 10 секунд
              .listener(new RequestListener<Bitmap>() {
                  @Override
                  public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) {
                      if (e != null) {
                          Log.e("TAG", "Error loading image", e);
                      }
                      return false; // Возврат false для выполнения дальнейшей обработки
                  }
    
                  @Override
                  public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) {
                      Toast.makeText(getApplicationContext(), "Image loaded successfully!", Toast.LENGTH_SHORT).show();
                      return false; // Возврат false для выполнения дальнейшей обработки
                  }
              })
              .into(mainImage);
    }

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...