Android 改造 API 以检索 png 图像
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25462523/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Retrofit API to retrieve a png image
提问by Pradeep CR
Hi I am new to Retrofit framework for Android. I could get JSON responses from REST services using it but I don't know how to download a png using retrofit. I am trying to download the png from this url: http://wwwns.akamai.com/media_resources/globe_emea.png. What should be response Object to be specified in the Callback<> to achieve this.
嗨,我是 Android 的 Retrofit 框架的新手。我可以使用它从 REST 服务获得 JSON 响应,但我不知道如何使用改造下载 png。我正在尝试从此网址下载 png:http: //wwwns.akamai.com/media_resources/globe_emea.png。要在 Callback<> 中指定的响应对象应该是什么来实现这一点。
回答by Miguel Lavigne
As mentioned you shouldn't use Retrofit to actually download the image itself. If your goal is to simply download the content without displaying it then you could simply use an Http client like OkHttpwhich is another one of Square's libraries.
如前所述,您不应该使用 Retrofit 来实际下载图像本身。如果您的目标是简单地下载内容而不显示它,那么您可以简单地使用像OkHttp这样的 Http 客户端,它是 Square 的另一个库。
Here's a few lines of code which would have you download this image. You could then read the data from the InputStream.
这是几行代码,可以让您下载此图像。然后您可以从 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
}
});
Even though Retrofit isn't the man for the job to answer your question, the signature of your Interface definition would like this. But again don't do this.
尽管 Retrofit 不是回答您问题的人,但您的接口定义的签名会是这样。但再次不要这样做。
public interface Api {
@GET("/media_resources/{imageName}")
void getImage(@Path("imageName") String imageName, Callback<Response> callback);
}
回答by Spark.Bao
Of course we usually use Picassoto load image, but sometimes we really need use Retrofitto load a special image (like fetch a captcha image), you need add some header for request, get some value from header of response (of course you can also use Picasso + OkHttp, but in a project you have already use Retrofit to handle most of net requests), so here introduce how to implement by Retrofit 2.0.0 (I have already implemented in my project).
当然我们通常使用Picasso来加载图片,但有时我们真的需要使用Retrofit来加载一个特殊的图片(比如获取验证码图片),你需要为请求添加一些头部,从响应头部中获取一些值(当然你可以也使用Picasso + OkHttp,但是在一个项目中你已经使用了Retrofit来处理大部分的网络请求),所以这里介绍一下如何通过Retrofit 2.0.0来实现(我已经在我的项目中实现了)。
The key point is that you need use okhttp3.ResponseBody
to receive response, else Retrofit will parse the response data as JSON, not binary data.
关键是你需要okhttp3.ResponseBody
用来接收响应,否则 Retrofit 会将响应数据解析为 JSON,而不是二进制数据。
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
}
});
回答by Yuraj
Retrofit is a REST library, you can use Retrofit only to get image URL but for displaying Image you should use Picasso: http://square.github.io/picasso/
Retrofit 是一个 REST 库,您只能使用 Retrofit 来获取图像 URL,但要显示图像,您应该使用 Picasso:http: //square.github.io/picasso/
回答by Alécio Carvalho
Declare it returning Call for instance:
声明它返回 Call 例如:
@GET("/api/{api}/bla/image.png")
Call<ResponseBody> retrieveImageData();
then convert it to Bitmap yourself:
然后自己将其转换为位图:
ResponseBody body = retrofitService.retrieveImageData().execute().body();
byte[] bytes = body.bytes();
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
回答by Vasily Bodnarchuk
Details
细节
- Android studio 3.1.4
- Kotlin 1.2.60
- Retrofit 2.4.0
- checked in minSdkVersion 19
- 安卓工作室 3.1.4
- 科特林 1.2.60
- 改造 2.4.0
- 签入 minSdkVersion 19
Solution
解决方案
object RetrofitImage
对象 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))
}
})
}
}
Usage 1
用法 1
RetrofitImage.getBitmapFrom(ANY_URL_STRING) {
// "it" - your bitmap
print("$it")
}
Usage 2
用法2
Extension for ImageView
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!!)
}
}
}
Usage of the extension
扩展的使用
imageView?.setBitmapFrom(ANY_URL_STRING)
回答by astryk
You could also use Retrofit to perform the @GET
and just return the Response
. Then in code you can do isr = new BufferedInputStream(response.getBody().in())
to get the input stream of the image and write it into a Bitmap, say, by doing BitmapFactory.decodeStream(isr)
.
您也可以使用 Retrofit 来执行@GET
并返回Response
. 然后在代码中,您可以isr = new BufferedInputStream(response.getBody().in())
获取图像的输入流并将其写入位图,例如,通过执行BitmapFactory.decodeStream(isr)
.
回答by Navneet Goel
I hope following code will help you:
我希望以下代码可以帮助您:
Include following function inside MainActivity.java
:
在里面包含以下函数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());
}
});
}
Following is the file handling code for 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;
}
}
This is done using Android Retrofit 2.0. I hope it helped you.
这是使用 Android Retrofit 2.0 完成的。我希望它对你有帮助。
回答by Ghita Tomoiaga
Retrofit is encoding your byte array to base 64. So decode your string and you are good to go. In this way you can retrieve a list of images.
Retrofit 将你的字节数组编码为 base 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);
}