改造API以检索png图像

时间:2014-08-23 13:37:16

标签: android retrofit

您好我是Android的Retrofit框架的新手。我可以使用它从REST服务获得JSON响应,但我不知道如何使用改造下载png。我想从这个网址下载png:  http://wwwns.akamai.com/media_resources/globe_emea.png。 什么应该响应要在Callback<>中指定的对象实现这一目标。

8 个答案:

答案 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完成的。我希望它对你有帮助。

来源:Image Download using Retrofit 2.0

答案 6 :(得分:2)

详细信息

  • Android Studio 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)

答案 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);
}