Salut, je suis nouveau dans le cadre Retrofit pour Android. Je pourrais obtenir des réponses JSON de REST services l'utilisant mais je ne sais pas comment télécharger un png en utilisant la modification. J'essaie de télécharger le png à partir de cette URL: http: //wwwns.akamai.com/media_resources/globe_emea.png . Quel devrait être l'objet de réponse à spécifier dans le rappel <> pour y parvenir.
Comme mentionné, vous ne devez pas utiliser Retrofit pour télécharger réellement l'image elle-même. Si votre objectif est de simplement télécharger le contenu sans l'afficher, vous pouvez simplement utiliser un client Http comme OkHttp qui est une autre des bibliothèques de Square.
Voici quelques lignes de code qui vous permettraient de télécharger cette image. Vous pouvez ensuite lire les données de InputStream.
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://wwwns.akamai.com/media_resources/globe_emea.png")
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException e) {
System.out.println("request failed: " + e.getMessage());
}
@Override
public void onResponse(Response response) throws IOException {
response.body().byteStream(); // Read the data from the stream
}
});
Même si Retrofit n'est pas l'homme du travail pour répondre à votre question, la signature de votre définition d'interface le souhaiterait. Mais encore une fois, ne faites pas ça.
public interface Api {
@GET("/media_resources/{imageName}")
void getImage(@Path("imageName") String imageName, Callback<Response> callback);
}
Bien sûr, nous utilisons généralement Picasso pour charger l'image, mais parfois nous avons vraiment besoin d'utiliser Retrofit pour charger une image spéciale (comme récupérer une image captcha), vous devez ajouter un en-tête pour demande, obtenez une certaine valeur de l'en-tête de la réponse (bien sûr, vous pouvez également utiliser Picasso + OkHttp, mais dans un projet, vous avez déjà utilisé Retrofit pour gérer la plupart des demandes nettes), alors voici ici comment mettre en œuvre par Retrofit 2.0.0 (I ont déjà mis en œuvre dans mon projet).
Le point clé est que vous devez utiliser okhttp3.ResponseBody
pour recevoir la réponse, sinon Retrofit analysera les données de réponse en JSON, et non en données binaires.
codes:
public interface Api {
// don't need add 'Content-Type' header, it's useless
// @Headers({"Content-Type: image/png"})
@GET
Call<ResponseBody> fetchCaptcha(@Url String url);
}
Call<ResponseBody> call = api.fetchCaptcha(url);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
if (response.body() != null) {
// display the image data in a ImageView or save it
Bitmap bmp = BitmapFactory.decodeStream(response.body().byteStream());
imageView.setImageBitmap(bmp);
} else {
// TODO
}
} else {
// TODO
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
// TODO
}
});
Retrofit est une bibliothèque REST, vous pouvez utiliser Retrofit uniquement pour obtenir l'URL de l'image, mais pour afficher l'image, vous devez utiliser Picasso: http://square.github.io/picasso/
Déclarez-le renvoyant l'appel par exemple:
@GET("/api/{api}/bla/image.png")
Call<ResponseBody> retrieveImageData();
puis convertissez-le vous-même en Bitmap:
ResponseBody body = retrofitService.retrieveImageData().execute().body();
byte[] bytes = body.bytes();
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Vous pouvez également utiliser Retrofit pour effectuer le @GET
Et renvoyer simplement le Response
. Ensuite, dans le code, vous pouvez faire isr = new BufferedInputStream(response.getBody().in())
pour obtenir le flux d'entrée de l'image et l'écrire dans un bitmap, par exemple, en faisant BitmapFactory.decodeStream(isr)
.
object RetrofitImage
object RetrofitImage {
private fun provideRetrofit(): Retrofit {
return Retrofit.Builder().baseUrl("https://google.com").build()
}
private interface API {
@GET
fun getImageData(@Url url: String): Call<ResponseBody>
}
private val api : API by lazy { provideRetrofit().create(API::class.Java) }
fun getBitmapFrom(url: String, onComplete: (Bitmap?) -> Unit) {
api.getImageData(url).enqueue(object : retrofit2.Callback<ResponseBody> {
override fun onFailure(call: Call<ResponseBody>?, t: Throwable?) {
onComplete(null)
}
override fun onResponse(call: Call<ResponseBody>?, response: Response<ResponseBody>?) {
if (response == null || !response.isSuccessful || response.body() == null || response.errorBody() != null) {
onComplete(null)
return
}
val bytes = response.body()!!.bytes()
onComplete(BitmapFactory.decodeByteArray(bytes, 0, bytes.size))
}
})
}
}
RetrofitImage.getBitmapFrom(ANY_URL_STRING) {
// "it" - your bitmap
print("$it")
}
Extension pour ImageView
fun ImageView.setBitmapFrom(url: String) {
val imageView = this
RetrofitImage.getBitmapFrom(url) {
val bitmap: Bitmap?
bitmap = if (it != null) it else {
// create empty bitmap
val w = 1
val h = 1
val conf = Bitmap.Config.ARGB_8888
Bitmap.createBitmap(w, h, conf)
}
Looper.getMainLooper().run {
imageView.setImageBitmap(bitmap!!)
}
}
}
tilisation de l'extension
imageView?.setBitmapFrom(ANY_URL_STRING)
J'espère que le code suivant vous aidera:
Inclure la fonction suivante dans MainActivity.Java
:
void getRetrofitImage() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
RetrofitImageAPI service = retrofit.create(RetrofitImageAPI.class);
Call<ResponseBody> call = service.getImageDetails();
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Response<ResponseBody> response, Retrofit retrofit) {
try {
Log.d("onResponse", "Response came from server");
boolean FileDownloaded = DownloadImage(response.body());
Log.d("onResponse", "Image is downloaded and saved ? " + FileDownloaded);
} catch (Exception e) {
Log.d("onResponse", "There is an error");
e.printStackTrace();
}
}
@Override
public void onFailure(Throwable t) {
Log.d("onFailure", t.toString());
}
});
}
Voici le code de gestion de fichier pour l'image:
private boolean DownloadImage(ResponseBody body) {
try {
Log.d("DownloadImage", "Reading and writing file");
InputStream in = null;
FileOutputStream out = null;
try {
in = body.byteStream();
out = new FileOutputStream(getExternalFilesDir(null) + File.separator + "AndroidTutorialPoint.jpg");
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
}
catch (IOException e) {
Log.d("DownloadImage",e.toString());
return false;
}
finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
int width, height;
ImageView image = (ImageView) findViewById(R.id.imageViewId);
Bitmap bMap = BitmapFactory.decodeFile(getExternalFilesDir(null) + File.separator + "AndroidTutorialPoint.jpg");
width = 2*bMap.getWidth();
height = 6*bMap.getHeight();
Bitmap bMap2 = Bitmap.createScaledBitmap(bMap, width, height, false);
image.setImageBitmap(bMap2);
return true;
} catch (IOException e) {
Log.d("DownloadImage",e.toString());
return false;
}
}
Cela se fait en utilisant Android Retrofit 2.0. J'espère que cela vous a aidé.
Retrofit est en train d'encoder votre tableau d'octets en base 64. Décodez donc votre chaîne et vous êtes prêt à partir. De cette façon, vous pouvez récupérer une liste d'images.
public static Bitmap getBitmapByEncodedString(String base64String) {
String imageDataBytes = base64String.substring(base64String.indexOf(",")+1);
InputStream stream = new ByteArrayInputStream(Base64.decode(imageDataBytes.getBytes(), Base64.DEFAULT));
return BitmapFactory.decodeStream(stream);
}