LoginSignup
3
1

More than 5 years have passed since last update.

PicassoでBasic認証がかかった画像を表示する

Last updated at Posted at 2018-08-31

前回からの続きです。

Picassoで画像をダウンロードしてみたものの、特定の画像だけ表示されず、

「なんで表示されねーんだ:anger:
「Basic認証がかかってるだと:question:
「Picassoでどーやるんだ:question:

ってなりました。

大部分で前回の記事と重複しますが、この記事だけで解決できるように全部書きます。

picasso2-okhttp3-downloaderの導入

Jakeさんが作ったpicasso2-okhttp3-downloaderを使います。

(2018/11/9 追記)
ダウンローダ(OkHttp3Downloader)はPicasso組み込みのものを使います。
そうしないと、setSingletonInstanceでPicassoの全通信にOkHttp3Downloaderを指定した場合、画像のダウンロードが行われません。

ログを見たいのでlogging-interceptorというのも追加しておきます。

app/build.gradle
dependencies {

    // (省略)

    implementation 'com.squareup.picasso:picasso:2.71828'
    implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
}

実装

このレイアウトのimageViewにインターネットから画像をダウンロードして表示しようと思います。

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />

</android.support.constraint.ConstraintLayout>

認証なし

まず、なんにも認証がかかっていない場合は、
公式のサンプル通りに実装すれば、普通に画像ダウンロードされて表示されます。

MainActivity.kt
package com.example.picassosample

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import com.squareup.picasso.Picasso
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        Picasso.get()
                .load("http://i.imgur.com/DvpvklR.png")
                .into(this.imageView)
    }
}

認証あり

Basic認証ありの場合は、こんな感じで、PicassoのインスタンスをBuiler経由で生成して、downloadメソッドの引数にOkHttp3Downloaderクラスのインスタンスを渡すようにします。
この時、通信に使うOkHttpClientクラスにInterceptorを追加して、HTTP通信に認証ヘッダをねじ込むようにしておきます。

MainActivity.kt
package com.example.picassosample

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import com.squareup.picasso.OkHttp3Downloader
import com.squareup.picasso.Picasso
import kotlinx.android.synthetic.main.activity_main.*
import okhttp3.Credentials
import okhttp3.OkHttpClient

class MainActivity : AppCompatActivity() {

    private val picasso: Picasso by lazy {

        val client = OkHttpClient.Builder()
                .addInterceptor { chain ->
                    val request = chain.request().newBuilder()
                            .addHeader("Authorization", Credentials.basic("basic_username", "basic_password"))
                            .build()
                    chain.proceed(request)
                }
                // ↓↓ログ出力用
                .addInterceptor(HttpLoggingInterceptor().apply {
                    level = HttpLoggingInterceptor.Level.HEADERS
                })
                // ↑↑ログ出力用
                .build()

        val downloader = OkHttp3Downloader(client)

        Picasso.Builder(this)
                .downloader(downloader)
                .build()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        this.picasso
                .load("https://url/with/basic/auth/sample.png")
                .into(this.imageView)
    }
}

こうすることで、Basic認証のかかった画像を表示できるようになります。

addInterceptorの代わりに↓↓でもいけるようです。
authenticatorと言うからにはこちらの方が正しい対応のような気がします。

                .authenticator { _, response ->
                    response.request().newBuilder()
                            .addHeader("Authorization", Credentials.basic("basic_username", "basic_password"))
                            .build()
                }

ログを見てみると認証ヘッダが追加されていることも分かります。

logcat
08-31 15:46:19.212 12643 12665 D OkHttp  : --> GET https://url/with/basic/auth/sample.png
08-31 15:46:19.212 12643 12665 D OkHttp  : Authorization: Basic YmFzaWNfdXNlcm5hbWU6YmFzaWNfcGFzc3dvcmQ=
08-31 15:46:19.212 12643 12665 D OkHttp  : --> END GET

しかし...

画像をキャッシュさせたい

上記のようなレイアウトの場合は分からなかったのですが、、ListViewに画像を表示させてみると、画像がキャッシュされないことに気づきました。
この場合、どうすればキャッシュが有効になるのかというと...

前出のコードをちょっと修正して、setSingletonInstanceというメソッドをpicassoのインスタンスを引数にして呼び出しておきます。
画像ロード時のPicassoの呼び出しは通常の呼び出し方法に戻します。

MainActivity.kt
package com.example.picassosample

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import com.squareup.picasso.OkHttp3Downloader
import com.squareup.picasso.Picasso
import kotlinx.android.synthetic.main.activity_main.*
import okhttp3.Credentials
import okhttp3.OkHttpClient

class MainActivity : AppCompatActivity() {

    private val picasso: Picasso by lazy {

        val client = OkHttpClient.Builder()
                .addInterceptor { chain ->
                    val request = chain.request().newBuilder()
                            .addHeader("Authorization", Credentials.basic("basic_username", "basic_password"))
                            .build()
                    chain.proceed(request)
                }
                // ↓↓ログ出力用
                .addInterceptor(HttpLoggingInterceptor().apply {
                    level = HttpLoggingInterceptor.Level.HEADERS
                })
                // ↑↑ログ出力用
                .build()

        val downloader = OkHttp3Downloader(client)

        Picasso.Builder(this)
                .downloader(downloader)
                .build()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        Picasso.setSingletonInstance(this.picasso)  // <-- ここ

        Picasso.get()                               // <-- ここ
                .load("https://url/to/be/required/sample.png")
                .into(this.imageView)
    }
}

このサンプルだと効果がわかりづらいですが、こうしておくと画像がキャッシュされるようになりました。

とりあえずは以上です。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1