Retrofit API для получения изображения PNG
Привет, я новичок в Retrofit Framework для Android. Я мог бы получить ответы JSON от REST-сервисов, используя его, но я не знаю, как загрузить png с помощью модернизации. Я пытаюсь загрузить png с этого URL: http://wwwns.akamai.com/media_resources/globe_emea.png. Каким должен быть ответный объект, который будет указан в Callback<> для достижения этой цели.
9 ответов
Как уже упоминалось, вы не должны использовать Retrofit для фактической загрузки самого изображения. Если ваша цель - просто загрузить контент, не отображая его, вы можете просто использовать Http-клиент, такой как OkHttp, который является еще одной из библиотек Square.
Вот несколько строк кода, которые позволят вам загрузить это изображение. Затем вы можете прочитать данные из 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
}
});
Несмотря на то, что Retrofit не подходит для ответа на ваш вопрос, подпись вашего определения интерфейса будет такой. Но опять же не делай этого.
public interface Api {
@GET("/media_resources/{imageName}")
void getImage(@Path("imageName") String imageName, Callback<Response> callback);
}
Конечно, мы обычно используем Picasso для загрузки изображения, но иногда нам действительно нужно использовать Retrofit для загрузки специального изображения (например, получить изображение с картинки), вам нужно добавить заголовок для запроса, получить некоторое значение из заголовка ответа (конечно, вы можете также используйте Picasso + OkHttp, но в проекте вы уже использовали Retrofit для обработки большинства сетевых запросов), поэтому здесь рассмотрим, как реализовать Retrofit 2.0.0 (я уже реализовал в своем проекте).
Ключевым моментом является то, что вам нужно использовать okhttp3.ResponseBody
чтобы получить ответ, иначе Retrofit будет анализировать данные ответа как JSON, а не двоичные данные.
коды:
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
}
});
Объявите, что он возвращает Call, например:
@GET("/api/{api}/bla/image.png")
Call<ResponseBody> retrieveImageData();
затем конвертируйте его в растровое изображение самостоятельно:
ResponseBody body = retrofitService.retrieveImageData().execute().body();
byte[] bytes = body.bytes();
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Retrofit - это библиотека REST. Вы можете использовать Retrofit только для получения URL-адреса изображения, но для отображения Image вам следует использовать Picasso: http://square.github.io/picasso/
подробности
- Студия Android 3.1.4
- Котлин 1.2.60
- Дооснащение 2.4.0
- проверено в minSdkVersion 19
Решение
объект 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))
}
})
}
}
Использование 1
RetrofitImage.getBitmapFrom(ANY_URL_STRING) {
// "it" - your bitmap
print("$it")
}
Использование 2
Расширение для 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!!)
}
}
}
Использование расширения
imageView?.setBitmapFrom(ANY_URL_STRING)
Вы также можете использовать Retrofit для выполнения @GET
и просто вернуть Response
, Тогда в коде вы можете сделать isr = new BufferedInputStream(response.getBody().in())
чтобы получить входной поток изображения и записать его в растровое изображение, скажем, выполнив BitmapFactory.decodeStream(isr)
,
Я надеюсь, что следующий код поможет вам:
Включить следующую функцию внутри 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());
}
});
}
Ниже приведен код обработки файла для изображения:
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;
}
}
Это делается с помощью Android Retrofit 2.0. Я надеюсь, что это помогло вам.
Источник: Загрузка изображений с использованием Retrofit 2.0
Простое и лучшее решение
Если ответом API является изображение, нет необходимости использовать модификацию для получения изображения. Используя GlideUrl, изображение можно легко визуализировать с помощью Glide.
val glideUrl = GlideUrl("APICall url",LazyHeaders.Builder()
.addHeader("X-Api-Key", "apiKey") // if any headers are required
.build())
Glide.with(requireContext()).load(glideUrl).into(imageview)
Модификация кодирует ваш байтовый массив в базу 64. Так что декодируйте вашу строку, и все готово. Таким образом, вы можете получить список изображений.
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);
}