您好我是Android的Retrofit框架的新手。我可以使用它从REST服务获得JSON响应,但我不知道如何使用改造下载png。我想从这个网址下载png: http://wwwns.akamai.com/media_resources/globe_emea.png。 什么应该响应要在Callback<>中指定的对象实现这一目标。
答案 0 :(得分:31)
如前所述,您不应使用Retrofit实际下载图像本身。如果你的目标只是简单地下载内容而不显示它,那么你可以简单地使用像OkHttp这样的Http客户端,这是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);
}
答案 1 :(得分:26)
当然我们通常使用 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
}
});
答案 2 :(得分:15)
Retrofit是一个REST库,您只能使用Retrofit来获取图片URL,但是为了显示Image,您应该使用Picasso:http://square.github.io/picasso/
答案 3 :(得分:9)
声明它返回Call for instance:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<!-- Bootstrap -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<h1>SLİDER 1</h1>
<!-- SLIDER 1-->
<div id="carousel-1" class="carousel slide" data-ride="carousel">
<div class="carousel-inner" role="listbox">
<div class="item active">
<img src="https://cdn.pixabay.com/photo/2016/12/26/02/13/bishan-1931390_960_720.jpg" alt="...">
</div>
<div class="item">
<img src="https://cdn.pixabay.com/photo/2016/12/26/15/34/simplicity-1932331_960_720.jpg" alt="...">
<div class="carousel-caption">
</div>
</div>
</div>
<a class="left carousel-control" href="#carousel-1" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="right carousel-control" href="#carousel-1" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
<!-- SLIDER 1 END-->
<h1>SLİDER 2</h1>
<!-- SLIDER 2-->
<div id="carousel-2" class="carousel slide" data-ride="carousel">
<div class="carousel-inner" role="listbox">
<div class="item active">
<img src="https://cdn.pixabay.com/photo/2016/12/26/02/13/bishan-1931390_960_720.jpg" alt="...">
</div>
<div class="item">
<img src="https://cdn.pixabay.com/photo/2016/12/26/15/34/simplicity-1932331_960_720.jpg" alt="...">
<div class="carousel-caption">
</div>
</div>
</div>
<a class="left carousel-control" href="#carousel-2" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="right carousel-control" href="#carousel-2" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
<!-- SLIDER 2 END-->
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
</body>
</html>
然后自己将其转换为位图:
@GET("/api/{api}/bla/image.png")
Call<ResponseBody> retrieveImageData();
答案 4 :(得分:3)
您还可以使用Retrofit执行@GET
并返回Response
。然后在代码中,您可以isr = new BufferedInputStream(response.getBody().in())
获取图像的输入流并将其写入位图,例如,通过执行BitmapFactory.decodeStream(isr)
。
答案 5 :(得分:2)
我希望以下代码能为您提供帮助:
在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完成的。我希望它对你有帮助。
答案 6 :(得分:2)
对象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")
}
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)
答案 7 :(得分:0)
Retrofit正在将字节数组编码为以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);
}