[Android] [Java] Laden Sie Bilder auf GCS (Google Cloud Storage) mit Stream mit Glide herunter

Glide Glide ist eine Bibliothek zum Laden und Zwischenspeichern von Bildern für Android. https://github.com/bumptech/glide

Mit Gradle können Sie es wie folgt installieren.

build.gradle


repositories {
    mavenCentral()
    google()
}

dependencies {
    implementation 'com.github.bumptech.glide:glide:4.8.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
}

Vorbereitung

Originalmodell

Definieren Sie eine Klasse namens "GcsImage", die die auf GCS vorhandenen Dateien mit Bucket und PATH angibt.

GcsImage.java


public class GcsImage {

    private final String mBucket;
    private final String mFilename;

    public GcsImage(@NonNull String bucket, @NonNull String filename) {
        mBucket = bucket;
        mFilename = filename;
    }

    public String getBucket() { return mBucket; }

    public String getFilename() { return mFilename; }
}

Glide Module Folgen Sie dem Link unten, um einen "ModelLoader" zum Laden des "GcsImage" zu definieren. Writing a custom ModelLoader

The first step is to implement the ModelLoader interface. Before we do so, we need to make two decisions:

  1. What type of Model should we handle?
  2. What type of Data should we produce for that Model?

Wie Sie sehen können, gibt ModelLoader den zu behandelnden Modell- und Datentyp an.

Das Modell kann "String" usw. sein, aber dieses Mal verwenden wir unser eigenes "GcsImage". Als Datentyp werden standardmäßig die Decoder "InputStream" und "ByteBuffer" vorbereitet.

GcsImageLoader.java


public class GcsImageLoader implements ModelLoader<GcsImage, InputStream> {

    private Context mContext;

    public GcsImageLoader(Context context) {
        mContext = context;
    }

    @Nullable
    @Override
    public LoadData<InputStream> buildLoadData(@NonNull GcsImage gcsImage, int width, int height, @NonNull Options options) {
        //Wenn der Bucket-Name und der Dateiname identisch sind, werden Cache-Daten verwendet.
        return new LoadData<>(new ObjectKey(gcsImage.getBucket() + '/' + gcsImage.getFilename()), new GcsImageFetcher(gcsImage));
    }

    @Override
    public boolean handles(@NonNull GcsImage gcsImage) {
        return true;
    }

    private class GcsImageFetcher implements DataFetcher<InputStream> {
        private GcsImage gcsImage;

        GcsImageFetcher(GcsImage gcsImage) {
           this.gcsImage = gcsImage;
        }

        @Override
        public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
            try {
                //Beschreibt den tatsächlichen Lesevorgang. Hier haben wir unsere eigene Klasse implementiert.
                InputStream stream = CloudStorageUtils.downloadToStream(mContext, gcsImage.getBucket(), gcsImage.getFilename());
                callback.onDataReady(stream);
            } catch (IOException e) {
                callback.onLoadFailed(e);
            }
        }

        @Override
        public void cleanup() {}

        @Override
        public void cancel() {}

        @NonNull
        @Override
        public Class<InputStream> getDataClass() {
            return InputStream.class;
        }

        @NonNull
        @Override
        public DataSource getDataSource() {
            return DataSource.REMOTE;
        }
    }

    public static class GcsImageLoaderFactory implements ModelLoaderFactory<GcsImage, InputStream> {
        private Context context;

        public GcsImageLoaderFactory(Context context) {
            this.context = context;
        }

        @NonNull
        @Override
        public ModelLoader<GcsImage, InputStream> build(@NonNull MultiModelLoaderFactory multiFactory) {
            return new GcsImageLoader(context);
        }

        @Override
        public void teardown() {}
    }
}

Ich habe auch eine Methode namens "CloudStorageUtils.downloadToStream ()" erstellt und in der folgenden Klasse definiert.

CloudStorageUtils.java


public class CloudStorageUtils {

    @WorkerThread
    public static InputStream downloadToStream(@NonNull Context context, @NonNull String bucket,
                                               @NonNull String name) throws IOException {
        Storage storage = getStorageService(context);
        Storage.Objects.Get get = storage.objects().get(bucket, name);
        return get.executeMediaAsInputStream();
    }

    @WorkerThread
    @NonNull
    public static Storage getStorageService(@NonNull Context context) throws IOException {
        HttpTransport transport = new NetHttpTransport();
        JsonFactory jsonFactory = new JacksonFactory();
        //Der Teil zum Abrufen von Authentifizierungsinformationen wird auch in einer anderen Klasse definiert.
        Credential credential = GoogleApiCredentialFactory.getCredential(context);
        return new Storage(transport, jsonFactory, credential);
    }
}

GoogleApiCredentialFactory.java


public class GoogleApiCredentialFactory {

    private static Credential sCredential;

    public static synchronized Credential getCredential(@NonNull Context context) {
        if (sCredential == null) {
            //Lesen Sie die JSON-Datei mit Stream und holen Sie sich den Berechtigungsnachweis.
            try (InputStream is = context.getAssets().open(BuildConfig.GCP_CREDENTIAL)) {
                List<String> scopes = new ArrayList<>();
                scopes.add(StorageScopes.DEVSTORAGE_FULL_CONTROL);
                GoogleCredential credential = GoogleCredential.fromStream(is);
                sCredential = credential.createScoped(scopes);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return sCredential;
    }
}

Geben Sie für "BuildConfig.GCP_CREDENTIAL" den Pfad zur JSON-Datei an, die den GCP-Dienstkontoschlüssel enthält.

Fügen wir nun den erstellten GcsImageLoader hinzu.

GcsImageGlideModule.java


@GlideModule
public class GcsImageGlideModule extends AppGlideModule {

    @Override
    public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
        registry.prepend(GcsImage.class, InputStream.class, new GcsImageLoader.GcsImageLoaderFactory(context));
    }
}

Durch Annotieren von "@ GlideModule" erkennt Glide "GcsImageGlideModule", das von "AppGlideModule" erbt.

Wie oben erwähnt, muss "build.gradle" den Annotation Processor beschreiben.

Siehe: Modulklassen und Anmerkungen.

Implementierung

Das Programm, das das Bild auf GCS mit dem von mir erstellten GlideModule liest, ist wie folgt. Hier wird das Bild in "ImageView" mit dem Namen "mImageView" angezeigt.

Glide.with(this).load(new GcsImage(bucket, filename)).into(mImageView);

Mit dem oben genannten kann das Bild sicher angezeigt werden.

Recommended Posts

[Android] [Java] Laden Sie Bilder auf GCS (Google Cloud Storage) mit Stream mit Glide herunter
Versuchen Sie, Firebase Cloud-Funktionen unter Android (Java) zu verwenden.
Verwenden Sie Java 11 mit Google Cloud-Funktionen
Verwenden von JupyterLab + Java mit WSL unter Windows 10
Sobel-Filter mit OpenCV unter Android (Java)
Problem der langsamen Verarbeitung bei Verwendung von Active Storage mit Cloud-Speicher (GCS, S3 usw.)
[Java] Holen Sie sich Bilder mit der Google Custom Search API
Versuchen Sie die Kommunikation mit gRPC auf einem Android + Java-Server
Verwenden von Java 8 mit Bluemix (auf Liberty Runtime & DevOps Service)
Erstellen Sie ein internes Maven-Repository in Google Cloud Storage
Versuchen Sie die Bildklassifizierung mit TensorFlow Lite unter Android (JAVA).
Bequemer Download mit JAVA
Java-Download mit Ansible
Verwenden mehrerer Java-Versionen mit Brew auf Mac + jEnv
Ich habe versucht, die CameraX-Bibliothek mit Android Java Fragment zu verwenden
Laden Sie Dateien mit dem SDK (Java-Version) auf Aspera hoch, das mit IBM Cloud Object Storage (ICOS) geliefert wird.